MoveWindow not sending WM_SIZE on deeply nested windows



Hi,


I found an issue where MoveWindow would not send a WM_SIZE message to the
window whose size I've requested to change.

To reproduce this, I've setup a window (level 0) with a child (level 1)
which has another child (level 2), and so on. When I resize `level 0', I get
a WM_SIZE message and I'm calling `MoveWindow' on child at level 1 to resize
it, which triggers a WM_SIZE message on child at level 1 and I call
MoveWindow on child at level 2 and so on.

It will stop sending the WM_SIZE message at a certain level. With the above
example it is quite visible, when you resize the top window you should get
some nested rectangle, however you will see that after about a few level the
rectangle gets truncated. The reason is that they are still at their
original size (100x100) and haven't be resized as expected.

At the same time, I've checked how much nesting I could do and found that at
level 47, a call to `SetParent' will fail with error code 87 (Parameter
being incorrect). The failure to SetParent will be shown through a dialog
box showing the result of the call to GetLastError

Any documentations about the limits of nesting windows? Or workaround for
the above problems?

Thanks,
Manu


#include "windows.h"

HINSTANCE hInst;
HWND top_window, default_parent; // Top window handle.
HWND lastHwnd; // Last created window handle

#define szWindowClass "WINDOW"
#define szTopWindowClass "TOP_WINDOW"
#define MAX_COUNT 50
HWND Hwnds[MAX_COUNT];
int windowCount;

extern LRESULT CALLBACK window_procedure (HWND, UINT, WPARAM, LPARAM);

int find_window (HWND hwnd) {
int i;
for (i = 0; i < windowCount; i++) {
if (hwnd == Hwnds[i]){
return i;
}
}
i = -1;
return i;
}

void display_error () {
LPVOID lpMsgBuf;
CHAR szBuf[5120]; DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);
sprintf(szBuf, "%s\nGetLastError returned %u\n", lpMsgBuf, dw);
MessageBox( NULL, szBuf, "Error", MB_OK | MB_ICONINFORMATION );
LocalFree( lpMsgBuf );
}

ATOM register_class (LPTSTR a_class)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)window_procedure ;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInst;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = a_class;
wcex.hIconSm = NULL;

return RegisterClassEx(&wcex);
}

void add_widget ()
{
HWND hwnd, last_parent;

hwnd = CreateWindowEx(WS_EX_CONTROLPARENT, szWindowClass, "Child window",
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
0, 0, 1200, 1200, default_parent, 0, hInst, NULL);

if (!hwnd) {
display_error ();
}
Hwnds[windowCount++]= hwnd;

if (!lastHwnd) {
last_parent = SetParent (hwnd, top_window);
} else {
last_parent = SetParent (hwnd, lastHwnd);
}

if (!last_parent) {
display_error ();
}

MoveWindow (hwnd, 1, 1, 100, 100, 0);
ShowWindow (hwnd, SW_SHOWDEFAULT);
UpdateWindow (hwnd);
lastHwnd = hwnd;
}

BOOL init ()
{
HWND hwnd;

default_parent = CreateWindow(szTopWindowClass, "Test",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);

if (!default_parent) {
display_error ();
return FALSE;
}

top_window = CreateWindow(szTopWindowClass, "Test", WS_OVERLAPPEDWINDOW,
0, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);

if (!top_window) {
display_error ();
return FALSE;
}

ShowWindow(top_window, SW_SHOW);
UpdateWindow(top_window);

return TRUE;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR
lpCmdLine, int nCmdShow) {
MSG msg;
int i;

hInst = hInstance;

if (!register_class (szWindowClass)) {
display_error ();
return FALSE;
}

if (!register_class (szTopWindowClass)) {
display_error ();
return FALSE;
}

if (!init ()) {
display_error ();
return FALSE;
}

for (i = 0; i <= MAX_COUNT; i++) {
add_widget ();
}

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

void on_size (HWND hwnd) {
// Search window
int i;
RECT r;

// Find child window.
i = find_window (hwnd) + 1;

// Hwnds [i] might be null when `on_size' is called after creating `hwnd'.
if (Hwnds [i]) {
// Got a child!
GetClientRect (hwnd, &r);
MoveWindow (Hwnds[i], 1, 1, r.right - r.left - 2, r.bottom - r.top - 2,
0);
}
}

LRESULT CALLBACK window_procedure (HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam) {
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
int i;

switch (message)
{
case WM_SIZE:
on_size (hwnd);
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
i = find_window (hwnd);
if (i >= 0) {
if (i % 2 == 0) {
FillRect (hdc, &ps.rcPaint, (HBRUSH) GetStockObject (GRAY_BRUSH));
} else {
FillRect (hdc, &ps.rcPaint, (HBRUSH) GetStockObject (WHITE_BRUSH));
}
}
EndPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}



.



Relevant Pages

  • Re: Mouse Position
    ... VOID* pVertices; ... LONG WINAPI wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM ... HWND CrteWnd(const char *pszName, int x, int y, int w, int h) { ... // Create the application's window ...
    (microsoft.public.win32.programmer.directx.graphics)
  • Re: POOM Notifications
    ... Outlook notifications, ... HWND hWnd; ... BOOL InitInstance(HINSTANCE, int); ... // PURPOSE: Registers the window class. ...
    (microsoft.public.pocketpc.developer)
  • Re: POOM Notifications
    ... Outlook notifications, ... HWND hWnd; ... BOOL InitInstance(HINSTANCE, int); ... // PURPOSE: Registers the window class. ...
    (microsoft.public.pocketpc.developer)
  • How add buton onto title bar of any external active window?
    ... I want to add buttons ontoany active window. ... int sm_CXSIZE; ... static int WindowsFeaturesWidth(HWND hwnd, DWORD style) ... LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM ...
    (microsoft.public.win32.programmer.gdi)
  • Re: How add buton onto title bar of any external active window?
    ... I want to add buttons ontoany active window. ... int sm_CXSIZE; ... static int WindowsFeaturesWidth(HWND hwnd, DWORD style) ... LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM ...
    (microsoft.public.win32.programmer.gdi)