《Windows程序设计》之对话框

/////////////////////////////////////////////////////////////////////////
//《Windows程序设计》第11章对话框代码ABOUT2
/////////////////////////////////////////////////////////////////////////

#include <Windows.h>
#include "RESOURCE.H"

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
BOOL CALLBACK AboutDlgProc(HWND,UINT,WPARAM,LPARAM);

int iCurrentColor=IDC_BLACK,iCurrentFigure=IDC_RECT;

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
	static TCHAR szAppName[]=TEXT("About2");
	MSG msg;
	HWND hwnd;
	WNDCLASS wndclass;

	wndclass.style=CS_VREDRAW|CS_HREDRAW;
	wndclass.lpfnWndProc=WndProc;
	wndclass.cbClsExtra=0;
	wndclass.cbWndExtra=0;
	wndclass.hInstance=hInstance;
	wndclass.hIcon=LoadIcon(hInstance,szAppName);
	wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
	wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszClassName=szAppName;
	wndclass.lpszMenuName=szAppName;

	if(!RegisterClass(&wndclass))
	{
		MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR);
		return 0;
	}
	hwnd=CreateWindow(szAppName,TEXT("About Box Demo 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;
}

void PaintWindow(HWND hwnd,int iColor,int iFigure)
{
	static COLORREF crColor[8]={RGB(0,0,0),RGB(0,0,255),RGB(0,255,0),RGB(0,255,255),RGB(255,0,0),RGB(255,0,255),RGB(255,255,0),RGB(255,255,255)};
	HBRUSH hBrush;
	HDC hdc;
	RECT rect;

	hdc=GetDC(hwnd);
	GetClientRect(hwnd,&rect);
	hBrush=CreateSolidBrush(crColor[iColor-IDC_BLACK]);
	hBrush=(HBRUSH)SelectObject(hdc,hBrush);
	if(iFigure==IDC_RECT)
		Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);
	else
		Ellipse(hdc,rect.left,rect.top,rect.right,rect.bottom);
	DeleteObject(SelectObject(hdc,hBrush));
	ReleaseDC(hwnd,hdc);
}

//对下面这个函数不理解,常规想法应该是PaintWindow后再UpdateWindow,但事实这样不可以,系统会卡住
void PaintTheBlock(HWND hCtrl,int iColor,int iFigure)
{
	//使子窗口控件无效
	InvalidateRect(hCtrl,NULL,TRUE);
	//如果窗口更新的区域不为空,UpdateWindow函数通过发送一个WM_PAINT消息来更新指定窗口的客户区。
	//函数绕过应用程序的消息队列,直接发送WM_PAINT消息给指定窗口的窗口过程,如果更新区域为空,则不发送消息。
	//对此UpdateWindow还不是不懂
	UpdateWindow(hCtrl);
	PaintWindow(hCtrl,iColor,iFigure);
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	static HINSTANCE hInstance;
	PAINTSTRUCT ps;
	switch(message)
	{
	case WM_CREATE:
		//获取句柄,在下面要使用
		hInstance=((LPCREATESTRUCT)lParam)->hInstance;
		return 0;
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case IDM_APP_ABOUT:
			//根据对话框模板资源创建一个模态的对话框
			//这边是回调完成后才触发的
			//直到指定的回调函数通过调用EndDialog函数中止模态的对话框才能返回控制。
			//调用失败,返回-1
			//调用成功,返回EndDialog中的参数
			if(DialogBox(hInstance,TEXT("AboutBox"),hwnd,AboutDlgProc))
				//刷新窗口
				InvalidateRect(hwnd,NULL,TRUE);
			return 0;
		}
		break;
	case WM_PAINT:
		//这两行代码不清楚是怎么回事,但是去掉后,程序不能执行
                //使先前的无效区域有效
                BeginPaint(hwnd,&ps);
		EndPaint(hwnd,&ps);
		//画矩形或者是圆
		PaintWindow(hwnd,iCurrentColor,iCurrentFigure);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd,message,wParam,lParam);
}

BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
	static HWND hCtrlBlock;
	static int iColor,iFigure;
	switch(message)
	{
	//初始化
	case WM_INITDIALOG:
		iColor=iCurrentColor;
		iFigure=iCurrentFigure;
		//每组中指定选定一个,句柄,开始,结束,选中项
		CheckRadioButton(hDlg,IDC_BLACK,IDC_WHITE,iColor);
		CheckRadioButton(hDlg,IDC_RECT,IDC_ELLIPSE,iFigure);
		//获取设置面板中展示区控件的句柄
		hCtrlBlock=GetDlgItem(hDlg,IDC_PAINT);
		//设置焦点
		SetFocus(GetDlgItem(hDlg,iColor));
		//这个返回TRUE跟FALSE,好像对结果没啥影响,不知其原因
		return FALSE;
	case WM_COMMAND:
		//LOWORD(wParam)是指明哪个控件
		switch(LOWORD(wParam))
		{
		case IDOK:
			iCurrentColor=iColor;
			iCurrentFigure=iFigure;
			//这个返回关系着DialogBox的返回
			EndDialog(hDlg,TRUE);
			return TRUE;
		case IDCANCEL:
			EndDialog(hDlg,FALSE);
			return TRUE;
		case IDC_BLACK:
		case IDC_RED:
		case IDC_GREEN:
		case IDC_YELLOW:
		case IDC_BLUE:
		case IDC_MAGENTA:
		case IDC_CYAN:
		case IDC_WHITE:
			//设置颜色,用于画图
			iColor=LOWORD(wParam);
			//设置按键,用于显示
			CheckRadioButton(hDlg,IDC_BLACK,IDC_WHITE,LOWORD(wParam));
			//小窗口区的时时更新
			PaintTheBlock(hCtrlBlock,iColor,iFigure);
			return TRUE;
		case IDC_RECT:
		case IDC_ELLIPSE:
			iFigure=LOWORD(wParam);
			CheckRadioButton(hDlg,IDC_RECT,IDC_ELLIPSE,LOWORD(wParam));
			PaintTheBlock(hCtrlBlock,iColor,iFigure);
			return TRUE;
		}
		break;
	case WM_PAINT:
		PaintTheBlock(hCtrlBlock,iColor,iFigure);
		break;
	}
	return FALSE;
}
/////////////////////////////////////////////////////////////////////////
//在一开始生成子窗口时,调用过程如下:
//PaintTheBlock----------->UpdateWindow-------->PaintWindow
//在切换颜色与形状时,调用过程如下:
//UpdateWindow--------->PaintWindow
//UpdateWindow到底做了什么?不是说会调用WM_PAINT么,但是我设置断点却没有
/////////////////////////////////////////////////////////////////////////

看了几个帖子,好像大体理解了这个问题。

1、PaintTheBlock中传入的第一个参数并不是子窗口的,而是子窗口中一个Text控件的(用来画图的)。

2、调用InvalidateRect是来设置这个子窗口控件的区域无效

3、调用UpdateWindow是用来触发WM_PAINT,这个WM_PAINT是这个子窗口控件的WM_PAINT,而不是子窗口的。

4、上面两句代码的意思应该就是想清除这个文本控件的特征吧,然后直接来画图。

不知道这么理解对不对,还希望各位多多提意见

你可能感兴趣的:(windows,command,null,callback,winapi)