ابتدا تابعی با نام DrawBorder را برای ترسیم یک مستطیل تعریف می کنیم.

- دقت کنید که از آن جایی که در خارج از پیام WM_PAINT در حال رسم هستیم لذا ابتدا هندل DC یا همان display device context را برای انجام کارهای گرافیکی قسمت client area باید با استفاده از GetDC دریافت کنید و در پایان ترسیم نیز با ReleaseDC آزاد کنید.

- تابع SetROP2 با فلگ R2_NOT باعث می شود مستطیل ما با رنگی معکوس زنگ زمینه در هنگام drag کردن mouse نمایش داده شود.



کد PHP:
void DrawBorder(HWND hwndPOINT ptBegPOINT ptEnd)
{
    
HDC hdc ;
    
hdc GetDC (hwnd) ;
 
    
SetROP2 (hdcR2_NOT) ;
    
SelectObject (hdcGetStockObject (NULL_BRUSH)) ;
    
Rectangle (hdcptBeg.xptBeg.yptEnd.xptEnd.y) ;
 
    
ReleaseDC (hwndhdc) ;

تابع WndProc را همانند مثال قبل برای پیام ها به شکل زیر تغییر دهید:


کد PHP:
LRESULT CALLBACK WndProc(HWND hWndUINT message,
                      
WPARAM wParamLPARAM lParam)
{
    
int          wmIdwmEvent;
    
HDC             hdc ;
    
PAINTSTRUCT  ps ;
    static 
BOOL  drawingdrawBox ;
    static 
POINT ptBegptEndptBoxBegptBoxEnd ;
 
    switch (
message)
    {
    case 
WM_LBUTTONDOWN :
        
ptBeg.ptEnd.LOWORD (lParam) ;
        
ptBeg.ptEnd.HIWORD (lParam) ;
 
        
drawing TRUE ;
        return 
;
 
    case 
WM_MOUSEMOVE :
        if (
drawing)
        {
            
SetCursor (LoadCursor (NULLIDC_CROSS)) ;
            
DrawBorder (hWndptBegptEnd) ;  // clean previous drawing
 
            
ptEnd.LOWORD (lParam) ;
            
ptEnd.HIWORD (lParam) ;
 
            
DrawBorder (hWndptBegptEnd) ;
        }
        return 
;
 
    case 
WM_LBUTTONUP :
        if (
drawing)
        {
            
DrawBorder (hWndptBegptEnd) ;
 
            
ptBoxBeg    ptBeg ;
            
ptBoxEnd.x  LOWORD (lParam) ;
            
ptBoxEnd.y  HIWORD (lParam) ;
 
            
SetCursor (LoadCursor (NULLIDC_ARROW)) ;
 
            
drawing FALSE ;
            
drawBox TRUE ;
            
InvalidateRect (hWndNULLTRUE) ;
        }
        return 
;
 
    case 
WM_PAINT :
        
hdc BeginPaint (hWnd, &ps) ;
 
        if (
drawBox)
        {
            
SelectObject (hdcGetStockObject (LTGRAY_BRUSH)) ;
            
Rectangle (hdcptBoxBeg.xptBoxBeg.yptBoxEnd.xptBoxEnd.y) ;
        }
 
        if (
drawing)
        {
            
SetROP2 (hdcR2_NOT) ;
            
SelectObject (hdcGetStockObject (NULL_BRUSH)) ;
            
Rectangle (hdcptBeg.xptBeg.yptEnd.xptEnd.y) ;
        }
         
        
EndPaint (hWnd, &ps) ;
        return 
;
 
    case 
WM_COMMAND:
        
wmId    LOWORD(wParam);
        
wmEvent HIWORD(wParam);
        
// Parse the menu selections:
        
switch (wmId)
        {
        case 
IDM_about<b></b>:
            
DialogBox(hInstMAKEINTRESOURCE(IDD_ABOUTBOX), hWndAbout);
            break;
        case 
IDM_EXIT:
            
DestroyWindow(hWnd);
            break;
        default:
            return 
DefWindowProc(hWndmessagewParamlParam);
        }
        break;
 
    case 
WM_DESTROY :
        
PostQuitMessage (0) ;
        return 
;
 
    default:
        return 
DefWindowProc(hWndmessagewParamlParam);
    }
    return 
0;
}
 
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlgUINT messageWPARAM wParamLPARAM lParam)
{
    
UNREFERENCED_PARAMETER(lParam);
    switch (
message)
    {
    case 
WM_INITDIALOG:
        return (
INT_PTR)TRUE;
 
    case 
WM_COMMAND:
        if (
LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            
EndDialog(hDlgLOWORD(wParam));
            return (
INT_PTR)TRUE;
        }
        break;
    }
    return (
INT_PTR)FALSE;

پیام های mouse مورد استفاده :
- پیام WM_LBUTTONDOWN وقتی فراخوانی می شود که کلیک چپ mouse زده می شود.

- پیام WM_MOUSEMOVE وقتی که mouse در حال حرکت می باشد.
لذا با یک متغیر bool تست می کنیم که حتما پیام LBUTTONDOWN مقدار true داشته باشد و سپس عملیات انجام شود.

- پیام WM_LBUTTONUP وقتی کلیک چپ mouse آزاد می شود
پس از پایان این پیام تابع InvalidateRect را فراخوانی می کنیم تا با رفرش کردن تصویر در قسمت WM_PAINT ترسیم نهایی مستطیل انجام شود (متغیر drawBox وقتی true می شود)

- با استفاده از lParam های در پیام های mouse مختصات x و y را دریافت می کنیم.

- تابع SetCursor نشان mosue را به یک شکل دیگر مانند + تغییر می دهد.