HWND of Listbox in UserForm in Excel macro

J

Jozsef Bekes

Hi All,

I have created a wizzard like Excel macro application that uses UserForms as
dialogs. I have some listboxes on these dialogs. I would like to use
SendMessage to do some non trivial tasks on my control. All the examples I
have found on the Internet show that there is a hWnd property that contains
this value, but for my instance of Listbox vb complains that there is no
such property.

I have found this information at
http://forums.devx.com/archive/index.php/t-79377.html:

"The UserForm controls do not have a window handle property and the Forms
ListBox doesn't implement
the standard ListBox class."

My question is how to get the hwnd then, because this location does not
mention a way.

Thank you for all answers!

Regards,
Jozsi
 
R

RB Smissaert

I think the Listview has a window handle and has some other benefits, such
as mouse scrolling
and colour formatting.

RBS
 
N

NickHK

Whilst the listbox does not expose a .Hwnd property, it can be found. Using
Spy++, it is indicated as "F3 Server 028c0000" class.
Using the APIs FindWindow and FindWindowEx, you could get its HWnd.

However, if you need a lot of "non trivial" changes to this control, maybe
you should use something else.
RBS has suggested the ListView or maybe you should write a custom control.

Depends what you are trying to do .

NickHK
 
J

Jozsef Bekes

Hi RB and Nick,

Thank you for your answers. FindWindow could become complicated, as I have
more than one listbox, I do not know if it is easy to distinguish them (I do
not have the software right now, I will check it out - maybe a unique window
name would offer the solution)

I will consider using listview as well.

Thank you!

Jozsi
 
R

RB Smissaert

Distinguishing the different listboxes won't be a problem.
You could use the GetWindowRect API.

RBS
 
C

Chip Pearson

Jozsef Bekes said:
Thank you for your answers. FindWindow could become complicated, as I have
more than one listbox, I do not know if it is easy to distinguish them

You don't need FindWindow or FindWindowEx to get the HWnds and associate
them with the names of the controls. Try the following:

If you want to relate the name of a control with its HWnd, first create a
collection object in a standard module, in declarations section.

Dim ListBoxCollection As Collection

Then create a class module called CListBoxInfo containing the following
code:

Public Name As String
Public HWnd As Long

Then, in your UserForm object module, use the following Initialize
procedure:

Private Sub UserForm_Initialize()

Dim Ctrl As MSForms.Control
Dim LbxInfo As CListBoxInfo
Dim MeHWnd As Long
Dim Res As Long

MeHWnd = FindWindow("ThunderDFrame", Me.Caption)
If MeHWnd = 0 Then
Exit Sub
End If

Set ListBoxCollection = New Collection
For Each Ctrl In UserForm1.Controls
If TypeOf Ctrl Is MSForms.ListBox Then
Ctrl.SetFocus
Set LbxInfo = New CListBoxInfo
LbxInfo.HWnd = GetFocus
LbxInfo.Name = Ctrl.Name
ListBoxCollection.Add Item:=LbxInfo, key:=LbxInfo.Name
End If
Next Ctrl

End Sub

Now, you have a collection of classes that relate the HWnd to the Name of
the ListBox. To get the HWnd of a particular ListBox, use

Dim MyHWnd As Long
MyHWnd = ListBoxCollection("MyListBoxName").HWnd

Or for the reverse, to get the Name of a control based on its HWnd, you'd
have to loop through the collection:

Function ControlNameOfHWnd(HWnd As Long) As String
Dim MyHWnd As Long

Dim LbxInfo As CListBoxInfo
For Each LbxInfo In ListBoxCollection
If LbxInfo.HWnd = HWnd Then
ControlNameOfHWnd = LbxInfo.Name
Exit Function
End If
Next LbxInfo
End Sub

Once you have the name of the control, you can access any of its properties
with

UserForm1.Controls(MyControlName).ListIndex = 0

Keep in mind, though, that the since the ListBoxes on UserForms are not
standard VB6 ListBoxes, they will not respond (appropriately) to the LB_*
message numbers that you would use in SendMessage to VB6 ListBoxes. Using
SPY++ to look at the messages going to the HWnds, they are all WM_USER+nnn,
so without documentation on what those messages mean (and there is no public
documentation), you are very limited on how you might extend the
functionality of a MSFORMS.ListBox.




--
Cordially,
Chip Pearson
Microsoft MVP - Excel
www.cpearson.com
(email address is on the web site)
 
R

RB Smissaert

Nice tip, thanks.

RBS

Chip Pearson said:
You don't need FindWindow or FindWindowEx to get the HWnds and associate
them with the names of the controls. Try the following:

If you want to relate the name of a control with its HWnd, first create a
collection object in a standard module, in declarations section.

Dim ListBoxCollection As Collection

Then create a class module called CListBoxInfo containing the following
code:

Public Name As String
Public HWnd As Long

Then, in your UserForm object module, use the following Initialize
procedure:

Private Sub UserForm_Initialize()

Dim Ctrl As MSForms.Control
Dim LbxInfo As CListBoxInfo
Dim MeHWnd As Long
Dim Res As Long

MeHWnd = FindWindow("ThunderDFrame", Me.Caption)
If MeHWnd = 0 Then
Exit Sub
End If

Set ListBoxCollection = New Collection
For Each Ctrl In UserForm1.Controls
If TypeOf Ctrl Is MSForms.ListBox Then
Ctrl.SetFocus
Set LbxInfo = New CListBoxInfo
LbxInfo.HWnd = GetFocus
LbxInfo.Name = Ctrl.Name
ListBoxCollection.Add Item:=LbxInfo, key:=LbxInfo.Name
End If
Next Ctrl

End Sub

Now, you have a collection of classes that relate the HWnd to the Name of
the ListBox. To get the HWnd of a particular ListBox, use

Dim MyHWnd As Long
MyHWnd = ListBoxCollection("MyListBoxName").HWnd

Or for the reverse, to get the Name of a control based on its HWnd, you'd
have to loop through the collection:

Function ControlNameOfHWnd(HWnd As Long) As String
Dim MyHWnd As Long

Dim LbxInfo As CListBoxInfo
For Each LbxInfo In ListBoxCollection
If LbxInfo.HWnd = HWnd Then
ControlNameOfHWnd = LbxInfo.Name
Exit Function
End If
Next LbxInfo
End Sub

Once you have the name of the control, you can access any of its
properties with

UserForm1.Controls(MyControlName).ListIndex = 0

Keep in mind, though, that the since the ListBoxes on UserForms are not
standard VB6 ListBoxes, they will not respond (appropriately) to the LB_*
message numbers that you would use in SendMessage to VB6 ListBoxes. Using
SPY++ to look at the messages going to the HWnds, they are all
WM_USER+nnn,
so without documentation on what those messages mean (and there is no
public
documentation), you are very limited on how you might extend the
functionality of a MSFORMS.ListBox.




--
Cordially,
Chip Pearson
Microsoft MVP - Excel
www.cpearson.com
(email address is on the web site)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top