/
//《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、上面两句代码的意思应该就是想清除这个文本控件的特征吧,然后直接来画图。
不知道这么理解对不对,还希望各位多多提意见