Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对话框不正确地重新绘制其背景_C++_Winapi_Gdi - Fatal编程技术网

C++ 对话框不正确地重新绘制其背景

C++ 对话框不正确地重新绘制其背景,c++,winapi,gdi,C++,Winapi,Gdi,我有一个对话框,应该有一个自定义图像作为背景 我没有作为位图或任何其他格式的整个图像,所以我必须从头开始绘制它 我使用一个图标(屏幕截图左下角的男性),一个EMF文件(下面屏幕截图上的地图),其余由绿色渐变笔刷、浅灰色阴影笔刷和文本组成-所有这些都使用GDI绘制。我的绘图结果如下所示(屏幕截图也包括控件): 当我向左移动对话框,然后将其移回原始位置时,我面临的问题就会显现出来。下一个屏幕截图中的图片底部显示了发生的伪影: 对话框是无模式的,我在WM\u CTLCOLORDIALOG中绘制了整

我有一个对话框,应该有一个自定义图像作为背景

我没有作为位图或任何其他格式的整个图像,所以我必须从头开始绘制它

我使用一个
图标(屏幕截图左下角的男性),一个
EMF
文件(下面屏幕截图上的地图),其余由绿色渐变笔刷、浅灰色阴影笔刷和文本组成-所有这些都使用
GDI
绘制。我的绘图结果如下所示(屏幕截图也包括控件):

当我向左移动对话框,然后将其移回原始位置时,我面临的问题就会显现出来。下一个屏幕截图中的图片底部显示了发生的伪影:

对话框是无模式的,我在
WM\u CTLCOLORDIALOG
中绘制了整个图像,然后返回
NULL\u笔刷

以下是
WM\u CTLCOLORDIALOG
处理程序的相关代码片段(注意,我直接在DC上绘制,没有双缓冲区。。原因是这是一个快速测试代码,很快就出错了):

视觉样式已启用-这可能很重要,我不知道

我没有处理
WM_ERASEBKGND
WM_SIZE
WM_MOVE
对话框无法调整大小。)。我试过了,但没有效果(对于
WM\u-ERASEBKGND
返回
TRUE
,对于
WM\u-SIZE
WM\u-MOVE
返回
invalidate
)。我在网上找不到任何帮助我的东西


问题:如何更改我的代码以修复我面临的错误?

您处理了错误的消息


您不应该在
WM\u CTLCOLORDLG
消息上绘制任何内容。只需将绘制代码移动到
WM_ERASEBKGND
处理程序。

您正在滥用
WM_CTLCOLORDLG
消息。它旨在提供一种简单的方法来更改对话框的背景色,而不是自定义绘制对话框

您应该在那里返回
NULL\u BRUSH
,甚至完全忽略消息,然后在
WM\u ERASEBKGND
中进行背景绘制

或者更好,您可以忽略
WM_ERASEBKGND
,在
WM_PAINT
中进行绘制,就像其他窗口一样

更新:在下面的一些注释之后,问题似乎是调用
GradientFill()
三角形时顶点的顺序。即:

  • 顶点按顺时针方向列出:绘制三角形
  • 顶点按逆时针方向列出:不绘制三角形
也许是另一种方式,我永远也说不出

不管怎么说,为什么有时候它不管顺序如何都能工作,为什么有时候它只在特定的顺序下工作,这仍然是个谜。此外,这是否在任何地方都有记录


我猜这可能是驾驶员/2D加速问题。。。因此,这将取决于DC是显示还是内存,但很难说。

好。下一个问题是重新绘制整个窗口。请注意,窗口的左侧部分(确实需要更新)绘制为OK。问题是窗口的主(右)部分,在从左侧移动窗口后实际上不需要更新

WM_ERASEBKGND
处理程序中,可以调用
getUpdate()
获取需要更新的矩形


如果不想对代码进行太多更改,至少可以在绘制任何内容之前调用例如
IntersectClipRect()
API。这将把你所有的画都剪辑到那个矩形上。

