user3366592
user3366592

Reputation: 449

c++ - SetPixel() is too slow

I'm writing a program similar to "Paint" in Windows. At first I tried to make a "pencil" function handling WM_MOUSEMOVE message and calling SetPixel() properly. But when mouse moves too fast, not all pixels are appearing (they look like sparse). I think I must replace that SetPixel() function with another code, but I don't know what.

Upvotes: 1

Views: 1543

Answers (2)

ikh
ikh

Reputation: 10417

  1. Catch WM_LBUTTONDOWN, and set capture on your window saving the first mouse coord.

  2. Catch WM_MOUSEMOVE, and draw line from first coord to now coord. Then, save the now coord into first mouse coord.

  3. repeat 2.

  4. Catch WM_LBUTTONUP, and release capture.

Example:

#include <windows.h>
#include <windowsx.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
    WNDCLASS wc;
    HWND hWnd;
    MSG msg;

    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = L"adf";
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    RegisterClass(&wc);

    hWnd = CreateWindow(L"adf", NULL, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInst, NULL);
    ShowWindow(hWnd, SW_NORMAL);

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

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    static int prevx, prevy;

    switch (iMsg)
    {
    case WM_LBUTTONDOWN:
        prevx = GET_X_LPARAM(lParam);
        prevy = GET_Y_LPARAM(lParam);
        SetCapture(hWnd);
        return 0;
    case WM_LBUTTONUP:
        ReleaseCapture();
        return 0;
    case WM_MOUSEMOVE:
        if (GetCapture() == hWnd)
        {
            HDC hdc = GetDC(hWnd);
            MoveToEx(hdc, prevx, prevy, NULL);
            LineTo(hdc, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
            prevx = GET_X_LPARAM(lParam);
            prevy = GET_Y_LPARAM(lParam);
            ReleaseDC(hWnd, hdc);
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, iMsg, wParam, lParam);
}

Upvotes: 3

Sanchises
Sanchises

Reputation: 863

This is because the mouse may move more than one pixel on each 'update', and is not a fault in SetPixel. Instead, you should remember the last pixel that had a mouseover, and draw a line between the two pixels (I think the correct function is DrawLine()). See ikh's answer for a detailed description of that method.

Upvotes: 6

Related Questions