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