Hi,
While revising my functions, I had to wonder if my CreateFont was not missing a parameter... Wouldn't be good if I added a hWnd parameter to pass to GetDC function instead of NULL. I'm not sure what difference it could make and this is what I ask here.
Also, do I need to use ReleaseDC to release the device context or is it useless in this case.
;
; Creates a font from the specified parameters
; The returned handle must be freed by the caller with DeleteObject
;
; Returns the font handle or NULL if it fails
;
; p_dwPointSize = Font size
; p_dwWeight = FW_ constant
; p_bItalic = Italic font (FALSE / TRUE)
; p_bUnderline = Underline font (FALSE / TRUE)
; p_bStrikeout = Strikeout font (FALSE / TRUE)
; p_lpszFontName = Pointer to the font name
;
AzmtCreateFontA PROC p_dwPointSize:DWORD, p_dwWeight:DWORD, p_bItalic:DWORD, \
p_bUnderline:DWORD, p_bStrikeout:DWORD, p_lpszFontName:DWORD
;
; nHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72)
;
invoke GetDC, NULL
invoke GetDeviceCaps, eax, LOGPIXELSY
mul p_dwPointSize
mov ecx, 72
add eax, 72/2 ; round the calculated point size to the nearest integer
xor edx, edx
div ecx
neg eax ; the font mapper provides the closest match for the character height (negative value)
invoke CreateFontA, eax, 0, 0, 0, p_dwWeight, p_bItalic, p_bUnderline, p_bStrikeout, DEFAULT_CHARSET, \
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, p_lpszFontName
ret
AzmtCreateFontA ENDP
Any comments about improvements are welcomed.
Per the documentation for the GetDC function:
QuoteThe GetDC function retrieves a common, class, or private DC depending on the class style of the specified window.
...
After painting with a common DC, the ReleaseDC function must be called to release the DC.
Per the documentation for the ReleaseDC function:
Quote
It has no effect on class or private DCs
So I think if the DC obtained with GetDC(null) is a common DC, then ReleaseDC should be able to free it. This test code, which should be compiled as a console app, indicates that the DC obtained with GetDC(null) is a common DC, and therefore should be released with ReleaseDC.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
hInst dd 0
hWnd dd 0
_x dd 0
_y dd 0
hdc_common dd 0
hdc_window dd 0
hdc_private dd 0
wc WNDCLASSEX <>
msg MSG <>
className db "test_class",0
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
mov hInst, rv(GetModuleHandle, NULL)
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_OWNDC ; <== to create private DC
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInst
mov wc.hbrBackground, rv(GetStockObject, BLACK_BRUSH)
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, OFFSET className
mov wc.hIcon, rv(LoadIcon, NULL, IDI_APPLICATION)
mov wc.hCursor, rv(LoadCursor, NULL, IDC_ARROW)
mov wc.hIconSm, 0
invoke RegisterClassEx, ADDR wc
W = 400
H = 300
invoke GetSystemMetrics, SM_CXSCREEN
shr eax, 1
sub eax, W / 2
mov _x, eax
invoke GetSystemMetrics, SM_CYSCREEN
shr eax, 1
sub eax, H / 2
mov _y, eax
invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW,
ADDR className,
chr$("Test"),
WS_OVERLAPPED or WS_SYSMENU,
_x, _y, W, H,
NULL, NULL,
hInst, NULL
mov hWnd, eax
invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke UpdateWindow, hWnd
msgLoop:
invoke GetMessage, ADDR msg, NULL, 0, 0
.IF eax != 0
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp msgLoop
.ENDIF
exit msg.wParam
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
WndProc proc hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg
CASE WM_CREATE
invoke GetDC, NULL
mov hdc_common, eax
.IF hdc_common == 0
print "GetDC(NULL) failed",13,10
.ENDIF
invoke GetWindowDC, hwnd
mov hdc_window, eax
.IF hdc_window == 0
print "GetWindowDC(hwnd) failed",13,10
.ENDIF
invoke GetDC, hwnd
mov hdc_private, eax
.IF hdc_private == 0
print "GetDC(hwnd) failed",13,10
.ENDIF
;-----------------------------------
; ReleaseDC always returns success.
;-----------------------------------
print "ReleaseDC(hwnd, hdc_common):",9
invoke ReleaseDC, hwnd, hdc_common
print ustr$(eax),13,10
print "ReleaseDC(hwnd, hdc_window):",9
invoke ReleaseDC, hwnd, hdc_window
print ustr$(eax),13,10
print "ReleaseDC(hwnd, hdc_private):",9
invoke ReleaseDC, hwnd, hdc_private
print ustr$(eax),13,10,13,10
;------------------------------------------------
; ReleaseDC frees only common and window DCs, so
; SaveDC should now fail for a common or window
; DC and succeed for a private DC.
;------------------------------------------------
print "SaveDC(hdc_common):",9
invoke SaveDC, hdc_common
.IF eax == 0
mov eax,LastError$()
print eax,13,10
.ELSE
print "OK"
.ENDIF
print "SaveDC(hdc_window):",9
invoke SaveDC, hdc_window
.IF eax == 0
mov eax,LastError$()
print eax,13,10
.ELSE
print "OK"
.ENDIF
print "SaveDC(hdc_private)",9
invoke SaveDC, hdc_private
.IF eax == 0
print ustr$(eax),13,10
mov eax,LastError$()
print eax,13,10
.ELSE
print "OK"
.ENDIF
CASE WM_CLOSE
invoke DestroyWindow, hwnd
CASE WM_DESTROY
invoke PostQuitMessage, NULL
DEFAULT
invoke DefWindowProc, hwnd, uMsg, wParam, lParam
ENDSW
ret
WndProc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
ReleaseDC(hwnd, hdc_common): 1
ReleaseDC(hwnd, hdc_window): 1
ReleaseDC(hwnd, hdc_private): 1
SaveDC(hdc_common): The handle is invalid.
SaveDC(hdc_window): The handle is invalid.
SaveDC(hdc_private) OK
Michael,
It is not all the examples I've found on the web that use ReleaseDC in a function like that and that's why I posted this question because I couldn't find a reason anywhere. Also, the difference between common, class and private DCs is not evident or should I say, is not evident for a person like me who don't know alot about the underlying knowledge of GUI stuff. MSDN is not always crystal clear for noobs.
I didn't thought to do a test like yours and, as always, your methodology is perfect.
Thanks
Quote from: jdoe on December 05, 2008, 08:01:42 PM
Also, the difference between common, class and private DCs is not evident or should I say, is not evident for a person like me who don't know alot about the underlying knowledge of GUI stuff. MSDN is not always crystal clear for noobs.
A DC is private
ONLY when you create a window with the class style CS_OWNDC, all other DCs are common (Class DCs are not applicable to Win32/64, they are a legacy from 16 bit Windows and can be ignored). So, you must always call ReleaseDC except in the extremely rare case that you have decided to manage your own DC.
Hope this answers your question about DC types.
Quote from: donkey on December 06, 2008, 08:49:06 AM
Hope this answers your question about DC types.
For sure it does !
:U