-
HDC and HFONT
I'm curios as to why this
Code:
void initialize_font(HFONT hf, HWND hwnd) {
HDC hdc;
TEXTMETRIC tm;
hdc = GetDC(hwnd);
hf = CreateFont(20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
SelectObject(hdc, hf);
GetTextMetrics(hdc, &tm);
printf("Char Height is %d Average Char Width is %d\n", tm.tmHeight, tm.tmAveCharWidth);
}
results in a different average character width to this
Code:
void initialize_font(HFONT hf, HWND hwnd) {
HDC hdc, hdc2;
TEXTMETRIC tm;
hdc = GetDC(hwnd);
hdc2 = GetDC(hwnd);
hf = CreateFont(20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
SelectObject(hdc, hf);
GetTextMetrics(hdc2, &tm);
printf("Char Height is %d Average Char Width is %d\n", tm.tmHeight, tm.tmAveCharWidth);
}
I understand that each call to GetDC() will result in a different handle to the device context getting returned but shouldn't the handles both be pointing to the same client area and so have the same text metrics?
-
Perhaps you should try actually drawing some text using both device contexts, so you can see the difference.
> GetTextMetrics(hdc2, &tm);
Because it seems to me that this just returns whatever the default font of the dc is, before you would call selectObject with a new font.
-
To add to Salem's answer...
Think of a HDC as a structure. It contains a full set of default GDI objects when created or 'got' (GetDC), these include a FONT, PEN, BRUSH, etc
You changed the FONT in one HDC and not the other, so there should be a difference (unless the FONT you changed too was the same as the default FONT).
BTW You have a number of GDI leaks.
PCs have a very limited amount of GDI memory. Try adding GDI Objects to the items displayed in TaskManager and see how many you are leaking.
.NET compilers treat GDI objects as 'default' and will garbage collect them (at some point), but your code is just bad practice/form.
If you create a GDI object you should DeleteObject(), but DeleteObject() may not work while the GDI object is selected in a DC.
So if you use SelectObject() to change a GDI object in a DC you should catch the returned GDI object and SelectObject() this default GDI back into the DC so you can clean up both the GDI you created and the DC.
To clean up a DC you 'got' from GetDC() you should call ReleaseDC() (once you have returned the default GDI objects).
-
Now I understand what an HDC is, I can see that it will cause a leak in the above code as hdc is local to the function and so not accessible once the function returns. The font in question though is to be used throughout the life of the program, so do I really have to CreateFont() and DeleteObject() every time I want to use it rather than just deleting at the end of the program?
-
I cannot answer as I do not have enough info on how your app works.
Generally you create a memory DC when the app starts (with global scope), with its own bitmap and collection of GDIs (pen, brush, font, etc).
When the app closes you put the default GDIs back and clean up the GDIs you got or created.
When you need to draw to the screen you draw to this memory DC and generate a paint message.
Your paint handler then copies (BitBlt()) your memory DC to the screen DC from the PAINTSTRUCT filed in the BeginPaint().
If for some reason you only need a font...
Give the font global scope.
When you need to use it.
Code:
//witten from memory, not compiled....
//get the screen DC
HDC hdc = GetDC(NULL);
//select in the global font
HFONT *defaultFont = (HFONT*)SelectObject(hdc, globalFont);
//write text
//clean up
//put the DC back to default state
SelectObject(hdc, defaultFont);
//now release the DC
ReleaseDC(hdc);
NOTE: This should not be done in the WM_PAINT handler!