yottaawesome / programming-windows-5th-edition

Unofficial source code repo for Charles Petzold's Programming Windows 5th Edition.
https://www.microsoftpressstore.com/store/programming-windows-9780735692633
84 stars 35 forks source link

Is it necessary add `WS_CLIPCHILDREN` when `CreateWindow` in `Ch11\Colors2\Colors2.c`? #4

Closed yanpeng closed 1 year ago

yanpeng commented 1 year ago

Hi,

I am back. :)

Recently I finished the chapter 11 Diaglog Boxes, when reviewing the programs of this chapter, I think it is unnecessary to add WS_CLIPCHILDREN when CreatWindow in Colors2.c of chapter 11. The reason is as follows:

  1. The dialog box is a top-level window (a pop up window with style WS_POPUP), it is owned by the main window, not its child window. According to MSDN, the third parameter of CreateDialog is hWndParent which is a handle to the window that owns the dialog box, not a handle to the window whose child window is this dialog box.
  2. Since they are all top-level windows, this dialog box is just a sibling of the main window, they all have the WS_CLIPSIBLINGS style, even if it was not specified. (by reference 1, this can be verified.)
  3. According to Child Window Update Region, if this dialog box is a child window of the main window, when invalidating the whole client area of the main window, the dialog box should receive a WM_PAINT message, on the premise of removing the WS_CLIPCHILDREN from CreateWindow. In fact, it didn't receive that message.

How do you think about this, sir?

References

  1. Win32 Window Hierarchy and Styles
  2. CreateDialogA Macro
  3. Child Window Update Region
yottaawesome commented 1 year ago

Hi, I'll review the docs and the book and see what I find regarding this.

yottaawesome commented 1 year ago

As far as I can see from the docs and testing the sample, WS_CLIPCHILDREN doesn't appear to make any difference. On page 528, the author does note that the "windows style for the main window includes WS_CLIPCHILDREN, which allows the program to repaint the main window without erasing the dialog box". However, I couldn't confirm this behaviour, so I'm not sure if the author made a mistake or this was behaviour back when the samples were first written but is no longer the case.

I'll dig around a bit more.

yanpeng commented 1 year ago

windows style for the main window includes WS_CLIPCHILDREN, which allows the program to repaint the main window without erasing the dialog box

the author said that. I think he made a mistak. From both theoretical and practical aspects, this dialog box is not a child of the main window. From the code

HWND hWnd = CreateWindowEx(
    WS_EX_APPWINDOW, appName, appName, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
    NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, cmdShow);
UpdateWindow(hWnd);

HWND hDlgModeless = CreateDialog(hInstance, appName, hWnd, DlgWndProc);

HWND hWndOwner = GetParent(hDlgModeless);
HWND hWndParent = GetAncestor(hDlgModeless, GA_PARENT);

the return values of GetParent(hDlgModeless) and GetAncestor(hDlgModeless, GA_PARENT) are different, the former is hWnd, which is not the parent of hDlgModeless, or the return values should be same. The latter is the handle of the desktop window?

By the way, what confuses me on learning Win32 GUI programming is the following questions:

  1. How does Windows organize the windows? what's the hierarchy and relation between them?
  2. How to understand the concept of Z order? How does the Z order change dynamically when spawning a new window (both top level window and child window)?
  3. How does the drawing order relate to Z order?
yottaawesome commented 1 year ago

I think there are two independent concepts at play here: the owner and the parent. The GetParent() function is a bit misleading, because according to the docs, it can return the owner of a window or the parent. On the other hand, according to the docs, GetAncestor() excludes the owner. There's another function -- GetWindow() -- which can be used to find the owner.

My testing using these functions indicates that hWnd is indeed the owner -- but not the parent -- of hDlgModeless. This would suggest that the CreateDialogW()'s hWndParent argument is misleadingly named, and the docs even says this argument is actually the owner of the dialog window.

So yeah, it looks like either an error by the author or behaviour that has changed since the samples were first written.

Regarding your questions, I did find this link which might be insightful. I also found this link and this link that might also shed some further light.

yanpeng commented 1 year ago

it looks like either an error by the author or behaviour that has changed since the samples were first written.

This may explain why the author appears to have made a mistake in the book.

Yeah, I read all links you provide and some others. After some exploration, I think I can explain some drawing phenomenons from some simple principles. Thanks for your help, sir.