Win32: Having a dialog as a child of another window

Started by
37 comments, last by Evil Bill 20 years, 5 months ago
I''m trying to get a dialog window (created with CreateDialog()), to be the child window of another window (which is created with DialogBox() [although it shouldn''t matter]). The reason is, i''m trying to create a settings page for my app. I have at least 13 pages, and i''ll be adding more, so my property sheet is getting rather crowded. So i was thinking of having a listbox control on the left of my settings dialog, and a space where i could have a dialog for the settings for each page. I''ve tried using SetParent(), but that freezes the app (neither dialog is displayed, but the dialog gets created, because i can;t click on the main app window). Has anyone made a settings page like this before? Cheers, Steve
Member of the Unban Mindwipe Society (UMWS)
Advertisement
Anyone?
Member of the Unban Mindwipe Society (UMWS)
Third argument to CreateDialog is hwndParent, a handle to the parent window.

Skizz
Yeah, but all that does is stopes the parent window being activated until the dialog has been closed. I need the dialog to be like a control on the parent dialog.
Thanks for the reply.

Cheers,
Steve
Member of the Unban Mindwipe Society (UMWS)
Are you using a modal dialog or a modeless dialog? Your inability to click on the app window while it''s "up" makes me think modal, so I would suggest you look at how modeless dialogs work, because that would prevent the dialog from freezing anything else, which I think is what you''re trying for.

Really though I''m not entirely clear on why you think you need yet another dialog.

-fel
~ The opinions stated by this individual are the opinions of this individual and not the opinions of her company, any organization she might be part of, her parrot, or anyone else. ~
Sorry, my explanation is rubbish
Lemme get some code...

Ok. I have a modal dialog for my settings dialog. Heres what my WM_INTIDIALOG handler looks like:
case WM_INITDIALOG:   GetWindowRect(GetDlgItem(hDlg,IDC_POSITION),&rc);   ShowWindow(GetDlgItem(hDlg,IDC_POSITION),SW_HIDE);   hWndPage = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_SETTINGS_CONNECTION),hDlg,SettingsDlgProcConnection);   SetParent(hWndPage,hDlg);   ShowWindow(hWndPage,SW_SHOW);   break;

IDC_POSITION is a static control that covers the area i want my ''page'' to be. IDD_SETTINGS_CONNECTION is a dialog resource that i used for my property sheet.
Running that code causes the cursor to change to the hourglass, the main window to loose focus, and for the app to freeze (the main window isn''t redrawn).
If i comment out the SetParent() line, i get this:

As you can see, the settings dialog is set up fine, but its not a child window (perhaps i''m using the wrong word - i mean its not a control on the dialog).

There must be some way to achieve what i''m trying to do, after all - the property sheets do it.
I really don''t want to have to use a standard window, because that''d mean rewriting my settings pages (admitadly not too much, but i''d need a class for each page), but if its the only option then i''ll go for it.

Cheers,
Steve
Member of the Unban Mindwipe Society (UMWS)
Setting a window as a parent dialog means, well, probably a lot more than you want it to.

What exactly do you want that dialog to do that it won't do merely in terms of what dialog normal behavior is? Modal dialogs won't affect the rest of the application until they return anyway, as a rule.

If you really must have a dialog pointer I'd suggest passing it in on a constructer overload to avoid the "other stuff".

EDIT: looking over your post for the third or fourth time, I think I might see what you're trying to do. It begs the question, though, why aren't you just using PropertySheet from prsht.h? Giving a dialog a parent does not assume that you mean the dialog should be *on* the parent dialog. It just assumes spawn point, return point, and a few other things when you're running modeless, like callback handling.

-fel

[edited by - felisandria on November 10, 2003 2:09:49 PM]
~ The opinions stated by this individual are the opinions of this individual and not the opinions of her company, any organization she might be part of, her parrot, or anyone else. ~
I think you''re going to get into a mess doing want you want to do but here I go...

Assuming that you have "Master Dialog" with a list IDC_LIST and a static control IDC_STATIC_PANELAREA and three "panel" dialogs IDD_DIALOG_PANEL1, IDD_DIALOG_PANEL2, and IDD_DIALOG_PANEL3.

In the WM_INITDIALOG message you can create the three child panels and in the LBN_SELCHANGE message for the list you could move and show them. *WARNING! UGLY CODE AHEAD*
LRESULT CALLBACK PropertiesDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){  static HWND wWndPanel1 = 0;  static HWND wWndPanel2 = 0;  static HWND wWndPanel3 = 0;  switch (message)  {  case WM_INITDIALOG:    wWndPanel1 = CreateDialog(hInst,MAKEINTRESOURCE(IDD_DIALOG_PANEL1),hDlg,(DLGPROC)PanelProc);    wWndPanel2 = CreateDialog(hInst,MAKEINTRESOURCE(IDD_DIALOG_PANEL2),hDlg,(DLGPROC)PanelProc);    wWndPanel3 = CreateDialog(hInst,MAKEINTRESOURCE(IDD_DIALOG_PANEL3),hDlg,(DLGPROC)PanelProc);    SendDlgItemMessage( hDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)"Panel 1" );    SendDlgItemMessage( hDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)"Panel 2" );    SendDlgItemMessage( hDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)"Panel 3" );    SendDlgItemMessage( hDlg, IDC_LIST, LB_SELECTSTRING, 0, (LPARAM)"Panel 1" );    return TRUE;  case WM_COMMAND:    if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)     {      EndDialog(hDlg, LOWORD(wParam));      return TRUE;    }    else    {      switch ( HIWORD(wParam) )      {      case  LBN_SELCHANGE:        {          int nSelected = SendDlgItemMessage( hDlg, IDC_LIST, LB_GETSEL, 0, 0);          HWND hPanel = 0;          hPanel = SendDlgItemMessage( hDlg, IDC_LIST, LB_GETSEL, 0, 0) ? wWndPanel1 : hPanel;          hPanel = SendDlgItemMessage( hDlg, IDC_LIST, LB_GETSEL, 1, 0) ? wWndPanel2 : hPanel;          hPanel = SendDlgItemMessage( hDlg, IDC_LIST, LB_GETSEL, 2, 0) ? wWndPanel3 : hPanel;          if ( hPanel )          {            RECT rect;            GetWindowRect( GetDlgItem( hDlg, IDC_STATIC_PANELAREA ), &rect );            MoveWindow( hPanel, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE );            ShowWindow( hPanel, SW_NORMAL );          }        }        break;      }    }    break;  }  return FALSE;}

Sorry for the ugly code. I tried to keep it simple, not pretty.

There are a lot of problem with this approach. For example, the panels will not move when the parent does so you''ll have to watch for it and move them and tabbing between the controls will probably not work as you expect (e.g. you will not be able to tab back out to the list.

Full source here: ftp://ftp.cyberbrinedreams.com/pub/temp_code/multidialog.zip
---CyberbrineDreamsSuspected implementation of the Windows idle loop: void idle_loop() { *((char*)rand()) = 0; }
Easy solution: Just add | WS_CHILD to your window style, and your original method will work.
fel: Because i''ve currently got 12 pages, and theres goign to be at least 15. A property sheet just gets messy with too many tabs.

MauMan: Yeah, thats kinda what i wanna do, but i want to have the various pages as controls on the dialog rather than as seperate windows.

AP: I tried that but it didn''t work. I also did a SetWindowPos() afterwards, as the docs say (to update the style).
I can''t remember why, i''ll get back to you.

Cheers,
Steve
Member of the Unban Mindwipe Society (UMWS)

This topic is closed to new replies.

Advertisement