win32消息映射1-基本的SDK程序

win32程序是靠消息驱动,消息映射是win32编程的一大主题,作为win32平台上程序员,绝对有必要深入了解消息在程序中的流动。

消息映射在MFC的实现里,是用宏定义出一颗庞大的消息树,当有消息到来的时候,遍历这棵消息树去寻找对应的处理函数,但在流动的时候,有一个优先级的问题(关于这问题在《深入浅出MFC》里有阐述),这优先级会常常使人陷入迷惑当中。


而在delphi里,消息映射直接由编译器支持,这给delphi带来了很大的简洁性,但同时也缺乏一种灵活。

delphi处理消息的方式比MFC友好得多,比如一个Button,在Clicked消息到的时候,必定会触发OnClick函数,但是若深究为什么会触发OnClick函数就没那么容易了。

本文提出一个与MFC和Delphi都不同的实现方式,比MFC友好,比delphi的灵活。但是要注意,友好和灵活都是相对,有一利必有一弊,很多时候都是利弊之间的权衡。

本文要求的读者是C++的中级程序员,或有志于了解win32消息的读者。

在学习程序语言的书籍中,一开始总有个hello world程序,本文也不例外,若读者对win32 sdk的hello world程序很熟悉,可以略过不看(本不想写这hello world程序,但为了本文的完整性,最终还是加上)。

先看看Windows的消息结构,定义如下(摘自windows.h):

typedef struct tagMSG {
    HWND        hwnd;
    UINT        message;
    WPARAM      wParam;
    LPARAM      lParam;
    DWORD       time;
    POINT       pt;
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

其中,常用的只有四个字段:hwnd, message, wParam, lParam,根据message的不同,wParam和lParam有不同的含义。比如,若message为WM_CREATE消息,lParam指向一个类型为CREATESTRUCT的变量地址。但若message为WM_DESTROY消息,wParam和lParam的值则没有任何意义。

1.基本的SDK程序(摘自VC模板生成)

TCHAR szWindowClass[]= _T("Hello");
TCHAR szTitle[]= _T("Hello");

ATOM MyRegisterClass(HINSTANCE hInstance)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
 MyRegisterClass(hInstance);

 HWND hWnd = ::CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

 ::ShowWindow(hWnd, nCmdShow);
    ::UpdateWindow(hWnd);

 // Main message loop:
 MSG msg;
 while ( ::GetMessage(&msg, NULL, 0, 0))
 {
  ::TranslateMessage(&msg);
  ::DispatchMessage(&msg);
 }
 return int(msg.wParam);
}

首先,要向windows注册一个类(class),这个类名为szWindowClass(也就是"Hello"),其回调函数为WndProc:

ATOM MyRegisterClass(HINSTANCE hInstance)
{
 WNDCLASSEX wcex;
 // 初始化wcex的其它成员...
 wcex.lpszClassName = szWindowClass;
 wcex.lpfnWndProc = (WNDPROC)WndProc;

 return ::RegisterClassEx(&wcex);
}

接着,创建一个主窗口:

HWND hWnd = ::CreateWindow(szWindowClass, ...);

我们指定这个窗口的类名为szWindowClass(也就是"Hello"),在这里我们要明白,为什么要指定类名?指定类名最重要的意义是为这个窗口指定一个回调函数(也就是注册"Hello"类时指定的WndProc)。为什么要指定回调函数?它的意义在于,当窗口有消息到时,windows会通过这个回调函数来告诉窗口:“嘿,你有消息到了!”。(若这个类名没有被注册,创建窗口肯定是失败,这时候CreateWindow会返回0。)

紧接着,就进入消息处理循环:

while ( ::GetMessage(...) )
{
 // ....
}


粗粗一看,这个消息处理循环和我们刚才创建的窗口一点关系都没有,但实际上,由于每个注册的类,都有一个回调函数,当这些类的实例(也就是窗口)有消息到时,DispatchMessage会自动找到这个实例的回调函数来告知。

