Jump to content
  • Advertisement
Sign in to follow this  
p0is0n

CreateWindowEx for use in dialog controls

This topic is 3602 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

Hi, I am working on a dialog wrapper using Win32 and have run into a few problems, and so far useful information on the net has been hard to find. I have the dialog box created, and buttons, and the tests for if they are clicked working just fine, but I also need to be able to create a text input box, a text input box that only accepts numerical values, and a combo box. (All using CreateWindowEx). From searching on MSDN I came up with the following code for an edit box : HWND edit = CreateWindowEx(0, "Edit", NULL, WS_CHILD | WS_VISIBLE | ES_LEFT, editBoxRect.left, editBoxRect.top, editBoxRect.Width(), editBoxRect.Height(), m_hWnd, 0, m_hInst, 0); if(! IsWindow(edit)) return false; SendMessage(edit, WM_SETTEXT, 0, (LPARAM)defaultText.c_str()); In this function editBoxRect is a rect that is passed in to determine the position and size of the edit box, m_hWnd is the parent window (the dialog box), and m_hInst is the hInstance of the dialog box. This however does not work. The function does not fail, so the window created is valid, however the button code checking fails, but only with the addition of the function outlined above. I have no idea how the above code could be causing that (the button checking works perfectly without the above code in there), and was wondering if someone here could help by pointing me in the direction of some good tutorials on this (the sample code on MSDN just seems strange or annoyingly out of context), or by giving some help on creating edit boxes, and combo boxes using CreateWindowEx. Thanks in advance for any help on this!

Share this post


Link to post
Share on other sites
Advertisement
Your call to CreateWindowEx works fine. There must be something else, most likely the message pump or the window proc.

Show both, and also where and when you're calling the CreateWindowEx function.

Share this post


Link to post
Share on other sites
My WndProc :

switch(msg)
{
//On initialise dialog
case WM_INITDIALOG:
return true;

//Check the command messages
case WM_COMMAND:
//Check if ok or cancel have been clicked through the command
switch(LOWORD(wParam))
{
case IDOK:
m_isOkClicked = true;
return true;
case IDCANCEL:
m_isCancelClicked = true;
return true;
}

//Check the custom buttons
for(UINT i = 0; i < m_buttonVector.size(); i ++)
{
Is the button is a valid window
if(m_buttonVector->GetWindow())
{
//If the message has been sent from that button
if(m_buttonVector->GetWindow() == (HWND)lParam)
{
//Tell the button it has been clicked
m_buttonVector->SetClicked(true);
return true;
}
}
}

//Trap destroy message
case WM_CLOSE :
case WM_DESTROY :
m_isClosing = true;
break;
}

return DefWindowProc(hWnd, msg, wParam, lParam);



Message Pump :

//Allow other application and threads minimal time
Sleep(0);

//Check for Windows messages
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if(msg.message == WM_QUIT) return false;
}



Order of calls :
NOTE : These calls are made after the main window creation, and after the setting up of directX.

Create dialog box (uses CreateWindowEx)
Add Ok Button (uses CreateWindowEx)
Add Cancel Button (uses CreateWindowEx)
Add custom button (uses CreateWindowEx)
Add custom button (uses CreateWindowEx)
Add edit control (uses CreateWindowEx)

Then the code goes into a while loop that it sticks in until ok or cancel are pressed.

Check if buttons have been pressed.
Check if the 'X' on the dialog box has been clicked.
Call update that the message pump is in.

Also for refrence :
Creating a button :

m_hWnd = CreateWindowEx(0, "Button", buttonText.c_str(), WS_VISIBLE | WS_CHILD | WS_TABSTOP, buttonRect.left, buttonRect.top, buttonRect.Width(), buttonRect.Height(), parent, NULL, hInst, 0);

if(! IsWindow(m_hWnd)) return false;
SendMessage(m_hWnd, WM_SETFONT, (WPARAM)font, FALSE);




While debugging it showed that the actual error is when checking the status of the 'ok' button, checking the validity of the dialog box main window fails. (validity checked using IsWindow(hWnd)).
It makes no sense to me as the checking of the status of the buttons is in the while loop, and the while loop manages to make 2 full iterations with no problem, the third iteration of the while loop always falls over at checking the ok button (first call in while loop).

Share this post


Link to post
Share on other sites
So basically it's not the edit making trouble.

You're talking about a while loop, we need to see it to comment on it.

About your WindowProc though:

You should not return true, if you handle WM_COMMAND return 0.
Also your WM_COMMAND handler doesn't have a break, so it looks like any WM_COMMAND message that is not one of your handled cases will fall through to WM_CLOSE/WM_DESTROY and set the end-while-loop flag.

Share this post


