GetLargestDisplayMode(&cxBmp, &cyBmp);

#include <windows.h>

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

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hPrevI, PSTR szCL, int iCS) {
    static TCHAR szAppName[] = TEXT("Sketch");
    HWND         hwnd;
    MSG          msg;
    WNDCLASS     wndclass;

    wndclass.style         = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc   = WndProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance     = hI;
    wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = GetSysColorBrush(WHITE_BRUSH);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = szAppName;

    if(!RegisterClass(&wndclass)) {
        MessageBox(
            NULL,
            TEXT("Error!"),
            szAppName,
            MB_ICONERROR
        );
        return 0;
    }
    hwnd = CreateWindow(
        szAppName, TEXT("Sketch"), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hI, NULL
    );
    if(hwnd == NULL) {
        MessageBox(
            NULL,
            TEXT("Not enough memory to create bitmap!"),
            szAppName,
            MB_ICONERROR
        );
        return 0;
    }
    ShowWindow(hwnd, iCS);
    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage (&msg);
        FreeConsole();
    }
    return msg.wParam;
}

void GetLargestDisplayMode(int *pcxBitmap, int *pcyBitmap) {
    DEVMODE devmode;
    int     iModeNum = 0;
    *pcxBitmap = *pcyBitmap = 0;
    ZeroMemory(&devmode, sizeof(DEVMODE));
    devmode.dmSize = sizeof(DEVMODE);
    while(EnumDisplaySettings(NULL, iModeNum++, &devmode)) {
        *pcxBitmap = max(*pcxBitmap, (int) devmode.dmPelsWidth);
        *pcyBitmap = max(*pcyBitmap, (int) devmode.dmPelsHeight);
    }
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP) {
    static BOOL    fLButtonDown, fRButtonDown;
    static HBITMAP hBitmap;
    static HDC     hdcMem;
    static int     cxBmp, cyBmp, cxClient, cyClient, xMouse, yMouse;
    HDC            hdc;
    PAINTSTRUCT    ps;

    switch(msg) {
        case WM_CREATE:
            GetLargestDisplayMode(&cxBmp, &cyBmp);
            hdc = GetDC(hwnd);
            hBitmap = CreateCompatibleBitmap(hdc, cxBmp, cyBmp);
            hdcMem  = CreateCompatibleDC(hdc);
            ReleaseDC(hwnd, hdc);
            if(!hBitmap) {
                DeleteDC(hdcMem);
                return -1;
            }
            SelectObject(hdcMem, hBitmap);
            PatBlt(hdcMem, 0, 0, cxBmp, cyBmp, WHITENESS);
            return 0;

        case WM_SIZE:
            cxClient = LOWORD(lP);
            cyClient = HIWORD(lP);
            return 0;

        case WM_LBUTTONDOWN:
            if(!fRButtonDown)
                SetCapture(hwnd);
            xMouse = LOWORD(lP);
            yMouse = HIWORD(lP);
            fLButtonDown = TRUE;
            return 0;

        case WM_LBUTTONUP:
            if(fLButtonDown)
                SetCapture(NULL);
            fLButtonDown = FALSE;
            return 0;

        case WM_RBUTTONDOWN:
            if(!fLButtonDown)
                SetCapture(hwnd);
            xMouse = LOWORD(lP);
            yMouse = HIWORD(lP);
            fRButtonDown = TRUE;
            return 0;

        case WM_RBUTTONUP:
            if(fRButtonDown)
                SetCapture(NULL);
            fRButtonDown = FALSE;
            return 0;

        case WM_MOUSEMOVE:
            if(!fLButtonDown && !fRButtonDown)
                return 0;
            hdc = GetDC(hwnd);
            SelectObject(
                hdc,
                GetStockObject(
                    fLButtonDown ? BLACK_PEN : WHITE_PEN
                )
            );
            SelectObject(
                hdcMem,
                GetStockObject(
                    fLButtonDown ? BLACK_PEN : WHITE_PEN
                )
            );
            MoveToEx(hdc,    xMouse, yMouse, NULL);
            MoveToEx(hdcMem, xMouse, yMouse, NULL);
            xMouse = (short) LOWORD(lP);
            yMouse = (short) HIWORD(lP);
            LineTo(hdc,    xMouse, yMouse);
            LineTo(hdcMem, xMouse, yMouse);
            ReleaseDC(hwnd, hdc);
            return 0;

        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY);
            EndPaint(hwnd, &ps);
            return 0;

        case WM_DESTROY:
            DeleteDC(hdcMem);
            DeleteObject(hBitmap);
            PostQuitMessage(0);
            return 0;
    }
    return DefWindowProc(hwnd, msg, wP, lP);
}

Comentários