惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
腾讯CDC
D
Docker
G
Google Developers Blog
D
DataBreaches.Net
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
The Cloudflare Blog
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
量子位
美团技术团队
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - talenth

windows下简单使用webrtc nvm配置nodejs ATL开发office插件 windows编译pp-shitu webdriver windows下不同cpu架构PE文件区别 vs中/EHa、/EHs、/EHsc的区别 windows下注册一个打开特定扩展名的文件 yara规则学习 usb3.0+mvme固态安装win7 驱动程序获取内核版本号 提取shell32.dll中的字符串 常见编码 修理鼠标微动开关 InfinityHook原理 段描述符 tls1.3报文 签名证书 windows内核同步机制
主窗口,子窗口,拥有窗口关闭消息顺序
talenth · 2023-09-20 · via 博客园 - talenth

1 先说结论, 主窗口执行 DestroyWindow函数, 拥有窗口跟子窗口以及主窗口收到 WM_DESTROY, WM_NCDESTROY的顺序是有区别, 顺序如下:

main WM_CLOSE
owned WM_DESTROY
owned WM_NCDESTROY
main WM_DESTROY
sub WM_DESTROY
sub WM_NCDESTROY
main WM_NCDESTROY

  1 #include "stdafx.h"
  2 #include "msgTest.h"
  3 
  4 #define MAX_LOADSTRING 100
  5 #define SUB_WIN_CLASS L"subWinClass"
  6 #define SUB_WIN_NAME L"subWinName"
  7 
  8 #define OWNED_WIN_CLASS L"ownedWinClass"
  9 #define OWNED_WIN_NAME L"ownedWinName"
 10 
 11 // 全局变量: 
 12 HINSTANCE hInst = NULL; // 当前实例
 13 WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
 14 WCHAR szWindowClass[MAX_LOADSTRING];// 主窗口类名
 15 
 16 HWND gHMainWnd = NULL; //主窗口句柄
 17 HWND gSubWnd = NULL; // 子窗口句柄
 18 HWND gOwnedWnd = NULL; // 拥有的窗口
 19 
 20 // 此代码模块中包含的函数的前向声明: 
 21 ATOM MyRegisterClass(HINSTANCE hInstance);
 22 BOOL InitInstance(HINSTANCE, int);
 23 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
 24 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
 25 
 26 LRESULT CALLBACK WndProcSub(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 27 {
 28     switch (message)
 29     {
 30     case WM_CLOSE:
 31         OutputDebugStringW(L"sub WM_CLOSE\n");
 32         DestroyWindow(hWnd);
 33         break;
 34     case WM_DESTROY:
 35         OutputDebugStringW(L"sub WM_DESTROY\n");
 36         break;
 37     case WM_NCDESTROY:
 38         OutputDebugStringW(L"sub WM_NCDESTROY\n");
 39         break;
 40     default:
 41         return DefWindowProc(hWnd, message, wParam, lParam);
 42     };
 43 
 44     return 0;
 45 }
 46 
 47 bool CreateSubWnd(HINSTANCE hInstance, int nCmdShow)
 48 {
 49     WNDCLASSEXW wcex;
 50     wcex.cbSize = sizeof(WNDCLASSEX);
 51     wcex.style = CS_HREDRAW | CS_VREDRAW;
 52     wcex.lpfnWndProc = WndProc;
 53     wcex.cbClsExtra = 0;
 54     wcex.cbWndExtra = 0;
 55     wcex.hInstance = hInstance;
 56     wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MSGTEST));
 57     wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
 58     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
 59     wcex.lpszMenuName = NULL;
 60     wcex.lpszClassName = SUB_WIN_CLASS;
 61     wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
 62 
 63     if (!RegisterClassExW(&wcex))
 64         return false;
 65 
 66     gSubWnd = CreateWindowExW(WS_EX_CLIENTEDGE,SUB_WIN_CLASS, SUB_WIN_NAME, WS_CHILDWINDOW, 10, 10, 100, 100, gHMainWnd, nullptr, hInstance, nullptr);
 67     if (!gSubWnd)
 68         return false;
 69 
 70     ShowWindow(gSubWnd, nCmdShow);
 71     UpdateWindow(gSubWnd);
 72 
 73     return true;
 74 }
 75 
 76 LRESULT CALLBACK WndProcOwned(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 77 {
 78     switch (message)
 79     {
 80     case WM_CLOSE:
 81         OutputDebugStringW(L"owned WM_CLOSE\n");
 82         DestroyWindow(hWnd);
 83         break;
 84     case WM_DESTROY:
 85         OutputDebugStringW(L"owned WM_DESTROY\n");
 86         break;
 87     case WM_NCDESTROY:
 88         OutputDebugStringW(L"owned WM_NCDESTROY\n");
 89         break;
 90     default:
 91         return DefWindowProc(hWnd, message, wParam, lParam);
 92     };
 93 
 94     return 0;
 95 }
 96 
 97 bool CreateOwnedWnd(HINSTANCE hInstance, int nCmdShow)
 98 {
 99     WNDCLASSEXW wcex;
100     wcex.cbSize = sizeof(WNDCLASSEX);
101     wcex.style = CS_HREDRAW | CS_VREDRAW;
102     wcex.lpfnWndProc = WndProc;
103     wcex.cbClsExtra = 0;
104     wcex.cbWndExtra = 0;
105     wcex.hInstance = hInstance;
106     wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MSGTEST));
107     wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
108     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
109     wcex.lpszMenuName = NULL;
110     wcex.lpszClassName = OWNED_WIN_CLASS;
111     wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
112 
113     if (!RegisterClassExW(&wcex))
114         return false;
115 
116     gOwnedWnd = CreateWindowExW(0, OWNED_WIN_CLASS, OWNED_WIN_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, gHMainWnd, nullptr, hInstance, nullptr);
117     if (!gOwnedWnd)
118         return false;
119 
120     ShowWindow(gOwnedWnd, nCmdShow);
121     UpdateWindow(gOwnedWnd);
122 
123     return true;
124 }
125 
126 int APIENTRY wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR lpCmdLine,int nCmdShow)
127 {
128     UNREFERENCED_PARAMETER(hPrevInstance);
129     UNREFERENCED_PARAMETER(lpCmdLine);
130 
131     // TODO: 在此放置代码。
132 
133     // 初始化全局字符串
134     LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
135     LoadStringW(hInstance, IDC_MSGTEST, szWindowClass, MAX_LOADSTRING);
136     MyRegisterClass(hInstance);
137 
138     // 执行应用程序初始化: 
139     if (!InitInstance(hInstance, nCmdShow))
140     {
141         return FALSE;
142     }
143 
144     HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MSGTEST));
145 
146     // 主消息循环: 
147     MSG msg;
148     while (GetMessageW(&msg, NULL, 0, 0))
149     {
150         //if (!TranslateAcceleratorW(msg.hwnd, hAccelTable, &msg))
151         {
152             TranslateMessage(&msg);
153             DispatchMessageW(&msg);
154         }
155     }
156 
157     return (int) msg.wParam;
158 }
159 
160 ATOM MyRegisterClass(HINSTANCE hInstance)
161 {
162     WNDCLASSEXW wcex;
163 
164     wcex.cbSize = sizeof(WNDCLASSEX);
165 
166     wcex.style          = CS_HREDRAW | CS_VREDRAW;
167     wcex.lpfnWndProc    = WndProc;
168     wcex.cbClsExtra     = 0;
169     wcex.cbWndExtra     = 0;
170     wcex.hInstance      = hInstance;
171     wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MSGTEST));
172     wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
173     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
174     wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_MSGTEST);
175     wcex.lpszClassName  = szWindowClass;
176     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
177 
178     return RegisterClassExW(&wcex);
179 }
180 
181 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
182 {
183    hInst = hInstance; // 将实例句柄存储在全局变量中
184 
185    gHMainWnd = CreateWindowExW(0,szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 400, 200, nullptr, nullptr, hInstance, nullptr);
186    if (!gHMainWnd)
187    {
188       return FALSE;
189    }
190 
191    CreateSubWnd(hInstance, nCmdShow);
192    CreateOwnedWnd(hInstance, nCmdShow);
193 
194    ShowWindow(gHMainWnd, nCmdShow);
195    UpdateWindow(gHMainWnd);
196 
197    return TRUE;
198 }
199 
200 
201 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
202 {
203     if (hWnd == gSubWnd)
204         return WndProcSub(hWnd, message, wParam, lParam);
205     else if (hWnd == gOwnedWnd)
206         return WndProcOwned(hWnd, message, wParam, lParam);
207 
208     switch (message)
209     {
210     case WM_CREATE:
211         break;
212     case WM_COMMAND:
213     {
214         int wmId = LOWORD(wParam);
215         // 分析菜单选择: 
216         switch (wmId)
217         {
218         case IDM_ABOUT:
219             DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
220             break;
221         case IDM_EXIT:
222             DestroyWindow(hWnd);
223             break;
224         default:
225             return DefWindowProc(hWnd, message, wParam, lParam);
226         }
227     }
228     break;
229     case WM_PAINT:
230     {
231         PAINTSTRUCT ps;
232         HDC hdc = BeginPaint(hWnd, &ps);
233         // TODO: 在此处添加使用 hdc 的任何绘图代码...
234         EndPaint(hWnd, &ps);
235     }
236     break;
237     case WM_CLOSE:
238         OutputDebugStringW(L"main WM_CLOSE\n");
239         DestroyWindow(hWnd);
240         break;
241     case WM_DESTROY:
242         //PostQuitMessage(0);
243         OutputDebugStringW(L"main WM_DESTROY\n");
244         break;
245     case WM_NCDESTROY:
246         PostQuitMessage(0);
247         OutputDebugStringW(L"main WM_NCDESTROY\n");
248         break;
249     default:
250         return DefWindowProc(hWnd, message, wParam, lParam);
251     }
252     return 0;
253 }
254 
255 // “关于”框的消息处理程序。
256 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
257 {
258     UNREFERENCED_PARAMETER(lParam);
259     switch (message)
260     {
261     case WM_INITDIALOG:
262         return (INT_PTR)TRUE;
263 
264     case WM_COMMAND:
265         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
266         {
267             EndDialog(hDlg, LOWORD(wParam));
268             return (INT_PTR)TRUE;
269         }
270         break;
271     }
272     return (INT_PTR)FALSE;
273 }