新建窗口工程
vs2017 community
修改名称 和位置,点击确认即可,点击运行,出现一个窗口。
自建窗口
CreateWindowEx和CreateWindow的区别是EX多了窗口样式扩展
/**
1.窗口背景色设置
wcx.hbrBackground = xxx
(1) Color Types: COLOR_WINDOW
(2)
HGDIOBJ GetStockObject(
int fnObject
);
(3)
HBRUSH CreateSolidBrush(
COLORREF crColor
);
(4)
HBRUSH CreateHatchBrush(
int fnStyle,
COLORREF clrref
);
fnStyle: HS_BDIAGONAL HS_CROSS HS_DIAGCROSS
HS_FDIAGONAL HS_HORIZONTAL HS_VERTICAL
2.窗口风格设置 CreateWindow CreateWindowEx 中设置dwStyle
WS_BORDER:windows窄线边
WS_CAPTION:windows标题条,包含WS_BORDER
WS_CHILDWINDOW、WS_CHILD:窗口是一个子窗口,不能与WS_POPUP共用
WS_CLIPCHILDREN:作为父窗口,刷新时裁剪子窗口区域,提高刷新效率
WS_CLIPSIBLINGS:作为子窗口,刷新时裁剪其它子窗口的重叠区域,提高刷新效率
WS_DISABLED:关闭窗口响应,用户的任何操作均无效
WS_DLGFRAME:窗口有一个边框样式,通常与对话框一起使用。这种样式的窗口不能有标题栏。
WS_GROUP:窗口组件化时使用。
WS_HSCROLL:窗口含有水平滚动条。
WS_VSCROLL:窗口含有垂直滚动条。
WS_MAXIMIZE:窗口初始状态最大化。
WS_MINIMIZE:窗口初始状态最小化。
WS_ICONIC:同WS_MINIMIZE
WS_MAXIMIZEBOX:窗口含有最大化按钮
WS_MINIMIZEBOX:窗口含有最小化按钮
WS_OVERLAPPED:重叠模式,含有标题框和边框
WS_TILED:同WS_OVERLAPPED
WS_OVERLAPPEDWINDOW:(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
WS_TILEDWINDOW:同WS_OVERLAPPEDWINDOW
WS_POPUP:弹出窗口模式,不能与WS_CHILD共用
WS_POPUPWINDOW:WS_POPUP | WS_BORDER | WS_SYSMENU
WS_SIZEBOX:窗口具有可伸缩边框。
WS_THICKFRAME:同WS_SIZEBOX
WS_SYSMENU:标题栏带系统菜单,即关闭按钮。
WS_TABSTOP:作为窗口中的控件,设置了WS_TABSTOP标志的控件可以通过TAB键焦点轮转。
WS_VISIBLE:窗口是否可见。 由ShowWindow设置
3.窗口行为设置: ShowWindow(hWnd, nCmdShow);
SW_HIDE
SW_SHOW
SW_MAXIMIZE
SW_MINIMIZE
SW_FORCEMINIMIZE
SW_SHOWDEFAULT
SW_SHOWMAXIMIZED
SW_SHOWMINIMIZED
SW_SHOWMINNOACTIVE
SW_SHOWNA
SW_SHOWNOACTIVATE
SW_SHOWNORMAL
SW_RESTORE
4.窗口图标设置
HICON LoadIcon(
HINSTANCE hInstance,
LPCTSTR lpIconName ==> MAKEINTRESOURCE
);
HANDLE LoadImage(
HINSTANCE hinst,
LPCTSTR lpszName, ==> MAKEINTRESOURCE
UINT uType,
int cxDesired, ==> GetSystemMetrics
int cyDesired, ==> GetSystemMetrics
UINT fuLoad
);
int GetSystemMetrics( //单位像素
int nIndex
);
图标文件icon制作
在线制作ICON文件 https://www.ico.la/
离线制作ICON文件 软件介绍:anytoicon
*/
#include <Windows.h>
#include "resource.h"
LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
int width = GetSystemMetrics(SM_CXSMICON);
int height = GetSystemMetrics(SM_CYSMICON);
//4 设置窗口ICON
//HICON hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
HICON hIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, width, height, LR_DEFAULTCOLOR);
HBRUSH hRedBrush = CreateSolidBrush(RGB(0x66, 0, 0x66)); //refcolor RRGGBB
HBRUSH hHatchBrush = CreateHatchBrush(HS_CROSS, RGB(0x66, 0, 0x66));
WNDCLASSEXW wcx;
wcx.cbSize = sizeof(WNDCLASSEXW);
//wcx.style = 0;
wcx.style = CS_HREDRAW;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = hIcon;
wcx.hCursor = NULL;
//1 设置窗口背景颜色
//wcx.hbrBackground = (HBRUSH)COLOR_ACTIVEBORDER; //NULL; ALT+F4
//wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_PEN);
//wcx.hbrBackground = hRedBrush;
wcx.hbrBackground = hHatchBrush;
wcx.lpszMenuName = NULL;
wcx.hIconSm = hIcon;
wcx.lpszClassName = L"MainWindowClass";
wcx.lpfnWndProc = WinProc;
//1.注册窗口
ATOM win = RegisterClassEx(&wcx);
//2.创建窗口
HWND hWnd = CreateWindow(
L"MainWindowClass",
L"袁春旭的窗口",
WS_OVERLAPPEDWINDOW,
0,
0,
800,
600,
(HWND)NULL,
(HMENU)NULL,
hInstance,
(LPVOID)NULL
);
if (!hWnd)
{
MessageBox(NULL, L"创建窗口失败", L"提示", MB_OK);
return 0;
}
//3. 显示窗口
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//4. 消息获取,分发
MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL))
{
//TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
添加ICON
透明窗体
使用CreateWindow
/**
设置透明窗口
CreateWindowEx
WS_EX_LAYERED:分层窗口
LONG GetWindowLong(
HWND hWnd,
int nIndex
);
LONG SetWindowLong(
HWND hWnd,
int nIndex,
LONG dwNewLong
);
BOOL SetLayeredWindowAttributes(
HWND hwnd,
COLORREF crKey,
BYTE bAlpha,
DWORD dwFlags
);
*/
#include <Windows.h>
LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HBRUSH hRedBrush = CreateSolidBrush(RGB(0x66, 0, 0x66)); //refcolor RRGGBB
HBRUSH hHatchBrush = CreateHatchBrush(HS_CROSS, RGB(0x66, 0, 0x66));
WNDCLASSEXW wcx;
wcx.cbSize = sizeof(WNDCLASSEXW);
wcx.style = CS_HREDRAW;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = NULL;// hIcon;
wcx.hCursor = NULL;
wcx.hbrBackground = hHatchBrush;
wcx.lpszMenuName = NULL;
wcx.hIconSm = NULL;// hIcon;
wcx.lpszClassName = L"MainWindowClass";
wcx.lpfnWndProc = WinProc;
//1.注册窗口
ATOM win = RegisterClassEx(&wcx);
//2.创建窗口
HWND hWnd = CreateWindow(
//WS_EX_LAYERED,
L"MainWindowClass",
L"袁春旭的窗口",
WS_OVERLAPPEDWINDOW,
0,
0,
800,
600,
(HWND)NULL,
(HMENU)NULL,
hInstance,
(LPVOID)NULL
);
if (!hWnd)
{
MessageBox(NULL, L"创建窗口失败", L"提示", MB_OK);
return 0;
}
//3. 显示窗口
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
LONG nRet = GetWindowLong(hWnd, GWL_EXSTYLE);//获取当前的窗口属性
nRet = nRet | WS_EX_LAYERED;//增加属性
SetWindowLong(hWnd, GWL_EXSTYLE, nRet);//设置属性 这三步等价于CreateWindowEx的第一个参数
SetLayeredWindowAttributes(hWnd, 0, 123, LWA_ALPHA);
//4. 消息获取,分发
MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL))
{
//TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
使用CreateWindowEx
/**
设置透明窗口
CreateWindowEx
WS_EX_LAYERED:分层窗口
LONG GetWindowLong(
HWND hWnd,
int nIndex
);
LONG SetWindowLong(
HWND hWnd,
int nIndex,
LONG dwNewLong
);
BOOL SetLayeredWindowAttributes(
HWND hwnd,
COLORREF crKey,
BYTE bAlpha,
DWORD dwFlags
);
*/
#include <Windows.h>
LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HBRUSH hRedBrush = CreateSolidBrush(RGB(0x66, 0, 0x66)); //refcolor RRGGBB
HBRUSH hHatchBrush = CreateHatchBrush(HS_CROSS, RGB(0x66, 0, 0x66));
WNDCLASSEXW wcx;
wcx.cbSize = sizeof(WNDCLASSEXW);
wcx.style = CS_HREDRAW;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = NULL;// hIcon;
wcx.hCursor = NULL;
wcx.hbrBackground = hHatchBrush;
wcx.lpszMenuName = NULL;
wcx.hIconSm = NULL;// hIcon;
wcx.lpszClassName = L"MainWindowClass";
wcx.lpfnWndProc = WinProc;
//1.注册窗口
ATOM win = RegisterClassEx(&wcx);
//2.创建窗口
HWND hWnd = CreateWindowEx(
WS_EX_LAYERED,
L"MainWindowClass",
L"袁春旭的窗口",
WS_OVERLAPPEDWINDOW,
0,
0,
800,
600,
(HWND)NULL,
(HMENU)NULL,
hInstance,
(LPVOID)NULL
);
if (!hWnd)
{
MessageBox(NULL, L"创建窗口失败", L"提示", MB_OK);
return 0;
}
//3. 显示窗口
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
SetLayeredWindowAttributes(hWnd, 0, 123, LWA_ALPHA);
//4. 消息获取,分发
MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL))
{
//TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
win消息机制
1 消息的概念
消息是指windows操作系统发给应用程序的一个通告,告诉程序某个特定的事件发生了。比如用户点击鼠标,会引发相关的消息,并交给相应的程序去处理。最终处理消息的是应用程序的窗口函数,如果程序不负责处理的话,系统会作出默认的处理。
从数据结构的角度来说,消息是一个结构体,包含了消息的类型标识符以及其他的一些附加消息。
系统定义的结构体MSG用于表示消息,MSG具有如下形式
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM IParam;
DWORD time;
POINT pt;
}MSG;
其中hwnd是窗口的句柄,这个参数决定哪个窗口过程函数对消息进行处理;message是一个消息常量,用来表示消息的类型;wParam 和lParam 都是32 位的附加信息,具体表示什么内容,要视消息的类型而定;time是消息发送的时间;pt是消息发送时鼠标所在的位置。
windows 是一个消息驱动的系统,windows的消息提供了应用程序之间、应用程序与windows 系统之间进行通信的手段。应用程序想要实现的功能由消息来触发,并且靠对消息的响应和处理来完成。必须注意的是,消息并非是抢占性的,无论事件的缓急,总是按照达到的先后依次处理。缺点是就是可能使一些实时外部事件得不到及时处理。
windows可视化交互方式一般是通过窗口来实现的。窗口一般在某一个线程内创建的。windows系统通过消息机制来管理交互,消息被发送,保存,处理,一个线程会维护自己的一套消息队列,以保持线程间的独占性。队列的特点无非是先进先出,这种机制可能实现一种异步的需求响应过程。
1、windows 消息的类型
消息可由系统或者应用程序产生。系统在发生输入事件(用户敲击键盘、移动鼠标)时产生消息。系统也可以产生消息来响应用程序带来的变化(设置系统字体)。同时应用程序可以产生消息使窗体执行任务,或者与基他应用程序通信。
windows 消息类型可以分为以下两大类:
1)系统定义的消息:非用户定义的消息,基范围在【0x0000,0x03ff】之间,又可以分为三小类:
窗口消息:与窗口的内部运作有关,创建窗口,绘制窗口,销毁窗口
命令消息:一般特指WM_COMMAND消息,与处理用户请求有关,通常由控件或者菜单产生。
通知消息:特指WM_NOTIFY消息。通常指一个窗口内的子控件发生了一些事情,需要通知父窗口。通知消息只适用于标准的窗口控件(按钮、列表框、组合框、编辑框,以及化公共控件树状视图、列表视图)。
2)应用定义的消息
WM_USER : 【0X0400-0X7FFF】, 用户自定义的消息范围。
WM_APP : 【0X8000-0XBFFF】,用于程序之间的消息通信。
RegisterWindoMessage :【0XC000-0XFFFF】
2、消息队列
从windows维护的角度上看有两种消息队列:
1)系统消息队列:这是一个系统唯一的队列,设备驱动会把操作输入转化成消息存在系统队列中,然后系统会把此消息放到目标窗口所在的线程消息队列中等待处理。
2)线程消息队列:每一个GUI线程都会维护宋一个线程消息队列(这个队列只有在线程调用GDI函数时才会创建,默认不创建,这是为了避免给Non-GUI线程创建消息队列,所有线程产生时并没有消息队列,仅当线程第一次调用GDI函数时系统才给线程创建一个消息队列)。然后线程消息队列中的消息会被送到相应的窗口过程处理。
注:线程消息队列中WM_PAINT / WM_TIMER只有在队列中没有其他消息 时候才会被处理,WM_PAINT消息还会被合并以提高效率。其他所有消息以先进先出的方式被处理。
3、队列消息和非队列消息
从消息的发送途径上来看可以分为队列消息和非队列消息
1)队列消息:消息会先保存在消息队列中,消息循环会从此队列中取出消息并分发到各窗口处理。如鼠标、键盘消息。例如:当键盘事件被触发后,相应的键盘驱动程序就会把这些事件转换成相应的消息,然后输送到系统消息队列中,由windows 系统进行处理,windows系统则在适当的时机,从系统消息队列中取出一个消息,根据MSG消息结构确定要送往哪一个窗口,然后把取出的消息送往创建窗口的线程的相应队列中,接下来就由线程消息队列处理了。
2)非队列消息:消息会绕过系统消息队列和线程消息队列直接发送到窗口过程被处理,非队列消息也可以由应用程序调用系统函数产生。系统典型发送非队列消息来通知一个窗口,一个事件影响了它。例如,当用户激活一个新窗口,系统发送给窗口 WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR消息。这些消息通知窗口它已经被激活了,键盘输入正指向该窗口,鼠标光标已经移至了窗口边框内。当应用程序调用某些系统函数时,也会窗口非队列消息,比如,应用程序在调用SetWindowPos时,系统将发送WM_WINDOWPOSCHANGED消息
注:postMessage发送的消息是队列消息,它会把消息Post到消息队列中,SendMessage发送的消息是非队列消息,直接送到窗口过程处理。
4、发送消息
发送消息的函数:PostMessage / PostThreadMessage / SendMessage
postMessage 把消息放到指定的窗口所在的线程消息队列中后立即返回,消息可能不被处理。
PostThreadMessage 把消息放到指定线程的消息队列中后立即返回。
SendMessage 直接把消息送到窗口过程处理,处理后才返回,如果消息不被处理,发送消息的线程将一直处于阻塞状态,等待消息返回。
同一线程内发消息
SendMessage 发送消息时,由user32.dll模块调用目标窗口消息处理程序,并将结果返回,SendMessage在同一个线程里面发送消息不进入线程消息队列,PostMessage发送消息要先放到消息队列,然后通过消息循环分派到目标窗口(DispatchMessage)。
不同线程间发消息
SendMessage 发送消息到目标窗口的消息队列,然后发送消息的线程在user32.dll模块内监视和等待消息的处理结果,直到目标窗口处理才返回,SendMessage在返回之前还可能需要做许多工作,如响应别的线程向它发送的SendMessage。PostMessage到别的线程的时候最好使用PostThreadMessage代替。PostMessage 的HWND参数可以为NULL,相当于PostThreadMessage+GetCrrentThreadId。
注:在windows 中每个消息队列最多只能存放一定数量的消息,超过的将不会被处理掉。
5、接收消息
BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
BOOL PeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);
BOOL WaitMessage();
GetMessage主要是从指定的窗口hWnd中取出wMsgFilterMin和wMsgFilterMax参数给出的消息范围内的消息,消息取出后就从消息队列中删除该消息。GetMessage从消息队列中取不到消息,则线程就会被挂起,直到取出消息来返回。
PeekMessage只是从消息队列中查询消息,如果有消息,则立刻返回true;没有则返回false。如果有消息,PeekMessage中wRemoveMsg参数中设置的是PM_REMOVE则在取出消息并将消息从队列中删除,若设置是PM_NOREMOVE消息就不会从消息队列中取出。
waitMessage 功能:当一个线程的消息队列中没有消息存在时,waitMessage函数会使该线程中断并处于等待状态,同时把控制权交给其它线程,直到被中断那个线程的消息队列中有了新的消息为止。
6、转换消息
TranslateMessage:把一个virtual-key消息转化成字符消息,并放到当前线程的消息队列中,消息循环下一次取出处理。
TranslateAccelerator:将快捷键对应到相应的菜单命令。它会把WM_KEYDOWN或者WM_SYSKEYDOWN转化成快捷键表中相应的WM_COMMAND或者WM_SYSCOMMAND消息,然后把转化后的WM_COMMAND或者WM_SYSCOMMAND消息直接发送到窗口过程处理,处理完后才会返回。返回值:若函数调用成功,则返回非零值,若函数调用失败则返回零。
2 windows编程原理
Windows 是一消息(Message)驱动式系统,Windows 消息提供了应用程序与应用程序之间、应用程序与Windows 系统之间进行通讯的手段。应用程序要实现的功能由消息来触发,并靠对消息的响应和处理来完成。Windows 系统中有两种消息队列,一种是系统消息队列,另一种是应用程序消息队列。计算机的所有输入设备由 Windows 监控,当一个事件发生时,Windows 先将输入的消息放入系统消息队列中,然后再将输入的消息拷贝到相应的应用程序队列中,应用程序中的消息循环从它的消息队列中检索每一个消息并发送给相应的窗口函数中。一个事件的发生,到达处理它的窗口函数必须经历上述过程。
用程序队列中,应用程序中的消息循环从它的消息队列中检索每一个消息并发送给相应的窗口函数中。一个事件的发生,到达处理它的窗口函数必须经历上述过程。所谓消息就是描述事件发生的信息,Windows程序是事件驱动的,用这一方法编写程序
避免了死板的操作模式,因为Windows程序的执行顺序将取决于事件的发生顺序,具有不可预知性。Windows操作系统,计算机硬件,应用程序之间具有如下图所示的关系:
箭头1 说明操作系统能够操纵输入输出设备,例如让打印机打印;箭头2说明操作系统能够感知输入输出设备的状态变化,如鼠标单击,按键按下等,这就是操作系统和计算机硬件之间的交互关系,应用程序开发者并不需要知道他们之间是如何做到的,我们需要了解的操作系统与应用程序之间如何交互。箭头3是应用程序通知操作系统执行某个具体的操作,这是通过调用操作系统的API来实现的;操作系统能够感知硬件的状态变化,但是并不决定如何处理,而是把这种变化转交给应用程序,由应用程序决定如何处理,向上的箭头4说明了这种转交情况,操作系统通过把每个事件都包装成一个称为消息结构体MSG来实现这个过程,也就是消息响应,要理解消息响应,首先需要了解消息的概念和表示。
3 windows消息循环
消息循环是Windows应用程序存在的根本,应用程序通过消息循环获取各种消息,并通过相应的窗口过程函数,对消息加以处理;正是这个消息循环使得一个应用程序能够响应外部的各种事件,所以消息循环往往是一个Windows应用程序的核心部分。Windows 的消息机制如图2所示:
Windows 操作系统为每个线程维持一个消息队列,当事件产生时,操作系统感知这一事件的发生,并包装成消息发送到消息队列,应用程序通过GetMessage()函数取得消息并存于一个消息结构体中,然后通过一个TranslateMessage()和DispatchMessage()解释和分发消息,下面的代码描述了Windows 的消息循环。
while(GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
TranslateMessage(&msg)对于大多数消息而言不起作用,但是有些消息,比如键盘按键按下和弹起(分别对于KeyDown 和KeyUp 消息),却需要通过它解释,产生一个WM_CHAR消息,TtanslateMessage仅为那些由键盘驱动器映射为ASCII字符的键产生WM_CHAR消息。 你可以理解为,获取键盘消息转换成wm认识的ASCII字符,然后传递给指定的指针地址,进行处理。DispatchMessage(&msg)负责把消息分发到消息结构体中对应的窗口,交由窗口过程函数处理。GetMessage()在取得WM_QUIT 之前的返回值都为TRUE,也就是说只有获取到WM_QUIT 消息才返回FALSE,才能跳出消息循环。
4、消息的处理
取得的消息将交由窗口处理函数进行处理,对于每个窗口类Windows为我们预备了一个默认的窗口过程处理函数DefWindowProc(),这样做的好处是,我们可以着眼于我们感兴趣的消息,把其他不感兴趣的消息传递给默认窗口过程函数进行处理。每一个窗口类都有一个窗口过程函数,此函数是一个回调函数,它是由Windows操作系统负责调用的,而应用程
序本身不能调用它。以switch语句开始,对于每条感兴趣的消息都以一个case引出
WM_CREATE:窗口创建消息
WM_MOVE:窗口移动消息
WM_SIZE:窗口大小变化消息
WM_ACTIVATE:窗口活动消息,窗口由非活动状态转变为活动状态
WM_LBUTTONDOWN:鼠标左键按下
获取鼠标位置:
x = LOWORD(lParam); //获取鼠标x位置,相对窗口
y = HIWORD(lParam); //获取鼠标y位置,相对窗口
GetCursorPos(&pt); //获取鼠标位置,相对屏幕
GetSystemMetrics (SM_MOUSEPRESENT); 确定鼠标是否存在
GetSystemMetrics (SM_CMOUSEBUTTONS); 确定鼠标按键数量
WM_KEYDOWN:有按键按下
鼠标双击事件:
WM_LBUTTONDBLCLK 鼠标左键双击 WM_RBUTTONDBLCLK 鼠标右键双击 WM_MBUTTONDBLCLK 鼠标中键双击
wcx.style = CS_DBLCLKS 使用前需要设置
键盘按键消息:
ALT按键消息
WM_SYSKEYDOWN
非ALT按键消息
WM_KEYDOWN
WM_CLOSE:关闭应用程序窗口
WM_DESTROY:关闭应用程序
WM_QUIT:关闭消息循环
只有关闭了消息循环,应用程序的进程才真正退出(在任务管理器里消失)。
win32应用程序的完整退出过程:点击窗口右上角的关闭按钮,发送WM_CLOSE消息。此消息处理中调用DestroyWindow函数,发送WM_DESTROY消息。此消息处理中调用PostQuitMessage(0)函数,发送WM_QUIT消息到消息队列中。GetMessage捕获到WM_QUIT,返回0,退出循环(应用程序真正退出)。
tips:按照上述正常流程,WM_QUIT是不会到达窗口过程的。(因为在GetMessage截获了WM_QUIT消息之后,程序已经彻底退出了!)
5 QT与消息循环
https://blog.csdn.net/weixin_33962326/article/details/112141013