Question regarding amount of render targets in Direct2D

I'm working on calculator project, it consists of several BS_OWNERDRAW style buttons to represent numbers.

I create ID2D1HwndRenderTarget for each of these buttons, that is I have a render target pointer for each child control, to perform drawing.

Drawing common controls with directX is possible by binding HDC to direct2D render target
ID2D1HwndRenderTarget->BinDC(...)

My question is: is this correct way? is it good to have so many render targets, for each child control?
I heard we should not use multiple render targets in program, but how do we then draw individual controls with Direct2D?

thanks in advance!


edit:
I gave an example of calculator program, but my question is in general, is it ok to create render targets for each control or part of a window.
Last edited on
malibor wrote:
My question is: is this correct way? is it good to have so many render targets, for each child control?
I heard we should not use multiple render targets in program, but how do we then draw individual controls with Direct2D?
I don't have any answer for you. I've been looking through various docs and tutorials on and off over the past few days as I want to use Direct2D with an MFC (probably) project that will require custom controls. At the moment I have only seen one ID2D1HwndRenderTarget used.
Last edited on
Thank you for input, I'm going trough various docs and tuts as well and regarding this problem I learned that drawing common or custom controls with Direct2D is possible with single render target.

but it's ID2D1DCRenderTarget not ID2D1HwndRenderTarget note the DC prefix instead of Hwnd!

basically single ID2D1DCRenderTarget is used to draw multiple common controls by binding HDC to render target ID2D1DCRenderTarget->BinDC(...)

You might me interested in reading following:
https://docs.microsoft.com/en-us/windows/desktop/direct2d/direct2d-and-gdi-interoperation-overview

Here is example code snippet from my project for drawing a BS_OWNERDRAW buttons with direct2d

I put comment on most important part of the code where single render target is used for drawing.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...SNIP...
class MainWindow : public BaseWindow<MainWindow>
{
public:
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;

private:
	ID2D1Factory* pDirectFactory = nullptr;
	IDWriteFactory* pWriteFactory = nullptr;
	ID2D1DCRenderTarget* pRenderButton = nullptr; // here is single render target for buttons
	ID2D1HwndRenderTarget* pRenderWindow = nullptr;
	ID2D1SolidColorBrush* pBrush = nullptr;
	IDWriteTextFormat* pTextFormat = nullptr;

...SNIP...


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
...SNIP...
void MainWindow::DrawButton(const LPARAM& lParam) // function called during WM_DRAWITEM message for all buttons
{
	HRESULT hr = CreateGraphicsResources();

	if (SUCCEEDED(hr))
	{
		auto pdis = (DRAWITEMSTRUCT*)lParam;
		std::wstring text = GetButtonText(pdis->CtlID);

		pRenderButton->BindDC(pdis->hDC, &pdis->rcItem); // here bind HDC of a button to rendertarget
		pRenderButton->BeginDraw();
		if (pdis->itemState & ODS_SELECTED)
		{
			D2D1_RECT_F layoutRect = D2D1::RectF(
				static_cast<float>(pdis->rcItem.left + 1.f),
				static_cast<float>(pdis->rcItem.top + pdis->rcItem.bottom / 4.f + 1.f),
				static_cast<float>(pdis->rcItem.right),
				static_cast<float>(pdis->rcItem.bottom));

			D2D1_POINT_2F pt1 = D2D1::Point2F(static_cast<float>(pdis->rcItem.left), static_cast<float>(pdis->rcItem.top));
			D2D1_POINT_2F pt2 = D2D1::Point2F(static_cast<float>(pdis->rcItem.left), static_cast<float>(pdis->rcItem.bottom));
			D2D1_POINT_2F pt3 = D2D1::Point2F(static_cast<float>(pdis->rcItem.right), static_cast<float>(pdis->rcItem.top));

			pRenderButton->Clear(D2D1_COLOR_F(D2D1::ColorF(D2D1::ColorF::LightGray)));
			pBrush->SetColor(D2D1::ColorF(D2D1::ColorF::DarkGray));
			pRenderButton->DrawLine(pt1, pt2, pBrush, 4.f);
			pRenderButton->DrawLine(pt1, pt3, pBrush, 4.f);

			pBrush->SetColor(D2D1::ColorF(D2D1::ColorF::Black));
			pRenderButton->DrawText(
				text.c_str(),
				static_cast<UINT32>(text.length()),
				pTextFormat,
				layoutRect, pBrush);
		}
		hr = pRenderButton->EndDraw();

		if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
		{
			DischardGraphicsResources();
		}
... SNIP...
Last edited on
but it's ID2D1DCRenderTarget not ID2D1HwndRenderTarget note the DC prefix instead of Hwnd!
yeh, I was reading about ID2D1HwndRenderTarget so it was fresh in my head, I did mean ID2D1DCRenderTarget.
Last edited on
Registered users can post here. Sign in or register to post.