Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Property Sheets in detail

135 views
Skip to first unread message

Thomas Steinbach

unread,
Jun 6, 2009, 8:39:21 AM6/6/09
to
Hello,

how can I move and/or completely delete the Buttons
OK, Cancel, Apply or Help from a property sheet dialog.?

Something like this:

hWndOK = GetDlgItem(hWnd, IDOK);
DestroyWindow(hWndOK

in the INITDIALOG doesn't work.

An how can I modify the room between the sheets
and the border of the dialog (to fit my other program layout)

Additional how can I add more space to the PropertySheetDIALOG
(not the sheets) to add a common element (eg. tree view) for all
sheets, not just one sheet?

Finally: It si possible to hide the tabs of the tab-control?
perhaps to add a custom navigation through the tabs
(eg. tree)?

Thomas

Christian ASTOR

unread,
Jun 6, 2009, 8:56:06 AM6/6/09
to
Thomas Steinbach wrote:

> how can I move and/or completely delete the Buttons
> OK, Cancel, Apply or Help from a property sheet dialog.?

You can do anything on PSCB_INITIALIZED notification (hide, move, etc)

Thomas Steinbach

unread,
Jun 6, 2009, 11:31:39 AM6/6/09
to
Hello Christian,

>> how can I move and/or completely delete the Buttons
>> OK, Cancel, Apply or Help from a property sheet dialog.?
>
> You can do anything on PSCB_INITIALIZED notification (hide, move, etc)

Great, seems that this was the key hint for me. But still
have a problem with the pfnCallback function and _HOW_ to
code and call that function?

The structure says it is not a fuction Pointer like the pfnDlgProc member.
But passing the concrete Message "PSCB_INITIALIZED" while the PSP
is initializing can't be right. But what do I have to do now? I don't find a
usefull
example by MSDN or Web and its still not working :-(

If I debug the App, the function "PropSheetProc" is called when the
PSP is initializing. But the Button still exist after creation-

Please have a look at these two functions:


HWND CreatePropertySheet(HWND hWndOwner, struct MyDATA *pDat)
{
PROPSHEETPAGE psp[3];
PROPSHEETHEADER psh = {0};

psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USETITLE | PSP_PREMATURE | PSH_USECALLBACK;
psp[0].hInstance = GetModuleHandle(0);
psp[0].pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PP_COMMON);
psp[0].pszIcon = NULL;
psp[0].pfnDlgProc = PsDataInputProc;
psp[0].pszTitle = TEXT(STR_PP_COMMON);
psp[0].lParam = (LPARAM)pDat;
/*psp[0].pfnCallback = PropSheetProc;*/
psp[0].pfnCallback = (LPFNPSPCALLBACK)PropSheetProc(hWndOwner,
PSCB_INITIALIZED, 0);

/*psp[1].dwSize = sizeof(PROPSHEETPAGE);*/
/*psp[2].dwSize = sizeof(PROPSHEETPAGE);*/

psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_PROPSHEETPAGE;
psh.hwndParent = hWndOwner;
psh.hInstance = GetModuleHandle(0);
psh.pszIcon = NULL;
psh.pszCaption = (LPCSTR)TEXT("Options");
psh.nPages = sizeof(psp)/sizeof(PROPSHEETPAGE);
psh.ppsp = (LPCPROPSHEETPAGE)&psp;

return (HWND)PropertySheet(&psh);
}

int CALLBACK PropSheetProc(HWND hWnd, UINT uMsg, LPARAM lParam)
{
HWND hWndOK = NULL;

switch( uMsg )
{
case PSCB_INITIALIZED:
hWndOK = GetDlgItem(hWnd, PSBTN_OK);
DestroyWindow(hWndOK);
return (INT_PTR)TRUE; /* PSCB_INITIALIZED */
case PSCB_PRECREATE:
return (INT_PTR)TRUE; /* PSCB_PRECREATE */
case PSCB_BUTTONPRESSED:
return (INT_PTR)TRUE; /* PSCB_BUTTONPRESSED */
}

return (INT_PTR)FALSE; /* uMsg */
}

Do you know where and what is my misstake?
Hope that someone knows this. Because I don't find
an appropriate example.

Do I have to implement the "PropSheetPageProc" too?


Thomas


PS: For a complete reference the pfnDlgProc


BOOL APIENTRY PsDataInputProc(HWND hWnd, UINT uMsg, UINT wParam, LONG
lParam)
{
int wmId = 0;
int wmEvent = 0;
PROPSHEETPAGE *ps;
struct MyDATA * pDat;

pDat = (struct MyDATA *)GetWindowLongPtr(hWnd, GWL_USERDATA);

switch( uMsg )
{
case WM_INITDIALOG:
ps = (PROPSHEETPAGE *)lParam;
pDat = (struct MyDATA *)ps->lParam;
SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)pDat);
/* CODE */
return TRUE;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
/* parse the WM_COMMAND selections */
switch( wmId )
{
case IDC_RADIO_BUTTON1:
/* CODE */
return (INT_PTR)TRUE;
default:
break; /* wmId */
}
return (INT_PTR)FALSE; /* WM_COMMAND */
case WM_NOTIFY:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch( wmId )
{
case IDC_TREE_OPTIONS:
switch( ((LPNMHDR)lParam)->code )
{
case TVN_SELCHANGED:
/* CODE */
return (INT_PTR)TRUE;
default:
break; /* ((LPNMHDR)lParam)->code */
}
return (INT_PTR)FALSE; /* IDC_TREE_OPTIONS */
default:
break; /* wmId */
}
switch( ((NMHDR FAR *)lParam)->code )
{
case PSN_SETACTIVE:
break;
case PSN_APPLY: /* OK, CANCEL or APPLY */
/*if( AllOk() ) {*/
if( TRUE ) {
SetWindowLong(hWnd, DWL_MSGRESULT, PSNRET_NOERROR);
}else {
SetWindowLong(hWnd, DWL_MSGRESULT,
PSNRET_INVALID_NOCHANGEPAGE);
}
return TRUE;
case PSN_KILLACTIVE: /* if page changed or OK is pressed */
SetWindowLong(hWnd, DWL_MSGRESULT, FALSE);
return 1;
case PSN_RESET: /* all changes since last PSN_APPLY will be lost */
SetWindowLong(hWnd, DWL_MSGRESULT, FALSE);
break;
}
return (INT_PTR)TRUE; /* WM_NOTIFY */
}
return FALSE;
}

