CWnd::CreateEx() fails after replacing WS_CHILD with WS_POPUP - mfc

When user click a button, I would like to bring up another window. So in the OnBnClicked..() function, I added following code:
CWnd* window = new CWnd;
BOOL result = window->CreateEx(WS_EX_CLIENTEDGE, _T("STATIC"), _T("Hi"), WS_CHILD | WS_VISIBLE, 0, 0, 20, 20, m_hWnd, (HMENU)1234);
window->ShowWindow(SW_SHOW);
This works, except it created a child window. What I need is a separate window. So I modified the code by changing "WS_CHILD" to "WS_POPUP", and "m_hWnd" to "NULL".
CWnd* window = new CWnd;
BOOL result = window->CreateEx(WS_EX_CLIENTEDGE, _T("STATIC"), _T("Hi"), WS_POPUP | WS_VISIBLE, 0, 0, 20, 20, NULL, (HMENU)1234);
window->ShowWindow(SW_SHOW);
But now, the CreateEx() call returns FALSE. I would appreciate some pointer.
[Edit:]
I updated the code as following. But still seeing the same issue. Also, even when CreateEx() returns FALSE, GetLastError() actually returns 0.
CWnd* window = new CalibrationWindow;
LPCTSTR className = NULL;
if (!className) {
className = AfxRegisterWndClass(
CS_VREDRAW | CS_HREDRAW,
::LoadCursor(NULL, IDC_ARROW),
(HBRUSH) ::GetStockObject(WHITE_BRUSH),
::LoadIcon(NULL, IDI_APPLICATION));
}
BOOL isValid = ::IsWindow(GetSafeHwnd());
BOOL result = window->CreateEx(0, _T(className), _T("Hi"), WS_POPUP | WS_VISIBLE, 0, 0, 20, 20, m_hWnd, (HMENU)1234);
DWORD errorCode;
if (!result) {
errorCode = GetLastError();
}
window->ShowWindow(SW_SHOW);

The nID or nIDorHMenu parameter for CWnd::CreateEx is an 'overloaded' parameter that either specifies a control ID or a menu ID.
For a child window (WS_CHILD window styles) it is the control identifier. You can specify any value as long as it is unique among all child windows with the same parent window.
For a popup window on the other hand (a window that does have WS_CHILD window style) it is the menu identifier. In this case it has to be a valid HMENU. Passing a made up value will cause window creation to fail.

Here's how to create a window out of your CWnd-derived class using a different method:
CWndDerived myWnd;
LPCTSTR className = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,
nullptr,
(HBRUSH) ::GetStockObject(WHITE_BRUSH),
nullptr);
myWnd.CreateEx(
0, // WS_EX_TOPMOST
className,
_T("Title"),
WS_POPUP | WS_BORDER | WS_CAPTION | WS_MAXIMIZEBOX | WS_SYSMENU,
0, 0, 300, 200,
m_hWnd,
nullptr,
nullptr);
This allows you to have your CWndDerived myWnd as a member variable (should you need it) of your other window and retain all the goodies that come with MSVC's MFC class editor.
I hope this helps

Related

Why CreateWindowEx will add WS_CAPTION by default?

I'm trying to create an window by CreateWindowEx, but seams even I give both dwExStyle dwStyle value 0, the window still have WS_CAPTION style.
Code snippet as following:
_hWnd = CreateWindowExW(iExStyle, pszClassName, pszTitle, iStyle | WS_CLIPCHILDREN, dX, dY, dWidth, dHeight,
hWndParent, 0, hInstance, NULL);
ASSERT(GetWindowLong(_hWnd, GWL_STYLE) & WS_CAPTION == 0); //<---- This will failed.
dwStyle = 0x00000000L means WS_OVERLAPPED or WS_TILED, this window has a title bar and a border.
Window Styles
As emax says, WS_OVERLAPPED (0) is the default and results in:
The window is an overlapped window. An overlapped window has a title bar and a border. Same as the WS_TILED style.
If you are creating a child window you must specify WS_CHILD and if you are creating a "popup" window you must use WS_POPUP or WS_POPUPWINDOW.
A tooltip for example would use WS_POPUP and WS_EX_TOOLWINDOW + WS_EX_TOPMOST...

Win 32 API, drawing two child windows with vertical splitter bar

Below is code, which I am using for creating child windows:
case WM_CREATE:
hInst = ((LPCREATESTRUCT) lParam) -> hInstance;
hWnd1 = CreateWindowEx( WS_EX_CLIENTEDGE | WS_EX_LEFT,
"edit", NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | ES_MULTILINE | WS_VSCROLL,
0, 0, 0, 0,
hWnd, (HMENU) 1,
hInst, NULL );
hWnd2 = CreateWindowEx( WS_EX_CLIENTEDGE | WS_EX_LEFT,
"edit", NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | ES_MULTILINE | WS_VSCROLL,
0, 0, 0, 0,
hWnd, (HMENU) 2,
hInst, NULL );
But this code produces horizontal splitter, and I want vertical splitter.
First I thought, if I change height and width parameters, I could create vertical splitter. But it was of no use.
For full code and sample example (in order to save space on SO):
http://old.sumitbirla.com/software/src/splitter.c
So, what is exactly keyword/parameter, which would produce vertical splitter bar.
The code you posted just creates two child windows. It has nothing to do with vertical or horizontal splitter. Handle the WM_SIZE message in the parent window to position and size the child windows for a vertical or horizontal split.

