I have a combobox with 100 items in it which, when scrolled, makes continuous changes to 42 statics. If the combobox is colasped and the combo is scrolled, the text becomes invisible and the color of the statics disappears after scrolling through approx 50+ items. If the following code is remarked out, the text in the combo stays visible. Why? thanks...
.elseif uMsg==WM_CTLCOLORSTATIC ; Sets unidentifed statics to 00FF8888h.
invoke SetTextColor, wParam, 0
invoke SetBkMode, wParam, TRANSPARENT
mov eax, lParam
cmp eax, hSTC_DATE
jne _noColor
invoke CreateSolidBrush, 00FFBBBBh
ret
_noColor:
invoke SetTextColor, wParam, 0FFFFFFh
invoke CreateSolidBrush, 0008800h
ret
From the remarks section for the WM_CTLCOLORSTATIC documentation:
Quote
The system does not automatically destroy the returned brush. It is the application's responsibility to destroy the brush when it is no longer needed.
You could test this by substituting GetSysColorBrush for GetSolidBrush and see if the problem goes away. Alternatively, you could create brushes of the necessary colors using GetSolidBrush in your WM_CREATE or WM_INITDIALOG handler, return the handle of one of these brushes from your WM_CTLCOLORSTATIC handler, and then delete the brushes with DeleteObject before your application exits.
Yes, part of the problem might be that you create a brush on every WM_CTLCOLORSTATIC message, which can occur a hell of a lot, and you run out of resources.
As michael said, create them all first then return the saved brush handle.
Any sort of gdi handle uses resources, that's why msdn usually says to delete it as soon as you've finished with it.
This post reminded me: Why is the limit of window handles per process 10,000?
(http://blogs.msdn.com/oldnewthing/archive/2007/07/18/3926581.aspx)
Here's your snippet modified to work a little more politely with the GDI...
.elseif uMsg==WM_CREATE ; or WM_INITDIALOG for dialog boxes
invoke CreateSolidBrush, 00FFBBBBh
mov hBrushUnknown, eax
invoke CreateSolidBrush, 0008800h
mov hBrushNormal, eax
mov eax,FALSE
ret
.elseif uMsg==WM_CTLCOLORSTATIC ; Sets unidentifed statics to 00FF8888h.
invoke SetTextColor, wParam, 0
invoke SetBkMode, wParam, TRANSPARENT
mov eax, lParam
cmp eax, hSTC_DATE
jne _noColor
mov eax,hBrushUnknown
ret
_noColor:
invoke SetTextColor, wParam, 0FFFFFFh
mov eax,hBrushNormal
ret
.elseif uMsg==WM_CLOSE
invoke DeleteObject, hBrushUnknown
invoke DeleteObject, hBrushNormal
All of you are correct, I moved the CreateSolidBrush to WM_INITDIALOG and it worked, but this brought up another question. I tried creating the handles LOCAL and they did not work. I moved them to .data and and the did work, (again) why? Thanks...
Quote from: hotrod on January 02, 2010, 11:54:41 AM
I tried creating the handles LOCAL and they did not work.
LOCAL variables are valid until you hit the
ret. In a WndProc, you must rely on permanent variables. So you need to use the .data or, better, the .data? section for handles that are being used permanently.
You can and should use LOCAL handles only if you create, use and immediately delete an object.
Thanks to all for the info.