Win32下绘图程序(一)画线、画矩形、画椭圆

1、实现效果:



2、创建一个Win32工程:



3、介绍几个绘图的函数:

绘直线用到的函数:

1
2
3
4
5
6
7
8
9
MoveToEx
The MoveToEx  function  updates the current position 
to the specified point and optionally returns the previous position.  
BOOL MoveToEx(
   HDC hdc,           // handle to device context
   int X,             // x-coordinate of new current position
   int Y,             // y-coordinate of new current position
   LPPOINT lpPoint    // old current position
);

1
2
3
4
5
6
7
8
9
LineTo
The LineTo  function  draws a line from the current position up to, 
but not including, the specified point. 
 
BOOL LineTo(
   HDC hdc,     // device context handle
   int nXEnd,   // x-coordinate of ending point
   int nYEnd    // y-coordinate of ending point
);

绘制矩形:

1
2
3
4
5
6
7
8
9
10
11
Rectangle
The Rectangle  function  draws a rectangle.
The rectangle is outlined by using the current pen and filled by using the current brush. 
 
BOOL Rectangle(
   HDC hdc,          // handle to DC
   int nLeftRect,    // x-coord of upper-left corner of rectangle
   int nTopRect,     // y-coord of upper-left corner of rectangle
   int nRightRect,   // x-coord of lower-right corner of rectangle
   int nBottomRect   // y-coord of lower-right corner of rectangle
);

绘制椭圆:

1
2
3
4
5
6
7
8
9
10
11
12
Ellipse
The Ellipse  function  draws an ellipse. 
The center of the ellipse is the center of the specified bounding rectangle. 
The ellipse is outlined by using the current pen and is filled by using the current brush. 
 
BOOL Ellipse(
   HDC hdc,         // handle to DC
   int nLeftRect,   // x-coord of upper-left corner of rectangle
   int nTopRect,    // y-coord of upper-left corner of rectangle
   int nRightRect,  // x-coord of lower-right corner of rectangle
   int nBottomRect  // y-coord of lower-right corner of rectangle
);

绘制图像需要两个点,即绘图的起始点和终止点,可以由鼠标左键按下时的坐标作为起始点,鼠标左键释放时的坐标作为终止点。那么,就要响应两个消息:WM_LBUTTONDOWN和WM_LBUTTONUP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
WM_LBUTTONDOWN Notification
--------------------------------------------------------------------------------
The WM_LBUTTONDOWN message is posted when the user 
presses the left mouse button  while  the cursor is  in  the client area of a window.
If the mouse is not captured, the message is posted to the window beneath the cursor.
Otherwise, the message is posted to the window that has captured the mouse.
 
A window receives  this  message through its WindowProc  function
 
Syntax
 
WM_LBUTTONDOWN
     WPARAM wParam
     LPARAM lParam;
     
Parameters
 
wParam
Indicates whether various virtual keys are down. 
 
lParam
The low-order word specifies the x-coordinate of the cursor. 
The coordinate is relative to the upper-left corner of the client area. 
 
The high-order word specifies the y-coordinate of the cursor.
The coordinate is relative to the upper-left corner of the client area. 

重点是最后四句,它说:

lParam的低位(low-order)是鼠标光标的x坐标(x-coordinate),

lParam的高位(high-order)是鼠标光标的y坐标(y-coordinate)。

这样就构成了一个点(POINT)。

同理:消息WM_LBUTTONUP也是如此。


另外,参数还需要一个HDC,可以通过以下函数获得:

1
2
3
4
5
6
7
8
9
10
11
GetDC
The GetDC  function  retrieves a handle to a display device context (DC) 
for  the client area of a specified window or  for  the entire screen. 
You can use the returned handle  in  subsequent GDI functions to draw  in  the DC. 
 
The GetDCEx  function  is an extension to GetDC,
  which gives an application more control over how and whether clipping occurs  in  the client area. 
 
HDC GetDC(
   HWND hWnd    // handle to window
);

注意:GetDC用完后必须用ReleaseDC释放

1
2
3
4
After painting  with  a common DC, the ReleaseDC  function  must be called to release the DC. 
Class and private DCs  do  not have to be released. 
ReleaseDC must be called from the same thread that called GetDC. 
The number of DCs is limited only by available memory. 


