Windows零基础入门:3.1 窗口过程函数的使用和背景知识详解

3537 人浏览 | 时间: 2015-09-24 11:37:14 | 作者: codexia

    通过前面一系列的课程,把窗口类风格总算讲完了,而且每一个风格都经过深度挖掘,我自己也是查了不少资料,思考过很久才学习到了不少东西。相信不管是你以前学没学过,都会有很多的收获。
    上节课说第二章差不多结束,并不是说不讲窗口类结构体变量的其他几个成员的赋值等内容了,而是其他几个成员,就只是一个赋值过程,需要讲的东西,则是其他一片天地,赋值很简单,而背后的各种技术背景,则不简单。我们都要用专门的章节讲。
    后面的几个成员,都与窗口类本身并不密切,不过因为是零基础入门的,所以,每一个成员使用中的各种细节,都会尽可能多的讲到。不仅让你会使用,而且知道为什么这么使用。
    第三章用来讲解WinMain函数中的代码的各种细节,而具体各个方面的深入知识,将以单独的章节详细介绍。本节课讲解窗口过程。
    窗口过程,也可以叫做窗口消息处理过程。实际上,它就是一个函数而已。然而,这个函数,并不是程序员写程序来调用的,而是给操作系统调用的,也就是回调函数。对于回调函数的理解和使用,请参考学习《简单的介绍回调函数原理和使用》和《函数调用与回调函数的设计原理的深入对比分析》。回调函数是什么,以及回调函数和函数调用的区别,我就不在此重复了。自己看文章哦。
    可是你知道吗?为什么窗口过程要做成回调函数呢?不知道你想过这个问题没有。作为Windows底层的结果和框架设计,必然是操作系统做好后就固定不变的,然而不同的程序需要不同的处理,怎么才能以不变应万变呢?是的,就是使用回调函数机制。

LRESULT CALLBACK WindowProc(
  _In_  HWND hwnd,
  _In_  UINT uMsg,
  _In_  WPARAM wParam,
  _In_  LPARAM lParam
);
     首先说一下,_In_对应的还有_Out_。很多人对这个确实很陌生。其实他们只是一个修饰符,让你更清楚这个参数是程序输入的,还是接受输出结果的。_In_自然就是调用函数时要主动传递进去的参数,而_Out_则是传递一个变量地址给函数,然后函数执行完后,会将结果复制到你传的变量里。如果你对这些没什么感觉的话,可以直接忽略掉他们。
    窗口过程函数的名字,你可以随意取,这个对于Window来说,没有什么感觉,因为程序代码编译之后,这些函数名只是一个代号,在二进制代码中,只是成为了函数代码的一个地址偏移数字而已。不过,你肯定要在窗口类结构体变量赋值给窗口过程时,要赋值你声明的这个函数咯。
    每一个函数都有返回值,窗口过程也是函数,当然也有返回值。不过怪异的是,又是一个“新类型”,LRESULT!你会接触越来越多的“新类型”,其实他们只是基本类型的别名哦。前面课程讲过一个钛合金眼镜哦,不知道你会用了没有。这里就不重复讲了。
    我们发现,LRESULT的声明如下:
typedef LONG_PTR LRESULT;
typedef long LONG_PTR;
     实际上,LRESULT就是一个long类型咯。至于返回值是消息的处理结果,并且不同的消息不一样。这里就不好说了。反正你知道,它返回的是一个long类型的值即可。
    而CALLBACK在讲解WinMain时已经讲过了,都是__stdcall的别名而已。参数中的hwnd就是消息中传递的窗口的句柄。系统要根据窗口句柄来投递消息,同时消息中自然含有窗口句柄的值,hwnd参数就是窗口句柄咯。
    为什么窗口处理过程中还要窗口句柄参数呢?因为窗口过程并不是一个窗口独立拥有的,它和窗口类一样,和很多窗口一起共同拥有,如果不用窗口句柄传递进去,窗口过程又怎么知道在处理哪个窗口的消息呢。
    第二参数uMsg则是消息的ID,代表一个消息,比如WM_PAINT重绘消息。在窗口过程中,通过switch对消息进行分类处理,不同的消息做不同的处理。这里就是一个识别消息对消息分类的效果。标准的消息都是以WM_开头的,WM_是Windows Message的缩写,就是窗口消息的意思。
    至于后面两个参数的类型,声明如下:
typedef UINT_PTR WPARAM;
typedef LONG_PTR LPARAM;
typedef unsigned int UINT_PTR;
typedef long LONG_PTR;
     那么他们实际上还是整型类型哦。不要太惊讶哦。实际上,需要的参数通过这两个参数传递,一般都是要经过类型强制转换的。具体使用,我们将在详细处理里面解释哦。
    不过,对于初学者来说,肯定分不清楚这两个参数的意思。实际上很简单的。这两个参数的值,都是根据第二个参数的消息ID不同而不同。第三个参数wParam与uMsg挨得近,自然也就是消息密切相关的信息了。而lParam则是除了密切相关的额外信息外,在第三个参数放不下,所以,在lParam中传递。不过,很多消息没有额外的信息,所以默认为0即可。
    声明好窗口过程函数后,然后给窗口类结构体变量的窗口过程成员赋值即可,直接填写窗口过程的函数名。声明窗口过程后,那么就要实现这个函数,就是在函数中写代码咯。至于在窗口过程写代码,这个在消息处理部分讲解。
请微信扫码阅读
为防止恶意爬虫,
已开启反爬机制

Win32课程菜单