Windows program design读书笔记第2章

首先,放上一个程序:
#include <windows.h>
LRESULT CALLBACK Wndproc (HWND, UNIT, 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.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))							//put the pointer which points to wndclass into RegisterClass
{
	MessageBox (NULL, TEXT("This program requires Windows NT!"), szAppname, MB_ICONERROR);
	return 0;
}

hwnd = CreatWindow( szAppName,							//set the exact feature of windows chuangkou, and send it to hwnd
					TEXT("The Hello Program"),
					WS_OVERLAPPEDWINDOW,
					CW_USEDEFAULT,
					CW_USEDEFAULT,
					CW_USEDEFAULT,
					CW_USEDEFAULT,
					NULL,
					NULL,
					hInstance,
					NULL);

ShowWindow (hwnd, iCmdshow);
UpdateWindow (hwnd);

while (GetMessage (&msg, NULL, 0, 0))
{
	TranslateMessage (&msg);
	DispatchMessage (&msg);
}
return msg.wParam;

LRESULT CALLBACK WndProc (HWND hwnd, UNIT message, WPARAM wparam, LPARAM lParam)
{
HDC				hdc;
PAINTSTRUCT		ps;
RECT			rect;

switch (message)
{
case WMCREATE:
	playground (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
	return 0;

case MWM_PAINT:
	hdc = BeginPaint (hwnd, &ps);

	GetClientRect (hwnd, &rect);

	DrawText (hdc, TEXT ("Hello, window98!"), -1, &rect, DT_SINGLELINE | DT_CENTER |DT_VCENTER);
	EndPaint (hwnd, &ps);
	return 0;

case MWM_DESTROY:
	PostQuitMessage (0);
	return 0;
}
return DefWindowproc (hwnd, message, wParam, lParam);
}

其中,WINDCLASS的参数

  1. wndclass.style = CS_HREDRAW | CS_VREDRAW;
    移动或调整窗口高度/宽度时候,重新绘制整个窗口
  2. wndclass.cbCLlsExtra, windlass.cbWndExtra
    额外空间
  3. wndclass.hInstance
    实例句柄,将WINAPI WinMain中的第一个自动生成的参数拷贝过来即可
  4. wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  5. wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
  6. wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
  7. wndclass.lpszMenuName = NULL;
    菜单
  8. wndclass.lpszClassName = szAppName; //其值是一个事先定义的字符串
    窗口类的命名

WINDCLASS设定了基本属性,而CreatWindow来设定更个性化特征

消息机制
窗口的诞生
给winclass窗口类结构的各个成员赋值——将指向窗口类的指针用RegisterClass注册窗口类——可以使用CreateWindow来生成一个窗口实例(窗口已经在内存中存储,因此会返回一个句柄)——调用ShowWindow显示窗口——UpdateWindow更新窗口()——消息循环!!!

——————————————————————————————————————————
Windows是一个事件驱动,基于消息的操作系统。Windows强调的是事件触发,并且事件之间是无序的。
Window在接收到一些事件触发后就会将事件转化为对应的消息,将其投放在消息队列中

系统会根据消息的所有者,将系统消息进行下放各个应用程序的应用队列里。
Q:怎么知道哪个消息属于哪个窗口呢
A:以下是MSG类型结构变量msg的定义

typedef struct tagMSG {
HWND hwnd; //指定接受消息的窗口句柄,滑动鼠标后所滞留的窗口
UINT message; //用于标识信息的数字
WPARAM wParam;
LPARAM lParam;
DWORD time; //消息进入消息队列的时间
POINT pt; //POINT是另外一种结构,是用来获取鼠标具体位置,来填充窗口句柄?
#ifdef _MAC
DWORD lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

POINT的定义
typedef struct tagPOINT
{
LONG x;
LONG y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;

开启消息循环的GetMessage函数用于从消息队列中对信息进行检索:
GetMessage (&msg, NULL, 0, 0)
该调用将一个指向msg的MSG结构变量的指针传给Windows。其第二,第三和第四个参数均为NULL和0,表明该程序希望获取由该程序所创建的所有窗口的信息。

如果从消息队列中检索到的信息的message字段不等于WM_QUIT(0x0012),则GetMessage将返回一个非0值(程序退出),否则返回0。

如果不是0,则进行翻译和分配
GetMessage (&msg, NULL, 0, 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg); //将msg结构返回给Windows
}

Windows用从消息队列中获得的下一条消息来填充消息结构的各个字段!!!
接下来Windows会将这条消息发送给合适的窗口过程来处理,windows调用了窗口过程。在处理完消息后,将控制权转回给Windows,后者还将为DispatchMessage调用服务。直到接收到VM_QUIT。

消息机制Extra
消息队列是FIFO的形式
先进入的消息会先出来
VM_PAINT, VM_TIMER, WM_QUIT 属于特例。操作系统会把它们时刻放在消息队列的最后,让其他的消息先执行,如VM_PAINT如果放在前面,会一直重新绘制窗口。
消息其实会分为队列化消息和非队列化消息。非队列消息优先级高于队列化消息,会先执行非队列消息。

发布了47 篇原创文章 · 获赞 10 · 访问量 1744

猜你喜欢

转载自blog.csdn.net/Antonio_Salieri/article/details/96045883
今日推荐