为什么你用WM_CTLCOLORDLG而不是WM_PAINT来绘制对话框?地图有任何功能用途吗?你能在上面画些别的东西吗?如果不是,我会建议不要把时间花在不相关的东西上,也不要把图像和背景图案都去掉。@Markransem:我是一个初学者,不知道如何正确地实现它。@Dialogicus:我的客户强迫我使用这种背景,我认为这只是一种“不必要的装饰”,但是我能做什么…只是看错了图片,我怀疑在你如何发送梯度填充的坐标时有一个错误。我可以想象,如果你得到的坐标顺序错误或计算错误,你可能会得到两个三角形的颜色,就像你看到的那样。我会把注意力集中在那里,观察调试器中发生了什么。我确实尝试过,但失败了。我将再试一次并报告我的结果。非常感谢。向您致意。好的,在将
案例WM\u CTLCOLORDIALOG
更改为
案例WM\u ERASEBKGND
之后,以及在更改
返回(INT\u PTR)GetStockObject(NULL\u笔刷)之后
进入
返回TRUE
,我得到了相同的效果。我试图从
WM_ERASEBKGND
返回
TRUE
,并在
WM_paint
中绘制图片。
HDC
是通过调用
BeginPaint
获得的,绘制代码相同,只是
(HDC)wParam
BeginPaint
中的DC替换-剩余部分。有什么想法吗?非常感谢。最好的问候。一个疯狂的猜测:电动势正在改变DC中的某些东西,使你的三角形无法工作。尝试在
playenhetafile()
之前调用
SaveDC()
,在之后调用
RestoreDC()
。另外,检查
GradientFill
的返回值是否有错误。我已经注释掉了绘制
EMF
的部分,但问题仍然存在。我已经注释掉了页脚的绘图,并用画笔(
LTGRAY\u brush
)绘制了那个矩形。这个问题似乎消失了。我的函数
drawFooter
调用
GradientFill
API,如上所述。可能我传递的顶点值不正确?我试试看
case WM_CTLCOLORDLG:
    {   
        RECT rect; // dialog's client rectangle

        GetClientRect( hwnd, &rect );

        // ligh gray brush for hatched brush

        HBRUSH hbPozadina = CreateSolidBrush( RGB( 242, 242, 242 ) );

        FillRect( (HDC)wParam, &rect, hbPozadina );

        // cleanup

        DeleteObject( hbPozadina );

        // draw grid "manualy"

        LOGBRUSH lbPozadina;

        HGDIOBJ hPenPozadina = NULL, hOldPenPozadina;

        lbPozadina.lbColor = RGB( 255, 255, 255 );
        lbPozadina.lbHatch = 0;
        lbPozadina.lbStyle = BS_SOLID;

        hPenPozadina = ExtCreatePen( PS_COSMETIC | PS_SOLID, 1, &lbPozadina, 0, NULL); 

        hOldPenPozadina = SelectObject((HDC)wParam, hPenPozadina);

        // draw vertical lines

        for( int i = rect.left + 12; i< rect.right; i += 12)
        {
            MoveToEx((HDC)wParam, i, rect.top, NULL );

            LineTo((HDC)wParam, i, rect.bottom - rect.top + 1 );
        }

        // draw horizontal lines

        for( int i = rect.top + 12; i< rect.bottom; i += 12)
        {
            MoveToEx((HDC)wParam, rect.left, i, NULL );

            LineTo((HDC)wParam, rect.right - rect.left + 1, i );
        }

        //clean up

        SelectObject((HDC)wParam, hOldPenPozadina);

        DeleteObject(hPenPozadina);

        // draw metafile of the map

        HENHMETAFILE hemf = GetEnhMetaFile( L".\\resources\\KartaDlg.emf" );
        ENHMETAHEADER emh; 
        GetEnhMetaFileHeader( hemf, sizeof(emh), &emh ); 

        // remove the "status bar" from the calculation

        RECT r;

        r.top = rect.top;
        r.bottom = rect.bottom - 30;
        r.left = rect.left;
        r.right = rect.right;

        // calculate rescaled metafile

        UINT o_height = emh.rclFrame.bottom - emh.rclFrame.top, 
            o_width =  emh.rclFrame.right - emh.rclFrame.left;

        float scale = 0.5;

        scale = (float)( r.right - r.left ) / o_width;

        if( (float)( r.bottom - r.top ) / o_height  <  scale )
            scale = (float)( r.bottom - r.top ) / o_height;

        int marginX = ( r.right - r.left ) - (int)( o_width * scale );
        int marginY = ( r.bottom - r.top ) - (int)( o_height * scale );

        marginX /= 2;
        marginY /= 2;

        r.left = r.left + marginX;
        r.right = r.right - marginX;
        r.top = r.top + marginY;
        r.bottom = r.bottom - marginY;

        // Draw the picture.  

        PlayEnhMetaFile( (HDC)wParam, hemf, &r ); 

        // Release the metafile handle.  

        DeleteEnhMetaFile(hemf); 

        // this function draws green gradient and icon

        drawFooter( (HDC)wParam, rect, 
            RGB( 0x48, 0xAC, 0xC6), RGB( 0x31, 0x83, 0x99 ) ); 

        //========= draw right text in status bar =============//

        SetBkMode( (HDC)wParam, TRANSPARENT );

        SIZE sBaner; // needed for proper positioning

        HFONT hf, hfOld;

        long lfHeight;

        lfHeight = -MulDiv( 8, GetDeviceCaps( (HDC)wParam, LOGPIXELSY), 72 );

        hf = CreateFont( lfHeight, 0, 0, 0, FW_BOLD, TRUE, 
            0, 0, 0, 0, 0, 0, 0, L"Arial Black" );

        hfOld = (HFONT)SelectObject( (HDC)wParam, hf ); // needed for proper cleanup

        GetTextExtentPoint32( (HDC)wParam, 
            L"ЦЕНТАР ЗА ОБНОВЉИВЕ ВОДНЕ ЕНЕРГЕТСКЕ РЕСУРСЕ",
            wcslen(L"ЦЕНТАР ЗА ОБНОВЉИВЕ ВОДНЕ ЕНЕРГЕТСКЕ РЕСУРСЕ"), 
            &sBaner );

        // position it properly

        r.bottom = rect.bottom;
        r.right = rect.left + sBaner.cx + 30;
        r.left = rect.left + 30;
        r.top = rect.bottom - rect.top - 30;

        // draw it 

        DrawTextEx( (HDC)wParam, 
            L"РУДАРСКО ГЕОЛОШКИ ФАКУЛТЕТ\nЦЕНТАР ЗА ОБНОВЉИВЕ ВОДНЕ ЕНЕРГЕТСКЕ РЕСУРСЕ",
            wcslen(L"РУДАРСКО ГЕОЛОШКИ ФАКУЛТЕТ\nЦЕНТАР ЗА ОБНОВЉИВЕ ВОДНЕ ЕНЕРГЕТСКЕ РЕСУРСЕ"), 
            &r, DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_WORDBREAK, 0 );

        SelectObject( (HDC)wParam, hfOld ); // proper cleanup

        DeleteObject( hf );

        //============== right text in the status bar ==================//

        lfHeight = -MulDiv( 10, GetDeviceCaps( (HDC)wParam, LOGPIXELSY), 72 );

        hf = CreateFont( lfHeight, 0, 0, 0, FW_BOLD, TRUE, 
            0, 0, 0, 0, 0, 0, 0, L"Arial" );

        hfOld = (HFONT)SelectObject( (HDC)wParam, hf ); // needed for proper cleanup

        GetTextExtentPoint32( (HDC)wParam, 
            L" Дејан Миленић & Ана Врањеш © 2013 сва права задржана",
            wcslen(L" Дејан Миленић & Ана Врањеш © 2013 сва права задржана"), 
            &sBaner );

        // position it properly

        r.bottom = rect.bottom;
        r.right = rect.right - 10;
        r.left = rect.right - rect.left - sBaner.cx - 10;
        r.top = rect.bottom - rect.top - sBaner.cy;

        // draw it 

        DrawTextEx( (HDC)wParam, 
            L" Дејан Миленић & Ана Врањеш © 2013 сва права задржана",
            wcslen(L" Дејан Миленић & Ана Врањеш © 2013 сва права задржана"), 
            &r, DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_WORDBREAK | DT_NOPREFIX, 0 );

        // perform proper cleanup

        SelectObject( (HDC)wParam, hfOld );

        DeleteObject(hf);
    }
    return (INT_PTR)GetStockObject(NULL_BRUSH);
