windows程序设计 例题解析 OWNDRAW.C

/*---------------------------------------------
   OWNDRAW.C -- Owner-Draw Button Demo Program
                (c) Charles Petzold, 1998
  ---------------------------------------------*/

#include <windows.h>

#define ID_SMALLER      1  //子控件1,缩小窗口
#define ID_LARGER       2  //子控件2,放大窗口功能

#define BTN_WIDTH        (8 * cxChar)
#define BTN_HEIGHT       (4 * cyChar)

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

HINSTANCE hInst ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("OwnDraw") ;
     MSG          msg ;
     HWND         hwnd ;
     WNDCLASS     wndclass ;
    
     hInst = hInstance ;
    
     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  = szAppName ;
     wndclass.lpszClassName = szAppName ;
    
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
    
     hwnd = CreateWindow (szAppName, TEXT ("Owner-Draw Button Demo"),
                          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 Triangle (HDC hdc, POINT pt[])
{
     SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ;
     Polygon (hdc, pt, 3) ;
     SelectObject (hdc, GetStockObject (WHITE_BRUSH)) ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static HWND      hwndSmaller, hwndLarger ;
     static int       cxClient, cyClient, cxChar, cyChar ;
     int              cx, cy ;
     LPDRAWITEMSTRUCT pdis ;
     POINT            pt[3] ;
     RECT             rc ;
    
     switch (message)
     {
     case WM_CREATE :

//主窗口客户区的大小
          cxChar = LOWORD (GetDialogBaseUnits ()) ;
          cyChar = HIWORD (GetDialogBaseUnits ()) ;
         
               // 创建两个子窗口控件 ,这个子窗口过程会受到两个wm_create消息,没们不需要写出这个子窗口过程,系统会自动处理 

               //BS_OWNERDRAW样式要再wm_create,wm_size,wm_drawitem后子窗口才会出现,即使指定了WS_VISIBLE样式
          hwndSmaller = CreateWindow (TEXT ("button"), TEXT (""),
                                      WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
                                      0, 0, BTN_WIDTH, BTN_HEIGHT,
                                      hwnd, (HMENU) ID_SMALLER, hInst, NULL) ;
         
          hwndLarger  = CreateWindow (TEXT ("button"), TEXT (""),
                                      WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
                                      0, 0, BTN_WIDTH, BTN_HEIGHT,
                                      hwnd, (HMENU) ID_LARGER, hInst, NULL) ;
          return 0 ;
         
     case WM_SIZE :
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;
         
               //移动两个按钮到指定的位置          
          MoveWindow (hwndSmaller, cxClient / 2 - 3 * BTN_WIDTH  / 2,
                                   cyClient / 2 -     BTN_HEIGHT / 2,
                      BTN_WIDTH, BTN_HEIGHT, TRUE) ;
         
          MoveWindow (hwndLarger,  cxClient / 2 +     BTN_WIDTH  / 2,
                                   cyClient / 2 -     BTN_HEIGHT / 2,
                      BTN_WIDTH, BTN_HEIGHT, TRUE) ;
          return 0 ;
         
     case WM_COMMAND ://当有子控件被按下,产生这个消息

//获取主窗口的大小
          GetWindowRect (hwnd, &rc) ;
         
               // Make the window 10% smaller or larger
         
          switch (wParam)
          {
          case ID_SMALLER : //缩小按钮被按下,主窗口缩小10%
               rc.left   += cxClient / 20 ;
               rc.right  -= cxClient / 20 ;
               rc.top    += cyClient / 20 ;
               rc.bottom -= cyClient / 20 ;
               break ;
              
          case ID_LARGER ://放到按钮被按下,主窗口放到10%

               rc.left   -= cxClient / 20 ;
               rc.right  += cxClient / 20 ;
               rc.top    -= cyClient / 20 ;
               rc.bottom += cyClient / 20 ;
               break ;
          }
         
          MoveWindow (hwnd, rc.left, rc.top, rc.right  - rc.left,
                            rc.bottom - rc.top, TRUE) ;//主窗口改变了,会产生wm_size消息,使得子控件重新定位到相对屏幕的位置
          return 0 ;
         
     case WM_DRAWITEM : //子控件改变时
          pdis = (LPDRAWITEMSTRUCT) lParam ;//指向drawitemstruct结构体的指针,保存着按钮大小,控件id等信息
          
               // 填充矩形          
          FillRect (pdis->hDC, &pdis->rcItem,
                    (HBRUSH) GetStockObject (WHITE_BRUSH)) ;
          //填充边框
          FrameRect (pdis->hDC, &pdis->rcItem,
                     (HBRUSH) GetStockObject (BLACK_BRUSH)) ;
         
               // Draw inward and outward black triangles
         
          cx = pdis->rcItem.right  - pdis->rcItem.left ;
          cy = pdis->rcItem.bottom - pdis->rcItem.top  ;
         
          switch (pdis->CtlID)
          {
          case ID_SMALLER : //若为缩小按钮

//确定三角形三个点的位置
               pt[0].x = 3 * cx / 8 ;  pt[0].y = 1 * cy / 8 ;
               pt[1].x = 5 * cx / 8 ;  pt[1].y = 1 * cy / 8 ;
               pt[2].x = 4 * cx / 8 ;  pt[2].y = 3 * cy / 8 ;
  //画三角形
               Triangle (pdis->hDC, pt) ;
              
               pt[0].x = 7 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;
               pt[1].x = 7 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;
               pt[2].x = 5 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;
              
               Triangle (pdis->hDC, pt) ;
              
               pt[0].x = 5 * cx / 8 ;  pt[0].y = 7 * cy / 8 ;
               pt[1].x = 3 * cx / 8 ;  pt[1].y = 7 * cy / 8 ;
               pt[2].x = 4 * cx / 8 ;  pt[2].y = 5 * cy / 8 ;
              
               Triangle (pdis->hDC, pt) ;
              
               pt[0].x = 1 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;
               pt[1].x = 1 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;
               pt[2].x = 3 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;
              
               Triangle (pdis->hDC, pt) ;
               break ;
              
          case ID_LARGER : //若为放到按钮
               pt[0].x = 5 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;
               pt[1].x = 3 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;
               pt[2].x = 4 * cx / 8 ;  pt[2].y = 1 * cy / 8 ;
              
               Triangle (pdis->hDC, pt) ;
              
               pt[0].x = 5 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;
               pt[1].x = 5 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;
               pt[2].x = 7 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;
              
               Triangle (pdis->hDC, pt) ;
              
               pt[0].x = 3 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;
               pt[1].x = 5 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;
               pt[2].x = 4 * cx / 8 ;  pt[2].y = 7 * cy / 8 ;
              
               Triangle (pdis->hDC, pt) ;
              
               pt[0].x = 3 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;
               pt[1].x = 3 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;
               pt[2].x = 1 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;
              
               Triangle (pdis->hDC, pt) ;
               break ;
          }
         
               // Invert the rectangle if the button is selected
         
          if (pdis->itemState & ODS_SELECTED)  //按钮时被选中
               InvertRect (pdis->hDC, &pdis->rcItem) ; //选中后颜色反转
         
               // Draw a focus rectangle if the button has the focus
         
          if (pdis->itemState & ODS_FOCUS) //按钮有焦点后,画一个矩形           {                pdis->rcItem.left   += cx / 16 ;                pdis->rcItem.top    += cy / 16 ;                pdis->rcItem.right  -= cx / 16 ;                pdis->rcItem.bottom -= cy / 16 ;                               DrawFocusRect (pdis->hDC, &pdis->rcItem) ;           }           return 0 ;                case WM_DESTROY :           PostQuitMessage (0) ;           return 0 ;      }      return DefWindowProc (hwnd, message, wParam, lParam) ; }

相关文章
相关标签/搜索