Windows零基础入门:2.13 修改窗口类的机制和论证

2729 人浏览 | 时间: 2015-08-27 14:08:24 | 作者: codexia 会员文章,禁止转载

    修改窗口类的窗口过程,能够让所有用这个窗口类来创建的窗口都改变了窗口过程吗?或者换句话说,修改窗口过程,会让修改应用于后面创建的窗口上吗?更或者说,注册的窗口类信息(窗口过程)永久修改了吗?
    如果你有这些疑问,那么就继续往下看吧。
    不管是系统窗口类,还是应用程序的窗口类(局部和全局),都是遵循一套机制。这种设计理念,可以让这些保持一致,减少复杂度。这一点,我想,有点经验的人都会想到。只是系统窗口类和应用程序窗口类注册的时间、注册的主体以及制定窗口类参数的主体和窗口过程等都不一样罢了。
    对于这个思想,一定要清楚,也就是提高复用,降低重复编码。对于两种窗口类,也都是一套机制来创建和注册的。当然,对于其他的,也不会差的太多。那么对于修改窗口类来说,也是一致的。
    修改窗口类,并不会真的在写入窗口类的地方直接修改,然后永久保留。为什么?我们先说说系统公共窗口类。这个是系统中所有进程都可以使用的。我们确实可以修改系统窗口类。但是系统不会让我们的修改,导致其他进程使用的时候,变成你修改的样子。所以,系统会保证公共的系统类不能被任何其他的方式修改。
    那你是如何修改系统窗口类,还可以定制这些窗口的样式的呢?不让你直接修改系统的窗口类,是不让你直接修改让它,因为这个会影响别人。你的修改实际上是生成了一个副本,被修改的副本,会存储到一个地方。通过SetWindowLong的第一个参数窗口句柄我们得知,这个修改,只会对你这个窗口有效。你修改了窗口类之后,再用这个窗口类去创建其让窗口,其他窗口还是与原始窗口类的样子来工作的。也就是说,你对前面一个窗口的窗口类的窗口过程的修改,并不会影响到后面创建的窗口。
    那么这就说明,其实系统让你修改窗口类,是让你有一个单独定制一个窗口的机会,系统会将你的修改的部分,单独保存起来,并与你这个窗口关联,那么与这个关联的窗口相关的消息,用你指定的新的窗口类来执行,而其他的窗口类,也就是没有修改窗口过程的窗口,它们的消息还是默认的处理方式。
    系统窗口类是这么处理的,其实应用程序窗口类也是如此,他们都是一套思想做的。所以,窗口子类化(修改窗口的处理过程)就是一个单独的行为,只会影响到指定的窗口,不会影响到其他。
    下面给两个代码例子大家去验证。第一个窗口是用原始的窗口类来创建的,但是修改了这个窗口的窗口过程。那么他就会执行新的窗口过程来处理消息。如果是系统窗口类,那么你就可以定制这个窗口的行为了。而应用程序窗口类本来你就可以定义,不过你修改后,可以用另外一个窗口类来处理。而第二个窗口则是在第一个窗口修改了窗口过程后创建的,而创建出来的窗口,由原始的窗口的窗口过程处理,也就是说,不受你修改的窗口过程处理。这就证明了,你修改窗口过程的行为只对你指定的这个窗口有效。
代码1.修改系统窗口类效果图和代码

                      

第一个窗口被修改窗口过程背景成了灰色,单击可以弹出消息

                          

第二个窗口没有受到第一个窗口的窗口过程的修改,是系统默认的样子,单击没有弹出消息

#include <Windows.h>
#include <tchar.h>

LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK BTNProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow)
{
    MSG  msg;
    HWND hButton = CreateWindow(_T("Button"), _T("按钮"), WS_TILEDWINDOW, 0, 0, 600, 400, NULL, NULL, NULL, NULL);
    SetWindowText(hButton, _T("原始窗口标题_C++技术网"));
    ShowWindow(hButton, SW_SHOWNORMAL);
    SetWindowLong(hButton, GWL_WNDPROC, (LONG)BTNProc);

    HWND hButton2 = CreateWindow(_T("Button"), _T("按钮2"), WS_TILEDWINDOW, 0, 0, 600, 400, NULL, NULL, NULL, NULL);
    SetWindowText(hButton2, _T("新标题_C++技术网"));
    ShowWindow(hButton2, SW_SHOWNORMAL);

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

LRESULT CALLBACK BTNProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;

    switch (message)
    {
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);
        FillRect(hdc, &rect, (HBRUSH)GetStockObject(GRAY_BRUSH));
        DrawText(hdc, _T("新窗口上的文字 - C++技术网"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_LBUTTONDOWN:
        GetClientRect(hwnd, &rect);
        MessageBox(NULL, _T("新窗口单击"), _T("按钮"), MB_ICONINFORMATION);
        return 0;
    case WM_RBUTTONDOWN:
        GetClientRect(hwnd, &rect);
        MessageBox(NULL, _T("新窗口右击"), _T("按钮"), MB_ICONINFORMATION);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
#include <Windows.h>
#include <tchar.h>

LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK BTNProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szExeName[] = _T("Win32");
    HWND hwnd;
    MSG  msg;
    WNDCLASS wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WinProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szExeName;

    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, _T("注册窗口类失败,此程序需要运行在Windows NT平台下。"), szExeName, MB_ICONERROR);
        return 0;
    }

    HWND hButton = CreateWindow(szExeName, _T("按钮"), WS_TILEDWINDOW, 0, 0, 600, 400, NULL, NULL, NULL, NULL);
    SetWindowText(hButton, _T("原始窗口标题_C++技术网"));
    ShowWindow(hButton, SW_SHOWNORMAL);
    SetWindowLong(hButton, GWL_WNDPROC, (LONG)BTNProc);

    HWND hButton2 = CreateWindow(szExeName, _T("按钮2"), WS_TILEDWINDOW, 0, 0, 600, 400, NULL, NULL, NULL, NULL);
    SetWindowText(hButton2, _T("窗口2标题_C++技术网"));
    ShowWindow(hButton2, SW_SHOWNORMAL);

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

LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;

    switch (message)
    {
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);
        FillRect(hdc, &rect, (HBRUSH)GetStockObject(GRAY_BRUSH));
        DrawText(hdc, _T("原始窗口上的文字 - C++技术网"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_LBUTTONDOWN:
        GetClientRect(hwnd, &rect);
        MessageBox(NULL, _T("原始窗口按钮左击"), _T("按钮"), MB_ICONINFORMATION);
        return 0;
    case WM_RBUTTONDOWN:
        GetClientRect(hwnd, &rect);
        MessageBox(NULL, _T("原始窗口按钮右击"), _T("按钮"), MB_ICONINFORMATION);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
LRESULT CALLBACK BTNProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;

    switch (message)
    {
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);
        FillRect(hdc, &rect, (HBRUSH)GetStockObject(GRAY_BRUSH));
        DrawText(hdc, _T("新窗口上的文字 - C++技术网"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_LBUTTONDOWN:
        GetClientRect(hwnd, &rect);
        MessageBox(NULL, _T("新窗口单击"), _T("按钮"), MB_ICONINFORMATION);
        return 0;
    case WM_RBUTTONDOWN:
        GetClientRect(hwnd, &rect);
        MessageBox(NULL, _T("新窗口右击"), _T("按钮"), MB_ICONINFORMATION);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
当前文章为会员文章,请前往[用户中心]开通会员后继续阅读。

Win32课程菜单