News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Why does WM_CTLCOLORSTATIC crash?

Started by hotrod, January 01, 2010, 11:56:55 PM

Previous topic - Next topic

hotrod

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

MichaelW

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.
eschew obfuscation

sinsi

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.
Light travels faster than sound, that's why some people seem bright until you hear them.

sinsi

Light travels faster than sound, that's why some people seem bright until you hear them.

donkey

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
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

hotrod

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...

jj2007

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.

hotrod