程序中创建了主窗口,所以它必须为主窗口注册一个窗口类,创建窗口并且提供一个消息循环来为窗口处理消息。

注册窗口类

ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELLOCEME));
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szAppName;

return RegisterClass(&wc);
}

style域为窗口设置了类的风格。在Windows CE中,类风格被限制为:
CS_GLOBALCLASS 表示类是全局的。这个标志只是出于兼容性才提供的,因为Windows CE中所有窗口类都是进程级全局类。
CS_HREDRAW 告诉系统如果窗口改变了水平大小,就强制重画窗口。
CS_VREDRAW 告诉系统如果窗口改变了垂直大小,就强制重画窗口。
CS_NOCLOSE 如果[关闭]按钮出现在标题栏上,则使其失效。
CS_PARENTDC 让窗口使用父窗口的设备环境变量
CS_DBLCLKS 允许[双击]通知(Windows CE下敲击两次为双击)传递给父窗口

lpfnWndProc分配的是窗口的窗口过程的地址。因为该域定义为指向窗口过程的指针,所以在源代码中,必须在域被设置之前,定义该过程的声明。否则,编译器类型检查时会警告该行。

cbClsExra允许程序员为类结构增加额外的空间来存储只有应用程序才知道的类特定数据。cbWndExtra更加便于使用,这个域为Windows内部结构增加空间,该结构负责维护窗口每个实例的状态。不在窗口结构本身里存储大量的数据,应用程序应该存储一个指向应用程序特定结构的指针,该结构包含窗口每个实例的数据。在Windows CE里,cbClsExtra 和cbWndExtra域必须时4字节的倍数。

hInstance域设置为程序的实例句柄,该句柄指明拥有窗口的进程。hIcon域设置为窗口默认图标的句柄,但在Windows CE中并不支持该域,所以该域应该设置为NULL。(在Windows CE中,会在类的第一个窗口被创建后设置类的图标。对于Hello3,没有图标提供,并且与其它Windows版本不同,Windows CE中没有任何预定义图标用于装载。)

除非应用程序是为带鼠标的Windows CE系统设计的,否则hCursor域应该设置为NULL。幸运的是,如果系统不支持光标,调用LoadCursor (IDC_ARROW) 函数会返回NULL。

hbrBackground域规定Windows CE如何画窗口背景。Windows用这个域中指定的刷子brush(一个小的预定义的像素数组)来画窗口背景。Windows CE提供许多预定义的刷子,你可以用GetStockObject函数来装载。如果hbrBackground域是NULL,窗口必须处理WM_ERASEBKGND消息,重画窗口背景。

lpszMenuName域必须设置为NULL,因为Windows CE不直接支持有菜单的窗口。在Windows CE中,菜单由主窗口创建的命令工具条、命令带或菜单条控件提供。

lpszClassName设置为程序员定义的字符串,用于为Windows指明类的名字。Hello3用的是“MyClass”做为类名。

整个WNDCLASS类被填充后,RegisterClass函数被调用,并用指向WNDCLASS结构的指针作为唯一的参数。如果函数成功,一个标记窗口类的值被返,如果失败,函数返回0。

消息循环
主窗口创建后,WinMain进入消息循环,这是每个Windows 应用程序的心脏。

while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}

该循环很简单:调用GetMessage函数,从应用程序消息队列中获取下一个消息。如果没有消息可用,则调用进入等待期,阻塞应用程序线程直到消息可用。当消息可用,该函数返回包含在MSG结构的消息数据。MSG结构自身包含几个域,有的用于识别消息,有的提供特定消息参数,有的识别在消息被发送之前,被笔触摸过的最后屏幕位置点。该位置信息不同于标准Win32消息位置数据,在XP下,返回的位置是当前鼠标位置而不是最后点击(或者tapped,在Windows CE里)的位置。

TranslateMessage 把适当的键盘信息转换成字符信息。(后面会讨论其它信息过滤器,比如IsDialogMsg。)DispatchMessage 接下来告诉Windows把消息发给应用程序适当的窗口。

获取消息、转换消息、分发消息这个过程会一直循环到GetMessage 收到WM_QUIT消息,这会使GetMessage返回0,这一点不同于其它消息。从while子句可以看出,GetMessage返回0将导致循环终止。

消息循环终止后,程序除了清理和退出外几乎不做什么。在Hello3里,程序简单的从WinMain中返回。WinMain的返回值成为程序的返回码。传统上,最后一个消息WM_QUIT的wParam参数值包含有返回值。为了响应应用程序对PostQuitMessage的调用,WM_QUIT消息被发送出去,此时WM_QUIT的wParam参数值被填充。

窗口过程
发送或提交(send 或 post方式)主窗口的消息被送到MainWndProc过程中。和所有窗口过程一样,MainWndProc原型如下:
LRESULT CALLBACK MainWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam);

返回值类型LRESULT 实际上就是long型(在Windows里long是一个32位值),写成这种形式是为源代码和机器之间提供一个中间级。虽然你可以轻易的从包含文件中确定Windows编程时使用的变量的真实类型,但当你试图把代码做跨平台的转换时会产生问题。虽然了解变量类型的大小对计算内存使用是有用的,但没有什么好的理由去使用(实际上有很多不使用的理由)windows.h文件中提供的类型定义。

