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发出退出消息,让消息循环结束。