none
Highlighted list member at mouse position on .Dropdown RRS feed

  • Question

  • I have MyControl.Dropdown run on a combo box KeyPress event (first character only). This neatly drops the box down on first keypress so that the user can see immediately the auto-complete entry in the context of the rest of the value list. This, in turn, allows the user to arrow down to a close entry rather than continuing to type or pick up the mouse.

    However, if the mouse pointer happens to be already sitting within screen space occupied by the dropdown box when it appears, the line at the mouse position automatically turns black (i.e. as though it is the current line). My auto-complete works correctly based on characters typed; however, on that first keystroke, the highlighted list member is the one where the mouse pointer is, not the one indicating the result of auto-complete.

    For example, if my list consists of numerals 1 through 1000, and the mouse is about half an inch below the combo box, when I type a "2", the DropDown occurs; however, the line with "2" on it is not highlighted; instead, the highlighted might be 7 or 8--wherever the mouse pointer happens to be sitting at that moment. When I then continue and type a "1" (to go to "21"), the focus correctly goes to 21 on the list.

    But I find it odd that the mouse position, even though no click is associated with entering characters, "steals" the focus on that first click.

    I know, this is fairly geeky; however, I always strive to make everything work smoothly. Any ideas on how to get a combo box dropdown (by .Dropdown method) to ignore the current mouse position and follow auto-complete logic instead?


    Wednesday, November 16, 2016 7:53 AM

Answers

  • Hi Brian,

    I was able to duplicate your issue but wasn't able to find a simple solution. So, the only thing I could suggest is for you is to maybe try using an API to move the mouse pointer away from the dropdown area.

    See if this article helps...

    • Marked as answer by Brian D. Hart Thursday, November 17, 2016 6:25 PM
    Thursday, November 17, 2016 6:15 PM
  • For what it's worth, I tried this using a simple API call to move the mouse pointer to the top-left corner of the active control (before dropping down the  combo box), and it worked without seeming -- to me -- particularly disruptive.

    Dirk Goldgar, MS Access MVP
    Access tips: www.datagnostics.com/tips.html

    Thursday, November 17, 2016 11:32 PM