CALLBACK 类型指明该函数是EXE的外部入口点,这是Windows直接调用该过程所必须的。在桌面系统里,CALLBACK 指出参数是按类Pascal风格从右到左方式压进程序栈的,这和标准C语言方式相反。为外部入口点使用Pascal语言栈框架的原因可以追朔到Windows开发非常早的时期。使用固定大小、Pascal栈方式,意味着由被调用的过程来清理栈,而不是留给调用者来清理。这种方式可以有效的减少Windows及其附属程序的大小,所以早期的微软开发者认为这是一个好的方式。在Windows CE里,应用程序对所有函数都使用C栈框架,不管是否是外部调用。

传给窗口过程的第一个参数是窗口句柄,当您需要定义具体的窗口实例的时候,这个句柄是很有用的。wMsg参数表示发给窗口的消息。这不是WinMain消息循环里使用的MSG结构,而是一个包含消息值的unsigned整型。剩余两个参数,wParam 和lParam, 传递和具体消息有关的数据给窗口过程。它们的名字来自Win16时代,那时wParam是个16位值而lParam是32位值。同其它Win32操作系统一样,在Windows CE里,两个都是32位的。

和传统的窗口过程一样,Hello3的窗口过程通过一个switch语句解析wMsg消息ID。该switch语句包含2个case语句,一个用来解析WM_PAINT消息,另一个用来解析WM_DESTROY消息。这个窗口过程大概是窗口过程所能简化到及至的一个窗口过程了。

WM_PAINT
绘制窗口,处理WM_PAINT消息,这在任何Windows 程序中都是很重要的功能之一。窗口的外观是在程序处理WM_PAINT消息的过程中完成的。除了用您在注册窗口类时指定的刷子绘制默认背景外,Windows对处理该消息不提供任何帮助。Hello3中处理WM_PAINT消息如下:
case WM_PAINT:
// Get the size of the client rectangle
GetClientRect (hWnd, &rect);

hdc = BeginPaint (hWnd, &ps);
DrawText (hdc, TEXT ("Hello Windows CE!"), -1, &rect,
DT_CENTER | DT_VCENTER | DT_SINGLELINE);

EndPaint (hWnd, &ps);
return 0;
在窗口绘制之前,程序必须确定窗口大小。在Windows程序里,一个标准窗口被划分为两个区域--非客户区和客户区。窗口标题栏和可变大小的边框通常占据了窗口的非客户区,这个区域由Windows负责绘制。客户区属于窗口的内部区域,由应用程序负责绘制。应用程序通过调用GetClientRect 函数来确定客户区的大小和位置。该函数返回一个RECT结构,包含左上角、右下角坐标等描述客户区矩形边界的信息。分成客户区和非客户区的好处是,应用程序不必绘制那些窗口标准元素,例如标题栏。

其它版本的Windows提供一系列WM_NCxxx消息,允许您的应用程序绘制非客户区。在Windows CE里,窗口很少有标题栏。因为很少有非客户区,所以Windows CE不发送非客户端消息给窗口过程。

WM_PAINT消息里执行的所有绘制工作都必须由两个函数BeginPaint 和EndPaint包围。BeginPaint 函数返回设备环境句柄HDC。设备环境是物理显示设备(例如视频显示器或打印机)的逻辑代表。Windows程序从不直接修改显示硬件。相反,Windows用设备环境将程序与具体硬件隔离开。