Christian ASTOR

unread,
Jun 6, 2009, 12:43:22 PM6/6/09
to
Thomas Steinbach wrote:

> Great, seems that this was the key hint for me. But still
> have a problem with the pfnCallback function and _HOW_ to
> code and call that function?

Set the callback for PROPSHEETHEADER :

psh.dwFlags = PSH_PROPSHEETPAGE |PSH_USECALLBACK;
psh.pfnCallback = (PFNPROPSHEETCALLBACK)PropSheetProc;

then

hWndOK = GetDlgItem(hWnd, IDOK);

Thomas Steinbach

unread,
Jun 6, 2009, 1:35:31 PM6/6/09
to
Hello Christian,

As I described in my last post I already have added the dwFlag
PSH_USECALLBACK and implemented the PropSheetProc
decirbed here:
http://msdn.microsoft.com/en-us/library/bb760815(VS.85).aspx

and tried various IDs (IDOK and PSBTN_OK) using GetDlgItem
and DestroyWindow() in the PSCB_INITIALIZED Message
but the button still exist.

btw: If I implement it like you described above like

psh.pfnCallback = (PFNPROPSHEETCALLBACK)PropSheetProc;

The callback function is never reached. Even if the PSH_USECALLBACK
was given to the dwFlag member.

btw2: If I implement it like that:

psp[0].pfnCallback = (LPFNPSPCALLBACK)
PropSheetProc(hWndOwner, PSCB_INITIALIZED, 0);"

the callback function is reached, but has no effect.
Waht is wrong. I dont't understand that. :-(

Thomas

Christian ASTOR

unread,
Jun 6, 2009, 2:30:24 PM6/6/09
to
Thomas Steinbach wrote:

> psh.pfnCallback = (PFNPROPSHEETCALLBACK)PropSheetProc;
>
> The callback function is never reached. Even if the PSH_USECALLBACK
> was given to the dwFlag member.

I just add :

psh.dwFlags = PSH_PROPSHEETPAGE |PSH_USECALLBACK;
psh.pfnCallback = (PFNPROPSHEETCALLBACK)PropSheetProc;

to the MSDN sample props.c (Nancy CLUTS)

and it works for me (test on XP)...

Thomas Steinbach

unread,
Jun 6, 2009, 3:42:20 PM6/6/09
to
Hello Christian,

>> [...]


> I just add :
>
> psh.dwFlags = PSH_PROPSHEETPAGE |PSH_USECALLBACK;
> psh.pfnCallback = (PFNPROPSHEETCALLBACK)PropSheetProc;
>
> to the MSDN sample props.c (Nancy CLUTS)
> and it works for me (test on XP)...

hmm, I have vista. But that shouldn't be a problem.
And it's not just working - you can delete the default buttons?
Can you post (or email me) your complete code?

Do you have a link to the example props.c by Nancy Cluts ?
Can't find that at MSDN and I'm going crauy about this code ;-)

Thomas

Christian ASTOR

unread,
Jun 6, 2009, 5:01:42 PM6/6/09
to
Thomas Steinbach wrote:

