SETROP2

 《Windows程序设计》这本书的作者经常会使用一些相当巧妙但是令人费解的语句。在这个程序中,当我把WM_MOUSEMOVE中的Draw()函数去除了一个时发现画方块的过程中痕迹没有被清除,又百度了一遍才明白,作者用SetROP2(hdc,R2_NOT)实现了一个擦除功能。

/*
 * 这个程序是根据第七章BLOCKOUT1.C与BLOCKOUT2.C演化而来的,书上的
 * 程序过于复杂, 所以我重写了, 主要演示了SetCapture与ReleaseCapture
 * 的用法, 作者也使用了一种新的方法来进行画图, 我们将会看到SetROP2的妙用
 * by netrookie, ChinUnix
 */

#include <windows.h>

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

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("BlokOut1") ;
    HWND hwnd ;
    MSG msg ;
    WNDCLASS wndclass ;
    
    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 = NULL ;
    wndclass.lpszClassName = szAppName ;
    
    if (!RegisterClass (&wndclass))
    {
        MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
            szAppName, MB_ICONERROR) ;
        return 0 ;
    }
    
    hwnd = CreateWindow (szAppName, TEXT ("Mouse 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 Draw(HWND hwnd, POINT ptBeg, POINT ptEnd) {
    HDC hdc = GetDC(hwnd);
    /*
     * 将画刷与画笔的内置改变为客户区背景色的反转色
     */
    SetROP2(hdc, R2_NOT);
    /*
     * 只绘制边框,不绘制图形内部
     */
    SelectObject(hdc, GetStockObject(NULL_BRUSH));
    Ellipse(hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y);
    ReleaseDC(hwnd, hdc);
}

LRESULT CALLBACK WndProc(HWND hwnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam) {
    static POINT ptBeg, ptEnd;
    HDC hdc;
    PAINTSTRUCT ps;

    switch(message) {
    case WM_LBUTTONDOWN:
        /*
         * 我靠!如果不释放的话,连关闭应用程序都比较难。
         */
        SetCapture(hwnd);
        ptBeg.x = ptEnd.x = LOWORD(lParam);
        ptBeg.y = ptEnd.y = HIWORD(lParam);
        return 0;
    case WM_MOUSEMOVE:
        if(wParam & MK_LBUTTON) {
        /*
         * 清除上一次所画的图形  <<---就是这里,第一次是黑色,第二次就变成相反的白色覆盖了。
         * 这时ptEnd的坐标还没改变,所以就是将刚刚画的图形用和背景色相同的画笔或画刷重画一遍,也就是消除了
         */
        Draw(hwnd, ptBeg, ptEnd);
        ptEnd.x = LOWORD(lParam);
        ptEnd.y = HIWORD(lParam);
        Draw(hwnd, ptBeg, ptEnd);
        }
        return 0;
    case WM_LBUTTONUP:
        ptEnd.x = LOWORD(lParam);
        ptEnd.y = HIWORD(lParam);
        ReleaseCapture();
        InvalidateRect(hwnd, NULL, FALSE);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        SelectObject(hdc, CreateSolidBrush(RGB(0, 255, 0)));
        Ellipse(hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y);
        ReleaseDC(hdc, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值