Win32编程:创建属于你的第一个窗口

Win32编程:创建属于你的第一个窗口总结来说 先编写一个入口函数 WinMain 然后在入口函数里 进行窗口结构体的定义和注册 定义好了后进行创建窗口 CreateWindow 只是创建并没有显示 使用 ShowWindow 和 Updat

大家好,欢迎来到IT知识分享网。

目录

一、Win32程序的运行过程

二、创建Windows窗口

1、分析

2、完整代码 


一、Win32程序的运行过程

        Win32编程,也称为Windows编程。运行步骤主要包含:加载程序(操作系统加载程序的可执行文件(exe格式)到内存中,创建进程的地址空间,并分配必要的系统资源。),初始化(查找程序的主函数WinMain函数),消息循环(消息也就是事件响应信息,这里会获取一段信息),消息处理(收到消息,放入消息队列,程序会根据消息调用相应函数,如果为WM_QUIT,则退出程序)。

Win32编程:创建属于你的第一个窗口

        Win32 应用特点:界面一致,操作便利,所见即所得,多任务。 

二、创建Windows窗口

1、WinMain函数

   首先要编写WinMain函数,它是窗口编程的入口函数,相当于控制台应用的主函数,由操作系统调用填写参数,以下是其函数结构。

int WINAPI WinMain( HINSTANCE hInstance,//操作系统使用此值来标识 EXE (加载到) 可执行文件。 某些函数需要实例句柄Windows例如,加载图标或位图。 HINSTANCE hPrevInstance, //没有意义。 它用于 16 位Windows,但现在始终为零。 LPSTR lpCmdLine,//用于指定程序的命令行,是指向字符串的指针类型。 int nCmdShow//是一个标志,指示主应用程序窗口是最小化、最大化还是正常显示。 ) 
关键词 解释
HINSTANCE 程序实例句柄,用来标识唯一窗口。
LPSTR CHAR*
WINAPI Microsoft 定义的一种标准调用约定,主要用于 Windows API 函数

     WinMain函数内部要完成以下操作:1、定义并注册窗口类(设置其窗口类属性)。2、展现窗口。3、建立消息处理循环队列

2、定义注册窗口类

        在创建窗口之前,需要定义窗口结构体类WNDCLASS,并向Windows注册,它是Windows API 中用于定义窗口类的结构体

typedef struct tagWNDCLASS { UINT style; //窗口的风格 WNDPROC lpfnWndProc; //指定窗口的消息处理函数的窗口过程函数 int cbClsExtra : //指定分配给窗口类结构之后的额外字节数 int cbwndExtra; //指定分配给窗口实例之后的额外字节数 HINSTANCE hInstance : //指定窗口过程所对应的实例句柄 HICON hIcon; //指定窗口的图标 HCURSOR hCursor; //指定窗口的鼠标指针 HBRUSH hbrBackground; //指定窗口的背景画刷 LPCTSTR lpszMenuName; //窗口的菜单资源名称 LPCTSTR lpszClassName; //该窗口类的名称 }WNDCLASS, * PWNDCLASS; 
关键词 解释
UINT unsigned int
WNDPROC Windows API 中定义窗口过程的函数指针类型。窗口过程是一个回调函数,用于处理与窗口相关的消息。
HBRUSH 画刷句柄
HICON 图标句柄
HCURSOR 光标句柄
LPCTSTR char* 长指针常量字符串

        结构体填写完后,要向Windows系统去提交注册,成功返回TRUE,失败返回FALSE。

RegisterClass(&wndclass)

         注册完成后使用CreateWindow函数进行创建,该函数使用方法如下。

hwnd = CreateWindow(szAppName, // 类名 TEXT("Hello 程序"), // 窗口标题 WS_OVERLAPPEDWINDOW, // 窗口样式 CW_USEDEFAULT, // 默认水平位置 CW_USEDEFAULT, // 默认垂直位置 CW_USEDEFAULT, // 默认宽度 CW_USEDEFAULT, // 默认高度 NULL, // 没有父窗口 NULL, // 没有菜单 hInstance, // 应用程序实例的句柄 NULL); // 没有额外参数 

         CreateWindow函数结构如下:

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 );

 参数详解

  1. dwExStyle: 扩展窗口样式,这个值决定了窗口的一些行为和外观,常见的样式有:
    • WS_EX_LAYERED:使窗口成为一个分层窗口。
    • WS_EX_TRANSPARENT:使窗口变为透明。
    • WS_EX_TOOLWINDOW:创建工具窗口。
  2. lpClassName: 窗口类名,必须是通过 RegisterClass 或 RegisterClassEx 注册的窗口类名。此参数可以是窗口类的名称或窗口类的原始句柄。
  3. lpWindowName: 窗口标题,显示在窗口的标题栏中。
  4. dwStyle: 窗口的样式,这些样式决定了窗口的外观和功能。常见的窗口样式有:
    • WS_OVERLAPPED:重叠窗口(默认)。
    • WS_POPUP:弹出窗口。
    • WS_CHILD:子窗口。
    • WS_VISIBLE:创建时窗口可见。
  5. X: 窗口的左上角 x 坐标。
  6. Y: 窗口的左上角 y 坐标。
  7. nWidth: 窗口的宽度(以像素为单位)。
  8. nHeight: 窗口的高度(以像素为单位)。
  9. hWndParent: 父窗口的句柄。如果当前窗口是一个子窗口,则该参数为父窗口的句柄;如果是顶级窗口,则该参数为 NULL
  10. hMenu: 菜单的句柄,通常用于顶级窗口。如果窗口没有菜单,则此参数为 NULL
  11. hInstance: 应用程序的实例句柄,通常通过 GetModuleHandle(NULL) 获取。
  12. lpParam: 传递给窗口的额外数据指针,通常用于传递结构体或其他数据。

3、 建立消息处理循环队列

        由定义窗口结构体可得,需要一个消息处理函数WndProc,该函数也由Windows操作系统调用,但需要在定义窗口的结构体赋值。

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam) { HDC hdc; // 设备上下文句柄,用于绘制图形 PAINTSTRUCT ps; // 用于存储绘制信息的结构体 RECT rect; // 矩形结构体,用于定义绘制区域 switch (message) { case WM_CREATE: // 当窗口被创建时接收到的消息 PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC); // 播放声音文件 "hellowin.wav" return 0; // 处理完毕,返回0 case WM_PAINT: // 当窗口需要重绘时接收到的消息 hdc = BeginPaint(hwnd, &ps); // 开始绘制,获取设备上下文 GetClientRect(hwnd, &rect); // 获取窗口客户区的矩形区域 DrawText(hdc, TEXT("大家好"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // 在客户区绘制文本 "大家好",居中显示 EndPaint(hwnd, &ps); // 结束绘制 return 0; // 处理完毕,返回0 case WM_DESTROY: // 当窗口被销毁时接收到的消息 PostQuitMessage(0); // 发送退出消息,结束应用程序 return 0; // 处理完毕,返回0 } // 对于未处理的消息,调用默认窗口过程 return DefWindowProc(hwnd, message, wParam, IParam); }
关键词 解释
CALLBACK 这是一个调用约定,指示该函数是一个回调函数。Windows 在需要时会调用这个函数。
WPARAM 这是一个无符号整数,通常用于传递消息的附加信息。
HWND 这是一个句柄,表示窗口的句柄。
LPARAM 这是一个长整型,通常用于传递消息的附加信息,具体内容也取决于消息类型。

接着是创建窗口函数CreateWindow函数

HWND WINAPI CreateWindow( //返回值是窗口句柄 LPCTSTR lpClassName, //窗口类名,要与注册时指定的名称相同 LPCTSTR lpWindowName, //窗口标题 DWORD dwStyle, //窗口样式 int X, //窗口最初的x位置 int y, //窗口最初的y位置 int nWidth, //窗口最初的x大小 int nHeight, //窗口最初的y大小 HWND hWndParent, //父窗口句柄 HMENU hMenu, //窗口菜单句柄 HINSTANCE hInstance, //应用程序实例句柄 LPVOID lpParam //指向一个传递给窗口的参数值的指针,以便后续在程序中加以引用 ); 
关键词 解释
HWND 句柄,它是窗口的唯一标识符
LPCTSTR char* 长指针常量字符串
HMENU 指向窗口菜单的唯一标识符
DWORD 双字节32位无符号整数
LPVOID 指向任何类型的指针,通常用于表示通用数据指针,允许函数接受不同类型的数据。

2、完整代码 

        总结来说,先编写一个入口函数WinMain,然后在入口函数里,进行窗口结构体的定义和注册,定义好了后进行创建窗口CreateWindow,只是创建并没有显示,使用ShowWindow和UpdateWindow显示并更新窗口,然后进行消息循环,GetMessage和DispatchMessage获取并分发消息到消息处理函数WndProc(自己编写,系统调用),这样一个简单的窗口程序便结束了,以下是完整代码。

#include<Windows.h> #pragma comment(lib, "winmm") LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam) { HDC hdc; // 设备上下文句柄,用于绘制图形 PAINTSTRUCT ps; // 用于存储绘制信息的结构体 RECT rect; // 矩形结构体,用于定义绘制区域 switch (message) { case WM_CREATE: // 当窗口被创建时接收到的消息 PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC); // 播放声音文件 "hellowin.wav" return 0; // 处理完毕,返回0 case WM_PAINT: // 当窗口需要重绘时接收到的消息 hdc = BeginPaint(hwnd, &ps); // 开始绘制,获取设备上下文 GetClientRect(hwnd, &rect); // 获取窗口客户区的矩形区域 DrawText(hdc, TEXT("大家好"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // 在客户区绘制文本 "大家好",居中显示 EndPaint(hwnd, &ps); // 结束绘制 return 0; // 处理完毕,返回0 case WM_DESTROY: // 当窗口被销毁时接收到的消息 PostQuitMessage(0); // 发送退出消息,结束应用程序 return 0; // 处理完毕,返回0 } // 对于未处理的消息,调用默认窗口过程 return DefWindowProc(hwnd, message, wParam, IParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { // 定义应用程序名称 static TCHAR szAppName[] = TEXT("HelloWorld!"); HWND hwnd; // 主窗口的句柄 MSG msg; // 消息结构,用于窗口消息 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 = szAppName; // 将类名设置为应用程序名称 // 注册窗口类 if (!RegisterClass(&wndclass)) { // 如果注册失败,显示错误消息 MessageBox(NULL, TEXT("此程序的 RegisterClass 出错!"), szAppName, MB_ICONERROR); return 0; // 退出程序 } // 创建主窗口 hwnd = CreateWindow(szAppName, // 类名 TEXT("Hello 程序"), // 窗口标题 WS_OVERLAPPEDWINDOW, // 窗口样式 CW_USEDEFAULT, // 默认水平位置 CW_USEDEFAULT, // 默认垂直位置 CW_USEDEFAULT, // 默认宽度 CW_USEDEFAULT, // 默认高度 NULL, // 没有父窗口 NULL, // 没有菜单 hInstance, // 应用程序实例的句柄 NULL); // 没有额外参数 // 显示窗口并更新它 ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); // 消息循环以处理消息 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); // 将虚拟键消息转换为字符消息 DispatchMessage(&msg); // 将消息分发到窗口过程WndProc } // 返回消息的 wParam 作为退出代码 return msg.wParam; } 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/141788.html

(0)
上一篇 2025-05-14 20:26
下一篇 2025-05-14 20:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信