简体   繁体   English

绘图时防止闪烁

[英]Prevent Flickering When Drawing

So I have this code to draw a rectangle on my screen: 因此,我有以下代码在屏幕上绘制矩形:

LOGBRUSH m_LogBrush;
HBRUSH m_hBrush;
HPEN m_hPen;

HDC m_hDC;

void DrawBox(int x, int y, int r, int g, int b, int size, int thickness)
{
    // Brush style to hollow
    m_LogBrush.lbStyle = BS_NULL;

    // Create a logical brush and select into the context
    m_hBrush = CreateBrushIndirect(&m_LogBrush);
    SelectObject(m_hDC, m_hBrush);

    // Create a logical pen and select into the context
    m_hPen = CreatePen(PS_SOLID, thickness, RGB(r, g, b));
    SelectObject(m_hDC, m_hPen);

    // Draw the rectangle
    Rectangle(m_hDC, (x - size / 2), (y - size / 2), (x + size / 2), (y + size / 2));

    // Remove the object
    DeleteObject(m_hBrush);
    DeleteObject(m_hPen);
}

However, when being called repeatedly inside a loop it flickers on the screen. 但是,当在循环内被反复调用时,它会在屏幕上闪烁。 I was wondering if there was a way to prevent this flicker? 我想知道是否有办法防止这种闪烁?

Any help would be appreciated. 任何帮助,将不胜感激。

Thanks 谢谢

This should not be an answer, but I can not post code in comments: 这不应该是一个答案,但是我不能在注释中发布代码:

You have many GDI leaks in your code. 您的代码中有很多GDI泄漏。

Copy/paste the following code and report us if flickering diminishes : 复制/粘贴以下代码,并在闪烁减少时向我们报告:

void DrawBox(int x, int y, int r, int g, int b, int size, int thickness)
{
    // Brush style to hollow
    m_LogBrush.lbStyle = BS_NULL;

    // Create a logical brush and select into the context
    m_hBrush = CreateBrushIndirect(&m_LogBrush);
    HBRUSH hbrOldBrush = SelectObject(m_hDC, m_hBrush);

    // Create a logical pen and select into the context
    m_hPen = CreatePen(PS_SOLID, thickness, RGB(r, g, b));
    HPEN hpOldPen = SelectObject(m_hDC, m_hPen);

    // Draw the rectangle
    Rectangle(m_hDC, (x - size / 2), (y - size / 2), (x + size / 2), (y + size / 2));

    // Remove the object
    SelectObject(m_hDC, hbrOldBrush);  // first you must restore DC to original state
    SelectObject(m_hDC, hpOldPen);     // same here
    DeleteObject(m_hBrush);
    DeleteObject(m_hPen);

} }

Read on MSDN about GDI leaks. 在MSDN上阅读有关GDI泄漏的信息。

This should diminish flickering, but to completely remove flickering you should do the following: 这样可以减少闪烁,但是要完全消除闪烁,您应该执行以下操作:

  • Remove the CS_VREDRAW | CS_HREDRAW 删除CS_VREDRAW | CS_HREDRAW CS_VREDRAW | CS_HREDRAW from your window class definition; 窗口类定义中的CS_VREDRAW | CS_HREDRAW
  • return 1L in your window procedure ( or TRUE in your dialog box procedure ) in response to WM_ERASEBKGND ; 响应WM_ERASEBKGND在窗口过程中返回1L (在对话框过程中返回TRUE );
  • draw everything on a memory bitmap and then BitBlt it into your m_hDC -> this is called double buffering ( you can find many examples online ); 在内存位图上绘制所有内容,然后将其BitBlt放入m_hDC >这称为双缓冲 (您可以在网上找到许多示例);
    /*Hi You May Change Your Code To This*/ 

    LOGBRUSH m_LogBrush;
    //HBRUSH m_hBrush;
    //HPEN m_hPen;
    //HDC m_hDC;
    HWND m_hWND; //Your WindowHandle instead of your DC
    //
    void DrawBox(int x, int y, int r, int g, int b, int size, int thickness)
    {

    // Lock & Get Forground DC From m_hWND
    HDC m_hDC = GetDC(m_hWND);
    if (m_hDC != 0) //Make Sure It's ok
    {

    // Double Buffering Begins Here

    // Create Background DC From m_hDC
    HDC mem_m_hDC = CreateCompatibleDC(m_hDC);

    // Calculate Window Bounds
    RECT ClientRect = { 0 };
    GetClientRect(m_hWND, &ClientRect);

    // Create Background Buffer Frame
    BITMAPINFO bmi = { 0 };
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = ClientRect.right - ClientRect.left;
    bmi.bmiHeader.biHeight = ClientRect.bottom - ClientRect.top;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biPlanes = 1;
    HBITMAP memBMP = CreateDIBSection(mem_m_hDC, &bmi, DIB_RGB_COLORS, 0, 0, 0);

    // Select Background Buffer Frame
    SelectObject(mem_m_hDC, memBMP);

    // Brush style to hollow
    m_LogBrush.lbStyle = BS_NULL;

    // Create a logical brush and select into the context
    HBRUSH m_hBrush = CreateBrushIndirect(&m_LogBrush);
    HGDIOBJ oldHGDIOBJ1 = SelectObject(m_hDC, m_hBrush); //Save Old Seleteed GDI Object To oldHGDIOBJ1

    // Create a logical pen and select into the context
    HPEN m_hPen = CreatePen(PS_SOLID, thickness, RGB(r, g, b));
    HGDIOBJ oldHGDIOBJ2 = SelectObject(m_hDC, m_hPen); //Save Old Seleteed GDI Object To oldHGDIOBJ2

    // Draw the rectangle in Background Memory DC
    Rectangle(mem_m_hDC, (x - size / 2), (y - size / 2), (x + size / 2), (y + size / 2));

    // Copy Background DC To Forground DC
    BitBlt(m_hDC, 0, 0, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight, mem_m_hDC, 0, 0, SRCCOPY);

    // Delete Background Buffer Frame
    DeleteObject(memBMP);

    // Delete Background DC
    DeleteDC(mem_m_hDC);

    // Double Buffering Ends Here

    // Unlock Forground DC
    ReleaseDC(m_hWND, m_hDC);

    // Remove the objects
    DeleteObject(m_hBrush);
    DeleteObject(m_hPen);

    }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM