海螺集团网站建设招标公告,wordpress哪里找域名,重庆seo公司怎么样,商业公众号开发需要多少钱目录 Windows 窗口
窗口的基本概念
创建一个窗口的流程
句柄
创建窗口
设计注册窗口类
创建窗口
显示和更新窗口
创建消息循环
消息循环
建立消息循环
窗口过程函数
窗口程序模板#xff08;多字节#xff09;
窗口程序模板#xff08;Unicode#xff09; Wi…目录 Windows 窗口
窗口的基本概念
创建一个窗口的流程
句柄
创建窗口
设计注册窗口类
创建窗口
显示和更新窗口
创建消息循环
消息循环
建立消息循环
窗口过程函数
窗口程序模板多字节
窗口程序模板Unicode Windows 窗口
Winodws这个操作系统就是由窗口命名的可见窗口的重要性
窗口的基本概念
通过这篇微软官方文档可以了解到窗口的基本概念什么是窗口 - Win32 apps | Microsoft Learn
接下来了解一些更深层次的东西
Windows的窗口是由窗口类定义的窗口类定义了窗口的外观和行为并将其注册到系统中。每个窗口都是窗口类的一个实例它们具有相同的属性但可以拥有不同的内容和状态。
Windows 窗口通常包括以下几个部分
标题栏Title Bar位于窗口的顶部用于显示窗口的标题和一些控制按钮例如最小化、最大化、关闭等。菜单栏Menu Bar可选的位于窗口的顶部或程序的主窗口下方用于显示应用程序的菜单和子菜单。工具栏Tool Bar可选的通常位于窗口的顶部或菜单栏下方用于提供快捷方式和工具按钮。客户区Client Area窗口的主要部分用于显示应用程序的内容、控件和用户界面。状态栏Status Bar位于窗口的底部用于显示应用程序的状态信息、提示信息等。
除此之外窗口还可以包含各种控件例如按钮、文本框、列表框、复选框等以及自定义的绘图和布局逻辑。 创建一个窗口的流程
要有一个窗口类并且得到一个实例调用系统API注册窗口类需要指定回调函数再调用系统API创建窗口会返回一个窗口的句柄 句柄
程序员是不能直接操作窗口的需要调用系统的API
当应用程序请求创建一个新的句柄时操作系统内核会为该句柄分配一段内存空间来存储句柄所引用的对象或资源的相关信息并返回该句柄给应用程序。对于不同类型的句柄内核会使用不同的数据结构来管理它们。
句柄Handle是在计算机编程中用于表示对象或资源的标识符。在操作系统中句柄可以被认为是对对象或资源的引用程序可以通过句柄来访问和操作这些对象或资源。句柄是操作系统提供的一种标识和访问对象或资源的机制它由操作系统内核来管理
想要访问这些系统资源需要API句柄来实现
下面是一些常见的句柄类型及其含义
窗口句柄HWND窗口句柄是对窗口对象的引用可以用于标识和操作特定的窗口。通过窗口句柄程序可以改变窗口的属性、位置、大小发送消息到窗口以及获取窗口的属性和状态等。文件句柄File Handle文件句柄是对文件对象的引用用于表示打开的文件。通过文件句柄程序可以读取、写入、关闭文件以及获取文件的属性和状态等。设备句柄Device Handle设备句柄是对设备对象的引用用于表示打开的设备。通过设备句柄程序可以与设备进行通信执行设备操作例如读写设备数据、控制设备行为等。内存句柄Memory Handle内存句柄是对内存块的引用用于表示分配的内存。通过内存句柄程序可以读写分配的内存区域释放内存以及获取内存的相关信息。 创建窗口 创建一个窗口的基本流程
设计注册窗口类常见窗口实例显示窗口更新窗口消息循环窗口注册函数
这里演示的是Unicode的窗口类创建
设计注册窗口类
窗口类 设计窗口
WNDCLASS wc; //创建一个类名为 wc 的窗口类
wc.style CS_VREDRAW | CS_HREDRAW; //默认填CS_VREDRAM | CS_HREDRAM 的组合可通过位运算增加风格或删除风格
wc.lfnWndProc MyWindowProc; //窗口过程函数窗口回调函数
wc.cbClsExtra 0; //默认填0
wc.cbWndExtra 0; //默认填0
wc.hInstance hInstance; //标注这个窗口类属于哪个进程便于从消息队列获取该进程的消息
wc.hIcon NUll; //图标
wc.hCursor NULL; //光标
wc.hbrBackground (HBRUSH)COLOR_HIGHLIGHT;//由于是msdn上预定义的如果出现类型不匹配直接强转即可。
wc.lpszMenuName NULL; //菜单
wc.lpszClassName MyWindow; //窗口的类名
参数解释
wc.style成员style控制窗口的某些重要特性在WINDOWS.H中定义了一些前缀为CS的常量在程序中可组合使用这些常量.也可把sytle设为0. wc.style CS_HREDRAW | CS_VREDRAW它表示当窗口的纵横坐标发生变化时要重画整个窗口。eg无论你怎样拉动窗口的大小那行字都会停留在窗口的正中部而假如把这个参数设为0的话当改动窗口的大小时那行字则不一定处于中部了。wc.lfnWndProc窗口过程函数它将接收Windows发送给窗口的消息并执行相应的任务。并且必须在模快定义中回调它。WndProc是一个回调函数(详见消息循环)wc.cbClsExtra指定用本窗口类建立的所有窗口结构分配的额外字节数。当有两个以上的窗口属于同一窗口类时如果想将不同的数据和每个窗口分别相对应。则使用该域很有用。这般来讲你只要把它们设为0就行了,不必过多考虑。wc.hInstance标识应用程序的实例hInstance,当然实例名是可以改变的。 wc.hInstance MyhInstance ;这一成员可使Windows连接到正确的程序自己的程序。wc.hIcon成员hIcon被设置成应用程序所使用图标的句柄图标是将应用程序最小化时出现在任务栏里的的图标用以表示程序仍驻留在内存中。Windows提供了一些默认图标我们也可定义自己的图标VC里面专有一个制作图标的工具。wc.hCursor定义该窗口产生的光标形状。LoadCursor可返回固有光标句柄或者应用程序定义的光标句柄。IDC_ARROW表示箭头光标.wc.hbrBackground决定Windows用于着色窗口背景的刷子颜色函数GetStockObject返回窗口的颜色本程序中返回的是白色你也可以把它改变为红色等其他颜色.试试看wc.lpszMenuName用来指定菜单名本程序中没有定义菜单所以为NULL。wc.lpszClassName指定了本窗口的类名。类名是操作系统识别类的唯一ID wc.lpszClassName MyWindow;窗口类名必须自定义。 注册窗口类
ATOM Ret RegisterClass(ws); //告知操作系统if (Ret 0){MessageBox(NULL,注册窗口类失败,提示,MB_OK);} 创建窗口
创建窗口函数
HWND CreateWindow(LPCTSTR lpClassName, // 登记的窗口类名LPCTSTR lpWindowName, // 用来表明窗口的标题DWORD dwStyle, // 用来表明窗口的风格如有无最大化最小化按纽啊什么的int x, // 用来表明程序运行后窗口在屏幕中的坐标值。int y, // 用来表明程序运行后窗口在屏幕中的坐标值。int nWidth, // 用来表明窗口初始化时(即程序初运行时)窗口的大小即长度与宽度。int nHeight, // 用来表明窗口初始化时(即程序初运行时)窗口的大小即长度与宽度。HWND hWndParent, // 在创建窗口时可以指定其父窗口这里没有父窗口则参数值为0。HMENU hMenu, // 用以指明窗口的菜单菜单以后会讲这里暂时为0。HANDLE hInstance, // 应用程序实例句柄与程序绑定LPVOID lpParam // 最后一个参数是附加数据一般都是0。
); 显示和更新窗口
显示窗口
BOOL ShowWindow( HWND hWnd, // handle to windowint nCmdShow // show state);更新窗口
BOOL UpdateWindow( HWND hWnd // handle to window);参数1窗口句柄告诉ShowWindow()显示哪一个窗口
参数2第二个参数则告诉它如何显示这个窗口最小化(SW_MINIMIZE)普通(SW_SHOWNORMAL)还是最大化 (SW_SHOWMAXIMIZED)。
WinMain在创建完窗口后就调用ShowWindow函数并把iCmdShow参数传送给这个窗口。
WinMain()调用完ShowWindow后还需要调用函数UpdateWindow最终把窗口显示了出来。调用函数UpdateWindow将产生一个WM_PAINT消息这个消息将使窗口重画即使窗口得到更新.且不通过消息循环 创建消息循环
消息循环
Windows为每个正在运行的应用程序都保持一个消息队列。当你按下鼠标或者键盘时Windows并不是把这个输入事件直接送给应用程序而是将输入的事件先翻译成一个消息然后把这个消息放入到这个应用程序的消息队列中去。
消息结构体定义
typedef struct tagMSG {HWND hwnd;UINT message; //消息的类别也叫消息的ID,编号WPARAM wParam;LPARAM lParam;DWORD time;POINT pt;
} MSG;
操作系统将消息封装成MSG结构体投递到消息队列。
消息循环应用程序的WinMain函数通过执行一段代码从她的队列中来检索Windows送往她的消息。然后WinMain就把这些消息分配给相应的窗口函数以便处理它们这段代码是一段循环代码故称为”消息循环”。 拿到消息以后在通过获取的消息对应处理调用窗口回调函数 建立消息循环
消息循环以GetMessage调用开始它从消息队列中取出一个消息
MSG msg; //定义消息名
while (GetMessage (msg, NULL, 0, 0))
{TranslateMessage (msg) ; //翻译消息DispatchMessage (msg) ; //
}
return msg.wParam ;
GetMessage函数
BOOL GetMessage( LPMSG lpMsg, //接收消息的MSG结构的地址HWND hWnd, //窗口句柄,NULL则表示要获取该应用程序创建的所有窗口的消息UINT wMsgFilterMin, //指定消息范围。后面三个参数被设置为默认值UINT wMsgFilterMax //指定消息范围。后面三个参数被设置为默认值);
后面三个参数被设置为默认值这就是说你打算接收发送到属于这个应用程序的任何一个窗口的所有消息。
返回值
在接收到除WM_QUIT之外的任何一个消息后GetMessage()都返回TRUE。如果GetMessage收到一个WM_QUIT消息则返回FALSE如收到其他消息则返回TRUE。 TranslateMessage
消息用GetMessage读入后(注意这个消息可不是WM_QUIT消息)它首先要经过函数TranslateMessage()进行翻译这个函数会转换成一些键盘消息它检索匹配的WM_KEYDOWN和WM_KEYUP消息并为窗口产生相应的ASCII字符消息(WM_CHAR),它包含指定键的ANSI字符.但对大多数消息来说它并不起什么作用所以现在没有必要考虑它。 DispatchMessage
要求Windows将消息传送给在MSG结构中为窗口所指定的窗口过程。我们在讲到登记窗口类时曾提到过登记窗口类时我们曾指定Windows把函数WindosProc作为咱们这个窗口的窗口过程(就是指处理这个消息的东东)。就是说Windows会调用函数WindowsProc()来处理这个消息。 窗口过程函数
LRESULT CALLBACK WindowProc( HWND hwnd, // handle to windowUINT uMsg, // message identifierWPARAM wParam, // first message parameterLPARAM lParam // second message parameter);WM_DESTROY消息是在窗口被销毁时发送的。 在窗口从屏幕上删除后它被发送到正在被销毁的窗口的窗口过程。此消息首先发送到被销毁的窗口然后发送到被销毁的子窗口(如果有的话)。 在处理消息期间可以假定所有子窗口仍然存在。
LRESULT CALLBACK WndProc
(HWND hwnd, // handle to windowUINT uMsg, // message identifierWPARAM wParam, // first message parameterLPARAM lParam // second message parameter
)
{switch (uMsg){case WM_DESTROY: //销毁窗口的消息PostQuitMessage(0);//退出消息循环break;default:break;}return DefWindowProc(hwnd,uMsg,wParam,lParam);
}窗口程序模板多字节
#include windows.h
#pragma comment(lib, winmm) //PlaySound在Winmm.lib这个库中,当然需要链接它。LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{static wchar_t szAppName[] LHello Win;//设计窗口类WNDCLASS ws;ws.style CS_HREDRAW | CS_VREDRAW;ws.lpfnWndProc MyWndProc;ws.cbClsExtra NULL;ws.cbWndExtra NULL;ws.hInstance hInstance;ws.hIcon LoadIcon(NULL, IDI_APPLICATION);ws.hCursor LoadCursor(NULL, IDC_ARROW);ws.hbrBackground (HBRUSH)GetStockObject(WHITE_BRUSH);ws.lpszMenuName nullptr;ws.lpszClassName szAppName;//注册窗口类if (!RegisterClass(ws)){MessageBox(NULL, TEXT(注册窗口失败), TEXT(错误提示), MB_OK);return 0;}//创建窗口HWND HelloHwnd CreateWindow(szAppName,TEXT(The Hello Program),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL,);//显示窗口ShowWindow(HelloHwnd, iCmdShow);//更新窗口调用Begin使得画面有效UpdateWindow(HelloHwnd);//建立消息循环MSG msg;while (GetMessage(msg, NULL, 0, 0)){TranslateMessage(msg); //将msg结构传给Windows进行一些键盘转换DispatchMessage(msg); //使得自动调用消息窗口句柄所属的窗口过程函数}return msg.wParam; //结构的wParam字段是传递给PostQuitMessage函数的值通常是0。然后return叙述将退出WinMain并终止程序。
}//实现消息过程函数
LRESULT CALLBACK MyWndProc(HWND hwnd, //UINT message, //WPARAM wParam, //参数wParam表明窗口是非最小化还是非最大化是最小化、最大化还是隐藏LPARAM lParam //lParam参数包含了新窗口的大小新宽度和新高度均为16位值合在一起成为32位的lParam。
)
{PAINTSTRUCT ps; //PAINTSTRUCT结构中包含一些窗口消息处理程序可以用来更新显示区域的内容。RECT rect; //矩形结构HDC hdc; //绘图结构switch (message){case WM_CREATE:PlaySound(TEXT(G:\\CR40C程序设计\\二阶段\\SDK\\Windows程序设计实例\\HELLOWIN\\胜利.wav), NULL, SND_FILENAME | SND_ASYNC);return 0;//当窗口改变时//对WM_PAINT的处理几乎总是从一个BeginPaint呼叫开始//一旦显示区域变得无效正如在改变大小时所发生的情况一样WndProc就接收到一个新的WM_PAINT消息。//WndProc通过呼叫GetClientRect取得变化后的窗口大小并在新窗口的中央显示文字。case WM_PAINT:{//在设备客户区中央绘制文本hdc BeginPaint(hwnd, ps); //返回用于在客户端区域中绘制的显示设备上下文的句柄在BeginPaint呼叫中如果显示区域的背景还未被删除则由Windows来删除GetClientRect(hwnd, rect); //接受窗口改变后的尺寸信息。【x,y,高,宽】DrawText(hdc, //BeginPaint传回的设备内容句柄TEXT(Hello ,Windows 10!), //要输出的文字-1, //第三个参数是 -1指示字符串是以字节0终结的rect, //要输出的坐标DT_SINGLELINE | DT_CENTER | DT_VCENTER //系列位旗标旗标指示了文字必须显示在一行上水平方向和垂直方向都位于第四个参数指定的矩形中央);EndPaint(hwnd, ps); //释放ps函数资源结束绘制请求并释放设备上下文。}//不处理如果窗口消息处理程序不处理WM_PAINT消息这是很罕见的//它们必须被传送给DefWindowProc。DefWindowProc只是依次呼叫BeginPaint和EndPaint以使显示区域有效。return 0;case WM_DESTROY:PostQuitMessage(0); //发送WM_QUIT以结束消息循环return 0;}return DefWindowProc(hwnd, message, wParam, lParam); //操作系统待处理我们不处理的消息
} 窗口程序模板Unicode
#include windows.h
#pragma comment(lib, winmm) //PlaySound在Winmm.lib这个库中,当然需要链接它。LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{static char szAppName[] Hello Win;//设计窗口类WNDCLASS ws;ws.style CS_HREDRAW | CS_VREDRAW;ws.lpfnWndProc MyWndProc;ws.cbClsExtra NULL;ws.cbWndExtra NULL;ws.hInstance hInstance;ws.hIcon LoadIcon(NULL, IDI_APPLICATION);ws.hCursor LoadCursor(NULL, IDC_ARROW);ws.hbrBackground (HBRUSH)GetStockObject(WHITE_BRUSH);ws.lpszMenuName nullptr;ws.lpszClassName szAppName;//注册窗口类if (!RegisterClass(ws)){MessageBox(NULL, 注册窗口失败, 错误提示, MB_OK);return 0;}//创建窗口HWND HelloHwnd CreateWindow(szAppName,The Hello Program,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL,);//显示窗口ShowWindow(HelloHwnd, iCmdShow);//更新窗口调用Begin使得画面有效UpdateWindow(HelloHwnd);//建立消息循环MSG msg;while (GetMessage(msg, NULL, 0, 0)){TranslateMessage(msg); //将msg结构传给Windows进行一些键盘转换DispatchMessage(msg); //使得自动调用消息窗口句柄所属的窗口过程函数}return msg.wParam; //结构的wParam字段是传递给PostQuitMessage函数的值通常是0。然后return叙述将退出WinMain并终止程序。
}//实现消息过程函数
LRESULT CALLBACK MyWndProc(HWND hwnd, //UINT message, //WPARAM wParam, //参数wParam表明窗口是非最小化还是非最大化是最小化、最大化还是隐藏LPARAM lParam //lParam参数包含了新窗口的大小新宽度和新高度均为16位值合在一起成为32位的lParam。
)
{PAINTSTRUCT ps; //PAINTSTRUCT结构中包含一些窗口消息处理程序可以用来更新显示区域的内容。RECT rect; //矩形结构HDC hdc; //绘图结构switch (message){case WM_CREATE:PlaySound(G:\\CR40C程序设计\\二阶段\\SDK\\Windows程序设计实例\\HELLOWIN\\胜利.wav, NULL, SND_FILENAME | SND_ASYNC);return 0;//当窗口改变时//对WM_PAINT的处理几乎总是从一个BeginPaint呼叫开始//一旦显示区域变得无效正如在改变大小时所发生的情况一样WndProc就接收到一个新的WM_PAINT消息。//WndProc通过呼叫GetClientRect取得变化后的窗口大小并在新窗口的中央显示文字。case WM_PAINT:{//在设备客户区中央绘制文本hdc BeginPaint(hwnd, ps); //返回用于在客户端区域中绘制的显示设备上下文的句柄在BeginPaint呼叫中如果显示区域的背景还未被删除则由Windows来删除GetClientRect(hwnd, rect); //接受窗口改变后的尺寸信息。【x,y,高,宽】DrawText(hdc, //BeginPaint传回的设备内容句柄Hello ,Windows 10!, //要输出的文字-1, //第三个参数是 -1指示字符串是以字节0终结的rect, //要输出的坐标DT_SINGLELINE | DT_CENTER | DT_VCENTER //系列位旗标旗标指示了文字必须显示在一行上水平方向和垂直方向都位于第四个参数指定的矩形中央);EndPaint(hwnd, ps); //释放ps函数资源结束绘制请求并释放设备上下文。}//不处理如果窗口消息处理程序不处理WM_PAINT消息这是很罕见的//它们必须被传送给DefWindowProc。DefWindowProc只是依次呼叫BeginPaint和EndPaint以使显示区域有效。return 0;case WM_DESTROY:PostQuitMessage(0); //发送WM_QUIT以结束消息循环return 0;}return DefWindowProc(hwnd, message, wParam, lParam); //操作系统待处理我们不处理的消息
}