windows编程——窗口与消息1
来源:互联网 发布:淘宝平面模特拍照姿势 编辑:程序博客网 时间:2024/05/17 08:13
1.WinMain函数
WinMain( )函数与DOS程序的main( )函数基本起同样的作用,但有一点不同的是WinMain( )函数必须带有四个系统传递给它的参数。WinMain()函数的原型如下:int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
第一个参数hInstance是标识该应用程序的句柄。不过句柄又是什么呢?其实就是一个对象或项目的标识符。hIstance唯一地代表了该应用程序,Windows使用它管理内存中的各种对象。它十分重要。在后面的初始化程序主窗口的过程中就需要使用它作为参数。
第二个参数是hPrevInstance,给它NULL吧,这个参数只是为了保持与16位Windows的应用程序的兼容性。
第三个参数是lpCmdLine,是指向应用程序命令行参数字符串的指针。比如说,如果我们执行"test hello",则此参数指向的字符串为"hello"。
最后一个参数是nCmdShow,是用来指定窗口如何显示的整数。关于窗口显示方式的种类,将在下面说明。
2.注册窗口类
一个程序可以有许多窗口,但只有一个是主窗口,它是与该应用程序唯一对应的。
创建窗口前通常要填充一个窗口类WNDCLASS,并调用RegisterClass( )对该窗口类进行注册。每个窗口都有一些基本的属性,如窗口标题栏文字、窗口大小和位置、鼠标、背景色,窗口消息处理函数(后面会讲这个函数)的名称等等。注册的过程就是将这些属性告诉系统,然后再调用CreateWindow( )函数创建出窗口。
下面列出了WNDCLASS的成员:
UINT style; //窗口的风格
WNDPROC lpfnWndProc; //窗口消息处理函数的指针
int cbClsExtra; //分配给窗口类结构之后的额外字节数
int cbWndExtra; //分配给窗口实例之后的额外字节数
HANDLE hInstance; //窗口所对应的应用程序的句柄
HICON hIcon; //窗口的图标
HCURSOR hCursor; //窗口的鼠标
HBRUSH hbrBackground; //窗口的背景
LPCTSTR lpszMenuName; //窗口的菜单资源名称
LPCTSTR lpszClassName; //窗口类的名称
WNDCLASS的第一个成员style表示窗口类的风格,它往往是由一些基本的风格通过位的"或"操作(操作符"|")组合而成。下表列出了一些常用的基本窗口风格:
风格
含义
CS_HREDRAW
如果窗口宽度发生改变,重绘整个窗口
CS_VREDRAW
如果窗口高度发生改变,重绘整个窗口
CS_DBLCLKS
能感受用户在窗口中的双击消息
CS_NOCLOSE
禁用系统菜单中的"关闭"命令
CS_SAVEBITS
把被窗口遮掩的屏幕图像部分作为位图保存起来。当该窗口被移动时,Windows使用被保存的位图来重建屏幕图像
第二个成员是lpfnWndProc,给它消息处理函数的函数名称即可,必要时应该进行强制类型转换,将其转换成WNDPROC型。
接下来的cbClsExtra和wc.cbWndExtra一般都可以设为0。
然后的hInstance成员,给它的值是窗口所对应的应用程序的句柄,表明该窗口与此应用程序是相关联的。
下面的hIcon是让我们给这个窗口指定一个图标,这个程序没有设置。
鼠标也没有设置,因为编游戏时的鼠标都是在刷新屏幕时自己画上去的。
hbrBackground成员用来定义窗口的背景色。这里设为CreateSolidBrush (RGB(100, 0, 0)),即暗红色。关于CreateSolidBrush函数,请参阅4.10节。
lpszMenuName成员的值我们给它NULL,表示该窗口没有菜单。
WNDCLASS的最后一个成员lpszClassName是让我们给这个窗口类起一个独一无二的名称,因为Windows操作系统中有许许多多的窗口类。通常,我们可以用程序名来命名这个窗口类的名称。在调用CreateWindow( )函数时将要用到这个名称。
填充完WNDCLASS后,我们需要调用RegisterClass( )函数进行注册;该函数如调用成功,则返回一个非0值,表明系统中已经注册了这个窗口类。如果失败,则返回0。
3.创建窗口
当窗口类注册完毕之后,我们就可以创建一个窗口,这是通过调用CreateWindow( )函数完成的。窗口类中已经预先定义了窗口的一般属性,而在CreateWindow( )中的参数中可以进一步指定窗口更具体的属性。下面举一个例子来说明CreatWindow( )的用法:
hwnd= CreateWindow(
"Simple_Program",//创建窗口所用的窗口类的名称
"ASimple Windows Program", //窗口标题
WS_OVERLAPPEDWINDOW,//窗口风格,定义为普通型
100,//窗口位置的x坐标
100,//窗口位置的y坐标
400,//窗口的宽度
300,//窗口的高度
NULL,//父窗口句柄
NULL,//菜单句柄
hInstance,//应用程序句柄
NULL); //一般都为NULL
第一个参数是创建该窗口所使用的窗口类的名称,注意这个名称应与前面所注册的窗口类的名称一致。
第三个参数为创建的窗口的风格,下表列出了常用的窗口风格:
风格
含义
WS_OVERLAPPEDWINDOW
创建一个层叠式窗口,有边框、标题栏、系统菜单、最大最小化按钮,是以下几种风格的集合:WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX
WS_POPUPWINDOW
创建一个弹出式窗口,是以下几种风格的集合: WS_BORDER, WS_POPUP, WS_SYSMENU。必须再加上WS_CAPTION与才能使窗口菜单可见。
WS_OVERLAPPED & WS_TILED
创建一个层叠式窗口,它有标题栏和边框。
WS_POPUP
该窗口为弹出式窗口,不能与WS_CHILD同时使用。
WS_BORDER
窗口有单线边框。
WS_CAPTION
窗口有标题栏。
WS_CHILD
该窗口为子窗口,不能与WS_POPUP同时使用。
WS_DISABLED
该窗口为无效,即对用户操作不产生任何反应。
WS_HSCROLL / WS_VSCROLL
窗口有水平滚动条 / 垂直滚动条。
WS_MAXIMIZE / WS_MINIMIZE
窗口初始化为最大化 / 最小化。
WS_MAXIMIZEBOX / WS_MINIMIZEBOX
窗口有最大化按钮 / 最小化按钮
WS_SIZEBOX & WS_THICKFRAME
边框可进行大小控制的窗口
WS_SYSMENU
创建一个有系统菜单的窗口,必须与WS_CAPTION风格同时使用
WS_TILED
创建一个层叠式窗口,有标题栏
WS_VISIBLE
窗口为可见
如果窗口创建成功,CreateWindow( )返回新窗口的句柄,否则返回NULL。
4.显示和更新窗口
窗口创建后,并不会在屏幕上显示出来,要真正把窗口显示在屏幕上,还得使用ShowWindow( )函数,其原型如下:
BOOL ShowWindow( HWND hWnd, int nCmdShow );
参数hWnd就是要显示的窗口的句柄。
nCmdShow是窗口的显示方式,一般给它WinMain()函数得到的nCmdShow的值就可以了。常用的窗口显示方式有:
方式
含义
SW_HIDE
隐藏窗口
SW_MINIMIZE
最小化窗口
SW_RESTORE
恢复并激活窗口
SW_SHOW
显示并激活窗口
SW_SHOWMAXIMIZED
最大化并激活窗口
SW_SHOWMINIMIZED
最小化并激活窗口
ShowWindow( )函数的执行优先级不高,当系统正忙着执行其它的任务时窗口不会立即显示出来。所以我们使用ShowWindow( )函数后还要再调用UpdateWindow(HWND hWnd); 函数以保证立即显示窗口。
5.消息循环
在WinMain()函数中,调用InitWindow( )函数成功地创建了应用程序主窗口之后,就要启动消息循环,其代码如下:
for(;;)
{
if(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
{
if ( msg.message==WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Windows应用程序可以接收各种形式的信息,这包括键盘和鼠标的动作、记时器消息,其它应用程序发来的消息等等。Windows系统会自动将这些消息放入应用程序的消息队列中。
PeekMessage( )函数就是用来从应用程序的消息队列中按照先进先出的原则将这些消息一个个的取出来,放进一个MSG结构中去。如果队列中没有任何消息,PeekMessage()函数将立即返回。如果队列中有消息,它将取出一个后返回。
MSG结构包含了一条Windows消息的完整信息,它由下面的几部分组成:
HWND hwnd; //接收消息的窗口句柄
UINT message; //主消息值
WPARAM wParam; //副消息值1,其具体含义依赖于主消息值
LPARAM lParam; //副消息值2,其具体含义依赖于主消息值
DWORD time; //消息被投递到消息队列的时间
POINT pt; //鼠标的位置
该结构中的主消息表明了消息的类型,例如是键盘消息还是鼠标消息等。副消息的含义则依赖于主消息值,比如说如果主消息是键盘消息,那么wParam中存储了是键盘的哪个具体键;如果主消息是鼠标消息,那么LOWORD(lParam)和HIWORD(lParam)分别为鼠标位置的x和y坐标;如果主消息是WM_ACTIVATE,wParam就表示了程序是否处于激活状态。这里顺便说一下,定义一个POINT类型的变量curpos后,在程序的任意位置使用GetCursorPos(&curpos)都可以将鼠标坐标存储在curpos的成员x和y中。
PeekMessage( )函数的原型如下:
BOOL PeekMessage (
LPMSG lpMsg, //指向一个MSG结构的指针,用来保存消息
HWND hWnd, //指定哪个窗口的消息将被获取
UINT wMsgFilterMin, //指定获取的主消息值的最小值
UINT wMsgFilterMax, //指定获取的主消息值的最大值
UINTwRemoveMsg //得到消息后是否移除消息
);
PeekMessage( )的第一个参数的意义上面已解释。
第二个参数是用来指定从哪个窗口的消息队列中获取消息,其它窗口的消息将被过滤掉。如果该参数为NULL,则PeekMessage( )从该应用程序所有窗口的消息队列中获取消息。
第三个和第四个参数是用来过滤MSG结构中主消息值的,主消息值在wMsgFilterMin和wMsgFilterMax之外的消息将被过滤掉。如果这两个参数均为0,表示接收所有消息。
第五个参数用来设置分发完消息后是否将消息从队列中移除,一般设为PM_REMOVE即移除。
TranslateMessage( )函数的作用是把虚拟键消息转换到字符消息,以满足键盘输入的需要。DispatchMessage( )函数所完成的工作是把当前的消息发送到对应的窗口过程中去。
开启消息循环其实很简单,几乎所有的程序都是按照这个方法。我们完全不必去深究这些函数的作用,只是照抄即可。
另外,这里介绍的消息循环开启方法比用GetMessage( )的方法要好一些,因为GetMessage()如果得不到消息会一直等待,结果就耗费了许多宝贵的时间,使程序不能及时刷新。
- windows编程——窗口与消息1
- windows编程——窗口与消息2
- 初学Windows编程笔记1——窗口和消息
- 初学Windows编程笔记1——窗口和消息
- windows编程(窗口与消息)
- windows编程(二)——第一个窗口程序与消息机制
- windows窗口与消息
- Windows 窗口与消息
- Windows学习笔记4——窗口与消息<二>
- Windows学习笔记5——窗口与消息<三>
- Windows学习笔记6——窗口与消息<四>
- Windows核心编程笔记(二十) 窗口与消息
- windows编程学习笔记(1)创建窗口与消息循环
- windows程序设计--窗口与消息
- programming windows-----窗口与消息
- Windows程序设计--窗口与消息
- 2013.8.3 学习笔记《windows核心编程》(七) 窗口类,窗口显示更新与消息
- 窗口消息——Windows核心编程学习手札之二十六
- Oracle 学习笔记1
- Android各种访问权限Permission详解
- 黑马程序员—JAVA基础
- C#
- linux-xen-virbr0消失了?网上只有抄写怎么卸载virbr0的网卡,没人写怎么恢复的,我来补一个完整的
- windows编程——窗口与消息1
- Interleaving String
- 新装的系统上不了无线怎么办
- 黑马程序员_高新技术类加载器
- maven坐标
- iOS通讯录
- BFS求解迷宫问题初探(java版)
- HiGig/HiGig+/HiGig2简介
- Oracle存储过程详解(引用)+补充