Jump to content
  • Advertisement
Sign in to follow this  
Vanderry

[C++, Win32, MFC] Merging windows

This topic is 2949 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey guys !

I was wondering if there is any straightforward way of merging a dialog resource with arbitrary items into an already existing window. Right now I'm mainly concerned with having things like static text, edit controls and button controls in it, just to get some basic text input. I'm able to display the dialog as a separate window using DialogBox() but when I use CreateWindowEx() (possibly in the wrong manner) I only see the window background color.


hControlPanel = CreateWindowEx( 0,
WC_DIALOG,
0,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
200,
200,
hWndParent,
(HMENU)IDD_DIALOG1,
hInstance,
NULL );



Many thanks for any help !

- Dave

Share this post


Link to post
Share on other sites
Advertisement
Assuming I understand what you're trying to do in the code you posted, you can't use CreateWindowEx() like that. The hMenu argument to CreateWindow in the case of child controls specifies its ID not the ID of a resource. So what that code is doing is creating an empty child window of class WC_DIALOG that has child id IDD_DIALOG1.

To do what you want to do you need to create your dialog as a modeless dialog box using CreateDialog() and then re-parent it to the window you want it to be a child of. You can reparent the window by doing both of the following

(1) Call SetParent() on the dialog.
(2) Change its window style to have child style (have WS_CHILD defined) with SetWindowLongPtr() and will probably need to then call SetWindowPos() to get the style change to show up.

Share this post


Link to post
Share on other sites
Thank you jwezorek for your swift response (and sorry that my own took so long xP). I thought I had managed to use a resource in conjunction with CreateWindowEx previously but I just noticed that it was the predefined "IDC_TREE1".

The solution you suggested worked pretty nicely, although without having put too much effort into the dialog procedure yet, my edit controls don't respond to text input. That is, I can highlight them by clicking in them and the little blinking line appears as it should, but nothing happens when I attempt to write something. Do I need to work out some special response branch in the dialog procedure or have I misused any identifier in the initializing function calls?


HWND hControlPanel = CreateDialog( hInstance, MAKEINTRESOURCE( IDD_DIALOG1 ), hWndParent, (DLGPROC)CApplication::WndProcControlPanel );
SetParent( hControlPanel, hWndParent );
SetWindowLongPtr( hControlPanel, GWL_STYLE, WS_CHILD );
SetWindowPos( hControlPanel, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE );

Share this post


Link to post
Share on other sites
The thing with text not showing in your edit controls doesn't sound good ... If you make the dialog with CreateDialog() but don't reparent it, do the edit box work normally?

I know that there are certain Win32 controls that you can't reparent because they cache their parent windows internally in their implementation -- I guess, for speed reasons -- but I thought you'd be okay because the child controls will still have the dialog as their parent.

Share this post


Link to post
Share on other sites
Not 100% sure, but it might be an IsDialogMessage problem. Without it you have to process input focus yourself. Can I see your message loop, dialog procedure and main window procedure?

Share this post


Link to post
Share on other sites
Quote:
Original post by jwezorek
If you make the dialog with CreateDialog() but don't reparent it, do the edit box work normally?


If I don't reparent the window then it becomes even less responsive to input. I can still click the buttons in it but not highlight any of the textboxes, and the window becomes "unhooked" with a caption (although it can't be moved).

This is the main message loop
MSG msg;
while( 1 )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
{
break;
}
if( msg.message != WM_KEYDOWN )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
else
{
// Advance game frame
if( g_pApplication->GetDevice() != NULL )
{
g_pApplication->Update();
g_pApplication->Render();
}
}
}


This is the main window procedure
LRESULT CALLBACK CApplication::WndProcMain( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case ID_FILE_EXIT:
PostMessage( hWnd, WM_DESTROY, 0, 0 );
return 0;
}
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
case WM_SIZE:
g_pApplication->OnWindowResize();
StatusBarOnSize( hWnd, LOWORD( lParam ), HIWORD( lParam ), static_cast<UINT>(wParam) );
return 0;
}

return DefWindowProc( hWnd, message, wParam, lParam );
}


And this is the dialog window procedure, since I'm a bit unsure what needs to be in it I simply haven't added much yet.
LRESULT CALLBACK CApplication::WndProcControlPanel( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_COMMAND:
{
int id = LOWORD( wParam );

switch( id )
{
case IDOK:

case IDCANCEL:
EndDialog( hwnd, id );
}

return 0;
}
case WM_INITDIALOG:

default:
return FALSE; // Let system deal with msg
}
}

Share this post


Link to post
Share on other sites
You appear to be ignoring WM_KEYDOWN messages as well as not using IsDialogMessage(), which is why you are having input problems. I personally would choose a different design, one that doesn't use modeless dialogs in this case, but if you absolutely have to use dialog templates, I do believe it is possible to cook something up. Got a dialog resource template code sample to post too?

P.S.

Also, modeless dialogs don't use EndDialog.

