程序示例:HELLOWIN程序
#include <Windows.h>
#include <MMSystem.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
#pragma comment(lib, "winmm.lib")
//入口函数
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))
{
MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR);
return 0;
}
//创建窗口
hwnd = CreateWindow(szAppName, //窗口类名
TEXT("Random Rectangles"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口风格
CW_USEDEFAULT, //初始X(左上角)位置
CW_USEDEFAULT, //初始Y(左上角)位置
CW_USEDEFAULT, //初始X(宽度)大小
CW_USEDEFAULT, //初始Y(高度)大小
NULL, //父窗口句柄
NULL, //窗口菜单句柄
hInstance, //程序实例句柄
NULL); //作为WM_CREATE消息的附加参数lParam传入的数据指针
//显示窗口
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.avi"),NULL,SND_FILENAME | SND_ASYNC);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd,&PS);
GetClientRect(hwnd,&rect);
DrawText(hdc,TEXT("Hello,Windows 98!"),-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);
}
HELLOWIN.C中有几个大写的标识符,这些标识符是在Windows表头文件中定义的。有些标识符含有两个字母或者三个字母组成并后跟一个下划线的前缀:
前缀表示该常量所属的类别:
2.句柄简介:
句柄是一个(通常为32位的)整数,它代表一个对象。Windows中的句柄类似传统C或者MS-DOS程序设计中使用的文件句柄。程序几乎总是通过呼叫Windows函数取得句柄。程序在其它Windows函数中使用这个句柄,以使用它代表的对象。代号的实际值对程序来说是无关紧要的。但是,向您的程序提供代号的Windows模块知道如何利用它来使用相对应的对象。
3.窗口创建流程:
- 注册窗口类:窗口总是在窗口类的基础上创建的,窗口类用以标识处理窗口消息的窗口过程。可以在单个窗口类的基础上创建多个窗口。窗口类还定义了基于此类创建的窗口的其他一些特征,如窗口样式、图标、光标等。
- 创建窗口:窗口类定义了窗口的一般特征,因此可以使用同一窗口类创建许多不同的窗口,实际调用CreateWindow创建窗口时,可能指定有关窗口的更详细的信息,如窗口标题名、显示位置、显示大小等。
- 显示窗口:在CreateWindow调用返回之后,Window内部已经创建了这个窗口,这就是说,Windows已经分配了一块内存,用来保存关于在CreateWindow调用中指定窗口的全部信息,然而,此时窗口并未在视频显示器上显示,该需要调用函数ShowWindow。
4.消息循环:
调用UpdataWindow之后,窗口就出现在视频显示器上。程序现在需要准备读入用户用键盘和鼠标输入的数据。Windows为当前运行的每隔Windows程序维护一个“消息队列”。在发生输入事件之后,Windows将事件转换为一个“消息”,并将消息放入程序的消息队列中。
程序通过执行一块被称为“消息循环”的代码从消息队列中取出消息:
//消息循环
while(GetMessage(&msg,NULL,0,0))//从消息队列中取出消息
{
TranslateMessage(&msg); //将虚拟键消息转换为字符消息
DispatchMessage(&msg); //分派一个消息到窗口过程,由窗口过程函数对消息进行处理(实际是传给操作系统,由操作系统调用窗口过程函数对消息进行响应)
}
程序中实际的消息响应动作发生在窗口过程函数中。窗口过程函数确定了在窗口的显示区域中显示些什么以及窗口怎样响应使用者输入。
窗口过程所接受的每个消息均是用一个数值来标识的,也就是传给窗口过程的message参数。Windows头文件WINUSER.H为每个消息参数定义以「WM」(窗口消息)为前缀开头的标识符。
一般来说,Windows程序写作者使用switch和case结构来确定窗口过程接收的是什么消息,以及如何适当地处理它。窗口过程不予处理的所有消息应该被传给名为DefWindowProc的Windows函数。
一般来说,Windows程序写作者使用switch和case结构来确定窗口过程接收的是什么消息,以及如何适当地处理它。窗口过程不予处理的所有消息应该被传给名为DefWindowProc的Windows函数。
6.别调用我,我会调用你:
窗口过程与一个窗口类相关联,窗口类是程序调用RegisterClass注册的。依基于该类创建的窗口使用这个窗口过程来处理窗口的所有消息。Windows通过调用窗口过程来给窗口发送一个消息。
7.进队消息与不进队消息:
消息能够被分为“进队的”和“不进队的”。进队的消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新返回并分配给窗口过程。不进队的消息在Windows调用窗口时直接送给窗口过程。也就是说,进队的消息发送给消息队列,而不进队的消息发送给窗口过程。在两种情况下,窗口过程都将获得窗口所有的消息,它是窗口的消息中心。
进队消息基本上是用户输入的结果,包括击键、字符、鼠标移动等。
不进队消息通常来自调用特定的Windows函数,如调用CreateWindow函数时产生的WM_CREATE消息以及调用ShowWindow时产生的WM_SIZE和WM_SHOWWINDOW消息。
需要注意的是,消息循环和窗口过程并不是并发运行的。当一个消息循环从其消息队列中接收一个消息,然后调用DispatchMessage将消息发送给窗口过程时,直到窗口过程将控制返回给Windows,DispatchMessage才能返回。