0
votes

I moved the following code from an MFC dialog-based project to an MFC library dll:

CWnd dummyWnd;
standard = new Gdiplus::Font(dummyWnd.GetDC()->GetSafeHdc(), &logfont); //GetDC() returns null, which did not happen in an MFC dialog-based app

I need a temporary DC to create gdiplus fonts, measure strings and other utility functionality.

My Questions:

  • is it possible to use CWnd as I've done in the dialog based app?
  • or can I simply get a DC for that purpose in another way?
2
Please double check your original code: CWnd dummyWnd; creates a unattached (no window) CWnd object; then dummyWnd.GetDC(); tries to get a client area Device Context with no window attached. This should fail. See: docs.microsoft.com/en-us/cpp/mfc/reference/… and docs.microsoft.com/en-us/cpp/mfc/reference/…Richard Critten
Thanks for replying. I now wonder why the code did work in the dialog based project. I did not create() it there either.Jan Feldmann
@RichardCritten Updated the code to the exact code I was using. Why did that work in a dialog based mfc app?Jan Feldmann
CDC::GetSafeHdc: strange remark in the docs "...this member function also works with null pointers...." Your guess as to what that means is a good as mine. source: docs.microsoft.com/en-us/cpp/mfc/reference/…Richard Critten
Use CClientDC dc(NULL) to get desktop dc, followed by CreateCompatibleDC... see exampleBarmak Shemirani

2 Answers

0
votes

To create a temporary dc:

//create memory dc 
CClientDC dc(NULL);
CDC memdc;
memdc.CreateCompatibleDC(&dc);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, width, height);
memdc.SelectObject(bitmap);

But in this case you may not need a temporary dc. You can simply use the desktop dc, as long as you are not writing on the desktop dc, or not selecting anything in to desktop dc.

To get the desktop dc, using Windows APIs:

HDC hdc = ::GetDC(0);
standard = new Gdiplus::Font(hdc, &logfont);
...
ReleaseDC(0, hdc); //cleaup

Alternatively, use MFC

CClientDC dc(NULL);
standard = new Gdiplus::Font(dc.GetSafeHdc(), &logfont);

As for temporary windows, dummyWnd.GetDC()->GetSafeHdc() fails in debug mode and raises error, because MFC will check if window handle is valid.

In release mode it may actually work because it ends up calling ::GetDC(NULL) which is valid. It will however end in resource leak because ReleaseDC is never called.

0
votes

Since the font will be drawn on specific windows, the device context of the windows will be required for correct drawing. You send CWnd* as parameter to your function, which will be exported by your dynamic library.

// MyMfcLibrary.cpp
void InitializeFont(CWnd* pWnd)
{
   CClientDC dc(pWnd);
   Gdiplus::Font myfont(dc.GetSafeHdc()->GetSafeHdc(), &logfont);
   /**/
}