In a previous thread, I stated that ComboBox had problems with using GetWindowLong or SetWindowLong in conjunction with the GWL_USERDATA offset. As Donkey pointed out later, there is nothing wrong with the GWL_USERDATA offset on ComboBoxes.

The problem turns out to be that since I was using GWL_USERDATA to hold the address of my control descriptor, a handle with a null in this long would cause a bad pointer to my descriptor and blow up the program.

This is, in fact, the case with the ComboBox control. For the ctlcolor event for the text box portion, I get a handle containing 0 in the GWL_USERDATA offset. I detect this and do a GetParent and then check its GWL_USERDATA offset. It is a valid pointer to my ComboBox ComboBox descriptor, which I then use (with success).

If, in trying the GetParent, I still get a null pointer in GWL_USERDATA, so I jump to defwndproc.

My question is how can I obtain the handle that is presented when the listbox portion of the combobox is being colored with the ctlcolor event?
Posted on 2003-07-24 21:23:35 by msmith
The listbox for a combobox will never return the actual parent as it is actually last in a chain of windows of which the combobox is the root, use the following instead:
.ELSEIF eax == WM_CTLCOLORLISTBOX

invoke GetAncestor,lParam,GA_ROOT
This will return the handle of the ComboBox which owns the listbox

Sorry mssmith, I just tried that and it doesn't work, it just returns the same handle. I have a few ideas...
Posted on 2003-07-24 22:25:02 by donkey
OK, here's the thing, the listbox that is attached to the combobox has to be able to be displayed outside the bounding rectangle of the control. The problem is that the edit box is the bounding rectangle so the actual combo box cannot be the parent otherwise you would never see the listbox. In order to allow it to display properly MS pulled a fast one, they appear to have made the Desktop window it's parent, IOW there is no way to identify the combobox from the listbox handle, dumb move but that's the size of it. My only suggestion is to create a superclass and use that in place of all combo-boxes, set the extra info size to 4 and store the handle of the combo box there.
Posted on 2003-07-24 22:53:33 by donkey
Hi Donkey,

Thanks for the effort.

I guess with your second reply you will not be surprised at the following:

GA_ROOT and GA_ROOTOWNER make no color on either the text or the listbox sections.

GA_PARENT works like GetParent in that they both allow coloring of the text section but not the listbox section.

I haven't tried supercalssing yet. Is it difficult? (I know read the tutorial) :)
Posted on 2003-07-24 23:09:11 by msmith
It is also unfortunately very diffcult to superclass a combobox, all of my attempts in the last half hour have failed miserably. I checked the knowledge base, they had this, it was as I suspected:
However, the ComboLBox (list box) window for combo boxes that have the CBS_DROPDOWN or CBS_DROPDOWNLIST style is not a child of the ComboBox window. Instead, each ComboLBox window is a child of the desktop window. This is required so that, when the drop-down list box is dropped, it can extend outside the application window or dialog box. Otherwise, the list box would be clipped at the window or dialog box border.

Because the ComboLBox window is not a child of the ComboBox window, there is no simple method to get the handle of one window, given the other. For example, given a handle to the ComboBox, the handle to any associated drop- down list box is not readily available. The ComboLBox is a private class registered by USER that is a list box with the class style CS_SAVEBITS.

The best I can say is that the ComboBox listbox is not colored until it is displayed, at that point the WM_CTLCOLORLISBOX message is sent to get the brush handle. Since you have to press the button to have it displayed the combo box must have the focus when this message is recieved (as far as I can tell) so you can get the parent handle with a getfocus call. It's a hack method but I can't think of an exception offhand.

The handle of the listbox is available to the GetComboBoxInfo function, you can then use that to check the handle against, that's the only way I can think of that will guarantee a perfect match.
Posted on 2003-07-24 23:33:26 by donkey
Thanks again Donkey,

It's getting too late to try tonight, but it sounds like that last idea (GetComboBoxInfo function) might just work.

