[英]BeginDraw() paints over statusbar - resizing of renderTarget not respected
I have a windowed Direct2D app and added a statusbar to the window from common controls:我有一个窗口化的 Direct2D 应用程序,并从常用控件向窗口添加了一个状态栏:
InitCommonControls();
HWND hStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0,
hWnd, (HMENU)ID_STATUSBAR, GetModuleHandle(NULL), NULL);
The statusbar is showing up just fine, but as soon as I activate the BeginDraw()
& EndDRaw()
functions in my message loop, the statusbar is painted over, despite the fact I defined the height of the renderTarget
when initialising it状态栏显示得很好,但是一旦我在我的消息循环中激活了
BeginDraw()
和EndDRaw()
函数,状态栏就会被绘制出来,尽管我在初始化时定义了renderTarget
的高度
res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
GetClientRect(windowHandle, &rectWindow);
GetClientRect(statusHandle, &rectStatus);
rectRender.width = rectWindow.right;
rectRender.height = rectWindow.bottom - (rectStatus.bottom - rectStatus.top);
res = factory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(windowHandle, rectRender),
&renderTarget);
I also created a resize function我还创建了一个调整大小功能
RECT rectWindow{ 0 }, rectStatus{ 0 };
D2D1_SIZE_U rectRender{ 0 };
GetClientRect(windowHandle, &rectWindow);
GetClientRect(statusHandle, &rectStatus);
rectRender.width = rectWindow.right;
rectRender.height = rectWindow.bottom - (rectStatus.bottom - rectStatus.top);
renderTarget->Resize(rectRender);
InvalidateRect(windowHandle, NULL, FALSE);
and called in in WM_SIZING
and WM_SIZE:并呼吁在
WM_SIZING
和WM_SIZE:
case WM_SIZE:
case WM_SIZING:
hStatus = GetDlgItem(hWnd, ID_STATUSBAR);
gfx->Resize(hWnd, hStatus);
SendMessage(hStatus, WM_SIZE, 0, 0);
Doesn't BeginDraw()
respect the dimensions of the rendertarget and just take the entire window? BeginDraw()
尊重BeginDraw()
的尺寸并只占用整个窗口吗? And if so, should I consider using layers or is there something wrong in my code?如果是这样,我应该考虑使用层还是我的代码有问题?
EDIT: I received some downvotes for this question.编辑:我收到了一些反对这个问题的票。 If there's something wrong with my post, do let me know and I'll try to improve.
如果我的帖子有问题,请告诉我,我会努力改进。 I'm still fresh in the win32 world, but I've learned a lot from this platform.
我对 win32 世界还很陌生,但我从这个平台上学到了很多东西。 I would love to contribute with interesting questions and answers, but a simple -1 doesn't give me a clue what to improve.
我很乐意提供有趣的问题和答案,但是一个简单的 -1 并没有给我提供改进的线索。 I've read 2 evenings about the subject on MSDN and various forums but didn't see what I do wrong.
我已经在 MSDN 和各种论坛上阅读了 2 个晚上的主题,但没有看到我做错了什么。 I tried be as complete as possible by writing an complete example code that illustrates the issue.
我尝试通过编写说明问题的完整示例代码来尽可能完整。
For reference the entire code供参考整个代码
#include <windows.h>
#include <CommCtrl.h>
#include <d2d1.h>
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "d2d1.lib")
#define ID_STATUSBAR 1000
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
class Graphics
{
ID2D1Factory* factory;
ID2D1HwndRenderTarget* renderTarget;
ID2D1SolidColorBrush* brush;
public:
Graphics()
{
factory = NULL;
renderTarget = NULL;
brush = NULL;
}
~Graphics()
{
if (factory) factory->Release();
if (renderTarget) renderTarget->Release();
if (brush) brush->Release();
}
bool Init(HWND windowHandle, HWND statusHandle);
void BeginDraw() { renderTarget->BeginDraw(); }
void EndDraw() { renderTarget->EndDraw(); }
void Resize(HWND windowHandle, HWND statusHandle);
void DrawCircle(float x, float y, float r);
};
HINSTANCE hInstance;
Graphics* gfx;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
InitCommonControls();
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = TEXT("mainwindow");
RegisterClass(&wc);
HWND hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, TEXT("mainwindow"),
TEXT("MainWindow"), WS_OVERLAPPEDWINDOW, 100, 100, 800, 600,
NULL, NULL, hInstance, NULL);
if (!hWnd) return -1;
HWND hStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0,
hWnd, (HMENU)ID_STATUSBAR, GetModuleHandle(NULL), NULL);
gfx = new Graphics;
if (!gfx->Init(hWnd, hStatus))
{
delete gfx;
return -1;
}
ShowWindow(hWnd, nCmdShow);
MSG message{ 0 };
bool runGame = true;
while (runGame)
{
while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
if (message.message == WM_QUIT)
runGame = false;
}
gfx->BeginDraw();
gfx->DrawCircle(400.0f, 100.0f, 100.0f);
gfx->DrawCircle(400.0f, 300.0f, 100.0f);
gfx->DrawCircle(400.0f, 500.0f, 100.0f);
gfx->EndDraw();
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND hStatus;
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_SIZE:
case WM_SIZING:
hStatus = GetDlgItem(hWnd, ID_STATUSBAR);
gfx->Resize(hWnd, hStatus);
SendMessage(hStatus, WM_SIZE, 0, 0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
bool Graphics::Init(HWND windowHandle, HWND statusHandle)
{
RECT rectWindow{ 0 }, rectStatus{ 0 };
D2D1_SIZE_U rectRender{ 0 };
HRESULT res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
if (res != S_OK) return false;
GetClientRect(windowHandle, &rectWindow);
GetClientRect(statusHandle, &rectStatus);
rectRender.width = rectWindow.right;
rectRender.height = rectWindow.bottom - (rectStatus.bottom - rectStatus.top);
res = factory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(windowHandle, rectRender),
&renderTarget);
if (res != S_OK) return false;
res = renderTarget->CreateSolidColorBrush(D2D1::ColorF(1, 0, 0, 0), &brush);
if (res != S_OK) return false;
return true;
}
void Graphics::Resize(HWND windowHandle, HWND statusHandle)
{
if (renderTarget != NULL)
{
RECT rectWindow{ 0 }, rectStatus{ 0 };
D2D1_SIZE_U rectRender{ 0 };
GetClientRect(windowHandle, &rectWindow);
GetClientRect(statusHandle, &rectStatus);
rectRender.width = rectWindow.right;
rectRender.height = rectWindow.bottom - (rectStatus.bottom - rectStatus.top);
renderTarget->Resize(rectRender);
}
}
void Graphics::DrawCircle(float x, float y, float r)
{
brush->SetColor(D2D1::ColorF(1.0f, 0.0f, 0.0f, 1.0f));
renderTarget->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), r, r), brush, 1.0f);
}
You can add WS_CLIPCHILDREN
window style to your MainWindow
:您可以将
WS_CLIPCHILDREN
窗口样式添加到MainWindow
:
HWND hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, TEXT("mainwindow"),
TEXT("MainWindow"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 100, 100, 800, 600,
NULL, NULL, hInstance, NULL);
Alternatively, you can create another child window (sibling to status bar) and use that for your Direct2D
target.或者,您可以创建另一个子窗口(与状态栏同级)并将其用于
Direct2D
目标。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.