Windows编程基础,第一个Windows程序,注册窗口,创建窗口(下)

简介: Windows编程基础,第一个Windows程序,注册窗口,创建窗口

五.注册窗口类

1.窗口类的概念:

<1>.窗口类包含了窗口各种参数信息的结构

<2>.每个窗口都有一个窗口类,基于窗口类创建窗口

<3>.每个窗口类都有一个名称,使用前必须注册到操作系统内核中

2.窗口的分类

<1>.系统窗口类

系统已经定义好的窗口类,所有应用程序都可以使用,例如Button(按钮),edit(编辑框)

<2>.应用程序全局窗口类

由用户自己定义,当前应用程序所有模块中都可以使用

<3>.应用程序局部窗口类

由用户自己定义,当前应用程序中只有本模块可以使用

3.注册窗口类函数

ATOM RegisterClassExW(
  [in] const WNDCLASSEXW *unnamedParam1
);

在这里带大家看一下WNDCLASS结构体:

typedef struct tagWNDCLASSA {
  UINT      style;               //窗口风格
  WNDPROC   lpfnWndProc;         //窗口处理函数
  int       cbClsExtra;          //窗口类的附加数据buff的大小
  int       cbWndExtra;          //窗口类的附加数据buff的大小
  HINSTANCE hInstance;           //当前模块的实例句柄
  HICON     hIcon;               //窗口图标句柄
  HCURSOR   hCursor;             //鼠标句柄
  HBRUSH    hbrBackground;       //绘制窗口背景的画刷句柄
  LPCSTR    lpszMenuName;        //窗口菜单的资源id字符串
  LPCSTR    lpszClassName;       //窗口类的名称
} WNDCLASSA, *PWNDCLASSA, *NPWNDCLASSA, *LPWNDCLASSA;

大家也可以在微软的MSDN官方文档中查看:WNDCLASS结构体

4.style窗口类风格

应用程序全局窗口类的注册,需要在窗口类的风格中增加CS_GLOBALECLASS

应用程序局部窗口类,在注册窗口类时,不添加CS_GLOBALECLASS

具体的窗口类风格,大家可以到MSDN官方文档中查看:窗口类风格style

六.创建窗口

我们来看看创建窗口函数:

HWND CreateWindowExW(
  [in]           DWORD     dwExStyle,          //窗口的拓展风格
  [in, optional] LPCWSTR   lpClassName,        //已经注册的窗口类名称
  [in, optional] LPCWSTR   lpWindowName,       //窗口标题栏名称
  [in]           DWORD     dwStyle,            //窗口的基本风格
  [in]           int       X,
  [in]           int       Y,
  [in]           int       nWidth,
  [in]           int       nHeight,            //以上四个参数是决定窗口的位置
  [in, optional] HWND      hWndParent,         //父窗口句柄
  [in, optional] HMENU     hMenu,              //窗口的菜单句柄
  [in, optional] HINSTANCE hInstance,          //当前应用程序实例句柄
  [in, optional] LPVOID    lpParam             //窗口创建时的附加参数
);

这里给出MSDN官方文档地址:CreateWindowExW函数

那么在CreateWindow函数中,具体是如何实现的?

这里先给出一张图,我们围绕这张图来讲解:

