[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.excel.programming

Re: Window Class of UserForm controls

Bob Phillips

12/14/2006 6:15:00 PM

Here is a way to get the hWnd of userfcorm controls.

First create a class, I call it clsHWnd, with this simple code

Option Explicit

Public Name As String
Public hWnd As Long

Then in the userform, declare a couple of APIs and a collection

Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long

Private Declare Function GetFocus Lib "user32" () As Long

Private ListBoxCollection As Collection

and load it in the initialize event; add this

Private Sub Userform_Initialize()
Dim ctl As msforms.Control
Dim listHWnd As clshWnd
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 ctl In UserForm1.Controls
ctl.SetFocus
Set listHWnd = New clshWnd
listHWnd.hWnd = GetFocus
listHWnd.Name = ctl.Name
ListBoxCollection.Add Item:=listHWnd, Key:=listHWnd.Name
Next ctl

End Sub

You can just get hWnd from the collection, like so

MsgBox ListBoxCollection("ListBox1").hWnd

--

HTH

Bob Phillips

(replace xxxx in the email address with gmail if mailing direct)

"Martin" <Martin@discussions.microsoft.com> wrote in message
news:8312ABD6-70E9-4125-868D-DDD9636214B2@microsoft.com...
> Can anyone tell me the API Window Class of controls in a userform? Or,
even
> better, point me to a definitive list of the window classes in MS Office?
>
> I'm trying to find a way to to identify the hWnd of the active control
(not
> easy in VBA) so I can use context sensitive help.


5 Answers

Chip Pearson

12/15/2006 3:19:00 AM

0

Bob,

Not all controls have HWnds. Most MSForms are windowless contrrols. As far
as I know, only the Listbox and Frame controls have distinct HWnds. All
other controls share the same HWnd. For example, create a form with a
variety of controls, and use the following code in the user form.

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _
ByVal HWnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long

Private Function ClassName(HWnd As Long) As String
Dim CN As String
Dim N As Long
CN = String$(256, vbNullChar)
N = GetClassName(HWnd, CN, 256)
ClassName = Left$(CN, N)
End Function

Private Sub CommandButton1_Click()
Dim Ctrl As MSForms.Control
Dim HWndColl As New Collection

On Error Resume Next
For Each Ctrl In UserForm1.Controls
Err.Clear
Ctrl.SetFocus
If Err.Number <> 0 Then
Debug.Print "Control: " & Ctrl.Name & " cannot use SetFocus"
Else
Err.Clear
HWndColl.Add Item:=Ctrl.Name, Key:=CStr(GetFocus)
If Err.Number = 0 Then
Debug.Print Ctrl.Name & " has HWnd of " & CStr(GetFocus) & _
" ClassName: '" & ClassName(GetFocus) & "'"
Else
Debug.Print Ctrl.Name & " has the same HWnd as " & _
HWndColl(CStr(GetFocus)) & _
" ClassName: " & ClassName(GetFocus)
End If

End If
Next Ctrl
End Sub


You'll get output like

Control: Label1 cannot use SetFocus
ComboBox1 has HWnd of 15599310 ClassName: 'F3 Server 60000000'
ListBox1 has HWnd of 29427562 ClassName: 'F3 Server 60000000'
OptionButton1 has the same HWnd as ComboBox1 ClassName: 'F3 Server
60000000'
CommandButton1 has the same HWnd as ComboBox1 ClassName: 'F3 Server
60000000'
CommandButton2 has the same HWnd as ComboBox1 ClassName: 'F3 Server
60000000'
CommandButton3 has the same HWnd as ComboBox1 ClassName: 'F3 Server
60000000'
Frame1 has HWnd of 17434558 ClassName: 'F3 Server 60000000'
CommandButton4 has the same HWnd as ComboBox1 ClassName: 'F3 Server
60000000'


Note that the same HWnd is used by multiple controls and that the controls
are of the same Window Class 'F3 Server 60000000'.

Use the following code for CommandButton2:

Private Sub CommandButton2_Click()
Me.ListBox1.SetFocus
Debug.Print Me.ActiveControl.Name, CStr(GetFocus), ClassName(GetFocus)

Me.ComboBox1.SetFocus
Debug.Print Me.ActiveControl.Name, CStr(GetFocus), ClassName(GetFocus)

Me.CommandButton1.SetFocus
Debug.Print Me.ActiveControl.Name, CStr(GetFocus), ClassName(GetFocus)

End Sub

And you'll get output like
ListBox1 18352062 'F3 Server 60000000'
ComboBox1 16516814 'F3 Server 60000000'
CommandButton1 16516814 'F3 Server 60000000'

Note that all the class names are the same and that ComboBox1 and
CommandButton1 have the same HWnd.

The short answer to the original question is that MSForms controls don't
have HWnds.


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


"Bob Phillips" <bob.NGs@xxxx.com> wrote in message
news:O5Fmyu6HHHA.1240@TK2MSFTNGP03.phx.gbl...
> Here is a way to get the hWnd of userfcorm controls.
>
> First create a class, I call it clsHWnd, with this simple code
>
> Option Explicit
>
> Public Name As String
> Public hWnd As Long
>
> Then in the userform, declare a couple of APIs and a collection
>
> Private Declare Function FindWindow Lib "user32" _
> Alias "FindWindowA" _
> (ByVal lpClassName As String, _
> ByVal lpWindowName As String) As Long
>
> Private Declare Function GetFocus Lib "user32" () As Long
>
> Private ListBoxCollection As Collection
>
> and load it in the initialize event; add this
>
> Private Sub Userform_Initialize()
> Dim ctl As msforms.Control
> Dim listHWnd As clshWnd
> 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 ctl In UserForm1.Controls
> ctl.SetFocus
> Set listHWnd = New clshWnd
> listHWnd.hWnd = GetFocus
> listHWnd.Name = ctl.Name
> ListBoxCollection.Add Item:=listHWnd, Key:=listHWnd.Name
> Next ctl
>
> End Sub
>
> You can just get hWnd from the collection, like so
>
> MsgBox ListBoxCollection("ListBox1").hWnd
>
> --
>
> HTH
>
> Bob Phillips
>
> (replace xxxx in the email address with gmail if mailing direct)
>
> "Martin" <Martin@discussions.microsoft.com> wrote in message
> news:8312ABD6-70E9-4125-868D-DDD9636214B2@microsoft.com...
>> Can anyone tell me the API Window Class of controls in a userform? Or,
> even
>> better, point me to a definitive list of the window classes in MS Office?
>>
>> I'm trying to find a way to to identify the hWnd of the active control
> (not
>> easy in VBA) so I can use context sensitive help.
>
>


NickHK

12/15/2006 3:35:00 AM

0

Bob,
With your code, I get the same the same handle for all standard controls
(except a list view, etc) as that returned for the form's client area using;
ContHwnd = FindWindowEx(FindWindow("ThunderDFrame", Me.Caption), 0, "F3
Server 02950000", vbNullString)

which in a way seems correct, as I understodd these controls to be
windowless, drawn on the form.

Martin,
Here's an old MS article on showing Tool Tips. Not what you want, but..
http://support.microsoft.com/default.aspx?scid=kb;en...

Otherwise, each control has the HelpContextID property that you can set. You
also need the help file entered in Tools>VBA Project Properties>Help File
Name.

Ivan's site has a Excel/VBA equivalent of Spy++, which will tell all you
need, if it is exposed.
http://www.xcelfiles.com/A...

NickHK

"Bob Phillips" <bob.NGs@xxxx.com> wrote in message
news:O5Fmyu6HHHA.1240@TK2MSFTNGP03.phx.gbl...
> Here is a way to get the hWnd of userfcorm controls.
>
> First create a class, I call it clsHWnd, with this simple code
>
> Option Explicit
>
> Public Name As String
> Public hWnd As Long
>
> Then in the userform, declare a couple of APIs and a collection
>
> Private Declare Function FindWindow Lib "user32" _
> Alias "FindWindowA" _
> (ByVal lpClassName As String, _
> ByVal lpWindowName As String) As Long
>
> Private Declare Function GetFocus Lib "user32" () As Long
>
> Private ListBoxCollection As Collection
>
> and load it in the initialize event; add this
>
> Private Sub Userform_Initialize()
> Dim ctl As msforms.Control
> Dim listHWnd As clshWnd
> 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 ctl In UserForm1.Controls
> ctl.SetFocus
> Set listHWnd = New clshWnd
> listHWnd.hWnd = GetFocus
> listHWnd.Name = ctl.Name
> ListBoxCollection.Add Item:=listHWnd, Key:=listHWnd.Name
> Next ctl
>
> End Sub
>
> You can just get hWnd from the collection, like so
>
> MsgBox ListBoxCollection("ListBox1").hWnd
>
> --
>
> HTH
>
> Bob Phillips
>
> (replace xxxx in the email address with gmail if mailing direct)
>
> "Martin" <Martin@discussions.microsoft.com> wrote in message
> news:8312ABD6-70E9-4125-868D-DDD9636214B2@microsoft.com...
> > Can anyone tell me the API Window Class of controls in a userform? Or,
> even
> > better, point me to a definitive list of the window classes in MS
Office?
> >
> > I'm trying to find a way to to identify the hWnd of the active control
> (not
> > easy in VBA) so I can use context sensitive help.
>
>


Chip Pearson

12/15/2006 4:14:00 PM

0

> Ivan's site has a Excel/VBA equivalent of Spy++, which will tell all you
> need, if it is exposed.
> http://www.xcelfiles.com/A...
>

That's an interesting program, but it has a few bugs when reporting the
ClassName and WindowText of child windows.


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

"NickHK" <TungCheWah@Invalid.com> wrote in message
news:%23utuIo$HHHA.1252@TK2MSFTNGP02.phx.gbl...
> Bob,
> With your code, I get the same the same handle for all standard controls
> (except a list view, etc) as that returned for the form's client area
> using;
> ContHwnd = FindWindowEx(FindWindow("ThunderDFrame", Me.Caption), 0, "F3
> Server 02950000", vbNullString)
>
> which in a way seems correct, as I understodd these controls to be
> windowless, drawn on the form.
>
> Martin,
> Here's an old MS article on showing Tool Tips. Not what you want, but..
> http://support.microsoft.com/default.aspx?scid=kb;en...
>
> Otherwise, each control has the HelpContextID property that you can set.
> You
> also need the help file entered in Tools>VBA Project Properties>Help File
> Name.
>
> Ivan's site has a Excel/VBA equivalent of Spy++, which will tell all you
> need, if it is exposed.
> http://www.xcelfiles.com/A...
>
> NickHK
>
> "Bob Phillips" <bob.NGs@xxxx.com> wrote in message
> news:O5Fmyu6HHHA.1240@TK2MSFTNGP03.phx.gbl...
>> Here is a way to get the hWnd of userfcorm controls.
>>
>> First create a class, I call it clsHWnd, with this simple code
>>
>> Option Explicit
>>
>> Public Name As String
>> Public hWnd As Long
>>
>> Then in the userform, declare a couple of APIs and a collection
>>
>> Private Declare Function FindWindow Lib "user32" _
>> Alias "FindWindowA" _
>> (ByVal lpClassName As String, _
>> ByVal lpWindowName As String) As Long
>>
>> Private Declare Function GetFocus Lib "user32" () As Long
>>
>> Private ListBoxCollection As Collection
>>
>> and load it in the initialize event; add this
>>
>> Private Sub Userform_Initialize()
>> Dim ctl As msforms.Control
>> Dim listHWnd As clshWnd
>> 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 ctl In UserForm1.Controls
>> ctl.SetFocus
>> Set listHWnd = New clshWnd
>> listHWnd.hWnd = GetFocus
>> listHWnd.Name = ctl.Name
>> ListBoxCollection.Add Item:=listHWnd, Key:=listHWnd.Name
>> Next ctl
>>
>> End Sub
>>
>> You can just get hWnd from the collection, like so
>>
>> MsgBox ListBoxCollection("ListBox1").hWnd
>>
>> --
>>
>> HTH
>>
>> Bob Phillips
>>
>> (replace xxxx in the email address with gmail if mailing direct)
>>
>> "Martin" <Martin@discussions.microsoft.com> wrote in message
>> news:8312ABD6-70E9-4125-868D-DDD9636214B2@microsoft.com...
>> > Can anyone tell me the API Window Class of controls in a userform? Or,
>> even
>> > better, point me to a definitive list of the window classes in MS
> Office?
>> >
>> > I'm trying to find a way to to identify the hWnd of the active control
>> (not
>> > easy in VBA) so I can use context sensitive help.
>>
>>
>
>


Chip Pearson

12/15/2006 4:52:00 PM

0

"NickHK" <TungCheWah@Invalid.com> wrote in message
> You
> also need the help file entered in Tools>VBA Project Properties>Help File
> Name.

I tend not to use the HelpFile property because its path must be absolute.
Application.Help doesn't support relative paths. If you distribute the
workbook or add-in to a user and he stores it in a folder with a different
name, ThisWorkbook.VBProject.HelpFile will point to the wrong location.

I usually do any one of three things (I generally provide a real Help File
only for add-ins):

1) Set the HelpFile property to an unqualified file name, mandate that the
help file reside in the same directory as the XLA, and call it with

Application.Help ThisWorkbook.Path & Application.PathSeparator & _
ThisWorkbook.VBProject.HelpFile

2) Store the location of help file in the Registry.

Dim HelpFile As String
HelpFile = GetRegistry("HelpFile")
Application.Help HelpFile

where GetRegistry is part of a library of registry-related functions I
wrote to manage registry entries for an application.

3) Use the HTMLHelp API function with the HelpFile name stored in the
Registry. Using the HTMLHelp API is by far the preferred method since you
can control what is displayed.




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


