-
Oct 31st, 2014, 04:41 PM
#1
[RESOLVED] Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Anyone figured out how to "Add" an item to the ImageCombo control using API calls?
This is related to a request by fafalone but I'm taking a slightly different approach.
Just FYI, I know I could do it if I actually created the ImageControl from scratch, but I want to use the ImageCombo out of the mscomctl.ocx (Microsoft Windows Common Controls 6.0 (SP6)). It's just more intuitive to me when it's done that way. Maybe I'll make a custom control, but I'll still start with that control.
Ok, all I want to do is add a new item to that control via API. It's easy to do on the regular ComboBox. Just a bit of...
Code:
s = "hello world"
SendMessage Combo1.hWnd, CB_ADDSTRING, 0, s
... and voilĂ , you've got a new item. However, this just won't work with the ImageCombo. Here are some things I've tried, just taking shots in the dark:
Code:
s = "hello world"
SendMessage ImageCombo1.hWnd, CB_ADDSTRING, 0, s
or
SendMessage ImageCombo1.hWnd, CBEM_INSERTITEMA, 0, s
or
hCombo = SendMessage(ImageCombo1.hWnd, CBEM_GETCOMBOCONTROL, 0, ByVal 0&)
SendMessage hCombo, CB_ADDSTRING, 0, s
or
hCombo = SendMessage(ImageCombo1.hWnd, CBEM_GETCOMBOCONTROL, 0, ByVal 0&)
SendMessage hCombo, CBEM_INSERTITEMA, 0, s
All zip, nada, no cigar.
I'll explain why I want to do this if someone wants, but if anyone has a clue, that'd be great.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Oct 31st, 2014, 04:59 PM
#2
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
The VB control is really a container for 2 other controls. Inside of that control are 2 other controls: an owner drawn combobox and the edit control (textbox-like). So, you'd have to locate the combobox first & use that hWnd instead. So FindWindowEx or any other API that will return child windows of the imagecombo should do the trick.
-
Oct 31st, 2014, 05:23 PM
#3
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
*nods and also shakes my head*
Alrighty then, off to the land of EnumChildWindows. I'll be back, unless I can't find my way back from the rabbit-hole.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Oct 31st, 2014, 05:27 PM
#4
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Use FindWindowEx. EnumChildWindows requires a callback function & is overkill for a control that has just 2 children.
-
Oct 31st, 2014, 08:01 PM
#5
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
I'm actually just getting back from some chores, and I was actually already thinking that. EnumChildWindows was just what came to mind as a response. Now let's see if I can get to the bottom of this thing.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Oct 31st, 2014, 08:23 PM
#6
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Hmmm, The actual ImageCombo seems to have only one child, belonging to "ComboBox" class. That "ComboBox" window seems to have one further child, of the "Edit" class. In other words:
Code:
h1 = GetWindow(ImageCombo1.hWnd, GW_CHILD) ' This returns a handle to a "ComboBox" class.
h1 = GetWindow(h1, GW_HWNDNEXT) ' Returns ZERO.
or
Code:
h1 = GetWindow(ImageCombo1.hWnd, GW_CHILD)
h2 = GetWindow(h1, GW_CHILD) ' This returns handle to "Edit" class.
h2 = GetWindow(h2, GW_HWNDNEXT) ' Returns ZERO.
but what's most disturbing is:
Code:
h1 = GetWindow(ImageCombo1.hWnd, GW_CHILD)
h2 = SendMessage(ImageCombo1.hWnd, CBEM_GETCOMBOCONTROL, 0, 0)
(the above two return the exact same handle)
So, since the last two statements return the same handle, I seem to be back to square one.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Oct 31st, 2014, 08:24 PM
#7
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Just a thought. Many of the common controls have custom messages. Might be worth a google for something like "ImageCombo Messages MSDN"?
-
Oct 31st, 2014, 08:33 PM
#8
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Just for grins, I did it with FindWindowEx using a null class and title, but got exactly the same results.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Oct 31st, 2014, 09:22 PM
#9
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
It is easier to make your own control instead to understand the mystery messages...and make some lines of code to control it. In then next version of the MS control your code just be a nothing. MS has no obligation to use the same "secret" numbers for messages for ever.
-
Oct 31st, 2014, 09:39 PM
#10
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
The code below appears to have worked. But since VB seems to store entries in a collection, at worse, we are corrupting the control if overwriting the item data if VB uses the item data for its purposes. At best, we are doing nothing. This control may be pretty much off-limits to APIs unless one had control of the collection object VB uses for the imagecombo
Code:
Dim cWnd As Long, s As String
s = "LaVolpe"
cWnd = FindWindowEx(ImageCombo1.hWnd, cWnd, vbNullString, vbNullString)
SendMessage cWnd, CB_INSERTSTRING, 0, ByVal s
' ItemData is where string data resides when combobox has no CBS_HASSTRINGs window style
MsgBox SendMessage(cWnd, CB_GETITEMDATA, 0, ByVal 0&)
Edited: These two messages might be worth playing with?
CBEM_SETITEM
CBEM_GETITEM
Last edited by LaVolpe; Oct 31st, 2014 at 09:45 PM.
-
Oct 31st, 2014, 09:59 PM
#11
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Regular API works.
Code:
Public Function CBX_InsertItem(hCB As Long, sText As String, Optional iImage As Long = -1, Optional iOverlay As Long = -1, Optional lParam As Long = 0, Optional iItem As Long = -1) As Long
Dim cbxi As COMBOBOXEXITEMW
With cbxi
.mask = CBEIF_TEXT
.cchTextMax = Len(sText) + 1
.pszText = StrPtr(sText & vbNullChar)
.iItem = iItem
If iImage <> -1 Then
.mask = .mask Or CBEIF_IMAGE Or CBEIF_SELECTEDIMAGE
.iImage = iImage
.iSelectedImage = iImage
End If
If iOverlay <> -1 Then
.mask = .mask Or CBEIF_OVERLAY
.iOverlay = iOverlay
End If
If lParam Then
.mask = .mask Or CBEIF_LPARAM
.lParam = lParam
End If
End With
CBX_InsertItem = SendMessageW(hCB, CBEM_INSERTITEMW, 0, cbxi)
End Function
Edit: Actually I can't remember clearly if that was working before I converted it to CreateWindowEx-based. I may have been using regular add item, then API to set things.
Code:
Dim cbi As ComboItem, cbxi As COMBOBOXEXITEM
Set cbi = cbPath.ComboItems.Add(, , cbPath.Text)
cbxi.iItem = cbi.index - 1
cbxi.iImage = GetFileIconIndexPIDL(pidlfqNewRoot, SHGFI_SMALLICON)
cbxi.mask = CBEIF_IMAGE
Call SendMessage(cbPath.hWnd, CBEM_SETITEM, 0, cbxi)
Last edited by fafalone; Oct 31st, 2014 at 10:31 PM.
-
Oct 31st, 2014, 10:40 PM
#12
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Ok, I'm making progress. I've at least got it to add an item. I thought I had tried part of this before and it didn't work, but it's working now. But I now can't get the Unicode portion to work. Here's the problem:
Code:
Option Explicit
Private Const CBEIF_TEXT = &H1
Private Const CBEIF_IMAGE = &H2
Private Const WM_USER = &H400
Private Const CBEM_INSERTITEMA = (WM_USER + 1)
Private Const CBEM_INSERTITEMW = (WM_USER + 11)
Private Type COMBOBOXEXITEMA
mask As Long
iItem As Long
pszText As String
cchTextMax As Long
iImage As Long
iSelectedImage As Long
iOverlay As Long
iIndent As Long
lParam As Long
End Type
Private Type COMBOBOXEXITEMW
mask As Long
iItem As Long
pszText As Long
cchTextMax As Long
iImage As Long
iSelectedImage As Long
iOverlay As Long
iIndent As Long
lParam As Long
End Type
Private Declare Function SendMessageA Lib "user32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SendMessageW Lib "user32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Sub Form_Load()
Dim s As String
ImageCombo1.ImageList = Me.ImageList1
' This does NOT work.
Dim cbItemsW As COMBOBOXEXITEMW
s = ChrW$(1256) & ChrW$(1257) & ChrW$(1258) & ChrW$(1259)
cbItemsW.mask = CBEIF_TEXT Or CBEIF_IMAGE
cbItemsW.pszText = StrPtr(s)
cbItemsW.cchTextMax = Len(s)
SendMessageW ImageCombo1.hwnd, CBEM_INSERTITEMW, 0, cbItemsW
' This does work.
Dim cbItemsA As COMBOBOXEXITEMA
s = "hello world"
cbItemsA.mask = CBEIF_TEXT Or CBEIF_IMAGE
cbItemsA.pszText = s
cbItemsA.cchTextMax = Len(s)
SendMessageA ImageCombo1.hwnd, CBEM_INSERTITEMA, 0, cbItemsA
End Sub
You can comment out one or the other, or reverse order. None of that makes any difference. The ...W version just won't work. I even read some documentation that states that, when the Unicode string is in a UDT, it doesn't matter whether you use SendMessageA or SendMessageW, which makes sense because the Unicode string isn't in wParam or lParam. But I tried using SendMessageA in the first block, but no go.
I've attached my little test project (at this point in the problem) if someone thinks they can figure this out.ImageComboExample.zip
Last edited by Elroy; Oct 31st, 2014 at 10:43 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Oct 31st, 2014, 10:44 PM
#13
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Have you looked at this message? Even if it sets the flag appropriately, wonder if VB overrides it and forces ANSI?
CBEM_SETUNICODEFORMAT
P.S. If you click on one of the links I provided (here or in previous reply), you'll see all the messages that you could use for this imagecombo.
-
Oct 31st, 2014, 10:58 PM
#14
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
I'm getting VERY tired and will probably call it a night (after I splash a bit in a couple other threads), but that looks hopeful.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Nov 1st, 2014, 11:34 AM
#15
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Dang, and I was so hopeful too. Still doesn't work:
Code:
Private Sub Form_Load()
Dim s As String
Dim lResult As Long
'
ImageCombo1.ImageList = Me.ImageList1
'lResult = SendMessage(hComboBoxEx, CBEM_SETUNICODEFORMAT, fUnicode, 0)
'fUnicode: Determines the character set that is used by the control.
' If this value is nonzero, the control will use Unicode characters.
' If this value is zero, the control will use ANSI characters.
lResult = SendMessageA(ImageCombo1.hwnd, CBEM_SETUNICODEFORMAT, 1, 0)
' This does NOT work.
Dim cbItemsW As COMBOBOXEXITEMW
s = ChrW$(1256) & ChrW$(1257) & ChrW$(1258) & ChrW$(1259)
cbItemsW.mask = CBEIF_TEXT Or CBEIF_IMAGE
cbItemsW.pszText = StrPtr(s)
cbItemsW.cchTextMax = Len(s)
SendMessageA ImageCombo1.hwnd, CBEM_INSERTITEMW, 0, cbItemsW
' This does work.
'Dim cbItemsA As COMBOBOXEXITEMA
's = "hello world"
'cbItemsA.mask = CBEIF_TEXT Or CBEIF_IMAGE
'cbItemsA.pszText = s
'cbItemsA.cchTextMax = Len(s)
'SendMessageA ImageCombo1.hwnd, CBEM_INSERTITEMA, 0, cbItemsA
End Sub
I went ahead and included the whole routine here. The form is a single form with an ImageCombo1 and ImageList1 on it.
Code:
Option Explicit
Private Const WM_USER = &H400
Private Const CBEM_INSERTITEMA = (WM_USER + 1)
Private Const CBEM_SETIMAGELIST = (WM_USER + 2)
Private Const CBEM_GETIMAGELIST = (WM_USER + 3)
Private Const CBEM_SETITEMA = (WM_USER + 4)
Private Const CBEM_GETITEMA = (WM_USER + 5)
Private Const CBEM_GETCOMBOCONTROL = (WM_USER + 6)
Private Const CBEM_GETEDITCONTROL = (WM_USER + 7)
Private Const CBEM_SETEXSTYLE = (WM_USER + 8)
Private Const CBEM_GETEXSTYLE = (WM_USER + 9)
Private Const CBEM_GETEXTENDEDSTYLE = (WM_USER + 9) ' Same as above.
Private Const CBEM_HASEDITCHANGED = (WM_USER + 10)
Private Const CBEM_INSERTITEMW = (WM_USER + 11)
Private Const CBEM_SETITEMW = (WM_USER + 12)
Private Const CBEM_GETITEMW = (WM_USER + 13)
Private Const CBEM_SETEXTENDEDSTYLE = (WM_USER + 14)
'
Private Const CBEM_DELETEITEM = &H144
Private Const CBEM_SETUNICODEFORMAT = &H2005
Private Const CBEM_GETUNICODEFORMAT = &H2006
Private Const CBEM_SETWINDOWTHEME = &H200B
Private Const CBEIF_TEXT = &H1
Private Const CBEIF_IMAGE = &H2
Private Type COMBOBOXEXITEMA
mask As Long
iItem As Long
pszText As String
cchTextMax As Long
iImage As Long
iSelectedImage As Long
iOverlay As Long
iIndent As Long
lParam As Long
End Type
Private Type COMBOBOXEXITEMW
mask As Long
iItem As Long
pszText As Long
cchTextMax As Long
iImage As Long
iSelectedImage As Long
iOverlay As Long
iIndent As Long
lParam As Long
End Type
Private Declare Function SendMessageA Lib "user32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SendMessageW Lib "user32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Sub Form_Load()
Dim s As String
Dim lResult As Long
'
ImageCombo1.ImageList = Me.ImageList1
'lResult = SendMessage(hComboBoxEx, CBEM_SETUNICODEFORMAT, fUnicode, 0)
'fUnicode: Determines the character set that is used by the control.
' If this value is nonzero, the control will use Unicode characters.
' If this value is zero, the control will use ANSI characters.
lResult = SendMessageA(ImageCombo1.hwnd, CBEM_SETUNICODEFORMAT, 1, 0)
' This does NOT work.
Dim cbItemsW As COMBOBOXEXITEMW
s = ChrW$(1256) & ChrW$(1257) & ChrW$(1258) & ChrW$(1259)
cbItemsW.mask = CBEIF_TEXT Or CBEIF_IMAGE
cbItemsW.pszText = StrPtr(s)
cbItemsW.cchTextMax = Len(s)
SendMessageA ImageCombo1.hwnd, CBEM_INSERTITEMW, 0, cbItemsW
' This does work.
'Dim cbItemsA As COMBOBOXEXITEMA
's = "hello world"
'cbItemsA.mask = CBEIF_TEXT Or CBEIF_IMAGE
'cbItemsA.pszText = s
'cbItemsA.cchTextMax = Len(s)
'SendMessageA ImageCombo1.hwnd, CBEM_INSERTITEMA, 0, cbItemsA
End Sub
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Nov 1st, 2014, 11:53 AM
#16
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
for the unicode portion, does this work? Worth a quick try
Instead of: SendMessageA ImageCombo1.hwnd, CBEM_INSERTITEMW, 0, cbItemsW
use: SendMessageW ImageCombo1.hwnd, CBEM_INSERTITEMW, 0, cbItemsW
P.S. also curious what this API call returns:
IsWindowUnicode(ImageCombo1.hwnd)
-
Nov 1st, 2014, 11:56 AM
#17
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Yeah, I figured someone would spot that, but I always try about every combination of those things every time I try something different.
I did fire it up again and try that, and no cigar. Also, I did read that SendMessageA versus SendMessageW only matter when the string is directly in either wParam or lParam.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Nov 1st, 2014, 12:02 PM
#18
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Say LaVolpe,
I am doing the Unicode right in the UDT, aren't I? I don't do that too often and don't even have an example in my primary project.
I actually did try putting the string in a byte array and then passing the VarPtr(bb(0)), which I think would do the same thing I did with the StrPtr(s).
I didn't re-try that though after putting in the "lResult = SendMessageA(ImageCombo1.hwnd, CBEM_SETUNICODEFORMAT, 1, 0)" line.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Nov 1st, 2014, 12:15 PM
#19
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
It looks right to me, the cbItemsW.cchTextMax isn't applicable when setting text, is ignored by the target window.
You may have missed my question in the previous reply: IsWindowUnicode(ImageCombo1.hwnd) is non-zero or zero?
The answer to that will tell you whether the ANSI/unicode version of CreateWindowEx was used to create ImageCombo1
-
Nov 1st, 2014, 12:30 PM
#20
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Hmmm, ok, all three of the MsgBox responses return ZERO:
Code:
MsgBox IsWindowUnicode(ImageCombo1.hWnd)
lResult = SendMessageA(ImageCombo1.hWnd, CBEM_SETUNICODEFORMAT, 1, 0)
MsgBox lResult
MsgBox IsWindowUnicode(ImageCombo1.hWnd)
I'm assuming that the second ZERO returned means successful, but I can't seem to find documentation to verify that. And it's obviously not working because the last MsgBox is returning ZERO too.
This is a stubborn one.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Nov 1st, 2014, 01:27 PM
#21
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
regarding IsWindowUnicode
Originally Posted by msdn
If the window is a native Unicode window, the return value is nonzero.
If the window is not a native Unicode window, the return value is zero. The window is a native ANSI window.
So, ANSI window. We know we can get VB to display unicode though it normally won't. But will the imagecombo if it isn't a unicode window? Don't have the time to play along, sorry
-
Nov 1st, 2014, 05:05 PM
#22
Re: Using API to "Add" item to ImageCombo (mscomctl.ocx) control
Hey LaVolpe,
You've got absolutely nothing to apologize for. You've been GREAT in giving me ideas on ways to keep kicking at this thing. It all started as an idea from fafalone, but I've long wanted to develop a clean set of Unicode replacement controls for all the standard controls. I didn't think this ImageCombo would be so nettlesome, but it certainly is. I also tend to want to wrap things up once I start them, but that may not happen with this one. Tomorrow, I fly out for a 2 week consulting gig, so, unless this gets done today, it'll be on back burner for a while.
Again, I do appreciate your help. I think I'll mark this thread as resolved, in that the original question DID get resolved. I'll start another more focused thread if I get back to it. I've also still got some ideas to try. Maybe I can poke directly at that internal ComboBox window and get it to do something. I'm not sure I've got it in me to mess with it right now, but every avenue definitely hasn't been exhausted.
Take Care,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|