// Fills triangle with gradient brush

void GradientTriangle( HDC MemDC, 
    LONG x1, LONG y1, LONG x2, LONG y2, LONG x3, LONG y3, 
    COLORREF top, COLORREF bottom )
{
    TRIVERTEX vertex[3];

    vertex[0].x     = x1;
    vertex[0].y     = y1;
    vertex[0].Red   = GetRValue(bottom) << 8;
    vertex[0].Green = GetGValue(bottom) << 8;
    vertex[0].Blue  = GetBValue(bottom) << 8;
    vertex[0].Alpha = 0x0000;

    vertex[1].x     = x2;
    vertex[1].y     = y2;
    vertex[1].Red   = GetRValue(top) << 8;
    vertex[1].Green = GetGValue(top) << 8;
    vertex[1].Blue  = GetBValue(top) << 8;
    vertex[1].Alpha = 0x0000;

    vertex[2].x     = x3;
    vertex[2].y     = y3; 
    vertex[2].Red   = GetRValue(bottom) << 8;
    vertex[2].Green = GetGValue(bottom) << 8;
    vertex[2].Blue  = GetBValue(bottom) << 8;
    vertex[2].Alpha = 0x0000;

    // Create a GRADIENT_TRIANGLE structure that
    // references the TRIVERTEX vertices.

    GRADIENT_TRIANGLE gTriangle;

    gTriangle.Vertex1 = 0;
    gTriangle.Vertex2 = 1;
    gTriangle.Vertex3 = 2;

    // Draw a shaded triangle.

    GradientFill( MemDC, vertex, 3, &gTriangle, 1, GRADIENT_FILL_TRIANGLE);
}