那什么时候退出这个消息处理循环?当GetMessage检索到WM_QUIT消息的时候。那GetMessage什么检索到WM_QUIT消息?这就要看回调函数的实现。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 PAINTSTRUCT ps;
 HDC hdc;

 switch (message)
 {
     case WM_PAINT:
          hdc = ::BeginPaint(hWnd, &ps);
          ::TextOut( hdc, 0, 0, _T("Hello"), 5 );
          ::EndPaint(hWnd, &ps);
          break;
     case WM_DESTROY:
          ::PostQuitMessage(0);
          break;
     default:
          return ::DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}

上面已经说过,当窗口有消息时,windows会自动调用WndProc函数,窗口被关闭时,windows会自动往窗口发送WM_DESTROY消息,在这里,窗口关闭了,程序自然也要退出,所以,我们一旦收到WM_DESTROY,就调用PostQuitMessage往消息队列投递WM_QUIT消息,从而强制GetMessage返回FALSE,退出消息处理循环。

PostQuitMessage有一个参数,用来指示程序退出的返回值,这个值会被被存放到与WM_QUIT对应的msg.wParam里。另外,要注意到这个函数的名字有一个Post,不是Send,这说明WM_QUIT消息是添加到消息队列中,不会立即被触发。这样,就带来另外一个话题,若检索消息的时候,消息队列除了WM_QUIT消息之外,还有其它消息,那么先检索哪个消息?关于这个话题,就参阅《Windows 2000核心编程》。

在WndProc里,hWnd代表的是注册类的实例,若多个窗口都用同一个类名创建,只能通过hWnd区分,至于wParam和lParam,不同的message对应着不同的含义,这里不可能一一列举,需要的时候请查阅MSDN。

从上面的代码我们可以看出,一个SDK程序基本的框架为:
 1. 程序入口为WinMain;
 2. 注册一个class;
 3. 创建窗口并显示;
 4. 进入消息循环,直到遇到WM_QUIT消息。

从上面的代码上看,各个环节的实现都是很简单,真正能变得极为复杂的是那个窗口回调函数(WndProc)。当前只处理WM_PAINT和WM_DESTROY两个消息,代码看起来还是很清爽,但若处理n个消息呢?必然会有一个庞大的switch case列表。

另外一个的麻烦之处是,每个窗口几乎都有自己的私有数据,而在回调函数里,只有hWnd参数指明是哪个窗口,那如何通过hWnd找到对应的私有数据?

这些迹象表明,我们需要对SDK进行封装,才能以更合乎常规的方式来编写程序。

请点击这里下载'wabc'库的最终源码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
en.stm32cubemx-win-v6-9-1是一个针对STMicroelectronics的STM32微控制器系列的软件工具。这个软件工具可在Windows操作系统上使用,其版本号为6.9.1。 STM32微控制器系列是STMicroelectronics推出的一种低功耗、高性能的微控制器芯片系列。这些微控制器芯片广泛用于嵌入式系统、物联网设备、工业自动化以及各种电子产品中。STM32微控制器系列有多个不同的型号和系列,每个型号都有不同的功能和性能特点。 en.stm32cubemx-win-v6-9-1是用于STM32微控制器系列的软件工具。它具有通过图形化界面进行配置和生成代码的功能,使得开发人员可以更加方便地进行STM32微控制器的软件开发。通过这个软件工具,开发人员可以选择不同的模块、外设和功能,然后生成相应的初始化代码。这个软件工具还可以提供一些自动生成的模版,使得开发人员可以快速开始开发。 除了代码生成外,en.stm32cubemx-win-v6-9-1还提供了一些其他功能。例如,它可以通过图形化界面配置时钟树、引脚映射、中断优先级等。此外,该软件工具还可以集成其他开发环境,例如Keil或IAR,以便更直接地进行代码编辑和编译。 总而言之,en.stm32cubemx-win-v6-9-1是一个用于STM32微控制器系列的软件工具,它提供了图形化界面配置和生成代码的功能,帮助开发人员更方便地进行STM32微控制器的软件开发。它是一个很有用的工具,可以提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值