Can someone explain what is happening with this code...


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 15 of 15

Thread: Can someone explain what is happening with this code...

  1. #1
    Robert Tedesco Guest

    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!




  2. #2
    Grinder Guest

    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.




  3. #3
    Robert Tedesco Guest

    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.
    >
    >
    >




  4. #4
    Matthew Curland Guest

    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!
    >
    >
    >




  5. #5
    Matthew Curland Guest

    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.
    >




  6. #6
    Robert Tedesco Guest

    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.
    > >

    >
    >




  7. #7
    Matthew Curland Guest

    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.
    > > >

    > >
    > >

    >
    >




  8. #8
    Anthony Jones Guest

    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



  9. #9
    Robert Tedesco Guest

    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
    >
    >




  10. #10
    Robert Tedesco Guest

    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.
    > >

    >




  11. #11
    Rob Teixeira Guest

    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.
    >



  12. #12
    Matthew Curland Guest

    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
    > >
    > >

    >
    >




  13. #13
    Anthony Jones Guest

    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



  14. #14
    Rob Teixeira Guest

    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.
    >> >

    >>

    >
    >



  15. #15
    senthilkumar_sb Guest

    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.
    >
    >
    >



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center