Can someone explain what is happening with this code...
Can someone explain what these API function are doing, and basically what
the flow of this is. I'm not really familiar with Subclassing...
This is the form1 code:
Private Sub Form_Load()
With Combo1
.AddItem "A"
.AddItem "B"
.AddItem "C"
End With
Call SubClass(Form1.Combo1.hWnd)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Call UnSubClass(Form1.Combo1.hWnd)
End Sub
This is the .bas module code:
Private lpfnOld As Long
Private Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" _
(ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" _
Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, _
ByVal hWnd As Long, _
ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Public Const GWL_WNDPROC = (-4)
Public Const MOUSE_MOVE = &H134
Public Function SubClass(hWnd As Long) As Boolean
lpfnOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WndProc)
End Function
Public Function UnSubClass(hWnd As Long) As Boolean
UnSubClass = SetWindowLong(hWnd, GWL_WNDPROC, lpfnOld)
End Function
Public Function WndProc(ByVal hWnd As Long, _
ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Select Case uMsg
Case MOUSE_MOVE
Form1.Label1 = Form1.Combo1.List(Form1.Combo1.ListIndex)
End Select
WndProc = CallWindowProc(lpfnOld, hWnd, uMsg, wParam, lParam)
End Function
Thanks!
Re: Can someone explain what is happening with this code...
> Can someone explain what these API function are doing, and basically what
> the flow of this is. I'm not really familiar with Subclassing...
> Call SubClass(Form1.Combo1.hWnd)
> Call UnSubClass(Form1.Combo1.hWnd)
These two call begin and end subclassing. If you don't UnSubClass on your
way out, you'll more than likely crash your application.
When you subclass you establish a routine that gets call to handle the
window's messages. You keep a pointer to the previous function so that it
can be restored and so that you can pass messages along that you don't want
to handle.
The WndProc routine, below, is that routine:
> Public Function WndProc(ByVal hWnd As Long, _
> ByVal uMsg As Long, _
> ByVal wParam As Long, _
> ByVal lParam As Long) As Long
>
> Select Case uMsg
> Case MOUSE_MOVE
> Form1.Label1 = Form1.Combo1.List(Form1.Combo1.ListIndex)
> End Select
>
> WndProc = CallWindowProc(lpfnOld, hWnd, uMsg, wParam, lParam)
> End Function
By calling the previous window procedure (lpfnOld) regardless of the
message, this "handler" does not really handle any messages. It just peeks
at the MOUSE_MOVE message and sets a label on the form. That part of the
code, though, does not make much sense.
Re: Can someone explain what is happening with this code...
Grinder,
thanks a lot, but why does the last part not make any sense. it's just
displaying what the user ran their mouse over when scrolling through the
combo box.
thanks,
robert
"Grinder" <grinder@no.spam.maam.com> wrote in message
news:3cd00f51@10.1.10.29...
> > Can someone explain what these API function are doing, and basically
what
> > the flow of this is. I'm not really familiar with Subclassing...
>
> > Call SubClass(Form1.Combo1.hWnd)
> > Call UnSubClass(Form1.Combo1.hWnd)
>
> These two call begin and end subclassing. If you don't UnSubClass on your
> way out, you'll more than likely crash your application.
>
> When you subclass you establish a routine that gets call to handle the
> window's messages. You keep a pointer to the previous function so that it
> can be restored and so that you can pass messages along that you don't
want
> to handle.
>
> The WndProc routine, below, is that routine:
>
> > Public Function WndProc(ByVal hWnd As Long, _
> > ByVal uMsg As Long, _
> > ByVal wParam As Long, _
> > ByVal lParam As Long) As Long
> >
> > Select Case uMsg
> > Case MOUSE_MOVE
> > Form1.Label1 = Form1.Combo1.List(Form1.Combo1.ListIndex)
> > End Select
> >
> > WndProc = CallWindowProc(lpfnOld, hWnd, uMsg, wParam, lParam)
> > End Function
>
> By calling the previous window procedure (lpfnOld) regardless of the
> message, this "handler" does not really handle any messages. It just
peeks
> at the MOUSE_MOVE message and sets a label on the form. That part of the
> code, though, does not make much sense.
>
>
>
Re: Can someone explain what is happening with this code...
You're subclassing, which means that you're replacing the window procedure
for your comboboxes window with your own function. The ComboBox does not
have mouse events, so this is providing one. However, there are several
problems with this code that could cause you grief:
1) The subclassing is tied to a single instance of the form. If you show a
second instance, then you're in deep trouble.
2) You can't break in the debugger when the subclass is active
3) The MOUSE_MOVE constant name is a little strange. Generally, you use the
same constant names that the platform SDK defines (WM_MOUSEMOVE)
4) Unless this is a Style 2 (DropDown List) combo, you still won't get a
mouse move reliably because most of the visible portion of the combo is an
Edit control, which has a different hWnd.
To get you into a more stable subclassing environment to experiment and
learn in, look at the subclassing samples in my August 2001 VBPJ article on
'Pointers to Class Functions'. You'll be able to run code directly in your
form instead of a .bas module, and you'll be able to stop in the debugger.
Just avoid the Stop button and End statements and you'll be in
business. -Matt
"Robert Tedesco" <RTesc25@hotmail.com> wrote in message
news:3cd00a04$1@10.1.10.29...
> Can someone explain what these API function are doing, and basically what
> the flow of this is. I'm not really familiar with Subclassing...
>
>
> This is the form1 code:
> Private Sub Form_Load()
> With Combo1
> .AddItem "A"
> .AddItem "B"
> .AddItem "C"
> End With
>
> Call SubClass(Form1.Combo1.hWnd)
> End Sub
>
> Private Sub Form_Unload(Cancel As Integer)
> Call UnSubClass(Form1.Combo1.hWnd)
> End Sub
>
> This is the .bas module code:
> Private lpfnOld As Long
>
> Private Declare Function SetWindowLong Lib "user32" _
> Alias "SetWindowLongA" _
> (ByVal hWnd As Long, _
> ByVal nIndex As Long, _
> ByVal dwNewLong As Long) As Long
>
> Private Declare Function CallWindowProc Lib "user32" _
> Alias "CallWindowProcA" _
> (ByVal lpPrevWndFunc As Long, _
> ByVal hWnd As Long, _
> ByVal uMsg As Long, _
> ByVal wParam As Long, _
> ByVal lParam As Long) As Long
>
> Public Const GWL_WNDPROC = (-4)
> Public Const MOUSE_MOVE = &H134
>
> Public Function SubClass(hWnd As Long) As Boolean
> lpfnOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WndProc)
> End Function
>
> Public Function UnSubClass(hWnd As Long) As Boolean
> UnSubClass = SetWindowLong(hWnd, GWL_WNDPROC, lpfnOld)
> End Function
>
> Public Function WndProc(ByVal hWnd As Long, _
> ByVal uMsg As Long, _
> ByVal wParam As Long, _
> ByVal lParam As Long) As Long
>
> Select Case uMsg
> Case MOUSE_MOVE
> Form1.Label1 = Form1.Combo1.List(Form1.Combo1.ListIndex)
> End Select
>
> WndProc = CallWindowProc(lpfnOld, hWnd, uMsg, wParam, lParam)
> End Function
>
> Thanks!
>
>
>
Re: Can someone explain what is happening with this code...
It doesn't even do that because the dropdown list does not have the same
hWnd as the ComboBox, and the ListIndex doesn't change until you make a
selection. You get a Combox_Click event when the selection is changed
anyway, so there is a trivial way to write this code without
subclassing. -Matt
> Grinder,
>
> thanks a lot, but why does the last part not make any sense. it's just
> displaying what the user ran their mouse over when scrolling through the
> combo box.
>
Re: Can someone explain what is happening with this code...
I'm sorry, Matt. I don't understand what you're saying. When you run that,
the label displays the item you're on (the .listindex, which is changing as
you scroll through the items. I do realize that the change_event isn't
firing. Why is that? I'm not sure what is going on? And what more "trivial"
way is there to do this?
Thanks
"Matthew Curland" <mattcur@microsoft.com> wrote in message
news:3cd02b25@10.1.10.29...
> It doesn't even do that because the dropdown list does not have the same
> hWnd as the ComboBox, and the ListIndex doesn't change until you make a
> selection. You get a Combox_Click event when the selection is changed
> anyway, so there is a trivial way to write this code without
> subclassing. -Matt
>
> > Grinder,
> >
> > thanks a lot, but why does the last part not make any sense. it's just
> > displaying what the user ran their mouse over when scrolling through the
> > combo box.
> >
>
>
Re: Can someone explain what is happening with this code...
The Change event fires when you type in the textbox, the Click fires when
the ListIndex changes. The trivial way is:
Private Sub Combo1_Click()
Label1 = Combo1
End Sub
If you don't like using defaults, this can also be written as
Label1.Caption = Combo1.List(Combo1.ListIndex)
or
Label1.Caption = Combo1.[_Default]
The end result is essentially the same. Moving the mouse does not change the
ListIndex of the combo box, so the subclass code keeps changing the caption
property to the same value over and over. A UI where the label updates
suddenly on a mouse move is bizarre if moving the mouse to other regions
does not also affect a change in the label. -Matt
"Robert Tedesco" <RTesc25@hotmail.com> wrote in message
news:3cd038f7@10.1.10.29...
> I'm sorry, Matt. I don't understand what you're saying. When you run that,
> the label displays the item you're on (the .listindex, which is changing
as
> you scroll through the items. I do realize that the change_event isn't
> firing. Why is that? I'm not sure what is going on? And what more
"trivial"
> way is there to do this?
>
> Thanks
>
> "Matthew Curland" <mattcur@microsoft.com> wrote in message
> news:3cd02b25@10.1.10.29...
> > It doesn't even do that because the dropdown list does not have the same
> > hWnd as the ComboBox, and the ListIndex doesn't change until you make a
> > selection. You get a Combox_Click event when the selection is changed
> > anyway, so there is a trivial way to write this code without
> > subclassing. -Matt
> >
> > > Grinder,
> > >
> > > thanks a lot, but why does the last part not make any sense. it's just
> > > displaying what the user ran their mouse over when scrolling through
the
> > > combo box.
> > >
> >
> >
>
>
Re: Can someone explain what is happening with this code...
Matt,
>>
The end result is essentially the same. Moving the mouse does not change the
ListIndex of the combo box
<<
Actually that isn't true it's just that there is no event informing you of a
change in list index.
Yesterday I would have agreed with you but then over in vb.general Matt
Markus posted this:-
>>
Private Sub Form_Load()
Dim i As Integer
For i = 1 To 25
cbo.AddItem "Item: " & i
Next i
Tmr.Interval = 10
Tmr.Enabled = True
End Sub
Private Sub Tmr_Timer()
lbl.Caption = cbo.List(cbo.ListIndex)
End Sub
<<
I thought Nah that'll never work, but it does.
--
Anthony Jones
Nuesoft Ltd
Re: Can someone explain what is happening with this code...
What is wrong with this code then? Isn't it basically doing the same thing
as the code Matt Markus posted?
What is the best way to do this? What are the "wrongs" with doing it through
subclassing compared to the timer?
I also dont understand what Matt C. is saying. Is he saying that I shouldnt
do it this way? Because this way works: when I hover over an item in the
combo box, the name is displayed in the label. I understand that the labels
caption is being set over and over again with the same list index, of
course, until a new item is hovered over, then the list index changes. Why
is Matt C saying the list index only changes when the click event fires.
Obviously that is not true.
"Anthony Jones" <anthony.jones@nonuesoft.spamco.uk> wrote in message
news:3cd0487f@10.1.10.29...
> Matt,
>
> >>
> The end result is essentially the same. Moving the mouse does not change
the
> ListIndex of the combo box
> <<
>
> Actually that isn't true it's just that there is no event informing you of
a
> change in list index.
>
> Yesterday I would have agreed with you but then over in vb.general Matt
> Markus posted this:-
>
> >>
> Private Sub Form_Load()
> Dim i As Integer
>
> For i = 1 To 25
> cbo.AddItem "Item: " & i
> Next i
>
> Tmr.Interval = 10
> Tmr.Enabled = True
> End Sub
>
> Private Sub Tmr_Timer()
> lbl.Caption = cbo.List(cbo.ListIndex)
> End Sub
> <<
>
> I thought Nah that'll never work, but it does.
>
> --
> Anthony Jones
> Nuesoft Ltd
>
>
Re: Can someone explain what is happening with this code...
Okay, so what you're saying is that this *should not* be a feature added to
a UI ?
"Rob Teixeira" <RobTeixeira@@msn.com> wrote in message
news:3cd05c97$1@10.1.10.29...
>
>
> Perhaps, the way of looking at it is that you shouldn't count on this
behavior.
> In other words, under the current implementation, the control
"temporarily"
> (and i stress temporarily) changes the listindex while you're hovering
over
> the list. However, it does not commit the listindex change unless you
select
> an item (which then causes the Click event to fire).
> This behavior is not documented, it's a side effect (as far as i can
tell).
> That being the case, it's subject to change. You have no way of predicting
> what's really going on internally in the combobox code.
>
> -Rob
>
>
> "Robert Tedesco" <RTesc25@hotmail.com> wrote:
> >What is wrong with this code then? Isn't it basically doing the same
thing
> >as the code Matt Markus posted?
> >
> >What is the best way to do this? What are the "wrongs" with doing it
through
> >subclassing compared to the timer?
> >
> >I also dont understand what Matt C. is saying. Is he saying that I
shouldnt
> >do it this way? Because this way works: when I hover over an item in the
> >combo box, the name is displayed in the label. I understand that the
labels
> >caption is being set over and over again with the same list index, of
> >course, until a new item is hovered over, then the list index changes.
Why
> >is Matt C saying the list index only changes when the click event fires.
> >Obviously that is not true.
> >
>
Re: Can someone explain what is happening with this code...
Perhaps, the way of looking at it is that you shouldn't count on this behavior.
In other words, under the current implementation, the control "temporarily"
(and i stress temporarily) changes the listindex while you're hovering over
the list. However, it does not commit the listindex change unless you select
an item (which then causes the Click event to fire).
This behavior is not documented, it's a side effect (as far as i can tell).
That being the case, it's subject to change. You have no way of predicting
what's really going on internally in the combobox code.
-Rob
"Robert Tedesco" <RTesc25@hotmail.com> wrote:
>What is wrong with this code then? Isn't it basically doing the same thing
>as the code Matt Markus posted?
>
>What is the best way to do this? What are the "wrongs" with doing it through
>subclassing compared to the timer?
>
>I also dont understand what Matt C. is saying. Is he saying that I shouldnt
>do it this way? Because this way works: when I hover over an item in the
>combo box, the name is displayed in the label. I understand that the labels
>caption is being set over and over again with the same list index, of
>course, until a new item is hovered over, then the list index changes. Why
>is Matt C saying the list index only changes when the click event fires.
>Obviously that is not true.
>
Re: Can someone explain what is happening with this code...
Robert, you're right. Sorry about the confusion here, I tried to guess what
the code would do, and I was wrong.
Having to do this with a WM_MOUSEMOVE is unfortunate, but it may be the only
way. I would have assumed that a CBN_SELCHANGE notification would be sent
when the mouse changes the selection, but spyxx tells me it is not, even
though the combos current selection indicates a different value. Also, all
of the WM_MOUSEMOVE events will be forwarded from the constituent controls
to the main combobox control, so the subclassing code will work correctly.
To reduce flicker caused by updating the label on every mouse move, you may
want to limit changes by keeping your last-recorded listindex and only
updating the label on a change, or only update the label when the value
differs from the last recorded ListIndex in the Click event. If you want to
get a little more involved, then watch for CB_SHOWDROPDOWN as well and only
turn on the mousemove checking when the dropdown is open. You can record
changes made with the dropdown closed via the Click event.
The comments on how to get a lightweight and stable subclassing system with
the code running in your form instead of a .bas module still apply.
-Matt
"Robert Tedesco" <RTesc25@hotmail.com> wrote in message
news:3cd058b9$1@10.1.10.29...
> What is wrong with this code then? Isn't it basically doing the same thing
> as the code Matt Markus posted?
>
> What is the best way to do this? What are the "wrongs" with doing it
through
> subclassing compared to the timer?
>
> I also dont understand what Matt C. is saying. Is he saying that I
shouldnt
> do it this way? Because this way works: when I hover over an item in the
> combo box, the name is displayed in the label. I understand that the
labels
> caption is being set over and over again with the same list index, of
> course, until a new item is hovered over, then the list index changes. Why
> is Matt C saying the list index only changes when the click event fires.
> Obviously that is not true.
>
> "Anthony Jones" <anthony.jones@nonuesoft.spamco.uk> wrote in message
> news:3cd0487f@10.1.10.29...
> > Matt,
> >
> > >>
> > The end result is essentially the same. Moving the mouse does not change
> the
> > ListIndex of the combo box
> > <<
> >
> > Actually that isn't true it's just that there is no event informing you
of
> a
> > change in list index.
> >
> > Yesterday I would have agreed with you but then over in vb.general Matt
> > Markus posted this:-
> >
> > >>
> > Private Sub Form_Load()
> > Dim i As Integer
> >
> > For i = 1 To 25
> > cbo.AddItem "Item: " & i
> > Next i
> >
> > Tmr.Interval = 10
> > Tmr.Enabled = True
> > End Sub
> >
> > Private Sub Tmr_Timer()
> > lbl.Caption = cbo.List(cbo.ListIndex)
> > End Sub
> > <<
> >
> > I thought Nah that'll never work, but it does.
> >
> > --
> > Anthony Jones
> > Nuesoft Ltd
> >
> >
>
>
Re: Can someone explain what is happening with this code...
Frankly at this stage VB6 is unlikely to change this behaviour. IMO, if you
can find a way to acheive your goal without sub-classing you should go for
it.
--
Anthony Jones
Nuesoft Ltd
Re: Can someone explain what is happening with this code...
Nah, just saying you should be careful ;)
As far as the combobox is concerned, the only thing you can count on is that
the control will send a SELCHANGED notification when the selection changes
(not the mouseover temporary changes), and if you use the droplist, you'll
get either a SELENDOK or SELENDCANCEL notification.
-Rob
"Robert Tedesco" <RTesc25@hotmail.com> wrote:
>Okay, so what you're saying is that this *should not* be a feature added
to
>a UI ?
>
>"Rob Teixeira" <RobTeixeira@@msn.com> wrote in message
>news:3cd05c97$1@10.1.10.29...
>>
>>
>> Perhaps, the way of looking at it is that you shouldn't count on this
>behavior.
>> In other words, under the current implementation, the control
>"temporarily"
>> (and i stress temporarily) changes the listindex while you're hovering
>over
>> the list. However, it does not commit the listindex change unless you
>select
>> an item (which then causes the Click event to fire).
>> This behavior is not documented, it's a side effect (as far as i can
>tell).
>> That being the case, it's subject to change. You have no way of predicting
>> what's really going on internally in the combobox code.
>>
>> -Rob
>>
>>
>> "Robert Tedesco" <RTesc25@hotmail.com> wrote:
>> >What is wrong with this code then? Isn't it basically doing the same
>thing
>> >as the code Matt Markus posted?
>> >
>> >What is the best way to do this? What are the "wrongs" with doing it
>through
>> >subclassing compared to the timer?
>> >
>> >I also dont understand what Matt C. is saying. Is he saying that I
>shouldnt
>> >do it this way? Because this way works: when I hover over an item in
the
>> >combo box, the name is displayed in the label. I understand that the
>labels
>> >caption is being set over and over again with the same list index, of
>> >course, until a new item is hovered over, then the list index changes.
>Why
>> >is Matt C saying the list index only changes when the click event fires.
>> >Obviously that is not true.
>> >
>>
>
>
Re: Can someone explain what is happening with this code...
"Grinder" <grinder@no.spam.maam.com> wrote:
>> Can someone explain what these API function are doing, and basically what
>> the flow of this is. I'm not really familiar with Subclassing...
>
>> Call SubClass(Form1.Combo1.hWnd)
>> Call UnSubClass(Form1.Combo1.hWnd)
>
>These two call begin and end subclassing. If you don't UnSubClass on your
>way out, you'll more than likely crash your application.
>
>When you subclass you establish a routine that gets call to handle the
>window's messages. You keep a pointer to the previous function so that
it
>can be restored and so that you can pass messages along that you don't want
>to handle.
>
>The WndProc routine, below, is that routine:
>
>> Public Function WndProc(ByVal hWnd As Long, _
>> ByVal uMsg As Long, _
>> ByVal wParam As Long, _
>> ByVal lParam As Long) As Long
>>
>> Select Case uMsg
>> Case MOUSE_MOVE
>> Form1.Label1 = Form1.Combo1.List(Form1.Combo1.ListIndex)
>> End Select
>>
>> WndProc = CallWindowProc(lpfnOld, hWnd, uMsg, wParam, lParam)
>> End Function
>
>By calling the previous window procedure (lpfnOld) regardless of the
>message, this "handler" does not really handle any messages. It just peeks
>at the MOUSE_MOVE message and sets a label on the form. That part of the
>code, though, does not make much sense.
>
>
>