Link to post
Share on other sites
oh my god!
I can't believe i didnt catch that i missed the break out.
Turns out it was falling through there and going to close and destroy, thus causing close to be set and ending up with the window being destroyed meaning the IsWindow would fail.

Why is it always the stupid things like this that I can't find.
I have also set the handeled commands to return 0, thanks for pointing that out.
Thanks a lot for noticing it!

Share this post


Link to post
Share on other sites
Nitpick: I wouldn't use IsWindow() like that, CreateWindowEx returns NULL on failure.
There's a small chance that the following could happen:
1. Your code calls DestroyWindow() and your window handle is invalidated.
2. Some other application on the system creates a window and happens to get the same window handle as your app was using (The OS recycles them).
3. Your code calls IsWindow on the old window handle and it returns true, because the handle is for a valid window - it's just not the window you think it is.

Share this post


Link to post
Share on other sites
Hello pOison,
1-you should call PostQuitMessage(0) when you process WM_DESTROY message
2-I don't understand why you are using WS_style parameter passed to CreateWindowEx.
Quote:

Child windows must have a parent window and are confined to the client area of their parent. This is the major distinction between child windows and overlapped and pop-up windows. Child window parents can be top-level windows or other child windows. Child windows are positioned from their parent window's upper-left corner and not from the upper-left of the screen as are top-level windows. Child windows are clipped to the client area of their parent. Controls in a dialog box are child windows whose parent is the dialog box. Child windows must not be created with the CW_USEDEFAULT value for either the position or size of the window. Child windows that use CW_USEDEFAULT will exist but will have no size or position or both.

I have Charles Peztold's book on win32 /Windows programming
You should rather use WS_OVERLAPPEDWINDOW style

Share this post


Link to post
Share on other sites
Quote:
Original post by HolyGrail
Hello pOison,
1-you should call PostQuitMessage(0) when you process WM_DESTROY message
2-I don't understand why you are using WS_style parameter passed to CreateWindowEx.
Quote:

Child windows must have a parent window and are confined to the client area of their parent. This is the major distinction between child windows and overlapped and pop-up windows. Child window parents can be top-level windows or other child windows. Child windows are positioned from their parent window's upper-left corner and not from the upper-left of the screen as are top-level windows. Child windows are clipped to the client area of their parent. Controls in a dialog box are child windows whose parent is the dialog box. Child windows must not be created with the CW_USEDEFAULT value for either the position or size of the window. Child windows that use CW_USEDEFAULT will exist but will have no size or position or both.

I have Charles Peztold's book on win32 /Windows programming
You should rather use WS_OVERLAPPEDWINDOW style
1. Only if you want the application to quit. For dialogs, you generally don't want this. Calling PostQuitMessage() does all sorts of things behind the scenes, including preventing any more dialogs being created.
2. WS_OVERLAPPED has a value of 0, so not specifying WS_POPUP is the same as specifying WS_OVERLAPPED. WS_OVERLAPPEDWINOW is only if you need a full "Windows-looking" window with a caption, maximize and minimize box.

Share this post


Link to post
Share on other sites
@ EvilSteve
Is using IsWindow really that dangerous?
I read about window handle recycling at :
http://blogs.msdn.com/oldnewthing/archive/2007/07/17/3903614.aspx

But it just seemed to me like there wasn't much of a chance of the window being destroyed, then being reallocated in such a short time frame. In my program to create a dialog box a new instance of the dialog class needs to be created, then obviously m_hWnd is 0 until it is created so any calls on IsWindow will return false, and m_hWnd is set to 0 once the window is destroyed, so any calls will fail. The IsWindow check is only there as a safeguard that nothing goes wrong with the window in the short amount of time the window is alive for.

If using IsWindow is the wrong thing to do, any ideas on a different check, or should I just check that it is not NULL?

@ HolyGrail
Is that book on Windows programming any good?
I really should have one for refrence.

Share this post


Link to post
Share on other sites
Quote:
Original post by p0is0n
@ EvilSteve
Is using IsWindow really that dangerous?
I read about window handle recycling at :
http://blogs.msdn.com/oldnewthing/archive/2007/07/17/3903614.aspx

But it just seemed to me like there wasn't much of a chance of the window being destroyed, then being reallocated in such a short time frame. In my program to create a dialog box a new instance of the dialog class needs to be created, then obviously m_hWnd is 0 until it is created so any calls on IsWindow will return false, and m_hWnd is set to 0 once the window is destroyed, so any calls will fail. The IsWindow check is only there as a safeguard that nothing goes wrong with the window in the short amount of time the window is alive for.

If using IsWindow is the wrong thing to do, any ideas on a different check, or should I just check that it is not NULL?
It's unlikely, but it's certainly possible. You'd be better checking against NULL if your code sets it to NULL when its no longer valid (And it'll be ever so slightly better for performance)

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!