> Do you have a link to the example props.c by Nancy Cluts ?
> Can't find that at MSDN and I'm going crauy about this code ;-)

I've uploaded original sources :
http://myfreefilehosting.com/f/49ee102732_1.26MB

Thomas Steinbach

unread,
Jun 6, 2009, 9:58:51 PM6/6/09
to
Hello Christinan,

Thanx. The code looks a littele bit strange to me ;-)
But I solved the problem and got it...

Last Question about this. ;-)

How can I destroy/remove/hide the _disabled_ Apply button
in a property sheet.

I know "GetDlgItem()". But everybody in the net talks
about CPropertySheet, But I use pure and strict C code and the
ID_APPLY_NOW isn't defined. I can't finde the appropriate header :-(

I always get the error:

Error 1 error C2065: 'ID_APPLY_NOW' : undeclared identifier d:\active\test.c
1202 test

Does anybod knows that an how to remove that disabled button?
btw: I think it's a problem to remove a disabled Item, isn't it?

I also tried this:

hWndCancel = GetDlgItem(hWnd, IDCANCEL);
hWndApply = GetNextDlgGroupItem(hWnd, hWndCancel, FALSE);
DestroyWindow(hWndApply);

But the strange thing is, that the next item is the OK Button.
Anyway I can't get and don't know the ID of the Apply Button and
it is definitely _NOT_ the ID_APPLY_NOW :-(

Thomas

Christian ASTOR

unread,
Jun 7, 2009, 5:52:34 AM6/7/09
to
Thomas Steinbach wrote:

> Does anybod knows that an how to remove that disabled button?
> btw: I think it's a problem to remove a disabled Item, isn't it?
>
> I also tried this:
>
> hWndCancel = GetDlgItem(hWnd, IDCANCEL);
> hWndApply = GetNextDlgGroupItem(hWnd, hWndCancel, FALSE);
> DestroyWindow(hWndApply);
>
> But the strange thing is, that the next item is the OK Button.
> Anyway I can't get and don't know the ID of the Apply Button and
> it is definitely _NOT_ the ID_APPLY_NOW :-(

Normally,
hWndApply = GetDlgItem(hWnd, 0x3021);

Thomas Steinbach

unread,
Jun 7, 2009, 9:24:27 AM6/7/09
to
Hello Christian,

>>> [...]


>> But the strange thing is, that the next item is the OK Button.
>> Anyway I can't get and don't know the ID of the Apply Button and
>> it is definitely _NOT_ the ID_APPLY_NOW :-(
>
> Normally,
> hWndApply = GetDlgItem(hWnd, 0x3021);

Yes, that is what I found. Do you know where this is defined?
Is it always 12321 ?

Thomas

Christian ASTOR

unread,
Jun 7, 2009, 12:30:10 PM6/7/09
to
Thomas Steinbach wrote:

> Yes, that is what I found. Do you know where this is defined?
> Is it always 12321 ?

It's mainly defined in atlres.h
http://www.koders.com/c/fidC3413AC3DA92F46CB79680DAB4566552CF9E4F32.aspx

Thomas Steinbach

unread,
Jun 7, 2009, 4:22:00 PM6/7/09
to
Hello Christian,

>> Yes, that is what I found. Do you know where this is defined?
>> Is it always 12321 ?
>
> It's mainly defined in atlres.h
> http://www.koders.com/c/fidC3413AC3DA92F46CB79680DAB4566552CF9E4F32.aspx

Thank you for your help. Was very usefull.
I found today the PSH_NOAPPLYNOW flag which is probably the
best way to remove the apply button ;-)

Now I have a problem to point to my userdata and Get/SetWindowLongPtr
doesn't really work.
In the CreatePropertySheet function where I define the PSPs and the
PSP Header I set my user Data with:

SetWindowLongPtr(hWndOwner, GWL_USERDATA, (LONG_PTR)pDat);
psh.pfnCallback = (PFNPROPSHEETCALLBACK)PropSheetProc;

In the PropSheetProc funtion I need the Data, but don't know how to cast
the Pointer. Have the follwing code.

int CALLBACK PropSheetProc(HWND hWnd, UINT uMsg, LPARAM lParam)
{

PROPSHEETPAGE *ps;
PROPSHEETHEADER *psh;
struct MyDATA * pDat;

pDat = (struct MyDATA *)GetWindowLongPtr(hWnd, GWL_USERDATA);
switch( uMsg )
{

case PSCB_INITIALIZED:
pDat = (struct MyDATA *)lParam;
SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)pDat);


But this code doesn't work like in other DialogProcs, bcause the lParam
holds
a Template for the Resource of the Dialog.

Does anybody know how to get my user data?

Thomas

0 new messages