win32下的贝塞尔曲线

简单的利用windows api来实现的贝赛尔曲线。两个端点是固定的,垂直方向的位置为显示区域高度的一半,水平方向则分别位于显示宽度的1/4和3/4处。

两个控点可以改变,按住鼠标左键并拖动鼠标可以改变第一个控点,按住右键并拖动鼠标可以改变第二个控点。

如图:

代码如下:

#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("贝塞尔曲线");
    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("这个程序需要运行在Windows NT下!"), szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,
        TEXT("贝塞尔曲线!"),
        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 apt[])
{
    PolyBezier(hdc, apt, 4);

    MoveToEx(hdc, apt[0].x, apt[0].y, NULL);
    LineTo(hdc, apt[1].x, apt[1].y);

    MoveToEx(hdc, apt[2].x, apt[2].y, NULL);
    LineTo(hdc, apt[3].x, apt[3].y);
}

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

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

        apt[0].x = cxClient / 4;
        apt[0].y = cyClient / 2;

        apt[1].x = cxClient / 2;
        apt[1].y = cyClient / 4;

        apt[2].x = cxClient / 2;
        apt[2].y = 3 * cyClient / 4;

        apt[3].x = 3 * cxClient / 4;
        apt[3].y = cyClient / 2;

    case WM_LBUTTONDOWN:
    case WM_RBUTTONDOWN:
    case WM_MOUSEMOVE:
        if (wParam & MK_LBUTTON || wParam && MK_RBUTTON)
        {
            hdc = GetDC(hwnd);

            SelectObject(hdc, GetStockObject(WHITE_PEN));
            DrawBezier(hdc, apt);

            if (wParam & MK_LBUTTON)
            {
                apt[1].x = LOWORD(lParam);
                apt[1].y = HIWORD(lParam);
            }

            if (wParam & MK_RBUTTON)
            {
                apt[2].x = LOWORD(lParam);
                apt[2].y = HIWORD(lParam);
            }

            SelectObject(hdc, GetStockObject(BLACK_PEN));
            DrawBezier(hdc, apt);
            ReleaseDC(hwnd, hdc);
        }
        return 0;
    case WM_PAINT:
        InvalidateRect(hwnd, NULL, TRUE);
        hdc = BeginPaint(hwnd, &ps);
        DrawBezier(hdc, apt);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}

 

posted @ 2017-03-04 12:23  SubjectiveInitiative  阅读(404)  评论(0编辑  收藏  举报