Windows窗口过程

一、窗口类(WNDCLASS)

定义:窗口类是一个属性集,是Windows编程中用于创建窗口的模板。窗口类包含了窗口的各种信息的数据结构,每个窗口都具有窗口类,每个窗口都是基于自己的窗口类来进行创建窗口的。每一个窗口类都有一个名称,使用窗口类时必须注册到操作系统中去。
分类:窗口类可以分为系统窗口类、应用程序全局窗口类、应用程序局部窗口类。
系统窗口类——系统中已经定义好的窗口类,所有的的应用程序都可以使用 如:BUTTON EDIT。
应用程序全局窗口类——由用户自己定义的,当前应用程序所有模块都可以使用。
程序局部窗口类——由用户自己定义,当前应用程序中本模块中可以使用
结构:

typedef struct_WNDCLASS{
  UINT style;                 //窗口类的缓冲大小
  WNDPROC lpfnWndProc;        //窗口的消息处理函数的指针
  int cbClsExtra;             //窗口类的buff的缓冲大小
  int cbWndExtra;             //窗口的buff的缓冲大小
  HANDLE hInstance;           //当前窗口的实例
  HICON hIcon;                //窗口图标句柄
  HCURSOR hCursor;            //窗口鼠标句柄
  HBRUSH hbrBackground;       //绘制窗口背景的画刷句柄
  LPCTSTR lpszMenuName;       //窗口菜单资源ID的字符串
  LPCTSTR lpszClassName;      //窗口类的名称
  }WNDCLASS;

注意:1. 不建议使用全局窗口类,容易发生冲突,全局窗口实现的功能,局部窗口类都可以实现;

     2. 用户在创建窗口时,首先需要对窗口进行注册,即通过ATOM RegisterClassEx(CONST WNDCLASSEX *Ipwcx):将窗口类的结构写入操作系统中。

 

                Windows窗口过程_第1张图片

当调用完 CreateWindow 函数的时候:应用程序实例 以及 相应的消息队列已经生成了!

二、生成窗口步骤

1. 设计窗口类(WNDCLASS)
2. 注册窗口:将窗口类的信息写入操作系统的内核中。RegisterClass(窗口类结构体的指针),如RegisterClass(&wndclass)
3. 创建窗口:在内存中开辟一片空间,将窗口的数据(包括CreateWindows传入的数据和窗口类的数据)写入内存,并返回该内存的地址(窗口句柄)。hwnd = CreateWindow()
4. 显示及更新窗口:按照内存中的窗口数据绘制窗口。ShowWindow(HWND hWnd,int mCmdStyle) 、UpdateWindow( hwnd )
5. 消息循环:获取、翻译、分发窗口中的消息
6. 窗口的消息处理函数进行消息处理:处理窗口中的消息
以上对窗口的创建流程进行了概括,接下来对窗口创建过程进行详细的分析。

三、举例

在创建窗口 和 构造WNDCLASS的过程中,有两个相同参数lpszClassName(窗口名称)和hInstance(窗口实例),创建窗口CreateWindow 和 注册窗口RegisterClass,通过这2个参数联系起来的。

/**
一个简单的Win32应用程序,通过这个简单的实例讲解Windows消息是如何传递的
*/
#include 
 
//声明窗口过程函数
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
 
//定义一个全局变量,作为窗口类名
TCHAR szClassName[] = TEXT("SimpleWin32");
 
