如何在GUI窗口中使用WinApi(GDI)在C++中单击鼠标来设置像素?

Abz*_*zac 4 c++ windows user-interface winapi gdi

我试图通过鼠标点击设置像素,但是当我点击时没有任何反应.这是我的代码的一部分.

首先,我控制WM_SIZE中的窗口大小变化.比如,当我想用​​鼠标设置像素时,我得到窗口的宽度和高度,然后将窗口的内容复制到内存HDC和HBITMAP(在商店窗口中)(HBITMAP大小等于(宽度,高度)).事实上,我只复制到内存清除窗口.

而且在任何情况下我都将像素设置为内存DC.在下一个WM_PAINT消息处理中,我将内存DC绘制到屏幕.

.....
case WM_SIZE:
    {
        CheckWidthHeight();
        break;
    }
    case WM_MBUTTONDOWN:
    {
        if (firstTimeDraw)
        {
            CheckWidthHeight();
            StoreWindow();
            firstTimeDraw = false;
        }
        SetPixel(memoryDC, LOWORD(lParam), HIWORD(lParam), RGB(0,0,0));
        break;
    }
    case WM_PAINT:
    {
        RestoreWindow();
        break;
    }
.....
Run Code Online (Sandbox Code Playgroud)

我的函数和变量是:

HDC memoryDC;
HBITMAP memoryBitmap;
int width = 0, height = 0;
bool firstTimeDraw = true;

void CheckWidthHeight()
{
   RECT clientRect;
   GetClientRect(hwnd, &clientRect);
   width = clientRect.right - clientRect.left;
   height = clientRect.bottom - clientRect.top;
}

//Copy real window content to memory window
void StoreWindow()
{
   HDC hDC = GetDC(hwnd);
   memoryDC = CreateCompatibleDC(hDC);
   memoryBitmap = CreateCompatibleBitmap(hDC, width, height);
   SelectObject(memoryDC, memoryBitmap);
   BitBlt(memoryDC, 0, 0, width, height, hDC, 0, 0, SRCCOPY);
   ReleaseDC(hwnd, hDC);
}

//Copy memory windows content to real window at the screen
void RestoreWindow()
{
   PAINTSTRUCT ps;
   HDC hDC = BeginPaint(hwnd, &ps);
   memoryDC = CreateCompatibleDC(hDC);
   SelectObject(memoryDC, memoryBitmap);
   BitBlt(hDC, 0, 0, width, height, memoryDC, 0, 0, SRCCOPY);
   EndPaint(hwnd, &ps);
}
Run Code Online (Sandbox Code Playgroud)

我做错了什么?

UPD:

在黑暗中拍摄:你正在处理中间按钮点击.您是否有机会点击鼠标左键或右键?:)

好.现在我使用WM_LBUTTONUP或WM_LBUTTONDOWN.什么也没发生.

UPD2:

  1. 更改内存DC时,您还需要使受影响的窗口部分无效,以便Windows为其生成WM_PAINT消息.InvalidateRect是一个很好的起点.

我放了这个代码

RECT rect;
GetClientRect(hwnd, &rect);
InvalidateRect(hwnd, &rect, true);
Run Code Online (Sandbox Code Playgroud)

在EndPaint之前.没有.比我在EndPaint之后移动它.没有.

  1. 在WM_PAINT处理程序中,您需要使用BeginPaint提供的DC并在完成后调用EndPaint.

我在RestoreWindow()中这样做.

我不知道有什么问题......

UPD3:

InvalidateRect()需要在SetPixel之后的WM_?BUTTONDOWN处理程序中发生(不在RestoreWindow()中) - 这是告诉Windows你想要首先获得WM_PAINT的东西.

好.我在你写这封邮件之前已经完成了.还是不行.

UPD4:

非常感谢,雷米!谢谢你们所有人.好吧!!

Mar*_*som 6

两件事情.

  1. 更改内存DC时,您还需要使受影响的窗口部分无效,以便Windows为其生成WM_PAINT消息.InvalidateRect是一个很好的起点.

  2. 在WM_PAINT处理程序中,您需要使用BeginPaint提供的DC并在完成后调用EndPaint.