Window creation fails with non-NULL hMenu parameter

In addition to the main window, I'm trying to create another top level window. The problem is that when I'm setting the second window's hMenu parameter to a non-NULL value, it doesn't show up.
e.g:
This window shows up (hMenu == 0)
case IDC_BUTTON_SEND_COMMAND:
{
CreateWindowExW(NULL,
L"CommandWindow", L"Send Command",
WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
100, 100, 600, 400,
NULL,
(HMENU)0,
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
break;
}
This window doesn't show up (hMenu == 4)
case IDC_BUTTON_SEND_COMMAND:
{
CreateWindowExW(NULL,
L"CommandWindow", L"Send Command",
WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
100, 100, 600, 400,
NULL,
(HMENU)4,
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
break;
}
I'm using Windows 7.
Passing (HMENU)4 as the hMenu parameter to CreateWindowEx to create a top level window tells the system to attach a menu to it. This menu has the menu handle 4. A menu handle (HMENU) is returned from functions like CreateMenu. If the handle is not a valid HMENU window creation fails.
Your observation, that the window doesn't show up is misleading yourself into believing that the window actually exists. The window doesn't exist, and CreateWindowEx returns NULL. Checking return values is advisable, and calling GetLastError when an API call fails is usually quite helpful.

Up-Down control doesn't show its position in its buddy window

I created an up-down control by the following code.
HWND hEdit, hUpDown;
hEdit = CreateWindowExW(WS_EX_CLIENTEDGE,
L"EDIT",
Content.c_str(),
ES_LEFT | WS_VISIBLE | WS_CHILD,
600,
260,
100,
25,
hWndParent,
NULL,
hInstance,
NULL);
INITCOMMONCONTROLSEX iccx;
iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccx.dwICC = ICC_UPDOWN_CLASS;
InitCommonControlsEx(&iccx);
hUpDown = CreateWindowExW( 0,
UPDOWN_CLASSW,
L"",
UDS_ARROWKEYS | UDS_ALIGNRIGHT | WS_VISIBLE | WS_CHILD,
0,
0,
0,
0,
hWndParent,
NULL,
hInstance,
NULL);
SendMessageW(hUpDown, UDM_SETBUDDY, (WPARAM) hEdit, (LPARAM) NULL);
SendMessageW(hUpDown, UDM_SETRANGE32, (WPARAM) 0, (LPARAM) 100);
Sleep(5000);
SendMessageW(hUpDown, UDM_SETPOS32, (WPARAM) NULL, (LPARAM) 20);
Sleep(5000);
SendMessageW(hUpDown, UDM_SETPOS32, (WPARAM) NULL, (LPARAM) 60);
I checked the return values of the SendMessageW() functions. They terminate successfully by returning the previous position value as documented.
The created up-down control looks normal:
The problem is, sending the UDM_SETPOS32 message, clicking the up and down arrows and pressing the up and down keys on the keyboard have no effect. I can't change the contents of the edit control (the buddy window of the up-down control) without directly typing something into it. It just stays empty.
I am able to type anything in it manually by using keyboard:
How do I change the position/value of this up-down control by pressing keyboard arrow keys, by clicking the arrows in the GUI and by sending UDM_SETPOS32 in the code? What am I missing in my code?
Use the style UDS_SETBUDDYINT to the up-down control while creating it.
From MSDN documentation:
UDS_SETBUDDYINT
Causes the up-down control to set the text of the buddy window (using the WM_SETTEXT message) when the position changes. The text consists of the position formatted as a decimal or hexadecimal string.
Change the creation code of the up-down control like this by adding the UDS_SETBUDDYINT style:
hUpDown = CreateWindowExW( 0,
UPDOWN_CLASSW,
L"",
UDS_SETBUDDYINT | UDS_ARROWKEYS | UDS_ALIGNRIGHT | WS_VISIBLE | WS_CHILD,
0,
0,
0,
0,
hWndParent,
NULL,
hInstance,
NULL);

Win32: How to create a bordless popup window

Win32 API provides many styles for window creating and I'm looking for a style that can remove a one-pixel border from the window that I created with this code:
DWORD dwExtStyle = 0;
DWORD dwStyle = WS_POPUPWINDOW;
m_hWnd = CreateWindowEx(
dwExtStyle,
className,
windowName,
dwStyle,
300,
300,
100,
100,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(m_hWnd, SW_SHOW);
and I got the result:
What combination of flags can remove the black border from the window.
Just use WS_POPUP instead of WS_POPUPWINDOW.
The macro WS_POPUPWINDOW is actually a set of flags:
#define WS_POPUPWINDOW (WS_BORDER | WS_POPUP | WS_SYSMENU)
The WS_BORDER flag is the one responsible of your black square.