windows程序设计第三章-Windows和消息

A Windows of One's Own

很简单,CreateWindow即可。等等,该函数的第一个参数怎么是window class name,这个窗口类又要有一个什么window procedure?

Architectural概论

    windows(窗口)是个object(对象)。 child windows(control windows):push buttons,radio buttons,check boxes.....

如何理解message呢,我们已经习惯调用操作系统的函数,但操作系统也可以调用应用程序的函数。当windows响应某一事件时,会通过调用相应的procedure代码,把message发送给程序。procedure代码要么是程序的一个函数,要么位于dll中。procedure根据消息完成一些操作,并将控制权交还给windows.

     窗口是基于窗口类创建的。后者规定了处理消息的窗口过程,可实例化多个窗口。 当windows程序运行时,Windows创建消息队列。有些消息存于队列,以待在windows的message loop中被抓取并dispatch,也有一些消息会直接送入窗口过程,而不进入消息队列。

HELLOWIN程序

#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))
	{
		MessageBox(NULL,TEXT("fail!"),szAppName,MB_ICONERROR);
		return 0;
	}

	hwnd = CreateWindow(szAppName,
						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;

//	return 0;
}
//WParam是int,LPARAM是long
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;

	switch(message)
	{
	case WM_CREATE:
		PlaySound(TEXT("D:\\Windows XP 启动.wav"),NULL,SND_FILENAME | SND_ASYNC);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd,&ps);
		GetClientRect(hwnd,&rect);
		DrawText(hdc,TEXT("Hello,高峰"),-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);
}

程序截图如下

image

客户区是指程序可draw的区域,通常位于边框和标题栏之间。

Thinking Globally

上面的windows基本框架以后可照搬。

 

windows函数调用

上面的程序包含了18个win函数调用,不解释先。

 

大写的标识符

其实都是些常数,其前缀有一定的意义,它们的定义都在头文件中可以查看。

 

新的数据类型

主要是MSG,WINDCLASS,PAINTSTRUCT和RECT

 

获得各种Handle

HINSTANCE, HWND, HDC(设备上下文的句柄),所谓句柄,就是一个和某一个对象联系起来的32位数字。依靠句柄,可在windows函数之间访问对象。

匈牙利命名法

变量名同时表征变量类型和变量意义。

Registering 窗口类

最重要的两个域为第二个lpfnWndProc和最后一个,前者指定窗口过程函数,后者指定窗口类名。

创建窗口

使用CreateWindow函数,返回hwnd(HWND类型,窗口句柄)

显示窗口

创建窗口后,窗口的信息位于内存,还没有显示在video display上。需调用ShowWindow将窗口在屏幕上显示。如ShowWindow的第二个参数为SW_SHOWNORMAL,则窗口的客户区将被擦拭。而调用UpdateWindow可导致客户区重绘(发送了WM_PAINT消息)。

消息循环

GetMessage函数抓取消息,除了抓取WM_QUIT消息会返回0终止循环之外,其他消息都返回非零数。

TranslateMessage(&msg);将做一些键盘消息转换(详情见第六章)。DispatchMessage(&msg);将消息返回给windows,windows再将其发送给适当的窗口过程进行处理。这意味着是windows调用了窗口过程函数WndProc,当WndProc处理完后,将控制权交还给windows,即回到DispatchMessage调用后,接着继续消息循环。

窗口过程

每个窗口过程函数都对应于一个窗口类。窗口过程一般由windows调用,但程序中也可通过SendMessage间接调用程序中的窗口过程。

处理消息

在switch中没处理的消息,应调用DefWindowProc。

播放声音文件

WM_CREATE是在CreateWindow函数中被直接作为消息参数,调用了窗口过程。使用PlaySound时,异步播放,这样当声音响起后,即返回到调用方,以继续下面的初始化。

WM_PAINT消息

      当客户区invalid必须要update时,将发送此消息。

      client区何时会invalid呢?当窗口初创时,整个client区都是invalid的,当调用UpdateWindow时,第一个WM_PAINT消息就这样产生了。当resize时,整个client区也会invalid,此时窗口过程也会收到WM_PAINT.当最小化后再次还原时,也会发送WM_PAINT。

     当窗口间互相重叠时,重叠部分被移开时,该部分invalid,也会发送WM_PAINT,但只重绘invalid部分。

     在BeginPaint中,如果client区背景还未擦掉,windows擦掉其背景。BeginPaint将使整个client区validated,它将返回一个device context的句柄,用以绘图。EndPaint用以释放DC句柄。

    GetClientRect中,left,top都是0,right,bottom反映客户区的长宽。

WM_DESTROY消息

用户点关闭按钮或点击系统菜单中的关闭命令时发送该消息。如果不在窗口过程中处理该消息,窗口是会被关掉,但程序没法终结。

windows编程的麻烦

几乎所有windows程序都在窗口过程中对消息做出响应,这是windows编程的大部分工作。在winMain中,不过就是窗口类注册,创建窗口,从消息队列取出并发送消息等事。

Don’t call me ,i’ll call you

在windows程序中,windows总是会调用你的程序,特别是窗口过程。

Queued and Nonqueued Messages

queued messages:放入消息队列。nonqueued消息,直接是windows调用某些函数的结果,并提供参数给WndProc的调用。

Get In and Out Fast

若处理某个消息耗时很长,20章有解决办法。

posted on 2010-05-09 05:51  speedmancs  阅读(444)  评论(0编辑  收藏  举报

导航