windows第一个窗口程序转自windows程序设计王艳平老师编著
转
目录:
1.窗口程序
2.分析
注册窗口类别
建立窗口
显示窗口
消息循环
窗口消息处理程序
3.注意事项
窗口程序:
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
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))
{
//在Windows 98中,大多数Unicode函数无法执行,MessageBoxW是个例外
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
//建立窗口
hwnd = CreateWindow (szAppName, // window class name
TEXT ("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ; //显示窗口
UpdateWindow (hwnd) ; //重画显示区域
//消息循环,用于从消息队列中取出消息,并做相应处理
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
//窗口消息处理程序
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
//GetClientRect函数检索一个窗口的客户区坐标rect
GetClientRect (hwnd, &rect) ;
DrawText (hdc, TEXT ("Hello, Windows Vista!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
运行程序,将会出现一个窗口并发出响声,窗口中央有一行文字。如下图:
分析:
1.注册窗口类别
窗口依照某一窗口类别建立,窗口类别用以标识处理窗口消息的窗口消息处理程序。
在为程序建立窗口之前,必须首先呼叫RegisterClass注册一个窗口类别。该函数只需要一个参数,即一个指向型态为WNDCLASS的结构指针。
WNDCLASS是一个窗口类结构:
{
UINT style ; //窗口类别样式
WNDPROC lpfnWndProc ; //设定消息处理程序
int cbClsExtra ; //用于在窗口类别结构和Windows内部保存的窗口结构中预留一些额外空间
int cbWndExtra ; //同上
HINSTANCE hInstance ; //程序的执行实体句柄
HICON hIcon ; //为所有依据这个窗口类别建立的窗口设置一个图标
HCURSOR hCursor ; //设置鼠标光标
HBRUSH hbrBackground ; //指定依据这个类别建立的窗口背景颜色
LPCTSTR lpszMenuName ; //指定窗口类别菜单
LPCTSTR lpszClassName ; //必须给出一个类别名称
}
在WinMain中为WNDCLASS定义一个结构,通常像这样:
然后,你就可以初始化该结构的10个字段,并呼叫RegisterClass。
在初始化该结构的10个字段后,HELLOWIN呼叫RegisterClass来注册这个窗口类别。该函数只有一个参数,即指向WNDCLASS结构的指针。
2.建立窗口
窗口类别定义了窗口的一般特征,因此可以使用同一窗口类别建立许多不同的窗口。呼叫CreateWindow建立窗口时,可以指定有关窗口的更详细的信息。
下面是HELLOWIN.C中的CreateWindows呼叫,每一个字段都做了完整的说明:
TEXT ("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
此程序建立的窗口是一个普通的重迭式窗口。它含有一个标题列,标题列左边有一个系统菜单按钮,标题列右边有缩小、放大和关闭图示,四周还有一个表示窗口大小的边框。这是标准样式的窗口,名为WS_OVERLAPPEDWINDOW,出现在CreateWindow的「窗口样式」参数中。此样式是几种位旗标的组合:
WS_CAPTION | /
WS_SYSMENU | /
WS_THICKFRAME | /
WS_MINIMIZEBOX | /
WS_MAXIMIZEBOX)
「窗口标题」是显示在标题列中的文字。
注释着「initial x position」和「initial y position」的参数指定了窗口左上角相对于屏幕左上角的初始位置。由于这些参数使用CW_USEDEFAULT标识符,指示Windows使用重迭窗口的内定位置。(CW_USEDEFAULT定义为0x80000000。)内定情况下,Windows依次对新建立的窗口定位,使各窗口左上角的垂直和水平距离在屏幕上按一定的大小递增。与此类似,注释着「initial x size」和「initial y size」的参数分别指定窗口的宽度和高度。同样使用了CW_USEDEFAULT标识符,表明希望Windows使用内定尺寸。
在建立一个「最上层」窗口,如应用程序窗口时,注释为「父窗口句柄」的参数设定为NULL。通常,如果窗口之间存在有父子关系,则子窗口总是出现在父窗口的上面。应用程序窗口出现在桌面窗口的上面,但不必为呼叫CreateWindow而找出桌面窗口的句柄。
因为窗口没有菜单,所以「窗口菜单句柄」也设定为NULL。「程序执行实体句柄」设定为执行实体句柄,它是作为WinMain的参数传递给这个程序的。最后,「建立参数」指标设定为NULL,可以用这个参数存取稍后程序中可能引用到的数据。
CreateWindow传回被建立的窗口的句柄,该句柄存放在变量hwnd中,后者被定义为HWND型态(「窗口句柄型态」)。Windows中的每个窗口都有一个句柄,程序用句柄来使用窗口。许多Windows函数需要使用hwnd作为参数,这样,Windows才能知道函数是针对哪个窗口的。如果一个程序建立了许多窗口,则每个窗口均有一个句柄。窗口句柄是Windows程序所处理最重要的句柄之一。
3.显示窗口
在CreateWindow呼叫传回之后,Windows内部已经建立了这个窗口。这就是说,Windows已经配置了一块内存,用来保存在CreateWindow呼叫中指定窗口的全部信息跟一些其它信息,而Windows稍后就是依据窗口句柄找到这些信息的。
然而,光是这样子,窗口并不会出现在视讯显示器上。您还需要两个函数呼叫,一个是:
第一个参数是刚刚用CreateWindow建立的窗口句柄。第二个参数是作为参数传给WinMain的iCmdShow。它确定最初如何在屏幕上显示窗口,是一般大小、最小化还是最大化。在开始菜单中安装程序时,使用者可能做出最佳选择。如果窗口按一般大小显示,那么WinMain接收到后传递给ShowWindow的就是SW_SHOWNORMAL﹔如果窗口是最大化显示的,则为SW_SHOWMAXIMIZED。而如果窗口只显示在工作列上,则是SW_SHOWMINNOACTIVE。
ShowWindow函数在显示器上显示窗口。如果ShowWindow的第二个参数是SW_SHOWNORMAL,则窗口的显示区域就会被窗口类别中定义的背景画刷所覆盖。函数呼叫:
这个函数会重画显示区域。它经由发送给窗口消息处理程序(即HELLOWIN.C中的WndProc函数)一个WM_PAINT消息做到这一点。
4.消息循环
呼叫UpdateWindow之后,窗口就出现在视讯显示器上。程序现在必须准备读入使用者用键盘和鼠标输入的数据。Windows为当前执行的每个Windows程序维护一个「消息队列」。在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中。
程序通过执行一块称之为「消息循环」的程序代码从消息队列中取出消息:
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
msg变量是型态为MSG的结构,型态MSG在WINUSER.H中定义如下:
{
HWND hwnd ; //接收消息的窗口句柄
UINT message ; //消息标识符。这是一个数值,用以标识消息。
WPARAM wParam ; //一个32位的「message parameter(消息参数)」
LPARAM lParam ; //一个32位的消息参数,其值与消息有关
DWORD time ; //消息放入消息队列中的时间
POINT pt ; //消息放入消息队列时的鼠标坐标
}
MSG, * PMSG ;
POINT数据型态也是一个结构,它在WINDEF.H中定义如下:
{
LONG x ;
LONG y ;
}
POINT, * PPOINT;
消息循环以GetMessage呼叫开始,它从消息队列中取出一个消息。第二、第三和第四个参数设定为NULL或者0,表示程序接收它自己建立的所有窗口的所有消息。
只要从消息队列中取出消息的message字段不为WM_QUIT(其值为0x0012),GetMessage就传回一个非零值。WM_QUIT消息将导致GetMessage传回0。
TranslateMessage将msg结构传给Windows,进行一些键盘转换。
DispatchMessage又将msg结构回传给Windows。然后,Windows将该消息发送给适当的窗口消息处理程序,让它进行处理。这也就是说,Windows将呼叫窗口消息处理程序。
5.窗口消息处理程序
以上我们所讨论的都是必要的负担:注册窗口类别,建立窗口,然后在屏幕上显示窗口,程序进入消息循环,然后不断从消息队列中取出消息来处理。实际的动作发生在窗口消息处理程序中。窗口消息处理程序确定了在窗口的显示区域中显示些什么以及窗口怎样响应使用者输入。
在此程序中,窗口消息处理程序是命名为WndProc的函数。窗口消息处理程序可任意命名(只要求不和其它名字发生冲突)。一个Windows程序可以包含多个窗口消息处理程序。一个窗口消息处理程序总是与呼叫RegisterClass注册的特定窗口类别相关联。CreateWindow函数根据特定窗口类别建立一个窗口。但依据一个窗口类别,可以建立多个窗口。
//窗口消息处理程序总是定义为如下形式
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
//在此程序中,WndProc只选择处理三种消息:WM_CREATE、WM_PAINT和WM_DESTROY。窗口消息处理程序的结构如下:
switch (message)
{
case WM_CREATE:
//播放声音文件
PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
return 0 ;
case WM_PAINT:
//对WM_PAINT的处理几乎总是从一个BeginPaint呼叫开始,而以一个EndPaint呼叫结束,BeginPaint使显示区域变为有效。如果不呼叫BeginPaint和EndPaint(或者ValidateRect),则Windows不会使该区域变为有效。相反,Windows将发送另一个WM_PAINT消息,且一直发送下去。
hdc = BeginPaint (hwnd, &ps) ;
//GetClientRect函数检索一个窗口的客户区坐标rect
GetClientRect (hwnd, &rect) ;
//DrawText可以输出文字。第一个参数是从BeginPaint传回的设备内容句柄;第二个参数是要输出的文字;第三个参数是-1,指示字符串是以字节终结的;DrawText最后一个参数是一系列位旗标,旗标指示了文字必须显示在一行上,水平方向和垂直方向都位于第四个参数指定的矩形中央。
DrawText (hdc, TEXT ("Hello, Windows Vista!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
//通过呼叫PostQuitMessage以标准方式响应WM_DESTROY消息
PostQuitMessage (0) ;
return 0 ;
}
//呼叫DefWindowProc来为窗口消息处理程序不予处理的所有消息提供内定处理,这是很重要的。不然一般动作,如终止程序,将不会正常执行。
return DefWindowProc(hwnd, message, wParam, lParam);
}
程序通常不直接呼叫窗口消息处理程序,窗口消息处理程序通常由Windows本身呼叫。通过呼叫SendMessage函数,程序能够直接呼叫它自己的窗口消息处理程序。
3.注意事项
该程序使用了多媒体功能呼叫需要添加Windows多媒体链接库文件WINMM.LIB。可以在项目—>属性—>配置属性—>链接器—>输入—>附加依赖项里输入WINMM.LIB即可。
windows第一个窗口程序转自windows程序设计王艳平老师编著相关推荐
- 4.2第一个窗口程序
创建Win32工程和MessageBox函数 前面讲的程序都是使用控制台界面来接受输入.显示输出的.要想使用窗口界面与用户交互必须首先创建一个Win32工程. (1)运行VC++6.0,选择菜单命令& ...
- Eclipse中创建第一个窗口程序
之前在VS中用C#做程序开发时,做的最多的是Winform窗口.现在学习在Eclipse中用java编程序,也希望尽快学习如何写窗口程序,但是在选择Eclipse做开发工具的时候就听说Eclips ...
- python窗口程序-python操作Windows窗口程序
如果你想看更多舒适的布局和守时,有干货推动现场每天8点.定期获得数据接口和数据写入Excel表.Excel需要使用其他程序和需要打开.Pywin32处理是一个32位整数,用于标记对象在windows中 ...
- 【win32汇编】0x04 第一个窗口程序
第一个win32汇编窗口程序,主要来自 win32汇编语言程序设计,然后加上了自己查阅msdn文档的一些理解,基本过程: start入口地址 --> _WinMain主函数 --> 定义一 ...
- Win32汇编——第一个窗口程序
1.窗口程序的运行模式:消息驱动 2.窗口程序实现大部分功能的代码应该呆在同一个模块中--"消息处理"模块,这个模块可以随时应付所有类型的消息,只有这样才能随时响应用户的各种操作. ...
- 使用VS创建第一个窗口程序
我觉得C#或者说整个VS的开发环境或者功能对我最有吸引力的不是什么控制台程序,这种程序或者功能的实现使用Python等脚本语言实现起来似乎是更为便捷.对我真正有吸引力的是Windows的窗口程序. 接 ...
- 使用Qt生成第一个窗口程序
一.打开QtCreater,点击New Project 二.在Qt中,最常用的窗口程序为widgets控件程序,这里我们选择Qt Widgets Application 三.Qt生成的debug和re ...
- 【C#】SharpDevelop使用教程,C#写windows下第一个窗口程序,简单粗暴,初学者进,全图文,一看就明白
VS不说,功能强大,但是挺大. 下面,来说说轻量级IDE来写一个简单的windows程序. 首先,下载,不说了,最新版本5.x需要.net4.x支持,需要先安装.net framework 4.x框架 ...
- 通过Windows API 创建窗口的过程理解windows消息机制
一个基于windows API 的基于窗体.消息循环.事件驱动的 Windows C语言风格的Windows 程序. 创建一个Win32应用程序的步骤: 1.定义 WinMain 函数: 2.设计窗口 ...
最新文章
- 读书方法(如果努力有用的话,那还要天才干什么!)
- 统计学习笔记(4)——朴素贝叶斯法
- 提交spark的bug的地方
- 杜教筛模板(P4213 【模板】杜教筛(Sum))
- jquery ui datepicker 只能选今天以后的日期
- WordPress Event Easy Calendar插件多个跨站请求伪造漏洞
- element-ui中el-table的表头、内容样式
- 数据库MySQL/mariadb知识点——日志记录(2)二进制日志
- python业余项目_学会这8个优秀 Python 库用于业余项目,将大大减少程序员耗费的精力...
- Core Animation基础
- CSS也能控制表格的交替颜色
- 进入磁盘指令_Linux操作指令整理
- centos安装软件后没有快捷键,创建桌面快捷键的方式【pycharm的快捷键】
- FirstApp,iphone开发学习总结3,UIButton简单的操作
- PUN☀️四、服务器大厅建房解析
- acer 4741G驱动
- windows Server2016 关闭135端口
- 圆排列公式推导_数学广角早在公元三世纪,我国数学家刘徽为推导圆的面积公式而发明了 爱问知识人...
- 2018-2-13-windows-10预览版升级win10-7月29-10240.16384
- windows内网的情况下如何访问外网
热门文章
- 达梦数据库DCA培训心得
- echarts x轴 字 纵向_echarts柱状图表标题的位置竖立在Y轴上?
- 简易几何利用 ANSYS Multizone Meshing创建六面体网格应用案例
- 学生如何认证JB账户
- 【无标题】使用Oracle官方提供的ova文件建立Oracle 19c学习环境
- xilinx DDS ip 核测试使用
- 2019【李永乐考研数学】全程班视频
- 财政收入的各种统计口径
- mw325r 服务器无响应),水星(MERCURY)MW325R路由器连不上网怎么办?
- C/C++中的字符串比较函数strcmp/memcmp/CString.Compare/CString:CompareNoCase