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

推荐订阅源

W
WeLiveSecurity
T
Tenable Blog
Project Zero
Project Zero
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
S
Schneier on Security
Scott Helme
Scott Helme
S
Securelist
Know Your Adversary
Know Your Adversary
Vercel News
Vercel News
IT之家
IT之家
V
V2EX
F
Fortinet All Blogs
Simon Willison's Weblog
Simon Willison's Weblog
K
Kaspersky official blog
博客园_首页
T
Tailwind CSS Blog
The GitHub Blog
The GitHub Blog
Spread Privacy
Spread Privacy
Microsoft Security Blog
Microsoft Security Blog
Cisco Talos Blog
Cisco Talos Blog
The Register - Security
The Register - Security
有赞技术团队
有赞技术团队
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cyberwarzone
Cyberwarzone
Google DeepMind News
Google DeepMind News
The Hacker News
The Hacker News
L
LINUX DO - 热门话题
Hugging Face - Blog
Hugging Face - Blog
博客园 - 三生石上(FineUI控件)
A
Arctic Wolf
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
CXSECURITY Database RSS Feed - CXSecurity.com
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy & Cybersecurity Law Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CERT Recently Published Vulnerability Notes
S
SegmentFault 最新的问题
AWS News Blog
AWS News Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
P
Proofpoint News Feed
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Vulnerabilities – Threatpost

博客园 - 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 }