BeginPaint 填充一个PAINTSTRUCT结构,其结构如下:
typedef struct tagPAINTSTRUCT {
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT;

hdc就是BeginPaint函数返回的句柄。fErase指出窗口过程是否需要重画窗口背景。rcPaint是RECT结构,定义了需要重画的客户区。并假设在每个WM_PAINT消息中,整个客户区窗口都需要重画。当性能是需要考虑的问题时,该域是很有用的,因为有时仅仅需要重画部分窗口即可。即使当程序尝试重画rcPaint矩形以外的区域时,Windows也会阻止这么做的。该结构的其它域,fRestore, fIncUpdate, 和rgbReserved,属于Windows内部使用,应用程序可以忽略掉它们。

程序中唯一的绘制工作是在窗口绘制一行文本。程序调用DrawText函数来完成该绘制。如果您看一下该函数,很容易会明白这个调用在窗口上绘制了一行字符串“Hello Windows CE”。在DrawText返回后,调用EndPaint来通知Windows程序已经完成了窗口更新。

EndPaint调用同时也使没有被绘制的窗口其它区域有效。Windows保持一份无效窗口区域(也就是需要重画的区域)列表和有效区域(也就是已经更新的区域)列表。不论您是否在窗口画了什么,通过成对的调用BeginPaint和EndPaint,会通知Windows由您来处理窗口的无效区域。实际上,您必须调用BeginPaint和EndPaint,或者通过其它方式使窗口无效区域变有效,否则Windows会不断发送WM_PAINT消息给窗口,直到无效区域变有效。

WM_DESTROY
程序中处理的另一个消息是WM_DESTROY。当窗口即将被销毁时,该消息被送出。因为该窗口是应用程序主窗口,当窗口被销毁时应用程序将终止。处理WM_DESTROY消息的代码调用PostQuitMessage消息来触发该动作。PostQuitMessage函数将WM_QUIT消息放到到消息队列里。该函数的参数是返回码的值,该值放在WM_QUIT消息的wParam参数里传回应用程序。

如前所述,消息循环看到WM_QUIT消息就会退出循环。WinMain 接着调用TermInstance,在Hello3里,该函数什么也不做,只是返回。WinMain 接着返回,并终止程序。

转载于:https://blog.51cto.com/xyzlmn/818943

对VS2008生成智能win32程序简单理解相关推荐

  1. Generative Adversarial Networks 生成对抗网络的简单理解

    1. 引言 在对抗网络中,生成模型与判别相竞争,判别模型通过学习确定样本是来自生成模型分布还是原始数据分布.生成模型可以被认为是类似于一组伪造者,试图产生假币并在没有检测的情况下使用它,而判别模型类似 ...

  2. GAIL生成对抗模仿学习的简单理解

    文章目录 强化学习 模仿学习 模仿学习的三种方法 行为克隆 逆向强化学习 GAIL生成对抗模仿学习 强化学习 强化学习需要一个合适的reward函数去求解最优行动策略,但很多情况下不容易设以一个足够全 ...

  3. Win32程序简单演示-模拟电子表格移动光标到另一单元格

    /*-------------------------------------------------bobo,2020-01-18---------------------------------- ...

  4. 为什么要学Win32及Win32程序框架

    前言: 最近在看侯捷的<深入浅出MFC>,在理解MFC时觉得必须要掌握win32,才能更好的理解MFC,才能写出更有用的程序.于是将自己对win32程序的理解写了下来,供朋友们参考.文中的 ...

  5. VS2008下利用#pragma comment屏蔽VC/VS生成的exe程序的CMD窗口

    2016-6-1日注:此种方法并不适用于VS2012,在VS2012中屏蔽CMD的方法可以见博文:VS2012及VS系列怎样屏蔽CMD窗口~_昊虹图像算法-CSDN博客_vs 不打开cmd 有时候我们 ...

  6. 【MFC系列1】之简单Win32程序

    一.位运算 标志位组合:wParam = MK_RBUTTON|MK_CONTROL|MK_SHIFT 标志位的判断:wParam & MK_LBUTTON 标志位的分离:wParam &am ...

  7. VC++6.0 win32 控制台应用程序 简单应用 附代码

    **VC++6.0 win32 控制台应用程序 简单应用 附代码 ** .cpp 文件名 注意:在源文件添加如下声明: #include //没有.h using namespace std;//使用 ...

  8. 开发微信小程序,就是这么简单!可自动生成微信小程序源代码,配套JS SDK、接口和后台

    开发微信小程序,就是这么简单!自己动手,丰衣足食! 开发微信小程序有多简单?
 你只需要掌握前端开发,就可以轻松开发自己的微信小程序,实现自己的业务功能.借助果创云,无须域名.无须服务器.无须数据库, ...

  9. Win32 程序开发:一个简单的Win32程序

    1)什么是Win32 Win32是指Microsoft Windows操作系统的32位环境,与Win64 都为Windows常见环境.如今的Win32操作系统可以一边听音乐,一边编程,一边打印文档.W ...

最新文章

  1. 学习API网关遇到的名词
  2. C语言第一次博客作业
  3. UWP 查找模板中的控件
  4. Boost:计时系的测试
  5. java expextion_Java(20~24)
  6. Mongodb的update操作
  7. 调试人脸识别 无cpu版本出现的问题
  8. 高一计算机信息与技术知识点,高中信息技术必修知识点汇总
  9. vue-pdf 字体不显示
  10. Java-Maven使用jwtt验证
  11. linux邮件客户端配置文件,在Deepin V20下配置Evolution邮件客户端,添加新邮箱全过程...
  12. 《近代名老中医经验集》出版
  13. 克劳德・香农(Claude Shannon)于1937年发表《对继电器和开关电路中的符号分析》
  14. 【每日更新 Suggest 】leetcode解题
  15. 全国计算机平面设计资格证,政策透明—平面设计师证全国统一报名入口报考条件...
  16. 关于互联网时代的自助旅游
  17. 透过Bigbang《花路》销量战绩看QQ音乐的压倒性优势
  18. 历年CCF-CSP认证考试题目解法/思想
  19. PHP远程文件包含(RFI)并绕过远程URL包含限制
  20. 在洋葱(Onion)架构中实现领域驱动设计

热门文章

  1. Python学习 - 常用模块(二)
  2. 【转】JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)
  3. Redis服务器的启动过程分析
  4. POJ C++程序设计 编程题#7:字符串排序
  5. 老子《道德经》第三十三章
  6. FM实现F4帮助系列三:弹出框多筛选…
  7. Java入门需掌握的30个基本概念[转]
  8. JS性能优化之文档碎片-document.createDocumentFragment
  9. Ajax — 第五天
  10. 新版本微信导致的ios表单bug