窗口的消息处理

我们知道一个应用程序一般都不是只有一个窗口组成的,往往是多窗口组成的,比如一个对话框的窗口上有一个按钮,这里对话框是一个窗口,按钮也是一个窗口。如果一个对话框上有100个按钮,就是100个窗口,这样句柄会比较多。因而出现了DirectUI的设计方法,所有按钮和主窗口都是同一个窗口,采用分不同区域来绘画而成。这里就遇到了一个问题,每个窗口是独立存在的,但在前面的例子里,可以看到每个窗口都是调用PyWndProc函数来处理。意味着多个窗口的消息都抛给PyWndProc函数处理,这样处理起来只会越来越多,越来越复杂。站在面向对象设计角度来考虑,是否可以有一个更好的方案解决呢?这个是可以的,由于Windows里给每个窗口保留了一个用户数据字段,只要利用这个字段,就可以关联起每个窗口与消息类之间的关系。比如窗口1就调用窗口1的类来处理消息,窗口2就调用窗口2的类来处理消息,这样每个窗口的独立性就得到保障,不用担心窗口1的消息会跑到窗口2去。为此,我声明了一个类Controller,用这个类来处理窗口的消息,当然不同的窗口都可以继承这个类,而实现其它的窗口消息处理。创建类Controller的实例之后,把这个实例对象保存到窗口的GWL_USERDATA字段里。参考《Windows API一日一练》介绍创建窗口的函数,如下:

HWND CreateWindowEx(

DWORD dwExStyle,//窗口的扩展风格

LPCTSTR lpClassName,//指向注册类名的指针

LPCTSTR lpWindowName,//指向窗口名称的指针

DWORD dwStyle,//窗口风格

int x,//窗口的水平位置

int y,//窗口的垂直位置

int nWidth,//窗口的宽度

int nHeight,//窗口的高度

HWND hWndParent,//父窗口的句柄

HMENU hMenu,//菜单的句柄或是子窗口的标识符

HINSTANCE hInstance,//应用程序实例的句柄

LPVOID lpParam//指向窗口的创建数据

);

在这个API函数的最后字段lpParam,就是指向窗口用户自定义的数据,在这里,我把消息处理类对象的指针放到这里,就可以让每个窗口有自己的消息处理类了。

定义类Controller如下:

class Controller:
    def __init__(self):
        self.hWnd = HWND()
    def SetWnd(self, hWnd):
        self.hWnd = hWnd
    def MyWndProc(self, hWnd, Msg, wParam, lParam):
        if Msg == WM_DESTROY:           
            windll.user32.PostQuitMessage(0)
            return 0
        else:
            return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam)

在类Controller里,主要有成员变量self.hWnd,它是用来保存每个窗口的句柄;成员函数MyWndProc是用来处理每个窗口的消息,如果窗口没有处理,就会把这些消息传递给Windows系统默认处理,而这个处理默认消息的函数是DefWindowProcW函数。因为一个窗口的消息是有很多的,并不是每个窗口都需要处理这么多消息,因此只有需要的才处理,这样处理方式是非常方便的。


你可能感兴趣的:(窗口的消息处理)