Reputation: 65
I have a windowed Direct2D app and added a statusbar to the window from common controls:
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
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:
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? 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. I would love to contribute with interesting questions and answers, but a simple -1 doesn't give me a clue what to improve. I've read 2 evenings about the subject on MSDN and various forums but didn't see what I do wrong. 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);
}
Upvotes: 0
Views: 133
Reputation: 11311
You can add WS_CLIPCHILDREN
window style to your 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.
Upvotes: 1