鱼C论坛

 找回密码
 立即注册

恒信网络科技

https://fishc.com.cn/?210680

Windows API一日一练(7)GetMessage,TranslateMessage,DispatchMessage,PostQuitMessag ...

已有 932 次阅读2014-4-16 16:30 |个人分类:vc++学习

应用程序为了获取源源不断的消息,就需要调用函数GetMessage来实现,因为所有在窗口上的输入消息,都会放到应用程序的消息队列里,然后再发送给窗口回调函数处理。
函数GetMessage声明如下:
WINUSERAPI
BOOL
WINAPI
GetMessageA(
    __out LPMSG lpMsg,
    __in_opt HWND hWnd,
    __in UINT wMsgFilterMin,
    __in UINT wMsgFilterMax);
WINUSERAPI
BOOL
WINAPI
GetMessageW(
    __out LPMSG lpMsg,
    __in_opt HWND hWnd,
    __in UINT wMsgFilterMin,
    __in UINT wMsgFilterMax);
#ifdef UNICODE
#define GetMessage GetMessageW
#else
#define GetMessage GetMessageA
#endif // !UNICODE
lpMsg是从线程消息队列里获取到的消息指针。
hWnd是想获取那个窗口的消息,当设置为NULL时是获取所有窗口的消息。
wMsgFilterMin是获取消息的ID编号最小值,如果小于这个值就不获取回来。
wMsgFilterMax是获取消息的ID编号最大值,如果大于这个值就不获取回来。
函数返回值可能是0,大于0,或者等于-1。如果成功获取一条非WM_QUIT消息时,就返回大于0的值;如果获取WM_QUIT消息时,就返回值0值。如果出错就返回-1的值。
TranslateMessage是用来把虚拟键消息转换为字符消息。由于Windows对所有键盘编码都是采用虚拟键的定义,这样当按键按下时,并不得字符消息,需要键盘映射转换为字符的消息。
TranslateMessage函数用于将虚拟键消息转换为字符消息。字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage函数时被取出。当我们敲击键盘上的某个字符键时,系统将产生WM_KEYDOWNWM_KEYUP消息。这两个消息的附加参数(wParamlParam)包含的是虚拟键代码和扫描码等信息,而我们在程序中往往需要得到某个字符的ASCII码,TranslateMessage这个函数就可以将WM_KEYDOWNWM_ KEYUP消息的组合转换为一条WM_CHAR消息(该消息的wParam附加参数包含了字符的ASCII码),并将转换后的新消息投递到调用线程的消息队列中。注意,TranslateMessage函数并不会修改原有的消息,它只是产生新的消息并投递到消息队列中。
也就是说TranslateMessage会发现消息里是否有字符键的消息,如果有字符键的消息,就会产生WM_CHAR消息,如果没有就会产生什么消息。
 
函数TranslateMessage声明如下:
WINUSERAPI
BOOL
WINAPI
TranslateMessage(
    __in CONST MSG *lpMsg);
lpMsg是检查需要转换的消息。
前面已经介绍从系统队列里获取一条消息,然后经过快捷键的函数检查,又通过字符消息函数的转换,最后要做的事情就是调用DispatchMessage函数,它的意思就是说要把这条消息发送到窗口里的消息处理函数WindowProc
 
函数DispatchMessage声明如下:
WINUSERAPI
LRESULT
WINAPI
DispatchMessageA(
    __in CONST MSG *lpMsg);
WINUSERAPI
LRESULT
WINAPI
DispatchMessageW(
    __in CONST MSG *lpMsg);
#ifdef UNICODE
#define DispatchMessage DispatchMessageW
#else
#define DispatchMessage DispatchMessageA
#endif // !UNICODE
 
lpMsg是指向想向消息处理函数WindowProc发送的消息。
自然界面里,各种生物都是有其生命周期的。程序也是有其生命周期的,创建时就是它出生了,当它运行工作中就是成年期,最后少不了要死亡的,那么程序的死亡是怎么样出现的呢?像以前介绍函数GetMessage里是使用一个循环不断地检测消息,周止复始的,是不可能出现死亡的,但它会检测到消息WM_QUIT就退出来。那现在问题是谁发送WM_QUIT消息出来呢?这就是PostQuitMessage函数所做的工作。当你点击窗口右上角的关闭时,Windows就会把窗口从系统里删除,这时就会发出消息WM_DESTROY给窗口消息处理函数WindowProcWindowProc收到这条消息后,最需要做的一件事情就是调用PostQuitMessage发出退出消息,让消息循环结束。
 
函数PostQuitMessage声明如下:
WINUSERAPI
VOID
WINAPI
PostQuitMessage(
    __in int nExitCode); 
nExitCode是退出标识码,它被放到WM_QUIT消息的参数wParam里。
调用这个几个函数的例子如下:
#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 255
HINSTANCE hinst;
TCHAR szClass[MAX_LOADSTRING];
TCHAR szTitle[MAX_LOADSTRING];
ATOM MyRegisterClass(HINSTANCE hInstance);
LRESULT CALLBACK MyProc(HWND, UINT, WPARAM, LPARAM);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 MSG msg;
 HACCEL hAccelTab;
 LoadString(hInstance, IDS_SZCLASS, szClass, MAX_LOADSTRING); //加载资源里的字符串
 LoadString(hInstance, IDS_SZTITLE, szTitle, MAX_LOADSTRING); //加载资源里的字符串
 MyRegisterClass(hInstance);
 if(!InitInstance(hInstance, SW_SHOWNORMAL))
 {
  return FALSE;
 }
 hAccelTab = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTWIN));
  while (GetMessage(&msg, NULL, 0, 0)) //获取所有窗口的消息
  {
  TranslateMessage(&msg); //调用函数TranslateMessage作消息转换工作
  
  DispatchMessage(&msg);  //调用函数DispatchMessage发送消息
  }
 return msg.wParam;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
 hinst = hInstance;
 HWND hwnd;
 hwnd = CreateWindow(szClass, szTitle , WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
 
 if (!hwnd)
 {
  return FALSE;
 }
 ShowWindow(hwnd, nCmdShow);
 UpdateWindow(hwnd);
 return TRUE;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
 WNDCLASSEX wcex;
 
 
wcex.cbSize = sizeof(WNDCLASSEX);  
 
 wcex.style = CS_HREDRAW | CS_VREDRAW; 
 wcex.lpfnWndProc = MyProc;   
 wcex.cbClsExtra = 0;    
 wcex.cbWndExtra = 0;     
 wcex.hInstance = hInstance;   
 wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_MAIN));
 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
 wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
 wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MAIN); 
 wcex.lpszClassName = szClass;
 
 wcex.hIconSm = NULL;
 return RegisterClassEx(&wcex);
}
LRESULT CALLBACK MyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 PAINTSTRUCT ps;
 HDC hdc;
 switch(uMsg)
 {
 case WM_COMMAND:
  switch(LOWORD(wParam))
  {
  case IDM_ABOUT:
   DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUT), hwnd, NULL);
   break;
  default:
   return DefWindowProc(hwnd, uMsg, wParam, lParam);
  }
  break;
  case WM_CLOSE:
   DestroyWindow(hwnd);
   break;
  case WM_DESTROY:
   PostQuitMessage(0); //调用函数PostQuitMessage来处理退出应用程序
   break;
  case WM_PAINT:
   hdc = BeginPaint(hwnd,&ps);
   
   EndPaint(hwnd,&ps); 
  break;
 default:
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
 }
}
 

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-6 03:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

返回顶部