我正试图通过鼠标点击设置像素,但点击时没有任何反应。这是我的代码的一部分。
首先,我在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;
}
.....
我的函数和变量是:
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);
}
我做错了什么?
UPD:
在黑暗中拍摄:你正在处理中间按钮点击。您是否有机会点击鼠标左键或右键? :)
确定。现在我使用WM_LBUTTONUP或WM_LBUTTONDOWN。什么都没发生。
UPD2:
- 更改内存DC时,您还需要使受影响的窗口部分无效,以便Windows为其生成WM_PAINT消息。 InvalidateRect将是一个很好的起点。
醇>
我放置了这段代码
RECT rect;
GetClientRect(hwnd, &rect);
InvalidateRect(hwnd, &rect, true);
在EndPaint之前。没有。比我在EndPaint之后移动它。什么都没有。
- 在WM_PAINT处理程序中,您需要使用BeginPaint提供的DC,并在完成后调用EndPaint。
醇>
我在RestoreWindow()中执行此操作。
我还不知道问题是什么......
UPD3:
InvalidateRect()需要在SetPixel之后的WM_?BUTTONDOWN处理程序中发生(不在RestoreWindow()中) - 这是告诉Windows你想要首先获得WM_PAINT的东西。
确定。我在你写这封邮件之前已经完成了。还是不行。
UPD4:
非常感谢,雷米!谢谢你们所有人。好吧!!
答案 0 :(得分:6)
两件事。
更改内存DC时,您还需要使受影响的窗口部分无效,以便Windows为其生成WM_PAINT消息。 InvalidateRect是一个很好的起点。
在WM_PAINT处理程序中,您需要使用BeginPaint提供的DC,并在完成后调用EndPaint。
答案 1 :(得分:4)
当您致电RestoreWindow()
在屏幕上绘制位图时,您将消除用于绘制像素的memoryDC
变量。您仍然会将位图选入您现在丢失的原始HDC
,并且无法同时将位图选择到多个HDC
中(SelectObject()
的MSDN文档说明了这一点)。所以你实际上并没有在屏幕上绘制位图。
无需在CreateCompatibleDC()
内拨打SelectObject()
或RestoreWindow()
,因为您已经在HDC
内设置了位图和内存StoreWindow()
,所以他们原样使用它们。
试试这个:
HDC memoryDC = NULL;
HBITMAP memoryBitmap = NULL;
int width = 0, height = 0;
void CheckWidthHeight()
{
RECT clientRect;
GetClientRect(hwnd, &clientRect);
width = clientRect.right - clientRect.left;
height = clientRect.bottom - clientRect.top;
}
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);
}
void RestoreWindow()
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hwnd, &ps);
if (memoryDC)
BitBlt(hDC, 0, 0, width, height, memoryDC, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
}
...
case WM_SIZE:
{
CheckWidthHeight();
break;
}
case WM_LBUTTONDOWN:
{
if (!memoryDC)
StoreWindow();
if (memoryDC)
{
SetPixel(memoryDC, LOWORD(lParam), HIWORD(lParam), RGB(0,0,0));
RECT rect;
rect.left = LOWORD(lParam);
rect.top = HIWORD(lParam);
rect.right = rect.left + 1;
rect.bottom = rect.top + 1;
InvalidateRect(hwnd, &rect, TRUE);
}
break;
}
case WM_PAINT:
{
RestoreWindow();
break;
}
...