CreateWindow函数创建窗口过程:

  • 1:CreateWindow函数内部根据传入的窗口类名称,在应用程序局部窗口类中查找,如果找到与之匹配的,执行2,如果没有找到,执行3
  • 2:比较局部窗口类与创建窗口时传入的HINSTANCE变量,如果相等,说明创建和注册的窗口在同一个模块,创建窗口并返回
  • 3:在应用程序全局窗口类中查找窗口类名称,如果找到,执行4,否则执行5(这时候已经不需要比对hins参数了,因为之前提到了,应用程序全局窗口类当前应用程序任何一个模块都可以使用
  • 4:使用找到的窗口类信息,创建窗口并且返回
  • 5:在系统窗口类中查找,如果找到,创建窗口并且返回(这时候已不需要比对hins参数,理由同上),如果未找到,创建创库失败,返回0。
    这里给大家一段伪代码,表示创建窗口的过程:
CreateWindow(各种参数){
  匹配查找窗口类,即上述过程
  if(找到了){
    申请一块内存,将窗口的数据存该内存(该数据包括两部分,CreateWindow函数的参数和找到的窗口类信息)
    return 本内存句柄;
  }else{
  return 0;

七.无法正常关闭窗口问题

当我们写出第一个windows程序的时候,我们点击程序的关闭按钮,发现程序是不显示了,但是在任务管理器中仍然存在,说明我们的应用程序没有正常关闭。

我们来看看,为什么没有正常关闭?没有正常关闭的话,我们的程序停在了哪?

我们发现在代码的消息处理函数中有这样一段代码:

MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd,NULL, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int) msg.wParam;
}

我们可以发现我们的程序肯定停在了while循环中,我们分析发现,如果GetMessage函数返回值为0,那么程序就可以正常关闭,那么我们如何让GetMessage函数的返回值变为零呢?

我们可以将窗口处理函数这样写:

switch(msgID){
  case WM_DESTORY:{
    PostQuitMessage(0);
    break;
  }
}

这样我们写的应用程序就可以正常退出了,至于这其中的原理,我们会在后续章节中讲解到。

八.子窗口创建过程

子窗口的创建很简单,我们只需要满足两个条件;

  • 1.创建窗口时设置父窗口句柄
  • 2.创建窗口时,在style参数中加入WS_WHILD|WS_VISIBLE即可。
相关文章
|
4天前
|
Java C++
jni编程(windows+JDK11+clion)
jni编程(windows+JDK11+clion)
9 1
|
25天前
|
Windows
windows系统vbs脚本 恶搞关不掉的窗口 以及解决办法
windows系统vbs脚本 恶搞关不掉的窗口 以及解决办法
21 2
|
25天前
|
Windows
windows系统bat批处理 开机一键多个程序
windows系统bat批处理 开机一键多个程序
17 1
|
4天前
|
Java Nacos 微服务
Spring Cloud微服务在Windows本地开发时禁用Nacos注册中心注册
Spring Cloud微服务在Windows本地开发时禁用Nacos注册中心注册
|
2月前
|
Windows
LabVIEW启用/禁用Windows屏幕保护程序
LabVIEW启用/禁用Windows屏幕保护程序
27 4
LabVIEW启用/禁用Windows屏幕保护程序
|
6天前
|
C++ UED 开发者
逆向学习 MFC 篇:视图分割和在 C++ 的 Windows 窗口程序中添加图标的方法
逆向学习 MFC 篇:视图分割和在 C++ 的 Windows 窗口程序中添加图标的方法
7 0
|
2月前
|
存储 安全 搜索推荐
Windows之隐藏特殊文件夹(自定义快捷桌面程序)
Windows之隐藏特殊文件夹(自定义快捷桌面程序)
|
PHP Windows 容器
43、Windows驱动程序模型笔记(一)
1、通常,驱动程序在某些不可预测线程的上下文中应该使用异步方式处理I/O请求。我们使用术语任意线程上下文(arbitrary thread context)来描述驱动程序并不知道(或并不关心)处理器当前执行在哪一个线程上的上下文。
824 0
|
PHP Windows C++
44、Windows驱动程序模型笔记(二)
图示 原图2-13 DRIVER_OBJECT数据结构     I/O管理器使用驱动程序对象来代表每个设备驱动程序,见图2-13。就象我们将要讨论的许多数据结构一样,驱动程序对象是部分不透明的。这意味着虽然 DDK头中公开了整个结构,但我们仅能直接访问或修改结构中的某些域。
875 0
|
PHP Windows 算法
45、Windows驱动程序模型笔记(三)
4、DriverUnload例程     在WDM驱动程序中,DriverUnload例程的作用就是释放DriverEntry例程在全局初始化过程中申请的任何资源,但它几乎没什么可做。如果你在DriverEntry中备份了RegistryPath串,应该在这里释放备份所占用的内存。
1016 0