If it is OK to invoke the GetComboBoxInfo function immediately after creating the combo box, I will do so and then do a SetWindowLong on each of the 3 resultant handles, stuffing each one's GWL_USERDATA with the address of my descriptor. Then when the user causes the list box to drop down, the ctlcolor event will occur, and I will get a non-zero on the listbox's GWL_USERDATA and point to the correct descriptor, causing it to be colored.
Posted on 2003-07-25 01:13:25 by msmith
When I invoke GetComboBoxInfo, it returns an error 57 (hex) which is ERROR_INVALID_PARAMETER. Since there are 7 dwords in the structure, I assum I should put 28 into the first dword.




!Rect1 rd 4
!Rect2 rd 4

!cbSize dd 28
!rcItem dd !Rect1
!rcButton dd !Rect2
!stateButton dd 0
!hwndCombo dd 0
!hwndItem dd 0
!hwndList dd 0

...

invoke CreateWindowEx,0,!ControlType4,NULL,WS_VSCROLL+WS_VISIBLE+WS_CHILD+CBS_DROPDOWN,0,0,80,30,[OBMain],104,[!hinstance],NULL
mov [ComboBox],eax
invoke GetComboBoxInfo,[ComboBox],!cbSize

Posted on 2003-07-25 14:15:36 by msmith
I get 52 bytes for COMBOBOXINFO :
COMBOBOXINFO STRUCT

cbSize DWORD ? ;-> 4
rcItem RECT <?> ;-16
rcButton RECT <?> ;->16
stateButton DWORD ? ;-> 4
hwndCombo DWORD ? ;-> 4
hwndItem DWORD ? ;-> 4
hwndList DWORD ? ;-> 4
COMBOBOXINFO ENDS
Posted on 2003-07-25 14:27:33 by donkey
It looks to me like items 2 and 3 should be pointer to type rect, not the rect structures themselves which puts us back to 28.

MSDN says:


rcItem
Pointer to a RECT structure that specifies the coordinates of the edit box.
rcButton
Pointer to a RECT structure that specifies the coordinates of the button that contains the drop-down arrow.
Posted on 2003-07-25 14:57:58 by msmith
Our docs are at odds, mine say that they are RECT structures. (mine works BTW).
[b]Members[/b]


[b]cbSize[/b]
Specifies the size, in bytes, of the structure. The caller must set this to sizeof(COMBOBOXINFO).
[b]rcItem[/b]
A [b]RECT[/b] structure that specifies the coordinates of the edit box.
[b]rcButton[/b]
A [b]RECT[/b] structure that specifies the coordinates of the button that contains the drop-down arrow.
[b]stateButton[/b]
Specifies the combo box button state. This parameter can be one of the following values.
0 The button exists and is not pressed.
STATE_SYSTEM_INVISIBLE There is no button.
STATE_SYSTEM_PRESSED The button is pressed.
[b]hwndCombo[/b]
Handle to the combo box.
[b]hwndItem[/b]
Handle to the edit box.
[b]hwndList[/b]
Handle to the drop-down list.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/comboboxes/comboboxreference/comboboxstructures/comboboxinfo.asp
Posted on 2003-07-25 15:02:19 by donkey
Your right, the docs are at odds. Yours was right.

My program now has colored comboboxes (both edit and list).

The correct info was free off the web. The incorrect docs cost me $170.00 (MSDN subcription)

Thanks again.
Posted on 2003-07-25 16:21:03 by msmith
The MSDN library is now available as a three ISO download from Microsoft for free (APR 2003) that's where I got mine:

http://www.asmcommunity.net/board/index.php?topic=13270&highlight=MSDN+library
Posted on 2003-07-25 16:25:03 by donkey
Assuming the files ever finish downloading :) how do I open them?
Posted on 2003-07-26 16:44:43 by msmith
They have to burned onto a CD, they are in ISO format so any cd writer software can handle them. In Nero, just select "Burn Image" and choose the iso file.
Posted on 2003-07-26 16:48:18 by donkey
Posted on 2003-07-26 16:57:39 by lingo12