WM_INITDIALOG's return value also has special meaning, and should return TRUE if you don't want to override the default focus. There are a few dialog messages that don't follow the general rule of TRUE (processed), FALSE (do default); WM_INITDIALOG is one of them.

[Edited by - yadango on August 25, 2010 4:39:32 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by yadango
You appear to be ignoring WM_KEYDOWN messages as well as not using IsDialogMessage(), which is why you are having input problems. I personally would choose a different design, one that doesn't use modeless dialogs in this case, but if you absolutely have to use dialog templates, I do believe it is possible to cook something up. Got a dialog resource template code sample to post too?

P.S.

Also, modeless dialogs don't use EndDialog.

WM_INITDIALOG's return value also has special meaning, and should return TRUE if you don't want to override the default focus. There are a few dialog messages that don't follow the general rule of TRUE (processed), FALSE (do default); WM_INITDIALOG is one of them.


Thank you yadango for that informative problem analysis. I believe the reason I skipped that message type in the first place was that in an earlier application it was causing error sounds to be played whenever I was pressing keys without having focused a tree view within the window. I can see how IsDialogMessage() could be useful here to avoid some faulty message handling, although I'm not sure how this could be applied when messages are being passed as unsigned ints (I've stitched together several code samples I've found, hence the somewhat incoherent program structure). Can I somehow cast this UINT into a LPMSG or do I need to pass in the actual MSG structure as an argument for the window procedure?

Also, I wonder what would be another alternative to using modeless dialogs? The reason I chose to do it like this was simply because it's the only way I know that utilizes resource templates that can be constructed graphically.

Here's what the entire resource file looks like, I suspect there might be some excessive information in there as a result of my experiments :P


// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Swedish resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE)
#ifdef _WIN32
LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_MENU1 MENU
BEGIN
POPUP "File"
BEGIN
MENUITEM "Exit", ID_FILE_EXIT
END
END


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DIALOG1 DIALOGEX 0, 0, 316, 180
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,205,159,50,14
PUSHBUTTON "Cancel",IDCANCEL,259,159,50,14
EDITTEXT IDC_EDIT1,21,20,66,12,ES_AUTOHSCROLL
EDITTEXT IDC_EDIT2,142,68,83,28,ES_AUTOHSCROLL
EDITTEXT IDC_EDIT3,14,129,152,26,ES_AUTOHSCROLL
LTEXT "Static",IDC_STATIC,165,22,63,16
LTEXT "Static",IDC_STATIC,35,67,68,18
LTEXT "Static",IDC_STATIC,187,140,63,7
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 309
TOPMARGIN, 7
BOTTOMMARGIN, 173
END
END
#endif // APSTUDIO_INVOKED

#endif // Swedish resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED



Again, thanks ever so much for taking the time to help me. This feels like an important programming aspect to really understand.

Share this post


Link to post
Share on other sites
Quote:
Original post by Vanderry
[...] I believe the reason I skipped that message type in the first place was that in an earlier application [...]


That's why your edit controls aren't working, probably.

Quote:

I can see how IsDialogMessage() could be useful here to avoid some faulty message handling, although I'm not sure how this could be applied when messages are being passed as unsigned ints (I've stitched together several code samples I've found, hence the somewhat incoherent program structure). Can I somehow cast this UINT into a LPMSG or do I need to pass in the actual MSG structure as an argument for the window procedure?

Not sure, but I think you're misunderstanding how IsDialogMessage works. It would go in your message loop not your WndProc. Something like this:

while(GetMessage(&msg, NULL, 0, 0)) {
if (! IsDialogMessage(g_hToolbar, &msg)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

IsDialogMessage() is actually really poorly named because it isn't a simple predicate: the above is actually fielding the incoming messages in cases in which they are in fact dialog messages. Also, be aware, a hitch to the above is that if you have more than one modeless dialogs you have to keep track of the one that has focus yourself and test for the focus dialog in your message loop. But, anyway, all that doing this is going to get you, I believe, is that it will give your dialog standard behavior regarding keyboard navigation i.e. tab stops, etc. I'm pretty sure filtering out WM_KEYDOWN was what broke your edit boxes.
Quote:

Also, I wonder what would be another alternative to using modeless dialogs? The reason I chose to do it like this was simply because it's the only way I know that utilizes resource templates that can be constructed graphically.

The only way that I know to use dialog resources is with DialogBox or CreateDialog, unfortunately. Personally I don't use them much because of this. I generally just build up dialog-like things manually with lots of calls to CreateWindow: a pain for sure but it gives you the most flexibility in the long run.

[Edited by - jwezorek on August 25, 2010 1:24:11 PM]

Share this post


Link to post
Share on other sites
Agreed. A different design is in order since modeless dialogs are not designed to be child windows (but rather popup windows). I remember there being a hack, because you can have modeless dialogs as MDI children. I think I know what you want... something like this but with tabs working?

Another design, since it looks like a game you are writing, is to do what games usually do in this case: use custom windowless controls, drawn by your rendering system, instead.

[Edited by - yadango on August 25, 2010 4:33:49 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!