All replies

  • Hi Brian D. Hart,

    From the description of the thread it looks like you have issue with highlight the auto correct text instead of Mouse position.

    but you did not posted any code.

    so we are not able to judge this issue by only description.

    if you post the code then we can try to look in to that and test it on our side.

    because in your description you had mentioned many things which makes us confused to assume the real situation.

    so at this stage our suggestion can mislead you.

    so I suggest you to post the code and your desired output.

    we will try to suggest you further with that.

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, November 17, 2016 3:13 AM
    Moderator
  • Here is the code. In short, there is a public module that I call from KeyPress events to drop down the active control upon typing the first character, as long as that character is not 9, 13, or 27 (I do not want to drop down on Tab, Esc, or Enter). For the combo box, AutoExpand is True.

    In the standard module:

    Public ControlDropDownStatus As Boolean 
    
     Public Function ControlDropDown(Keystroke As Integer)
     Select Case Keystroke
         Case 9, 13, 27 'ignore TAB, ENTER, ESC
             ControlDropDownStatus = False
         Case Else
             Screen.ActiveControl.Dropdown
             ControlDropDownStatus = True
     End Select
      End Function

    In my form's module:

     Private Sub MyComboBox_Enter()
       ControlDropDownStatus = False
      End Sub
    
     Private Sub MyComboBox_KeyPress(KeyAscii As Integer)
      If KeyAscii = 27 Then ControlDropDownStatus = False
       If Not ControlDropDownStatus Then ControlDropDown (KeyAscii)
      End Sub

    This all works perfectly, but for one thing: if the mouse pointer happens to be sitting somewhere inside the space that becomes occupied by the dropdown box when it drops down, the highlighted line after the first keystroke. In the screenshot below, my mouse pointer (which does not appear in the screen shot) was just below the bottom of the form. As soon as I typed "1" in the box, the box (correctly) dropped down; however, the item "focus" went immediately (and incorrectly) to "8" based on the location of the mouse pointer at that moment. With the mouse moved out of the way, the focus would (correctly) go to "2" instead.

    I know it seems (and admittedly may, in fact be) trivial and is, in all likelihood, considered correct behavior for a combo box, but I try to build as much convenience as possible into my applications, and the current behavior is likely to be confusing to users, whose attention will be incorrectly drawn to the "8", while the true value of the box, if the user were to press Enter, would actually (and correctly) be "2". I understand that a combo box is intended to both AutoExpand and follow the mouse and that once the mouse is moved, the focus is to follow the mouse without changing the value until there is a click; however, in this case, where I am doing the dropdown programmatically, it just seems to me that the list member highlighted at the moment of dropdown should be associated with the keyboard event that triggered the dropdown (i.e. AutoExpand), not with the mouse position, since there was no mouse click or movement associated with the dropdown.


    Thursday, November 17, 2016 6:00 PM
  • Hi Brian,

    I was able to duplicate your issue but wasn't able to find a simple solution. So, the only thing I could suggest is for you is to maybe try using an API to move the mouse pointer away from the dropdown area.

    See if this article helps...

    • Marked as answer by Brian D. Hart Thursday, November 17, 2016 6:25 PM
    Thursday, November 17, 2016 6:15 PM
  • Thank you. It would probably not be worth writing an API call into my code. After all, this is supposed to just be a little extra convenience to the user. I embed this dropdown code into all my apps, since I have found that it is easier for the user to see the surrounding entries as soon as they begin typing than it is to manually click the dropdown arrow to see the list. But determining the dropdown area based on the numbers of rows so that I can move the mouse out of the way, or moving the mouse to the left or right out of the way, would seem kind of overkill. And you can imagine the response from users were the mouse to mysteriously move out of the way.

    I just thought perhaps there was some setting in Access itself allowing the developer to prioritize AutoExpand over mouse position, or at least not picking up mouse position until it is moved.

    Thursday, November 17, 2016 6:37 PM
  • Hi Brian,

    I agree; but unfortunately, I couldn't find a simpler solution since there wasn't a setting I could find to change the default behavior we're seeing.

    Good luck with your project.

    Thursday, November 17, 2016 7:29 PM
  • For what it's worth, I tried this using a simple API call to move the mouse pointer to the top-left corner of the active control (before dropping down the  combo box), and it worked without seeming -- to me -- particularly disruptive.

    Dirk Goldgar, MS Access MVP
    Access tips: www.datagnostics.com/tips.html

    Thursday, November 17, 2016 11:32 PM
  • This is a good idea! You can "move" the cursor somewhat over the dropdown arrow to simulate the user clicking on it to see the dropdown, which of course drops down because of your .Dropdown code.

    Nice work, Dirk.

    Friday, November 18, 2016 12:00 AM
  • Yes. Thank you, Dirk. I had not considered that. Rather than moving the cursor out of the way, move it to where it would have had to be for a mouse-click-initiated dropdown. That is brilliant and, as you indicate, one place I could move the cursor that would be perfectly logical given the current action.

    I will work on this...but would you care to post the API call you used? I assume I would have to first determine the current position of the combo box itself, in particular the dropdown arrow, then move the cursor to that location.

    Friday, November 18, 2016 5:58 AM
  • Yes. Thank you, Dirk. I had not considered that. Rather than moving the cursor out of the way, move it to where it would have had to be for a mouse-click-initiated dropdown. That is brilliant and, as you indicate, one place I could move the cursor that would be perfectly logical given the current action.

    I will work on this...but would you care to post the API call you used? I assume I would have to first determine the current position of the combo box itself, in particular the dropdown arrow, then move the cursor to that location.

    Note: I only placed the cursor at the top *left* of the control, not at the top right.  That's because I already had code written to do that.  Top right will be a bit trickier, because it will require calculating where the top right corner of the control window is, while Windows already knows directly where the top left corner is.  I'll look into that, but can't promise to get back to you right away.

    This is the code I used:

    Option Compare Database
    Option Explicit
    
    Private Type POINT
        X As Long
        Y As Long
    End Type
    
    Private Declare Sub ClientToScreen Lib "user32" (ByVal hWnd As Long, lpPoint As POINT)
    Private Declare Function GetFocus Lib "user32" () As Long
    Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
    
    Public Function MouseToControl( _
                ctl As Access.Control, _
                Optional LeaveFocus As Boolean = False)
        
        ' Move the mouse cursor to a specific control, passed
        ' as argument "ctl".  By default, the focus will be set to
        ' that control and left there;  however, this behavior can
        ' be controlled by the optional argument "LeaveFocus".
        ' If LeaveFocus is True, the focus will be returned to
        ' the control that originally had it.
        '
        ' Note that <ctl> must be a control that is capable of
        ' receiving the focus.  If it doesn't already have the
        ' focus, it *will* receive the focus, at least momentarily,
        ' even if the focus is then set back to the previously active
        ' control.  However, if <ctl> cannot receive the focus -- for
        ' example, if it's a label control -- then the cursor will
        ' move to the top left corner of the form.
        '
        ' Copyright © 2016 Dirk Goldgar, DataGnostics LLC
        ' License is freely granted to use this code in your applications,
        ' so long as the attribution and copyright remain intact.
    
        Dim ctlOld As Access.Control
        Dim hWnd As Long
        Dim pt As POINT
    
        On Error Resume Next
        If LeaveFocus Then Set ctlOld = Screen.ActiveControl
        
        ctl.SetFocus
        hWnd = GetFocus
        
        ClientToScreen hWnd, pt
        SetCursorPos pt.X, pt.Y
        
        If LeaveFocus Then
            If Not ctlOld Is Nothing Then
                ctlOld.SetFocus
            End If
        End If
        
    End Function
    

    With that code in a standard module, then you would modify your ControlDropDown procedure to add the line:

        MouseToControl Screen.ActiveControl

    before calling Screen.ActiveControl.Dropdown.


    Dirk Goldgar, MS Access MVP
    Access tips: www.datagnostics.com/tips.html

    Friday, November 18, 2016 4:43 PM