4、在窗口回调函数中进行相应的操作:

LRESULT  CALLBACK  WndProc( HWND  hWnd,  UINT  message,  WPARAM  wParam,  LPARAM  lParam)
{
     // 绘图类型
     enum
     {
         TYPE_LINE ,
         TYPE_RECT ,
         TYPE_ELLIPSE
     };
 
     int wmId, wmEvent;
     PAINTSTRUCT  ps;
     HDC  hdc;
     static  POINT  ptBegin;  
     static  POINT  ptEnd;
     static int nTypy =  TYPE_LINE ;
 
     switch (message)
     {
     case  WM_LBUTTONDOWN :
         ptBegin.x =  LOWORD (lParam);
         ptBegin.y =  HIWORD (lParam);
         break ;
     case  WM_LBUTTONUP :
         ptEnd.x =  LOWORD (lParam);
         ptEnd.y =  HIWORD (lParam);
        hdc = GetDC(hWnd);
         switch (nTypy)
         {
         case  TYPE_LINE :
             MoveToEx(hdc, ptBegin.x, ptBegin.y,  NULL );
             LineTo(hdc, ptEnd.x, ptEnd.y);
             break ;
         case  TYPE_RECT :
             Rectangle(hdc, ptBegin.x, ptBegin.y, ptEnd.x, ptEnd.y);
             break ;
         case  TYPE_ELLIPSE :
             Ellipse(hdc, ptBegin.x, ptBegin.y, ptEnd.x, ptEnd.y);
             break ;
         default:
             break ;
         }
        ReleaseDC(hWnd, hdc);
         break ;
     case  WM_COMMAND :
         wmId    =  LOWORD (wParam);
         wmEvent =  HIWORD (wParam);
         // 分析菜单选择:
         switch (wmId)
         {
         case  ID_TYPE_LINE :
             nTypy =  TYPE_LINE ;
             break ;
         case  ID_TYPE_RECT :
             nTypy = TYPE_RECT ;
             break ;
         case  ID_TYPE_ELLIPSE :
             nTypy =  TYPE_ELLIPSE ;
             break ;
         case  IDM_ABOUT :
             DialogBox(hInst,  MAKEINTRESOURCE ( IDD_ABOUTBOX ), hWnd, About);
             break ;
         case  IDM_EXIT :
             DestroyWindow(hWnd);
             break ;
         default:
             return  DefWindowProc(hWnd, message, wParam, lParam);
         }
         break ;
     case  WM_PAINT :
         hdc = BeginPaint(hWnd, &ps);
         //  TODO : 在此添加任意绘图代码...
 
         TextOut(hdc,  0 0 _T ( "Helllo World!" ), _tcslen( _T ( "Helllo World!" )));
 
         EndPaint(hWnd, &ps);
         break ;
     case  WM_DESTROY :
         PostQuitMessage( 0 );
         break ;
     default:
         return  DefWindowProc(hWnd, message, wParam, lParam);
     }
     return  0 ;
}

5、防止窗口刷新后绘制的图像丢失(用链表存储每次绘图的信息):