"NickHK" <TungCheWah@Invalid.com> wrote in message
news:%23utuIo$HHHA.1252@TK2MSFTNGP02.phx.gbl...
> Bob,
> With your code, I get the same the same handle for all standard controls
> (except a list view, etc) as that returned for the form's client area
> using;
> ContHwnd = FindWindowEx(FindWindow("ThunderDFrame", Me.Caption), 0, "F3
> Server 02950000", vbNullString)
>
> which in a way seems correct, as I understodd these controls to be
> windowless, drawn on the form.
>
> Martin,
> Here's an old MS article on showing Tool Tips. Not what you want, but..
> http://support.microsoft.com/default.aspx?scid=kb;en...
>
> Otherwise, each control has the HelpContextID property that you can set.
> You
> also need the help file entered in Tools>VBA Project Properties>Help File
> Name.
>
> Ivan's site has a Excel/VBA equivalent of Spy++, which will tell all you
> need, if it is exposed.
> http://www.xcelfiles.com/A...
>
> NickHK
>
> "Bob Phillips" <bob.NGs@xxxx.com> wrote in message
> news:O5Fmyu6HHHA.1240@TK2MSFTNGP03.phx.gbl...
>> Here is a way to get the hWnd of userfcorm controls.
>>
>> First create a class, I call it clsHWnd, with this simple code
>>
>> Option Explicit
>>
>> Public Name As String
>> Public hWnd As Long
>>
>> Then in the userform, declare a couple of APIs and a collection
>>
>> Private Declare Function FindWindow Lib "user32" _
>> Alias "FindWindowA" _
>> (ByVal lpClassName As String, _
>> ByVal lpWindowName As String) As Long
>>
>> Private Declare Function GetFocus Lib "user32" () As Long
>>
>> Private ListBoxCollection As Collection
>>
>> and load it in the initialize event; add this
>>
>> Private Sub Userform_Initialize()
>> Dim ctl As msforms.Control
>> Dim listHWnd As clshWnd
>> 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 ctl In UserForm1.Controls
>> ctl.SetFocus
>> Set listHWnd = New clshWnd
>> listHWnd.hWnd = GetFocus
>> listHWnd.Name = ctl.Name
>> ListBoxCollection.Add Item:=listHWnd, Key:=listHWnd.Name
>> Next ctl
>>
>> End Sub
>>
>> You can just get hWnd from the collection, like so
>>
>> MsgBox ListBoxCollection("ListBox1").hWnd
>>
>> --
>>
>> HTH
>>
>> Bob Phillips
>>
>> (replace xxxx in the email address with gmail if mailing direct)
>>
>> "Martin" <Martin@discussions.microsoft.com> wrote in message
>> news:8312ABD6-70E9-4125-868D-DDD9636214B2@microsoft.com...
>> > Can anyone tell me the API Window Class of controls in a userform? Or,
>> even
>> > better, point me to a definitive list of the window classes in MS
> Office?
>> >
>> > I'm trying to find a way to to identify the hWnd of the active control
>> (not
>> > easy in VBA) so I can use context sensitive help.
>>
>>
>
>


martin

12/15/2006 5:09:00 PM

0

First of all, thanks everyone for your useful comments. Nick, I've created
the VBA reference to the help file as you said and added help context ids to
my controls. In the help file I have header file and text file saved and
entered under Text Pop-ups, mapping to the help-context ids. Nothing happens
yet - do I still need to use the HTMLHelp(...HH_DISPLAY_TEXT_POPUP) code in
order to get my pop-ups (in which case I guess I'm back to the problem of all
controls in VBA userforms have the same hWnd)?

And can I extend this to context-sensitive help for custom menu options?

"NickHK" wrote:

> Bob,
> With your code, I get the same the same handle for all standard controls
> (except a list view, etc) as that returned for the form's client area using;
> ContHwnd = FindWindowEx(FindWindow("ThunderDFrame", Me.Caption), 0, "F3
> Server 02950000", vbNullString)
>
> which in a way seems correct, as I understodd these controls to be
> windowless, drawn on the form.
>
> Martin,
> Here's an old MS article on showing Tool Tips. Not what you want, but..
> http://support.microsoft.com/default.aspx?scid=kb;en...
>
> Otherwise, each control has the HelpContextID property that you can set. You
> also need the help file entered in Tools>VBA Project Properties>Help File
> Name.
>
> Ivan's site has a Excel/VBA equivalent of Spy++, which will tell all you
> need, if it is exposed.
> http://www.xcelfiles.com/A...
>
> NickHK
>
> "Bob Phillips" <bob.NGs@xxxx.com> wrote in message
> news:O5Fmyu6HHHA.1240@TK2MSFTNGP03.phx.gbl...
> > Here is a way to get the hWnd of userfcorm controls.
> >
> > First create a class, I call it clsHWnd, with this simple code
> >
> > Option Explicit
> >
> > Public Name As String
> > Public hWnd As Long
> >
> > Then in the userform, declare a couple of APIs and a collection
> >
> > Private Declare Function FindWindow Lib "user32" _
> > Alias "FindWindowA" _
> > (ByVal lpClassName As String, _
> > ByVal lpWindowName As String) As Long
> >
> > Private Declare Function GetFocus Lib "user32" () As Long
> >
> > Private ListBoxCollection As Collection
> >
> > and load it in the initialize event; add this
> >
> > Private Sub Userform_Initialize()
> > Dim ctl As msforms.Control
> > Dim listHWnd As clshWnd
> > 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 ctl In UserForm1.Controls
> > ctl.SetFocus
> > Set listHWnd = New clshWnd
> > listHWnd.hWnd = GetFocus
> > listHWnd.Name = ctl.Name
> > ListBoxCollection.Add Item:=listHWnd, Key:=listHWnd.Name
> > Next ctl
> >
> > End Sub
> >
> > You can just get hWnd from the collection, like so
> >
> > MsgBox ListBoxCollection("ListBox1").hWnd
> >
> > --
> >
> > HTH
> >
> > Bob Phillips
> >
> > (replace xxxx in the email address with gmail if mailing direct)
> >
> > "Martin" <Martin@discussions.microsoft.com> wrote in message
> > news:8312ABD6-70E9-4125-868D-DDD9636214B2@microsoft.com...
> > > Can anyone tell me the API Window Class of controls in a userform? Or,
> > even
> > > better, point me to a definitive list of the window classes in MS
> Office?
> > >
> > > I'm trying to find a way to to identify the hWnd of the active control
> > (not
> > > easy in VBA) so I can use context sensitive help.
> >
> >
>
>
>