Chinaunix首页 | 论坛 | 博客
  • 博客访问: 516090
  • 博文数量: 158
  • 博客积分: 4015
  • 博客等级: 上校
  • 技术积分: 1711
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-27 14:00
文章分类

全部博文(158)

文章存档

2010年(71)

2009年(87)

我的朋友

分类: C/C++

2010-01-07 18:29:40

图形基础中关于贝塞尔曲线的地方,我觉得非常有意思, 作者提前给我们演示了三个消息:

WM_LBUTTONDOWN
WM_RBUTTONDOWN
WM_MOUSEMOVE


BEZIER.C当中作者把这三个消息放到一起来使用, 当时怎么看怎么觉得别扭, 代码虽然简单了, 但是看着看着就会觉得湖涂, 所以我重写了, 三个消息分开处理, 代码量增加了, 但是更容易理解了:

#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("DrawBezier");
    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 = GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    
    if(!RegisterClass(&wndclass)) {
        MessageBox(NULL, TEXT("Register failure..."),
            szAppName, MB_ICONERROR);
        return 0;
    }
    
    hwnd = CreateWindow(szAppName,
        szAppName,
        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 DrawBezier(HDC hdc, POINT pt[]) {
    PolyBezier(hdc, pt, 4);
    MoveToEx(hdc, pt[0].x, pt[0].y, NULL);
    LineTo(hdc, pt[1].x, pt[1].y);
    
    MoveToEx(hdc, pt[2].x, pt[2].y, NULL);
    LineTo(hdc, pt[3].x, pt[3].y);
}

LRESULT CALLBACK WndProc(HWND hwnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam) {
    static int cxClient, cyClient;
    PAINTSTRUCT ps;
    static POINT pt[4];
    HDC hdc;
    
    switch(message) {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        pt[0].x = 0;
        pt[0].y = cyClient / 2;
        pt[1].x = cxClient / 4;
        pt[1].y = cyClient / 4;
        pt[2].x = 3 * cxClient / 4;
        pt[2].y = 3 * cyClient / 4;
        pt[3].x = cxClient;
        pt[3].y = cyClient / 2;
        return 0;
     // 在这里我单独处理了WM_LBUTTONDOWN消息  
    case WM_LBUTTONDOWN:
        hdc = GetDC(hwnd);
        SelectObject(hdc, GetStockObject(WHITE_PEN));
        DrawBezier(hdc, pt);
        pt[1].x = LOWORD(lParam);
        pt[1].y = HIWORD(lParam);
        SelectObject(hdc, GetStockObject(BLACK_PEN));
        DrawBezier(hdc, pt);
        ReleaseDC(hwnd, hdc);
        return 0;
    // 在这里我单独处理了WM_RBUTTONDOWN消息
    case WM_RBUTTONDOWN:
        hdc = GetDC(hwnd);
        SelectObject(hdc, GetStockObject(WHITE_PEN));
        DrawBezier(hdc, pt);
        pt[2].x = LOWORD(lParam);
        pt[2].y = HIWORD(lParam);
        SelectObject(hdc, GetStockObject(BLACK_PEN));
        DrawBezier(hdc, pt);
        ReleaseDC(hwnd, hdc);
        return 0;
    // 在这里我处理了WM_MOUSEMOVE消息
    case WM_MOUSEMOVE:
        hdc = GetDC(hwnd);
        if(wParam & MK_LBUTTON) {
            SelectObject(hdc, GetStockObject(WHITE_PEN));
            DrawBezier(hdc, pt);

            pt[1].x = LOWORD(lParam);
            pt[1].y = HIWORD(lParam);
            SelectObject(hdc, GetStockObject(BLACK_PEN));
            DrawBezier(hdc, pt);
        }

        if(wParam & MK_RBUTTON) {
            SelectObject(hdc, GetStockObject(WHITE_PEN));
            DrawBezier(hdc, pt);
            
            pt[2].x = LOWORD(lParam);
            pt[2].y = HIWORD(lParam);
            SelectObject(hdc, GetStockObject(BLACK_PEN));
            DrawBezier(hdc, pt);
        }
        ReleaseDC(hwnd, hdc);
        return 0;


    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        DrawBezier(hdc, pt);
        EndPaint(hwnd, &ps);
        return 0;
        
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}


如果只是更容易理解了, 那还不算什么, 我们可以提前练习这三个消息, 做一些有用的程序:
接下来我要做一个小小的画图程序:
先看一下运行结果:通过按住鼠标左键画矩形:
源代码:


#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("Drawing");
    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 = GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;

    if(!RegisterClass(&wndclass)) {
        MessageBox(NULL, TEXT("Register failure..."),
            szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,
        szAppName,
        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;
}

LRESULT CALLBACK WndProc(HWND hwnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam) {
    static cxClient, cyClient;
    static POINT pt[2];
    PAINTSTRUCT ps;
    HDC hdc;

    switch(message) {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;

    case WM_CREATE:

        // 这一步不可少的
        memset(pt, 0, sizeof(pt));
        return 0;

    // 当按住左键的时候,分配新的坐标, 并且用白色画刷清除上次的矩形
    case WM_LBUTTONDOWN:
        hdc = GetDC(hwnd);
        SelectObject(hdc, GetStockObject(WHITE_PEN));
        Rectangle(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
        pt[0].x = LOWORD(lParam);
        pt[0].y = HIWORD(lParam);
        ReleaseDC(hwnd, hdc);
        return 0;


    case WM_MOUSEMOVE:
        hdc = GetDC(hwnd);
        if(wParam & MK_LBUTTON) {
            SelectObject(hdc, GetStockObject(WHITE_PEN));
            Rectangle(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
            pt[1].x = LOWORD(lParam);
            pt[1].y = HIWORD(lParam);
            SelectObject(hdc, GetStockObject(BLACK_PEN));
            Rectangle(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
        }
        ReleaseDC(hwnd, hdc);
        return 0;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        Rectangle(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

我们可能会想, 为什么我们每次按下左键的时候, 上次画的矩形就消失呢, 可以不消失吗?
当然可以, 我们只要重写WM_LBUTTONDOWN, 其他不变:
源代码:


    case WM_LBUTTONDOWN:
        hdc = GetDC(hwnd);
        pt[0].x = LOWORD(lParam);
        pt[0].y = HIWORD(lParam);
        // 我们在里所做的这一步非常重要,当左键按下时,代表一个新的矩形

        // 将要产生, 如果不这么做, 在WM_MOUSEMOVE当中用白色画刷清除矩形的时候

        // 会产生问题.

        pt[1].x = pt[0].x;
        pt[1].y = pt[0].y;
        ReleaseDC(hwnd, hdc);
        return 0;

    case WM_MOUSEMOVE:
        hdc = GetDC(hwnd);
        if(wParam & MK_LBUTTON) {

            SelectObject(hdc, GetStockObject(WHITE_PEN));
            Rectangle(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
            pt[1].x = LOWORD(lParam);
            pt[1].y = HIWORD(lParam);
            SelectObject(hdc, GetStockObject(BLACK_PEN));
            Rectangle(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
        }
        ReleaseDC(hwnd, hdc);
        return 0;


阅读(791) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~