Windows消息循环
扫描二维码
随时随地手机看文章
1 #include2 #include3 #include "resource.h"
4
5 #define MAX_LOADSTRING 100
6 TCHAR szTitle[MAX_LOADSTRING] = _T("标题栏"); // 标题栏文本
7 TCHAR szWindowClass[MAX_LOADSTRING] = _T("MyClass"); // 主窗口类名
8
9
10 ATOM ToRegisterClass(HINSTANCE hInstance, int nShowCmd);//注册窗口类
11 HWND ToCreateWindow(LPCTSTR lpClassName,LPCTSTR lpWindowName,DWORD dwStyle,int x, int y, int nWidth,int nHeight, HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam);//创建窗口
12 BOOL ToShowWindow(HWND hWnd, int nCmdShow);//显示窗口
13 BOOL ToUpdateWindow(HWND hWnd);//更新窗口
14 WPARAM ToRecycleMessage(MSG msg);//消息循环
15 LRESULT CALLBACK ToWndProc(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam);//窗口过程
16
17 //——————————————————————————进入WinMain函数————————————————————————————
18 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
19 {
20 //————————————————————————————第一步:设计并注册窗口类————————————————————————————
21 ToRegisterClass(hInstance, nShowCmd);//当前实例句柄,窗口显示方式
22
23 //————————————————————————————第二步:创建窗口————————————————————————————
24 HWND hWnd = ToCreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
25
26 //————————————————————————————第三步:显示窗口————————————————————————————
27 ToShowWindow(hWnd, nShowCmd);
28
29 //————————————————————————————第四步:更新窗口————————————————————————————
30 ToUpdateWindow(hWnd);
31
32 //————————————————————————————第五步:消息循环————————————————————————————
33 MSG msg;
34 return ToRecycleMessage(&msg);//MSG结构的wParam成员的值是传递给PostQuitMessage函数参数,通常是0。
35 }
36
37 ATOM ToRegisterClass(HINSTANCE hInstance, int nShowCmd)
38 {
39 WNDCLASS lpWndClass;
40 lpWndClass.cbClsExtra = 0;//窗口类无扩展
41 lpWndClass.cbWndExtra = 0;//窗口实例无扩展
42 lpWndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//背景
43 lpWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);//鼠标
44 lpWndClass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDB_PNG1));//图标
45 lpWndClass.hInstance = hInstance;
46 lpWndClass.lpfnWndProc = ToWndProc;//窗口函数
47 lpWndClass.lpszClassName = szWindowClass;//窗口类名
48 lpWndClass.lpszMenuName = NULL;//菜单名
49 lpWndClass.style = CS_HREDRAW | CS_VREDRAW;//风格
50 return RegisterClass(&lpWndClass);
51 }
52
53 HWND ToCreateWindow(LPCTSTR lpClassName,LPCTSTR lpWindowName,DWORD dwStyle,int x, int y, int nWidth,int nHeight, HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam)
54 {
55 return CreateWindow(lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
56 }
57
58 BOOL ToShowWindow(HWND hWnd, int nCmdShow)
59 {
60 return ShowWindow(hWnd, nCmdShow);
61 }
62
63 BOOL ToUpdateWindow(HWND hWnd)
64 {
65 return UpdateWindow(hWnd);// 调用UpdateWindow函数会通过发送给窗口消息处理函数WndProc一个WM_PAINT消息,通过这个消息完成重绘显示区域的工作。
66 }
67
68 WPARAM ToRecycleMessage(MSG *msg)
69 {
70 int nRet;
71 while(nRet = GetMessage(msg, NULL, 0, 0) != 0)//收到WM_QUIT消息则跳出消息循环
72 {
73 if (nRet == -1)
74 {
75 return;
76 }
77 TranslateMessage(msg);//翻译消息
78 DispatchMessage(msg);//分发消息
79 }
80 return msg->wParam;
81 }
82
83 //窗口过程函数:处理窗口消息
84 LRESULT CALLBACK ToWndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
85 {
86 DWORD dwNum = 0;
87 wchar_t * pwSrc;
88 RECT rect;
89 PAINTSTRUCT ps;//创建绘制对象结构
90 HDC hdc = NULL;//创建设备描述句柄对象
91 static HWND hwndButton[3] = {NULL,NULL,NULL};
92 switch(uMsg)
93 {
94 case WM_COMMAND://处理按钮等发出的消息
95 break;
96 case WM_CHAR://处理键盘发出的消息
97 break;
98 case WM_CLOSE://关闭窗口消息
99 if (IDYES == MessageBox(hWnd, _T("结束?"), _T("提示"), MB_YESNO))
100 {
101 DestroyWindow(hWnd);
102 }
103 break;
104 case WM_DESTROY://处理WM_DESTROY消息必须调用PostQuitMessage函数,该函数向消息队列中发送WM_QUIT消息,让程序退出消息循环。
105 PostQuitMessage(0);
106 break;
107 default:
108 return DefWindowProc(hWnd, uMsg, wParam, lParam);//默认的窗口处理函数
109 break;
110 }
111 return 0;
112 }
113
114
1 HWND CreateWindow( 2 3 LPCTSTR lpClassName,//注册的窗口类型名称。 4 LPCTSTR lpWindowName,//窗口名称 5 DWORD dwStyle,//窗口类型 6 int x,//窗口左上角位置 7 int y,//窗口左上角位置 8 int nWidth,//窗口的宽度 9 int nHeight,//窗口的高度 10 HWND hWndParent,//父窗口 11 HMENU hMenu,//窗口菜单 12 HINSTANCE hInstance,//应用程序实例句柄 13 LPVOID lpParam//传送给窗口的自定义参数 14 );
1 BOOL GetMessage( 2 LPMSG lpMsg,//从线程消息队列里获取到的消息指针 3 HWND hWnd,//想获取那个窗口的消息,当设置为NULL时是获取所有窗口的消息。 4 UINT wMsgFilterMin,//获取消息的ID编号最小值,如果小于这个值就不获取回来。 5 6 UINT wMsgFilterMax//获取消息的ID编号最大值,如果大于这个值就不获取回来。 7 ); 8 9 //一般情况下最后两个参数都设置为0,表示所有消息 10 11 函数返回值可能是0,大于0,或者等于-1。如果成功获取一条非WM_QUIT消息时,就返回大于0的值;如果获取WM_QUIT消息时,就返回值0值。如果出错就返回-1的值。
nCmd:窗口显示方式,参数如下:
1 SW_FORCEMINIMIZE 是强制窗口最小化,主要使用在非窗口主线程的其它线程来操作。 2 SW_HIDE 是显示窗口为隐藏状态。 3 SW_MAXIMIZE 是显示窗口为最大化。 4 SW_MINIMIZE 是显示窗口为最小化。 5 SW_RESTORE 是从任务里恢复窗口显示。 6 SW_SHOW 是激活窗口为当前窗口,并且显示为当前的大小和位置。 7 SW_SHOWDEFAULT 是创建进程时显示窗口的值。 8 SW_SHOWMAXIMIZED 是激活窗口为当前窗口,并且显示最大化。 9 SW_SHOWMINIMIZED 是激活窗口为当前窗口,并且显示最小化。 10 SW_SHOWMINNOACTIVE 是显示窗口为最小化,但不激活它作为当前窗口。 11 SW_SHOWNA 是显示为当前的大小和位置,但不激活它作为当前窗口。 12 SW_SHOWNOACTIVATE 是显示当前窗口,但不激活它作为当前窗口。 13 SW_SHOWNORMAL 是显示当前窗口,但窗口是最小化或最大化时会恢复窗口为原来的大小和位置。
TranslateMessage:
用来把虚拟键消息转换为字符消息。由于Windows对所有键盘编码都是采用虚拟键的定义,这样当按键按下时,并不得字符消息,需要键盘映射转换为字符的消息。
TranslateMessage函数用于将虚拟键消息转换为字符消息。字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage函数时被取出。当我们敲击键盘上的某个字符键时,系统将产生WM_KEYDOWN和WM_KEYUP消息。这两个消息的附加参数(wParam和lParam)包含的是虚拟键代码和扫描码等信息,而我们在程序中往往需要得到某个字符的ASCII码,TranslateMessage这个函数就可以将WM_KEYDOWN和WM_ KEYUP消息的组合转换为一条WM_CHAR消息(该消息的wParam附加参数包含了字符的ASCII码),并将转换后的新消息投递到调用线程的消息队列中。注意,TranslateMessage函数并不会修改原有的消息,它只是产生新的消息并投递到消息队列中。
也就是说TranslateMessage会发现消息里是否有字符键的消息,如果有字符键的消息,就会产生WM_CHAR消息,如果没有就会产生什么消息。
PostQuitMessage:
nExitCode是退出标识码,它被放到WM_QUIT消息的参数wParam里。
VOID PostQuitMessage(int nExitCode);
当点击窗口右上角的关闭时,Windows就会把窗口从系统里删除,这时就会发出消息WM_DESTROY给窗口消息处理函数WindowProc,WindowProc收到这条消息后,最需要做的一件事情就是调用PostQuitMessage发出退出消息,让消息循环结束。