//应用程序主函数
int WINAPI WinMain (HINSTANCE hInstance,
                                  HINSTANCE hPrevInstance,
                                  LPSTR szCmdLine,
                                  int iCmdShow){
    /***********注意以下几步是windows窗口创建的流程*********************/
    //1.设计一个窗口类
    //(说明:在这里需要自己查一下 _WNDCLASS结构体,不过里边的成员就是以下被初始化的那些变量)
    WNDCLASS wndclass; 
    wndclass.style = CS_HREDRAW|CS_VREDRAW; //当窗口水平方向的宽度和垂直方向的高度变化时重绘整个窗口
    wndclass.lpfnWndProc = WndProc;//关联窗口过程函数
    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 = szClassName;//类名称
//};
 
    //2.注册窗口类
    if(!RegisterClass (&wndclass)){
        MessageBox (NULL, TEXT ("RegisterClass Fail!"), szClassName, MB_ICONERROR);
        return 0;
    }
 
    //3.创建一个窗口
    HWND hwnd;
    hwnd = CreateWindow(szClassName,//窗口类名称
           TEXT ("The Simple Win32 Application"),//窗口标题 
           WS_OVERLAPPEDWINDOW,//窗口风格,即通常我们使用的windows窗口样式
           CW_USEDEFAULT,//指定窗口的初始水平位置,即屏幕坐标系的窗口的左上角的X坐标
           CW_USEDEFAULT,//指定窗口的初始垂直位置,即屏幕坐标系的窗口的左上角的Y坐标
           CW_USEDEFAULT,//窗口的宽度
           CW_USEDEFAULT,//窗口的高度
           NULL,//父窗口句柄
           NULL,//窗口菜单句柄
           hInstance,//实例句柄
           NULL);
    
    //4.显示窗口
    ShowWindow(hwnd,iCmdShow);
    
    //5.更新窗口
    UpdateWindow(hwnd);
 
 
    //消息循环
    MSG msg;
    while(GetMessage(&msg,NULL,0,0))//从消息队列中取消息 
    {
           TranslateMessage (&msg);              //转换消息
           DispatchMessage (&msg);               //派发消息
    }
    return msg.wParam;
}
 
/**
*消息处理函数
*参数:窗口句柄,消息,消息参数,消息参数
*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    //处理感兴趣的消息
    switch (message)
    {
        case WM_DESTROY:
            //当用户关闭窗口,窗口销毁,程序需结束,发退出消息,以退出消息循环
            PostQuitMessage(0);
            return 0;
    }
    //其他消息交给由系统提供的缺省处理函数
    return ::DefWindowProc (hwnd, message, wParam, lParam);
}

四、

4.1 在窗口的创建之前,为什么要进行注册?

想创建什么样的窗口呢?那么,创建什么样的窗口呢?创建前,Window系统可不知道你要的是什么类型的窗口啊(比如标题栏上显示什么图标,鼠标形状是什么,窗口背景颜色等等)。这些类型信息应在你创建前事先告诉Window系统。可以采用这种方法:就是我们事先写一份要创建窗口的类型申请表,提交(注册)给Window系统。然后在创建时,可以让Windows按这个申请表来创建你所要的窗口了。也就是说我们还应该先提交一个申请表,申请成功后再根据这个表创建一个窗口。

4.2 窗口创建和注册之间有什么关系?

通过分析,我们惊奇的发现在创建窗口和构造WNDCLASS的过程中有两个相同参数lpszClassName(窗口名称)和hInstance(窗口实例),创建窗口和注册窗口通过这两个参数联系起来的。
CreateWindow函数的执行过程:

1.CreateWindow首先会根据窗口类的名称在应用程序局部窗口类中查找窗口类,如果找到执行2,若未找到执行3。
2.比较局部窗口类与创建窗口类传入的hinstance是否相同,如果相同在同一模块下创建该窗口。否则执行3。
3.在应用程序全局窗口类中查找,若查找到执行4,否则执行5。
4.使用窗口信息创建窗口并返回。因为要创建的是全局窗口所以不需要比对hInstance。
5.在系统窗口类中查找,若找到创建窗口,否则创建窗口失败,返回NULL。

CreateWindow找到相应的窗口类后会在内存中开辟一个空间来存储窗口类的信息并返回该内存地址的指针(句柄)。

参考:https://blog.csdn.net/qq_43725310/article/details/126103608

你可能感兴趣的:(#,Windows消息机制,windows)