// draw the window's footer ( "status bar" )

void drawFooter( HDC MemDC, RECT r, COLORREF top, COLORREF bottom )
{
    // bottom triangle

    GradientTriangle( MemDC, 
        r.right, r.bottom, 
        ( r.right - r.left ) / 2,
        r.bottom - r.top - 15,
        r.left, 
        r.bottom, 
        top, bottom );

    // upper triangle

    GradientTriangle( MemDC, 
        r.right, r.bottom - r.top - 30, 
        ( r.right - r.left ) / 2, 
        r.bottom - r.top - 15,
        r.left, 
        r.bottom - r.top - 30, 
        top, bottom );

    // left triangle

    GradientTriangle( MemDC, 
        r.left, r.bottom, 
        ( r.right - r.left ) / 2, 
        r.bottom - r.top - 15,
        r.left, 
        r.bottom - r.top - 30, 
        top, bottom );

    // right triangle

    GradientTriangle( MemDC, 
        r.right, 
        r.bottom - r.top - 30,
        ( r.right - r.left ) / 2,
        r.bottom - r.top - 15, 
        r.right, 
        r.bottom, 
        top, bottom );

    // draw icon

    DrawIconEx( MemDC, r.left, r.bottom - r.top - 30, 
        hiAdmin, // a global variable for icon
        30, 30, NULL, NULL, DI_NORMAL );
}