tianzhiya 发表于 2015-12-29 15:40:21

关于《windows程序设计》的原书代码About2中的疑问

本帖最后由 tianzhiya 于 2015-12-29 15:41 编辑


/*------------------------------------------
   ABOUT2.C -- About Box Demo Program No. 2
               (c) Charles Petzold, 1998
------------------------------------------*/

#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_HREDRAW | CS_VREDRAW ;
   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.lpszMenuName= szAppName ;
   wndclass.lpszClassName = 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 = { 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) ;
   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) ;
}

void PaintTheBlock (HWND hCtrl, int iColor, int iFigure)
{
   InvalidateRect (hCtrl, NULL, TRUE) ;
   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:
               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 intiColor, 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)) ;
          return FALSE ;
         
   case WM_COMMAND:
          switch (LOWORD (wParam))
          {
          case IDOK:
               iCurrentColor= iColor ;
               iCurrentFigure = iFigure ;
               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函数中有InvalidateRect和UpdateWindow函数,原本按理来说,不加UpdateWindow只是不会马上更新,但是去掉UpdateWindow函数后会导致一直不会画对话框的图像控件
注意这是在对话框的图像控件,而不是在客户区绘画。
rc文件和resource.h已上传
希望能得到大家的解答

santaclaus 发表于 2016-3-23 22:16:10

本帖最后由 santaclaus 于 2016-3-23 22:35 编辑

void PaintTheBlock (HWND hCtrl, int iColor, int iFigure)
{
   InvalidateRect (hCtrl, NULL, TRUE) ; //这句的意思是,在绘制新图像之前,先把hCtrl上旧的内容清除掉。
   
   //UpdateWindow的意思是,上述的操作要立即执行。然后再去执行PaintWindow,画出新的内容。
   //这个顺序是很好理解的,因为要绘制新内容前,得先清除旧的内容。
   //如果不UpdateWindow的话。系统会在hCtrl的消息队列中放入一条WM_PAINT消息。但这条消息不会被马上执行。
   //换句话讲,程序执行InvalidateRect后,会直接执行PaintWindow,此时此刻,新的内容确实在hCtrl上画出了。
   //但问题也来了,当本函数执行完后,因消息队列中,还有一条的WM_PAINT消息,所以程序会转去执行该消息。
   //这就意味着,对于hCtrl来说,那个“清除”操作延迟到现在才执行,所以就会把新的内容给“清除”掉。结果表现出来,好象这个函数就只擦除以前的内容,然后什么事都没干。
   UpdateWindow (hCtrl) ;
   PaintWindow (hCtrl, iColor, iFigure) ;
}

atmo 发表于 2015-12-29 16:02:10

学习学习了

wanli6599 发表于 2016-3-23 11:23:15

完全不明白你想表达什么
页: [1]
查看完整版本: 关于《windows程序设计》的原书代码About2中的疑问