LRESULT  CALLBACK  WndProc( HWND  hWnd,  UINT  message,  WPARAM  wParam,  LPARAM  lParam)
{
     // 绘图类型
     enum
     {
         TYPE_LINE ,
         TYPE_RECT ,
         TYPE_ELLIPSE
     };
 
     typedef struct tagPaintInfo 
     {
         POINT  ptBegin;
         POINT  ptEnd;
         int nType;
         tagPaintInfo *pNext;
     }PInfo;
 
     int wmId, wmEvent;
     PAINTSTRUCT  ps;
     HDC  hdc;
     static  POINT  ptBegin;  
     static  POINT  ptEnd;
     static int nTypy =  TYPE_LINE ;
     static bool bFlag =  true ;
     static PInfo *pHead =  NULL ;
     static PInfo *pEnd =  NULL ;
     static PInfo *pNew =  NULL ;
     PInfo *pTemp =  NULL ;
 
 
     switch (message)
     {
     case  WM_LBUTTONDOWN :
         ptBegin.x =  LOWORD (lParam);
         ptBegin.y =  HIWORD (lParam);
         break ;
     case  WM_LBUTTONUP :
         ptEnd.x =  LOWORD (lParam);
         ptEnd.y =  HIWORD (lParam);
        hdc = GetDC(hWnd);
         switch (nTypy)
         {
         case  TYPE_LINE :
             MoveToEx(hdc, ptBegin.x, ptBegin.y,  NULL );
             LineTo(hdc, ptEnd.x, ptEnd.y);
             break ;
         case  TYPE_RECT :
             Rectangle(hdc, ptBegin.x, ptBegin.y, ptEnd.x, ptEnd.y);
             break ;
         case  TYPE_ELLIPSE :
             Ellipse(hdc, ptBegin.x, ptBegin.y, ptEnd.x, ptEnd.y);
             break ;
         default:
             break ;
         }
 
        if  (bFlag)
        {
             pNew = (PInfo *)malloc(sizeof(PInfo));  
             pNew->ptBegin = ptBegin;
             pNew->ptEnd = ptEnd; 
             pNew->nType = nTypy;
             pNew->pNext =  NULL ;  
 
             pHead = pNew; // 因为是第一个节点,所以新建的节点即是头结点  
             pEnd = pHead; // 因为是第一个节点,所以头结点即是尾节点 
             bFlag =  false ;
        }
         else
         {
             // 创建一个新节点  
             pNew = (PInfo *)malloc(sizeof(PInfo));  
             pNew->ptBegin = ptBegin;
             pNew->ptEnd = ptEnd;
             pNew->nType = nTypy;
             pNew->pNext =  NULL ;  
 
             pEnd->pNext = pNew; // 将创建的新节点 连接到 链表末尾  
             pEnd = pNew;        // 链表的尾节点改变(变为新节点) 
         }
         break ;
     case  WM_COMMAND :
         wmId    =  LOWORD (wParam);
         wmEvent =  HIWORD (wParam);
         // 分析菜单选择:
         switch (wmId)
         {
         case  ID_TYPE_LINE :
             nTypy =  TYPE_LINE ;
             break ;
         case  ID_TYPE_RECT :
             nTypy = TYPE_RECT ;
             break ;
         case  ID_TYPE_ELLIPSE :
             nTypy =  TYPE_ELLIPSE ;
             break ;
         case  IDM_ABOUT :
             DialogBox(hInst,  MAKEINTRESOURCE ( IDD_ABOUTBOX ), hWnd, About);
             break ;
         case  IDM_EXIT :
             DestroyWindow(hWnd);
             break ;
         default:
             return  DefWindowProc(hWnd, message, wParam, lParam);
         }
         break ;
     case  WM_PAINT :
         hdc = BeginPaint(hWnd, &ps);
         //  TODO : 在此添加任意绘图代码...
         
         TextOut(hdc,  0 0 _T ( "Helllo World!" ), _tcslen( _T ( "Helllo World!" )));
 
         pTemp = pHead;
         while  (pTemp)
         {
             ptBegin = pTemp->ptBegin;
             ptEnd = pTemp->ptEnd;
             switch (pTemp->nType)
             {
             case  TYPE_LINE :
                 MoveToEx(hdc, ptBegin.x, ptBegin.y,  NULL );
                 LineTo(hdc, ptEnd.x, ptEnd.y);
                 break ;
             case  TYPE_RECT :
                 Rectangle(hdc, ptBegin.x, ptBegin.y, ptEnd.x, ptEnd.y);
                 break ;
             case  TYPE_ELLIPSE :
                 Ellipse(hdc, ptBegin.x, ptBegin.y, ptEnd.x, ptEnd.y);
                 break ;
             default:
                 break ;
             }
             pTemp = pTemp->pNext;
         }
 
         EndPaint(hWnd, &ps);
         break ;
     case  WM_DESTROY :
         while  (pHead)  
         {  
             pTemp = pHead->pNext;  
             free(pHead);  
             pHead = pTemp;  
         }  
         PostQuitMessage( 0 );
         break ;
     default:
         return  DefWindowProc(hWnd, message, wParam, lParam);
     }
     return  0 ;
}







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值