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

C++ 如何在C+;中设置鼠标单击时的像素+;在GUI窗口中使用WinApi(GDI)?,c++,windows,winapi,user-interface,gdi,C++,Windows,Winapi,User Interface,Gdi,我试图通过鼠标点击设置像素,但点击时什么也没发生。这是我的部分代码 首先,我控制窗口大小在WM_大小中的变化。 然后,当我第一次想用鼠标设置像素时,我得到窗口的宽度和高度,然后将窗口的内容复制到内存HDC和HBITMAP(存储窗口)(HBITMAP大小等于(宽度,高度))。事实上,我复制到内存中的只是一个清晰的窗口 在任何情况下,我都会将像素设置为内存DC。在下一个WM_绘制消息处理中,我将把内存DC绘制到屏幕上 ..... case WM_SIZE: { CheckWi

我试图通过鼠标点击设置像素,但点击时什么也没发生。这是我的部分代码

首先,我控制窗口大小在WM_大小中的变化。 然后,当我第一次想用鼠标设置像素时,我得到窗口的宽度和高度,然后将窗口的内容复制到内存HDC和HBITMAP(存储窗口)(HBITMAP大小等于(宽度,高度))。事实上,我复制到内存中的只是一个清晰的窗口

在任何情况下,我都会将像素设置为内存DC。在下一个WM_绘制消息处理中,我将把内存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消息。这将是一个很好的起点
  • 我把这个密码

    RECT rect;
    GetClientRect(hwnd, &rect);
    InvalidateRect(hwnd, &rect, true);
    
    在画完之前。没有什么。然后我在画画结束后移动它。没什么

  • 在WM_PAINT处理程序中,您需要使用BeginPaint提供的DC,并在完成后调用EndPaint
  • 我在RestoreWindow()中执行此操作

    我还不知道有什么问题

    UPD3:

    无效竖立()需要在SetPixel之后的WM_?BUTTONDOWN处理程序中发生(而不是在RestoreWindow()中)——这是告诉windows您首先要获得WM_u绘制的内容

    嗯。在你写这封信之前我已经做过了。还是不行

    UPD4:

    非常感谢你,雷米!谢谢大家。现在好了

    两件事

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

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


  • 调用
    RestoreWindow()
    在屏幕上绘制位图时,您正在擦除用于绘制像素的
    memoryDC
    变量。位图仍被选择到您现在丢失的原始
    HDC
    中,并且不能同时将位图选择到多个
    HDC
    s中(有关
    SelectObject()
    的MSDN文档也说明了这一点)。因此,您实际上根本没有在屏幕上绘制位图

    无需在
    RestoreWindow()
    中调用
    CreateCompatibleDC()
    SelectObject()
    ,因为您已经在
    StoreWindow()
    中设置了位图和内存
    HDC
    ,所以它们会按原样使用它们

    试试这个:

    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;
    }
    ...
    

    黑暗中的镜头:你正在处理中间的按钮点击。您是否碰巧单击了鼠标左键或右键?:)无效竖立()需要在SetPixel之后的WM_?BUTTONDOWN处理程序中发生(而不是在RestoreWindow()中)——这是告诉windows您首先要获得WM_u绘制的内容。