win32桌面应用程序初始代码解析(五)

本文深入解析了Win32编程中的MyRegisterClass和InitInstance函数,详细解释了WNDCLASSEX结构体的各字段作用,如窗口重绘风格、图标、背景等,并介绍了RegisterClassExW函数的功能及CreateWindowW函数的参数含义,如窗口样式组合WS_OVERLAPPEDWINDOW和位置参数CW_USEDEFAULT的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇主要讲下MyRegisterClassInitInstance


MyRegisterClass

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);  

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELLOWINDOWS));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_HELLOWINDOWS);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

首先,我们要知道,WNDCLASSEXW和WNDCLASSEX是同一个东西

我们来看下WNDCLASSEXW的结构

typedef struct tagWNDCLASSEXW {
    UINT        cbSize;
    /* Win 3.x */
    UINT        style;
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCWSTR     lpszMenuName;
    LPCWSTR     lpszClassName;
    /* Win 4.0 */
    HICON       hIconSm;
} WNDCLASSEXW, *PWNDCLASSEXW, NEAR *NPWNDCLASSEXW, FAR *LPWNDCLASSEXW;

cbsize:该结构体大小

style:窗口的风格

WNDPROC:该窗口的消息处理程序

cbWndExtra和CBClsExtra:暂时不用管它,是提供给窗口和类的额外内存,我们默认为0

hInstance:包含类的窗口过程的实例的句柄。即包含这个窗口消息处理程序的程序实例句柄。

hIcon:类图标的句柄。此成员必须是图标资源的句柄。如果为空,则系统提供默认句柄。

hCursor:类游标的句柄。此成员必须是游标资源的句柄。如果此成员为空,则每当鼠标移到应用程序的窗口中时,应用程序必须显式设置光标形状。

hbrBackground:类背景画笔的句柄。此成员可以是用于绘制背景的画笔的句柄,也可以是颜色值。

lpszMenuName:指向以空结尾的字符串的指针,该字符串指定类菜单的资源名称,该名称显示在资源文件中。如果使用整数标识菜单,请使用makeintresource宏。如果该成员为空,则属于该类的窗口没有默认菜单。 

lpszClassName:指向以空结尾的字符串或原子的指针。如果此参数是一个原子,则它必须是由先前对registerclass或registerclassex函数的调用创建的类原子。原子必须在lpszclassname的低位字中;高位字必须为零。 

如果lpszclassname是字符串,则指定窗口类名。类名可以是用registerclass或registerclassex注册的任何名称,也可以是任何预定义的控件类名。 

hIconsm:与窗口类关联的小图标的句柄。如果此成员为空,系统将搜索hicon成员指定的图标资源,以查找大小合适的图标用作小图标。 


即使看了参数解释,我相信很多人跟我一样对代码依然有不懂的地方。

问题一:CS_HREDRAW | CS_VREDRAW 什么意思?

首先|表示将两边数据进行或操作,结果是两者兼并的效果。然后我们来了解class style里的各个宏定义的意义

/*
 * Class styles
 */
#define CS_VREDRAW          0x0001 //如果移动或大小调整更改了工作区的高度,则重新绘制整个窗口。 
#define CS_HREDRAW          0x0002 //如果移动或大小调整更改了工作区的宽度,则重新绘制整个窗口。 
#define CS_DBLCLKS          0x0008 //当用户在属于该类的窗口中双击鼠标时,向窗口过程发送双击消息。 
#define CS_OWNDC            0x0020 //为类中的每个窗口分配唯一的设备上下文。 
#define CS_CLASSDC          0x0040 //分配一个要由类中所有窗口共享的设备上下文。
#define CS_PARENTDC         0x0080 //将子窗口的剪切矩形设置为父窗口的剪切矩形,以便子窗口可以在父窗口上绘制。
#define CS_NOCLOSE          0x0200 //禁用“窗口”菜单上的“关闭”。 
#define CS_SAVEBITS         0x0800 //将被此类窗口遮挡的屏幕图像部分保存为位图。删除窗口时,系统使用保存的位图还原屏幕图像
#define CS_BYTEALIGNCLIENT  0x1000//在字节边界(X方向)上对齐窗口的工作区。此样式影响窗口的宽度及其在显示中的水平位置。
#define CS_BYTEALIGNWINDOW  0x2000//在字节边界(X方向)上对齐窗口。此样式影响窗口的宽度及其在显示中的水平位置。 
#define CS_GLOBALCLASS      0x4000//指示窗口类是应用程序全局类。

我们不需要把每个宏定义都搞明白,只需要知道个大概。

那么答案显而易见就是如果移动或改变了窗口大小就会重绘窗口

问题二:RegisterClassExW函数干了什么呢?为什么需要注册窗口类?

https://zhidao.baidu.com/question/196021427.html   


InitInstance

我们只需要了解一个函数:CreateWindowW

HWND CreateWindowExW(
  DWORD     dwExStyle,
  LPCWSTR   lpClassName,
  LPCWSTR   lpWindowName,
  DWORD     dwStyle,
  int       X,
  int       Y,
  int       nWidth,
  int       nHeight,
  HWND      hWndParent,
  HMENU     hMenu,
  HINSTANCE hInstance,
  LPVOID    lpParam
);

dwExStyle:正在创建的窗口的扩展窗口样式。默认为0,之所以在CreateWindowW没有出现是因为被宏定义默认为0了。

lpClassName:窗口类名

lpWindowName:窗口名,也是本程序中的标题栏文本

dwStyle:正在创建的窗口的样式。此参数可以是窗口样式值和“备注”部分中指示的控件样式的组合。 

x:窗口的初始水平位置。

y:窗口的初始竖直位置。

nWidth:窗口宽度

nHeight:窗口高度

hWndParent:正在创建的窗口的父窗口或所有者窗口的句柄。

hMenu:菜单句柄

hInstance: 与窗口关联的模块实例的句柄 

lpParam:指向要通过wm_create消息的lparam参数指向的createstruct结构(lpcreateparams成员)传递给窗口的值的指针。

同样,我们直接看问题

问题一:第三个参数WS_OVERLAPPEDWINDOW是什么意思?

#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     | \
                             WS_CAPTION        | \
                             WS_SYSMENU        | \
                             WS_THICKFRAME     | \
                             WS_MINIMIZEBOX    | \
                             WS_MAXIMIZEBOX)

根据宏定义我们可以看到这是一个窗口样式的组合,这个叫做层叠式窗口,虽然我也不知道为什么要层叠式(捂脸)

问题二:为什么窗口的初始x位置指定为CW_USEDEFAULT后,y指定为0但窗口的y方向位置并不是0。对于后面的两个参数同理。

MSDN文档规定了它的规则:

The initial horizontal position of the window. For an overlapped or pop-up window, the x parameter is the initial x-coordinate of the window's upper-left corner, in screen coordinates. For a child window, x is the x-coordinate of the upper-left corner of the window relative to the upper-left corner of the parent window's client area. If this parameter is set to CW_USEDEFAULT, the system selects the default position for the window's upper-left corner and ignores the y parameter. CW_USEDEFAULT is valid only for overlapped windows; if it is specified for a pop-up or child window, the x and y parameters are set to zero.

描粗的句子说明了一切 :如果此参数设置为CW U USEFAULT,系统将选择窗口左上角的默认位置并忽略Y参数。


至此,所有的win32初始代码解析就结束了。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值