二)创建窗口
注册窗口类后,就可以创建窗口了,本程序中创建窗口的有关语句如下:
hwnd = CreateWindow (szAppName, // window class
name
TEXT ("欢迎你的到来!"), // 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
参数1:登记的窗口类名,这个类名刚才咱们在注册窗口时已经定义过了。
参数2:用来表明窗口的标题。
参数3: 用来表明窗口的风格,如有无最大化,最小化按纽啊什么的。
参数4,5: 用来表明程序运行后窗口在屏幕中的坐标值。
参数6,7: 用来表明窗口初始化时(即程序初运行时)窗口的大小,即长度与宽度。
参数8: 在创建窗口时可以指定其父窗口,这里没有父窗口则参数值为0。
参数9: 用以指明窗口的菜单,菜单以后会讲,这里暂时为0。
最后一个参数是附加数据,一般都是0。
CreateWindow()的返回值是已经创建的窗口的句柄,应用程序使用这个句柄来引用
该窗口。如果返回值为0,就应该终止该程序,因为可能某个地方出错了。如果一
个程序创建了多个窗口,则每个窗口都有各自不同的句柄.
(三)显示和更新窗口
API函数CreateWindow创建完窗口后,要想把它显示出现,还必须调用另一个
API函数ShowWindows.形式为:
ShowWindow (hwnd, iCmdShow);
其第一个参数是窗口句柄,告诉ShowWindow()显示哪一个窗口,而第二个参数则告
诉它如何显示这个窗口:最小化(SW_MINIMIZE),普通(SW_SHOWNORMAL),还是最大
化(SW_SHOWMAXIMIZED)。WinMain在创建完窗口后就调用ShowWindow函数,并把
iCmdShow参数传送给这个窗口。你可把iCmdShow改变为这些参数试试。
WinMain()调用完ShowWindow后,还需要调用函数UpdateWindow,最终把窗口显示
了出来。调用函数UpdateWindow将产生一个WM_PAINT消息,这个消息将使窗口重画
,即使窗口得到更新.
(四)创建消息循环
主窗口显示出来了,WinMain就开始处理消息了,怎么做的呢?
Windows为每个正在运行的应用程序都保持一个消息队列。当你按下鼠标或者键盘
时,Windows并不是把这个输入事件直接送给应用程序,而是将输入的事件先翻译
成一个消息,然后把这个消息放入到这个应用程序的消息队列中去。应用程序又是
怎么来接收这个消息呢?这就讲讲消息循环了。
应用程序的WinMain函数通过执行一段代码从她的队列中来检索Windows送往她的消
息。然后WinMain就把这些消息分配给相应的窗口函数以便处理它们,这段代码是
一段循环代码,故称为"消息循环"。这段循环代码是什么呢?好,往下看:
在咱们的第二只小板凳中,这段代码就是:
......
MSG msg; //定义消息名
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ; //翻译消息
DispatchMessage (&msg) ; //撤去消息
}
return msg.wParam ;
MSG结构在头文件中定义如下:
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG;
MSG数据成员意义如下:
参数1:hwnd是消息要发送到的那个窗口的句柄,这个窗口就是咱们用
CreateWindows函数创建的那一个。如果是在一个有多个窗口的应用程序中,用这
个参数就可决定让哪个窗口接收消息。
参数2:message是一个数字,它唯一标识了一种消息类型。每种消息类型都在
Windows文件中定义了,这些常量都以WM_开始后面带一些描述了消息特性的名称。
比如说当应用程序退出时,Windows就向应用程序发送一条WM_QUIT消息。
参数3:一个32位的消息参数,这个值的确切意义取决于消息本身。
参数4:同上。
参数5:消息放入消息队列中的时间,在这个域中写入的并不是日期,而是从
Windows启动后所测量的时间值。Windows用这个域来使用消息保持正确的顺序。
参数6:消息放入消息队列时的鼠标坐标.
消息循环以GetMessage调用开始,它从消息队列中取出一个消息:
GetMessage(&msg,NULL,0,0),第一个参数是要接收消息的MSG结构的地址,第二个
参数表示窗口句柄,NULL则表示要获取该应用程序创建的所有窗口的消息;第三,
四参数指定消息范围。后面三个参数被设置为默认值,这就是说你打算接收发送到
属于这个应用程序的任何一个窗口的所有消息。在接收到除WM_QUIT之外的任何一
个消息后,GetMessage()都返回TRUE。如果GetMessage收到一个WM_QUIT消息,则
返回FALSE,如收到其他消息,则返回TRUE。因此,在接收到WM_QUIT之前,带有
GetMessage()的消息循环可以一直循环下去。只有当收到的消息是WM_QUIT时,
GetMessage才返回FALSE,结束消息循环,从而终止应用程序。 均为NULL时就表示
获取所有消息。
消息用GetMessage读入后(注意这个消息可不是WM_QUIT消息),它首先要经过函数
TranslateMessage()进行翻译,这个函数会转换成一些键盘消息,它检索匹配的
WM_KEYDOWN和WM_KEYUP消息,并为窗口产生相应的ASCII字符消息(WM_CHAR),它包
含指定键的ANSI字符.但对大多数消息来说它并不起什么作用,所以现在没有必要
考虑它。
下一个函数调用DispatchMessage()要求Windows将消息传送给在MSG结构中为窗口
所指定的窗口过程。我们在讲到登记窗口类时曾提到过,登记窗口类时,我们曾指
定Windows把函数WindosProc作为咱们这个窗口的窗口过程(就是指处理这个消息的
东东)。就是说,Windows会调用函数WindowsProc()来处理这个消息。在
WindowProc()处理完消息后,代码又循环到开始去接收另一个消息,这样就完成了
一个消息循环。
下一个出场的东东就是窗口过程了,先歇一会儿再说吧?