GDI+ 文本闪烁,现在有黑色背景
GDI+ Text Flickering and Now with Black background
我正在开发 windows 桌面应用程序,令我沮丧的是我的文本在闪烁,因此在搜索时我发现了两种方法 - return true 用于 erasebkgnd 和双缓冲。第一种方法没有做任何事情,第二种方法由于某种原因使我的背景全黑并且它仍然闪烁。
下面是我调用绘画和缓冲的地方:
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
putImage(screen, hWnd);
RECT rc;
GetClientRect(hWnd, &rc);
HDC memdc;
auto hbuff = BeginBufferedPaint(screen, &rc, BPBF_COMPATIBLEBITMAP, NULL, &memdc);
EndBufferedPaint(hbuff, TRUE);
EndPaint(hWnd, &ps); } break;
下一部分是 putImage 函数
void putImage(HDC hdc, HWND hWnd)
{
Graphics graphic(hdc);
graphic.DrawImage(Image::FromFile(filePath), 10, 10);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
我想知道问题出在哪里,是否有解决办法。
my background all black
这个问题是因为你的背景没有填满。您可以像这样在绘制图像之前填充背景:
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
flickering
此问题是由于未正确使用 BeginBufferedPaint
。在绘制图像之前调用 BeginBufferedPaint
:
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
if (hbuff)
{
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
putImage(screen, hWnd);
hr = EndBufferedPaint(hbuff, TRUE);
}
EndPaint(hWnd, &ps); } break;
别忘了打电话给 BufferedPaintInit
and BufferedPaintUnInit
。例如像这样:
case WM_CREATE:
{
hr = BufferedPaintInit();
}
break;
//...
case WM_DESTROY:
{
BufferedPaintUnInit();
PostQuitMessage(0);
}
break;
更新:完整代码。
void putImage(HDC hdc, HWND hWnd)
{
Graphics graphic(hdc);
Image* image = Image::FromFile(L"path-to\test.png");
Status status = graphic.DrawImage(image, 10, 10);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DWORD err;
HRESULT hr;
static HDC memdc;
switch (message)
{
case WM_CREATE:
{
hr = BufferedPaintInit();
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
if (hbuff)
{
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
putImage(screen, hWnd);
hr = EndBufferedPaint(hbuff, TRUE);
}
EndPaint(hWnd, &ps); } break;
case WM_DESTROY:
{
BufferedPaintUnInit();
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
我正在开发 windows 桌面应用程序,令我沮丧的是我的文本在闪烁,因此在搜索时我发现了两种方法 - return true 用于 erasebkgnd 和双缓冲。第一种方法没有做任何事情,第二种方法由于某种原因使我的背景全黑并且它仍然闪烁。
下面是我调用绘画和缓冲的地方:
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
putImage(screen, hWnd);
RECT rc;
GetClientRect(hWnd, &rc);
HDC memdc;
auto hbuff = BeginBufferedPaint(screen, &rc, BPBF_COMPATIBLEBITMAP, NULL, &memdc);
EndBufferedPaint(hbuff, TRUE);
EndPaint(hWnd, &ps); } break;
下一部分是 putImage 函数
void putImage(HDC hdc, HWND hWnd)
{
Graphics graphic(hdc);
graphic.DrawImage(Image::FromFile(filePath), 10, 10);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
我想知道问题出在哪里,是否有解决办法。
my background all black
这个问题是因为你的背景没有填满。您可以像这样在绘制图像之前填充背景:
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
flickering
此问题是由于未正确使用 BeginBufferedPaint
。在绘制图像之前调用 BeginBufferedPaint
:
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
if (hbuff)
{
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
putImage(screen, hWnd);
hr = EndBufferedPaint(hbuff, TRUE);
}
EndPaint(hWnd, &ps); } break;
别忘了打电话给 BufferedPaintInit
and BufferedPaintUnInit
。例如像这样:
case WM_CREATE:
{
hr = BufferedPaintInit();
}
break;
//...
case WM_DESTROY:
{
BufferedPaintUnInit();
PostQuitMessage(0);
}
break;
更新:完整代码。
void putImage(HDC hdc, HWND hWnd)
{
Graphics graphic(hdc);
Image* image = Image::FromFile(L"path-to\test.png");
Status status = graphic.DrawImage(image, 10, 10);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DWORD err;
HRESULT hr;
static HDC memdc;
switch (message)
{
case WM_CREATE:
{
hr = BufferedPaintInit();
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
if (hbuff)
{
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
putImage(screen, hWnd);
hr = EndBufferedPaint(hbuff, TRUE);
}
EndPaint(hWnd, &ps); } break;
case WM_DESTROY:
{
BufferedPaintUnInit();
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}