当前位置:C++技术网 > 精选软件 > Windows零基础入门:2.9 窗口类与进程以及窗口过程的关系

Windows零基础入门:2.9 窗口类与进程以及窗口过程的关系

更新时间:2015-08-19 11:11:49浏览次数:1+次

    上节课介绍了窗口类的思想和相关概念。本节课来更加细致的介绍窗口类的具体的形式。如果你对窗口类的概念还不清楚,请去看上节课先。
    由上一节课我们知道,窗口类就是用来创建窗口的模板。既然是模板,必然有很多参数,用来确定窗口的特征。是的,窗口类就是一系列的窗口属性的集合,作为创建窗口的模板。一个窗口类可以创建很多个窗口,所以,窗口是窗口类的创建的一个实例。
    拿到具体的编程环境来讲,所有的窗口类从属于一个进程。也就是说,我们所提到的所有窗口类,都是工作在一个进程内的。在一个进程中创建的窗口类,不能跨进程使用。就像你在一个房间放了一个电视,这个房门是关闭的,你不可能在其他房间来看这个电视。进程之间就相当于多个隔离的房间。窗口类则只是这个房间中的一样东西而已。
    我们用同一个窗口类创建了大量的窗口,这些窗口都长得差不多一样,那么这些窗口的消息谁来处理呢?当然是窗口类中的成员--窗口过程。窗口过程就是一个函数指针,赋值后,就确定了用哪个函数来处理这些窗口消息。
    这也就意味着,这些窗口都由一个窗口过程在处理所有窗口的窗口消息。这个窗口过程和窗口类是这些窗口公用的。窗口过程处理消息,就可以决定这些窗口的外观和行为了。比如在WM_PAINT中处理,就可以对窗口进行绘制,而这个处理就影响所有由这个窗口类创建的窗口的外观。而在WM_LBUTTONDOWN消息中,处理的是鼠标左键单击消息,这个处理,也会影响到所有由这个窗口类创建的窗口单击时候的反应。这里的例子,不必细究,我们会在后面一一介绍的,这里你只要感觉出是这么回事就行了。
    既然窗口过程是所有窗口公用的,那么也就是说,这所有的窗口的外观和行为反应都是一样的。你要让你创建的窗口与众不同,那么你就要创建你自己的窗口类,然后用你自己的窗口类来创建自己的窗口。你在创建窗口类的时候,指定自己单独的一个窗口过程,来处理你这个窗口的消息,就可以让你的窗口的外观和行为与其他的不一样。
    那么创建自己的窗口类、注册自己窗口类和创建自己的窗口过程代码如下:

WNDCLASS wndclass;
wndclass.lpfnWndProc = MyProc;// - 窗口过程函数名
wndclass.lpszClassName = _T("MyClass");// - 窗口类名
...其他的成员赋值就不列出来了。
RegisterClass(&wndclass);// - 注册窗口类,登记窗口类到你的进程
CreateWindow(_T("MyClass"),...);// - 用自己的窗口类创建窗口

LRESULT CALLBACK MyProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
...// - 窗口类过程,处理所有的窗口消息,完成所有的功能。
}

     总的来说,这里就是上面的创建自己定制的窗口类,定制的内容包括确定自己的窗口类名,确定窗口消息处理的窗口过程函数名。注册自己窗口类,注册就是将这个窗口类信息保存在窗口类表中。创建窗口时就会根据窗口类名去查询窗口类信息。查到之后,就按照窗口类的信息来创建一个窗口。你提供的窗口过程函数,就用来处理所有的消息。
    以上就是定制窗口类的过程。你的这个窗口类,同样也可以创建很多的窗口,而创建的所有这些窗口也都公用你这个窗口类和窗口过程。
    窗口类注册一次后,后面再创建窗口时就不必再注册了。直接用这个窗口类名创建就可以了。所以,你可以在初始化的时候,将窗口类注册好,然后后面再用的时候直接用这个窗口类名来创建就好了。如果窗口类不想再使用了,就可以注销掉,用UnregisterClass就可以了。注销窗口类就是在窗口类表中删掉这个窗口类信息。删掉之后就不能再用了。
    而系统窗口类是系统创建的,又是什么情况?系统窗口类创建后存在哪,如何创建,什么时候创建,这些都是一个谜团吧。
    我们自己的窗口类的过程都全部了解了,我们就来看看系统窗口类。
    系统窗口类是系统创建的。当一个进程的任何一个线程第一次调用用户函数或者GDI函数时,系统就会为这个进程注册系统窗口类。注册登记的地方,并不是在系统里。前面说了,所有窗口类都属于一个进程的,所以,你进程使用的系统窗口类同样也属于你的进程。而系统注册,是为你的进程注册,注册完后,依然登记在你的进程窗口类表中。
    系统窗口类执行了以下过程:

WNDCLASS wndclass;
wndclass.lpfnWndProc = SysProc;// - 窗口过程函数名,系统定义好的
wndclass.lpszClassName = szClassName;// - 窗口类名,系统定义好的
...其他的成员赋值就不列出来了。
RegisterClass(&wndclass);// - 注册窗口类,系统帮你登记系统窗口类到你的进程中
     所以这个过程都是系统来完成,那么也就是说,窗口过程的确定以及窗口类名字都是系统确定的,这就是标准控件的窗口类名字为什么是预先固定好的原因。因为是系统帮你注册好的。所以,你要创建标准控件这些窗口,只需要执行:
CreateWindow(标准控件的窗口类名称,...);// - 用系统窗口类创建窗口
     如:CreateWindow("Button",...);// - 创建一个标准的按钮
    这里就创建了一个标准的按钮控件,标准的控件的窗口过程都是系统指定了,所有,你对控件的各种操作,都是系统预先确定好的窗口过程处理。你不要以为这按钮就不需要写窗口过程哦。只是系统已经帮你写好了而已。
    当然,如果你想更改系统默认的窗口过程,从而修改标准控件的行为,那么你就要去修改你进程中的这个系统窗口类的窗口过程。Windows提供了这个函数,我们可以做到。使用
SetWindowsLong(hWnd, GWL_WNDPROC, (LONG)NewProc);
     这个函数就可以修改第一个参数指定的窗口的窗口过程,NewProc是你的新的窗口过程名称,在这个函数中,就和普通的窗口过程函数一样处理你想处理的消息,就实现了修改标准控件的行为的效果。这个只提到这,后面再专门花一节课来讲如何实现修改。这个技术叫做窗口子类化,其实就是替换窗口过程的技术。事实上,这个可以替换任何一个窗口的已经设置好的窗口过程。
    你要理解为什么系统窗口类不用你注册却能用,是不是也可以修改系统注册的窗口类的窗口过程。而系统窗口类你是不能注销的。你也不必为此费心。