dcsimg
Results 1 to 37 of 37

Thread: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Resolved [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    I have a ComboBox loaded with items. One of the items is a separator bar. I don't want the user to be able to select this item. How would you prevent them from doing so? Ideally I'd like some way to make it non-selectable or disabled (is there an API that does this?).

    Sample CB items list
    =========
    1
    2
    3
    --- <--- Here's the separator bar
    4
    5
    6


    What I'm currently doing is changing the user's selection when they select the separator bar item. It works but it's a bit kludgey.

    TIA for your thoughts.

    (BTW - This is a VBCCR16 control so I do have additional properties and methods available to me over the standard VB6 version but I don't think it makes a difference for this issue.)
    Last edited by AAraya; Aug 1st, 2019 at 04:20 PM.

  2. #2
    Fanatic Member
    Join Date
    Feb 2003
    Posts
    725

    Re: Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by AAraya View Post
    I have a ComboBox loaded with items. One of the items is a separator bar. I don't want the user to be able to select this item. How would you prevent them from doing so? Ideally I'd like some way to make it non-selectable or disabled (is there an API that does this?).

    Sample CB items list
    =========
    1
    2
    3
    --- <--- Here's the separator bar
    4
    5
    6


    What I'm currently doing is changing the user's selection when they select the separator bar item. It works but it's a bit kludgey.

    TIA for your thoughts.

    (BTW - This is a VBCCR16 control so I do have additional properties and methods available to me over the standard VB6 version but I don't think it makes a difference for this issue.)
    Could you post your code and explain what you mean by "kludgey"?

  3. #3
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    7,098

    Re: Is it possible to make a ComboBox item non-selectable?

    You could always do something as simple as this:

    Code:
    Private Sub Combo1_Click()    
         If Combo1.Text = "---" Then Combo1.ListIndex = 0
    End Sub

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: Is it possible to make a ComboBox item non-selectable?

    This is what I'm currently doing. It works but it's not ideal. With this approach, the user is able to select that CB item, the combo box text momentarily shows the separator line, then the app changes the selection. The end result of these actions is some flashing.

    I was hoping to prevent the user from selecting the item in the first place.

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by Peter Swinkels View Post
    Could you post your code and explain what you mean by "kludgey"?
    Similar approach to what SOB posted.

    Code:
    Private Sub Combo1_Click()    
         If Combo1.Text = "---" Then Combo1.ListIndex = 0
    End Sub

  6. #6
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: Is it possible to make a ComboBox item non-selectable?

    You could certainly subclass the ComboBox and get it done. That would probably give you much cleaner looking results, but I'm not sure you want to dive into those complexities. Beyond what's been suggested above, I'm not sure you've got another option other than jumping into subclassing.

    I subclass the VB6 ComboBox for a particular application (individually coloring the dropdown items, and also putting tooltips on each item). It's not terribly difficult to subclass a ComboBox, but it's far from trivial as well.

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  7. #7

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by Elroy View Post
    You could certainly subclass the ComboBox and get it done. That would probably give you much cleaner looking results, but I'm not sure you want to dive into those complexities. Beyond what's been suggested above, I'm not sure you've got another option other than jumping into subclassing.

    I subclass the VB6 ComboBox for a particular application (individually coloring the dropdown items, and also putting tooltips on each item). It's not terribly difficult to subclass a ComboBox, but it's far from trivial as well.
    Is the subclassing code something you'd be able/willing to share?

  8. #8
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: Is it possible to make a ComboBox item non-selectable?

    I've posted a (very small) CodeBase which would be easy to adjust for this case here:
    http://www.vbforums.com/showthread.p...x-(OwnerDrawn)

    Since it allows Multi-Selections, the closing of the DropDown-area is suppressed "already by default".

    HTH

    Olaf

  9. #9
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by AAraya View Post
    Is the subclassing code something you'd be able/willing to share?
    Ok, the attached project has all kinds of stuff in it you don't need, but it does have an example of ComboBox subclassing. I cut this code out of a much larger project that's been in production for many years.

    When cutting it out, I did try and preserve a semblance of organization. You'll see that in the three BAS modules I provided. Again, there's a lot there you may not need, and could carefully trim out.

    The ComboBox is in a UserControl (UC), as that's the only example I had. However, if you work through it, you could take that piece out. However, it's probably not a bad idea to just leave it as a UC, and mold mine into something that does what you're after.

    Good luck with it,
    Elroy
    Attached Files Attached Files
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: Is it possible to make a ComboBox item non-selectable?

    Thanks Olaf and Elroy - I downloaded both your projects and played with the code. Ultimately I was able to use Elroy's code to change the forecolor of the separator item to a disabled text color. It's not actually disabled but at least visually it stands out as different from the rest so when the app auto-changes the selection, the user will have an idea of what's happening.

  11. #11
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    It will probably be a few days, but maybe I'll take a look at it and add an "Enabled" property to each item in the dropdown. If I get to it, I'll post what I do in this thread.
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  12. #12

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    duplicate...

  13. #13

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    I'm having one problem that perhaps you guys with Owner drawn controls can help with... When I disable the combo, the text in the edit portion of the combo disappears. Apparently I'm supposed to do some custom drawing for this case? All other custom drawing stuff is working properly for this combobox except for this one case. I've looked at all the custom-drawn combobox examples I could find on the web and none seem to do any special handling for this case. They all look pretty much like what I have.

    Any ideas?

    I realize that this is a separate question but it is part of the original issue which Olaf and Elroy helped me with so I chose to keep the follow-up question here.

  14. #14
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Hey AAraya,

    Typically, I'd dive into this and take a look at it for you. However, I'm trying to wrap up some other loose ends before going on a two-week vacation. If it's not solved before I get back, I'll almost certainly take a look at it then. For now, I'm just here for quick hit-or-miss stuff.

    In the meantime, you, or anyone else, is more than welcome to look at my code from post #9 to see what's going on.

    Also, AAraya, you may do others a favor if you attached a small VB6 project that outlined the problem, possibly with some cropped screenshots as well. Or, if you'd like to get fancy, a screen-movie-capture.

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  15. #15

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Hi Elroy,

    I found the problem on my own. I needed to check for an ItemState of ODS_COMBOBOXEDIT and set the PenColor to either COLOR_WINDOWTEXT or COLOR_GRAYTEXT depending on the enabled property of the control.

    Thanks so much for your help!

    Enjoy your vacay!

  16. #16
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Ok, procrastinating my packing. I went ahead and tweaked my UC combo and made it have the option of no-select items.

    It's nice in that they don't show selected even when hovering over them in the dropdown, and then certainly don't select if you try and click on them.

    There's actually two pieces to stopping them: 1) I had to suppress the Click event, and 2) I had to make sure the dropdown text didn't go into the edit portion of the ComboBox. But it's all done.

    Project is attached. In this test project, the green items (with a prefix line) are marked as "no select". The red items are normal items.

    I also recorded a short video:



    Here's the line where you call AddItem:

    Code:
    
    Public Sub AddItem(sItem As String, Optional lColor As Long = -1&, Optional bClickable As Boolean = True)
    
    

    The new option is basically the optional bClickable argument, which defaults to True.

    Enjoy,
    Elroy
    Attached Files Attached Files
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  17. #17

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Elroy - you rock! I had been working on this myself this morning and had come up with a solution very similar to yours already. Looking over your project confirmed my approach. Thank you!

    I really only have one issue that I'd like to solve right now. When the user selects a separator item with a mouse click, I suppress the click and take them back to the previously selected item. Works great! But when they scroll through the list via a keypress (up or down arrow), the behavior should be different - rather than taking them back to their previous selection, it should "skip" over to the next or previous non-separator item. I don't have that working yet. Currently I was only checking for combo selection change messages in the subclassing proc but I guess I'm going to have to determine if the selection changed due to mouse click or a key press event??? Do I have that right?

  18. #18
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Ahhh, I didn't think about that. I see that mine gets hung and won't skip over a no-select item when using the arrows. I know what it's doing. It's keeping track of the last valid selectable item and resetting to that. So, when down-arrowing (or up-arrowing), it just keeps re-selecting the previous item, never able to skip the no-select item and get beyond it.

    I'll have to think about that one. It's not a trivial solution because of the edge conditions. This probably isn't the case for you, but it will need to behave correctly if a no-select item is at the bottom (or top) of the list. That's what I mean by edge condition. Also, it's possible to have two (or more) no-select items together. Again, might not get to it before vacation.

    Take Care,
    Elroy
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  19. #19

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Correct, I don't have to worry about edge conditions in my case like you do. I just need to know if the CBN_SELECTION is caused by a mouse click or by an arrow key. Per MSDN documentation...

    CBN_SELCHANGE notification code
    Sent when the user changes the current selection in the list box of a combo box. The user can change the selection by clicking in the list box or by using the arrow keys.
    But there's no mention of how to know which action caused it.

    I'll continue to search for an answer as I'm sure there must be one - menus handle this properly so perhaps I need to look at some owner drawn menu stuff?

  20. #20
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Ok AAraya,

    I'm going to post some code, that has arrow functionality. It's just for the modSubclassing (Subclassing.bas) module. All else is the same as I posted in post #16. I've done some testing, but more is probably needed. What I've tested is: empty list in combo, top item non-selectable, bottom item non-selectable, duplicate contiguous items non-selectable, all items non-selectable ... and that all seems to work fine.

    The one bug I did find (not corrected) is that things go awry if you're using more than one of these things at the same time. Basically, those Static variables in the subclassing procedure get mucked. I've got procedures to deal with that (basically the SubclassExtraData, GetExtraData, and UnSubclassExtraData procedures that you can see [used in other cases of subclassing]), but I'm really running out of time. Plane leaving early tomorrow morning, and my wife is giving me strange looks because I'm not packing.

    Ok, here's the new code for modSubclassing:

    Code:
    Option Explicit
    '
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    '
    ' MODULE level stuff for general subclassing.
    '
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    '
    Public gbAllowSubclassing               As Boolean      ' Be sure to turn this on if you're going to use subclassing.
    Dim bSetWhenSubclassing_UsedByIdeStop   As Boolean      ' Never goes false once set by first subclassing, unless IDE Stop button is clicked.
    Private Const WM_DESTROY                As Long = &H2&  ' All other needed constants are declared within the procedures.
    '
    Private Declare Function SetWindowSubclass Lib "comctl32.dll" Alias "#410" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
    Private Declare Function GetWindowSubclass Lib "comctl32.dll" Alias "#411" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, pdwRefData As Long) As Long
    Private Declare Function RemoveWindowSubclass Lib "comctl32.dll" Alias "#412" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
    Private Declare Function NextSubclassProcOnChain Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    'Private Declare Function DefSubclassProc Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    '
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    '
    ' MODULE level stuff specific to individual subclassing needs.
    '
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    '
    Private Enum ExtraDataIDs
        ' These must be unique for each piece of extra data.
        ' They just give us 4 bytes each managed by ComCtl32.
        ID_ForMaxSize = 1
    End Enum
    #If False Then  ' Intellisense fix.
        Dim ID_ForMaxSize
    #End If
    '
    Private Type DRAWITEMSTRUCT
        CtlType As Long
        CtlID As Long
        ItemID As Long
        ItemAction As Long
        ItemState As Long       ' Bitflags: ODS_COMBOBOXEDIT    = &h1000& (edit control being drawn).
                                '           ODS_SELECTED        = &h0001&
                                '           ODS_DISABLED        = &h0004&
                                '           ODS_FOCUS           = &h0010&
                                '           ODS_NOACCEL         = &h0100&
                                '           ODS_NOFOCUSRECT     = &h0200&
                                '           Others, but they don't apply to combobox.
                                '
        hWndItem As Long        ' hWnd to the ComboBox.
        hDC As Long
        rcItem As RECT
        ItemData As Long
    End Type
    '
    Private Declare Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As Long
    Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
    Private Declare Function SetDCBrushColor Lib "gdi32" (ByVal hDC As Long, ByVal colorref As Long) As Long
    Private Declare Function SetDCPenColor Lib "gdi32" (ByVal hDC As Long, ByVal colorref As Long) As Long
    Private Declare Function SetBkMode Lib "gdi32" (ByVal hDC As Long, ByVal nBkMode As Long) As Long
    Private Declare Function SetTextColor Lib "gdi32" (ByVal hDC As Long, ByVal crColor As Long) As Long
    Private Declare Function Rectangle Lib "gdi32" (ByVal hDC As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal y2 As Long) As Long
    Private Declare Function DrawTextA Lib "user32" (ByVal hDC As Long, lpStr As Any, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
    '
    Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
    '
    
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    '
    ' Generic subclassing procedures (used in many of the specific subclassing).
    '
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    
    Private Sub SubclassSomeWindow(hWnd As Long, AddressOf_ProcToSubclass As Long, Optional dwRefData As Long, Optional uIdSubclass As Long)
        '
        ' In most cases, we just use hWnd for uIdSubclass.  However, in certain cases, we will use the same subclass procedure on the same hWnd
        ' with different uIdSubclass values.  For instance, if we want to "watch" a control, but we subclass the form to do this.  We may have
        ' several controls on the form we wish to "watch", but the form's hWnd and the subclass procedure will be the same.  Therefore, we can
        ' use different uIdSubclass values to keep it all straight.
        '
        ' The subclass uniqueness is defined by pfnSubclass and uIdSubclass (2nd and 3rd arguments in API calls).
        '
        ' This can be called AFTER the initial subclassing to update dwRefData.
        '
        If Not gbAllowSubclassing Then Exit Sub
        '
        If uIdSubclass = 0& Then uIdSubclass = hWnd
        bSetWhenSubclassing_UsedByIdeStop = True
        Call SetWindowSubclass(hWnd, AddressOf_ProcToSubclass, uIdSubclass, dwRefData)
    End Sub
    
    Private Sub SubclassExtraData(hWnd As Long, dwRefData As Long, ID As ExtraDataIDs)
        ' This is used solely to store extra data.
        '
        If Not gbAllowSubclassing Then Exit Sub
        '
        bSetWhenSubclassing_UsedByIdeStop = True
        Call SetWindowSubclass(hWnd, AddressOf DummyProcForExtraData, ID, dwRefData)
    End Sub
    
    Private Function GetSubclassRefData(hWnd As Long, AddressOf_ProcToSubclass As Long, Optional uIdSubclass As Long) As Long
        ' This one is used only to fetch the optional dwRefData you may have specified when calling SubclassSomeWindow.
        ' Typically this would only be used by the subclassed procedure, but it is available to anyone.
        If uIdSubclass = 0& Then uIdSubclass = hWnd
        Call GetWindowSubclass(hWnd, AddressOf_ProcToSubclass, uIdSubclass, GetSubclassRefData)
    End Function
    
    Private Function GetExtraData(hWnd As Long, ID As ExtraDataIDs) As Long
        Call GetWindowSubclass(hWnd, AddressOf DummyProcForExtraData, ID, GetExtraData)
    End Function
    
    Private Function IsSubclassed(hWnd As Long, AddressOf_ProcToSubclass As Long, Optional uIdSubclass As Long) As Boolean
        ' This just tells us we're already subclassed.
        Dim dwRefData As Long
        If uIdSubclass = 0& Then uIdSubclass = hWnd
        IsSubclassed = GetWindowSubclass(hWnd, AddressOf_ProcToSubclass, uIdSubclass, dwRefData) = 1&
    End Function
    
    Private Sub UnSubclassSomeWindow(hWnd As Long, AddressOf_ProcToSubclass As Long, Optional uIdSubclass As Long)
        ' Only needed if we specifically want to un-subclass before we're closing the form (or control),
        ' otherwise, it's automatically taken care of when the window closes.
        '
        ' Be careful, some subclassing may require additional cleanup that's not done here.
        If uIdSubclass = 0& Then uIdSubclass = hWnd
        Call RemoveWindowSubclass(hWnd, AddressOf_ProcToSubclass, uIdSubclass)
    End Sub
    
    Private Sub UnSubclassExtraData(hWnd As Long, ID As ExtraDataIDs)
        Call RemoveWindowSubclass(hWnd, AddressOf DummyProcForExtraData, ID)
    End Sub
    
    Private Function ProcedureAddress(AddressOf_TheProc As Long) As Long
        ' A private "helper" function for writing the AddressOf_... functions (see above notes).
        ProcedureAddress = AddressOf_TheProc
    End Function
    
    Private Function DummyProcForExtraData(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
        ' Just used for SubclassExtraData (and GetExtraData and UnSubclassExtraData).
        If uMsg = WM_DESTROY Then Call RemoveWindowSubclass(hWnd, AddressOf_DummyProc, uIdSubclass)
        DummyProcForExtraData = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
    End Function
    
    Private Function AddressOf_DummyProc() As Long
        AddressOf_DummyProc = ProcedureAddress(AddressOf DummyProcForExtraData)
    End Function
    
    Private Function IdeStopButtonClicked() As Boolean
        ' The following works because all variables are cleared when the STOP button is clicked,
        ' even though other code may still execute such as Windows calling some of the subclassing procedures below.
        IdeStopButtonClicked = Not bSetWhenSubclassing_UsedByIdeStop
    End Function
    
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    '
    ' The following are our functions to be subclassed, along with their AddressOf_... function.
    ' All of the following should be Private to make sure we don't accidentally call it,
    ' except for the first procedure that's actually used to initiate the subclassing.
    '
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    
    Public Sub SubclassForColorCombos(CtlHwnd As Long, TheObjPtr As Long)
        '
        ' This is used in conjunction with the ComboReplaceWithColor procedure.
        ' See notes in that ComboReplaceWithColor procedure for more details.
        '
        SubclassSomeWindow CtlHwnd, AddressOf ColorCombo_Proc, TheObjPtr
    End Sub
    
    Private Function ColorCombo_Proc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
        If uMsg = WM_DESTROY Then
            UnSubclassSomeWindow hWnd, AddressOf_ColorCombo_Proc, uIdSubclass
            ColorCombo_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
            Exit Function
        End If
        If IdeStopButtonClicked Then ' Protect the IDE.  Don't execute any specific stuff if we're stopping.  We may run into COM objects or other variables that no longer exist.
            ColorCombo_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
            Exit Function
        End If
        '
        Static sPrevText            As String
        Static iPrevIdx             As Long
        Static bPrevSet             As Boolean
        '
        Dim uDrawItem               As DRAWITEMSTRUCT
        Dim oBrush                  As Long
        Dim oThePen                 As Long
        Dim iRet                    As Long
        Dim sText                   As String
        Dim clr                     As ComboBoxColor
        Const ColorMask             As Long = &H80FFFFFF    ' As a note, for these colors, 7 bits of the high byte should always be zero (or available for other flags).  Only the sign bit is used (to indicate system colors).
        Const NotClickableFlag      As Long = &H1000000     ' As a note, for these colors, 7 bits of the high byte should always be zero (or available for other flags).  Only the sign bit is used (to indicate system colors).
        Dim cbn                     As Integer              ' On WM_COMMAND, passed in the high-word of wParam.
        Dim idx                     As Long
        Dim ItemData                As Long
        Dim bUpArrow                As Boolean
        Dim bDnArrow                As Boolean
        '
        Const WM_DRAWITEM           As Long = &H2B&
        Const ODT_COMBOBOX          As Long = 3&
        Const DC_PEN                As Long = 19&
        Const DC_BRUSH              As Long = 18&
        Const TRANSPARENT           As Long = 1&
        Const COLOR_WINDOW          As Long = 5&
        Const COLOR_WINDOWTEXT      As Long = 8&
        Const COLOR_HIGHLIGHT       As Long = 13&
        Const COLOR_HIGHLIGHTTEXT   As Long = 14&
        Const CB_GETLBTEXT          As Long = &H148&
        Const CB_GETLBTEXTLEN       As Long = &H149&
        Const DT_SINGLELINE         As Long = &H20&
        Const DT_VCENTER            As Long = &H4&
        Const DT_NOPREFIX           As Long = &H800&
        Const ODS_SELECTED          As Long = &H1&
        Const ODS_COMBOBOXEDIT      As Long = &H1000&   ' (edit control being drawn).
        Const WM_SETCURSOR          As Long = &H20&
        Const WM_COMMAND            As Long = &H111&
        Const CBN_SELCHANGE         As Integer = 1      ' This stops the click event.
        Const CB_GETCURSEL          As Long = &H147&
        '
        Select Case uMsg
        Case WM_SETCURSOR                                                                   ' Mouse-Move.
            Set clr = ComObjectFromPtr(dwRefData)
            clr.MouseMoveOnText
            Set clr = Nothing
            '
        Case WM_COMMAND
            GetMem2 ByVal (VarPtr(wParam) + 2&), cbn
            If Not bPrevSet Then iPrevIdx = -1&: bPrevSet = True
            Set clr = ComObjectFromPtr(dwRefData)
            idx = clr.ListIndex
            ItemData = clr.ItemData(idx)
            '
            If (ItemData And NotClickableFlag) = 0& Then
                iPrevIdx = idx
            Else
                ' If we're in here, we're on a non-clickable item.
                If cbn = CBN_SELCHANGE Then                                                 ' We don't need to mess with others.
                    bUpArrow = GetKeyState(vbKeyLeft) < 0 Or GetKeyState(vbKeyUp) < 0
                    bDnArrow = GetKeyState(vbKeyRight) < 0 Or GetKeyState(vbKeyDown) < 0
                    If bUpArrow Or bDnArrow Then
                        If bUpArrow Then
                            Do
                                idx = idx - 1&
                                If idx < 0& Then Exit Do
                                ItemData = clr.ItemData(idx)
                                If (ItemData And NotClickableFlag) = 0& Then Exit Do
                            Loop
                            If idx < 0& Then
                                clr.ListIndex = iPrevIdx                                        ' This stops the edit portion from changing.
                                Exit Function                                                   ' This prevents the click event.
                            Else
                                clr.ListIndex = idx
                                iPrevIdx = idx
                            End If
                        Else                                                                    ' Down arrow.
                            Do
                                idx = idx + 1&
                                If idx >= clr.ListCount Then Exit Do
                                ItemData = clr.ItemData(idx)
                                If (ItemData And NotClickableFlag) = 0& Then Exit Do
                            Loop
                            If idx >= clr.ListCount Then
                                clr.ListIndex = iPrevIdx                                        ' This stops the edit portion from changing.
                                Exit Function                                                   ' This prevents the click event.
                            Else
                                clr.ListIndex = idx
                                iPrevIdx = idx
                            End If
                        End If
                    Else
                        ' We've just click on a non-clickable item with mouse.
                        clr.ListIndex = iPrevIdx                                                ' This stops the edit portion from changing.
                        Exit Function                                                           ' This prevents the click event.
                    End If
                End If
            End If
            '
            Set clr = Nothing
            '
        Case WM_DRAWITEM
            CopyMemory uDrawItem, ByVal lParam, Len(uDrawItem)
            uDrawItem.ItemData = uDrawItem.ItemData
            '
            If uDrawItem.CtlType = ODT_COMBOBOX Then
                '
                ' Get brush and pen.
                oBrush = SelectObject(uDrawItem.hDC, GetStockObject(DC_BRUSH))
                oThePen = SelectObject(uDrawItem.hDC, GetStockObject(DC_PEN))
                '
                If (uDrawItem.ItemState And ODS_SELECTED) And ((uDrawItem.ItemData And NotClickableFlag) = 0&) Then
                    ' Draw highlight color rectangle.
                    SetDCBrushColor uDrawItem.hDC, GetRgbSystemColor(COLOR_HIGHLIGHT)
                    SetDCPenColor uDrawItem.hDC, GetRgbSystemColor(COLOR_HIGHLIGHT)
                    Rectangle uDrawItem.hDC, uDrawItem.rcItem.Left, uDrawItem.rcItem.Top, uDrawItem.rcItem.Right, uDrawItem.rcItem.Bottom
                    ' And now setup for drawing text.
                    SetDCPenColor uDrawItem.hDC, GetRgbSystemColor(COLOR_HIGHLIGHTTEXT)
                    SetTextColor uDrawItem.hDC, GetRgbSystemColor(COLOR_HIGHLIGHTTEXT)
                Else
                    ' Draw regular color rectangle.
                    If (uDrawItem.ItemState And ODS_COMBOBOXEDIT) Then              ' This is the actual edit box.
                        SetDCBrushColor uDrawItem.hDC, cboBackColorFromHwnd(uDrawItem.hWndItem)
                        SetDCPenColor uDrawItem.hDC, cboBackColorFromHwnd(uDrawItem.hWndItem)
                    Else                                                            ' This is something in the list.
                        SetDCBrushColor uDrawItem.hDC, GetRgbSystemColor(COLOR_WINDOW)
                        SetDCPenColor uDrawItem.hDC, GetRgbSystemColor(COLOR_WINDOW)
                    End If
                    Rectangle uDrawItem.hDC, uDrawItem.rcItem.Left, uDrawItem.rcItem.Top, uDrawItem.rcItem.Right, uDrawItem.rcItem.Bottom
                    ' And now setup for drawing text.
                    SetDCPenColor uDrawItem.hDC, uDrawItem.ItemData And ColorMask   ' The color is stored in the ItemData.
                    SetTextColor uDrawItem.hDC, uDrawItem.ItemData And ColorMask
                End If
                '
                ' We do this so our DrawText works the way we want.
                SetBkMode uDrawItem.hDC, TRANSPARENT
                '
                ' Fetch the text.
                sText = vbNullString
                If uDrawItem.ItemID >= 0& Then
                    iRet = SendMessageA(uDrawItem.hWndItem, CB_GETLBTEXTLEN, uDrawItem.ItemID, ByVal 0&)
                    If iRet Then
                        sText = Space$(iRet + 1&)
                        iRet = SendMessageA(uDrawItem.hWndItem, CB_GETLBTEXT, uDrawItem.ItemID, ByVal sText)
                        sText = Left$(sText, iRet)
                    End If
                End If
                '
                ' Draw the text.
                uDrawItem.rcItem.Left = uDrawItem.rcItem.Left + 2&                  ' Offset text by two pixels.
                DrawTextA uDrawItem.hDC, ByVal sText, Len(sText), uDrawItem.rcItem, DT_VCENTER Or DT_SINGLELINE Or DT_NOPREFIX
                '
                ' Clean-up.
                SelectObject uDrawItem.hDC, oBrush
                SelectObject uDrawItem.hDC, oThePen
                '
                ' Fire the MouseMoveOnList event ... but only if we're in the list and on our selected item, and only if we're on a clickable item.
                If (uDrawItem.ItemState And ODS_SELECTED) <> 0& And _
                   (uDrawItem.ItemState And ODS_COMBOBOXEDIT) = 0& And _
                   (uDrawItem.ItemData And NotClickableFlag) = 0& Then
                    If sText <> sPrevText Then
                        Set clr = ComObjectFromPtr(dwRefData)
                        clr.MouseMoveOnList sText                                   ' Return the text from the list item.
                        Set clr = Nothing
                        sPrevText = sText
                    End If
                End If
                '
                ' Get out.
                Exit Function
            End If
        End Select
        '
        ' If we fell out, just proceed as normal.
        ColorCombo_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
    End Function
    
    Private Function AddressOf_ColorCombo_Proc() As Long
        AddressOf_ColorCombo_Proc = ProcedureAddress(AddressOf ColorCombo_Proc)
    End Function

    I bolded the area where the changes were made (but there are a few changes in the module level code as well). (Also the bolding doesn't show well, but it's in the Case WM_COMMAND area.) Also, I made that uMsg test a Select Case, as I got tired of looking at those multiple If statements.

    Good Luck,
    Elroy
    Last edited by Elroy; Aug 7th, 2019 at 10:11 AM.
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  21. #21

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    I just came in to post that I had the arrow key functionality working now and I see that you've already posted Elroy! You handled this differently than I did. I see that you check the keystates in the cbn = CBN_SELCHANGE message handler. I did this a little differently...

    I created a separate handler for WM_KEYUP messages and check for wParam values of VK_UP or VK_DOWN and check if the next/previous item is selectable or not and handle accordingly. It's working well for me. I wonder if it makes more sense to keep it all in the CBN_SELCHANGE handler like you did however. Hmmm...

    You're also processing left and right arrow keys but I'm only checking for up and down. Are left and right keys used to navigate up and down a list?

    BTW - Thank you VERY MUCH for your time and efforts on this!

  22. #22
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by AAraya View Post
    Are left and right keys used to navigate up and down a list?
    When in a combo's dropdown, left is handled the same as up, and right is handled the same as down. I just tested in a regular combo to figure this out.

    Also, I'm taking a break from packing, so I'll look into getting rid of those static variables, and handling that more appropriately.

    Elroy
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  23. #23
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    5,693

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Ok, it's working much better now. You can have as many of the UCs as you want on a form.

    I've attached a demo project.

    There's still one small bug, and I'm not sure when I'll fix it. It doesn't crash anything, and it takes a certain set of circumstances to even find it:
    1. You've got to populate the UC combo with all non-selectable items (fourth combo in the demo).
    2. You've got to pull down the pulldown section with the mouse (little down triangle).
    3. Then you've got to tap the down arrow.
    4. Then, you've got to click off of that combo onto some other control.

    When it wraps back up, the first non-selectable item's text will be in the combo's textbox. The click event doesn't fire, but the text is still there, which is wrong.

    I tried tracking it down, but got a bit bogged down. I'll eventually get it going, but not right now.

    I tested all other conditions fairly well, and it works pretty good.

    Enjoy,
    Elroy
    Attached Files Attached Files
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  24. #24

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    I didn't know about Left and Right arrow in a combobox. Thanks! I added support for those keys.

    I also changed my key press approach to be like yours - I'm checking for GetAsyncKeyStates in the CBN_SELCHANGED notification code.

    I'm good now. Thanks again Elroy! Have a good and safe trip.

  25. #25
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    FWIW, here's the adaption of the example I've mentioned earlier:
    (with less code for the combo-ctl, modern subclassing, and nicer rendering-outputs which includes Icons):



    Zipped Example: VirtualCombo.zip

    HTH

    Olaf

  26. #26
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,605

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Hi Olaf, I saw that your VirutalCombo uses wqweto's modern subclassing(the last time you used The trick's subclassing). I have not had time to test wqweto's modern subclassing. I'd like to know, what are the advantages of wqweto's modern subclassing compared to The trick's subclassing? Thanks.

  27. #27

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by dreammanor View Post
    Hi Olaf, I saw that your VirutalCombo uses wqweto's modern subclassing(the last time you used The trick's subclassing). I have not had time to test wqweto's modern subclassing. I'd like to know, what are the advantages of wqweto's modern subclassing compared to The trick's subclassing? Thanks.
    You asked this question of Olaf but I'll chime in too. I recently switched to "The Trick's" subclasser in my program. I'm not doing anything too fancy with it - I'm catching time change notifications and also using it in this ComboBox to catch and process selection changed notifications. But it works great and is much easier to use than my previous methods. The fact that it's IDE-safe makes it a winner for me. I too am interested to hear if there are advantages to wqweto's version.

  28. #28
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by dreammanor View Post
    ...saw that your VirtualCombo uses wqweto's modern subclassing
    (the last time you used The trick's subclassing)...
    I'm not a fan of any thunking, because it's not easy to maintain (or "to get right", mistakes are easy to make even for experienced devs) -
    furthermore this ASM-stuff will work only on x86-CPUs (so the code is not really portable - e.g. to Win10-On-ARM).
    The RC5-lib for example does not contain any thunks or assembly-stuff.

    So I'd have preferred to use the RC5-SubClasser - though for these smaller Demos,
    (to make it RC5-independent), a thunked SubClasser was used to keep the CodeBase relatively clean...

    I started with "tricks", because it used quite the same concept as the one from RC5 (raising Events for the WinProc).
    It worked flawlessly, until I've introduced and loaded multiple Forms (each showing a different usage of the VirtualCombo).
    And that (multiple Forms loading/unloading) caused "occasional crashes" in the IDE (not directly whilst running,
    but later on - e.g. at Project-saving-time).

    @the trick
    I've not had the time to research what may be the cause for this - perhaps that "multiple forms scenario" gives you a hint already
    (all Forms using a VirtualCombo, which in turn is using two SubClassing-instances per Combo-Control-instance).
    I've uploaded a Demo with those Multiple-Forms here in the CodeBank:
    http://www.vbforums.com/showthread.p...=1#post5408731

    So I've switched to wqwetos recent attempt at the task - and I had only one crash with it so far...
    (and that was shortly after I've pasted extra-code into the cSubClass.cls, to add the Hooking,
    as well as the OneShotTimer-thunks - the crash came also a bit later in the same IDE-session).
    But that was the only one - and it behaved otherwise stable in all follow-up IDE-sessions, also
    with the "multiple-forms-loaded/unloaded" scenario ...
    (so I guess, it was my "editing-around" within the cSubClass-CodeModule itself, which may have caused the crash).

    I've updated the Combo-Source in the above linked CodeBank-Demo slightly,
    and would suggest to use that latest version from the CodeBank-thread (instead of the one posted here in this thread).

    HTH

    Olaf

  29. #29

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Olaf, I'm taking a look at your RC5 subclasser and I have two questions.

    1) Is it IDE safe?
    2) Your WindowProc parameters are different than "the tricks" and the previous one I worked with. In those when I wanted to override the default message handling with my own code, I would set a return value = 0 and set a DefCall/Default to False. When I wanted the default message handling, I would set DefCall/Default to True. Your class does have a Result param but does not have a DefCall/Default parameter. Please advise how I allow the default message handling and how I override it with my own.

    Thanks

  30. #30

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by AAraya View Post
    Olaf, I'm taking a look at your RC5 subclasser and I have two questions.

    1) Is it IDE safe?
    2) Your WindowProc parameters are different than "the tricks" and the previous one I worked with. In those when I wanted to override the default message handling with my own code, I would set a return value = 0 and set a DefCall/Default to False. When I wanted the default message handling, I would set DefCall/Default to True. Your class does have a Result param but does not have a DefCall/Default parameter. Please advise how I allow the default message handling and how I override it with my own.

    Thanks
    After playing with the RC5 subclasser I figured out how to use it so I have the answers to my two questions.
    1) NO
    2) To bypass normal message handling set Result = 0. To allow normal message handling use the CallWindowProc method of your subclasser.

    I had no success using your subclasser with a VBCCR ComboBox. Using "the Tricks" subclasser I am able to hook the combobox and receive all WM_COMMAND messages and CBN_SELCHANGED notifications. Using your subclasser to hook the combobox I received no WM_COMMAND messages. Hmmm. Nonetheless, since it's not IDE Safe I'll not likely use it. It's very inconvenient to not be able to stop my app from executing without getting a crash.

  31. #31
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by AAraya View Post
    Olaf, I'm taking a look at your RC5 subclasser and I have two questions.

    1) Is it IDE safe?
    It should be (to a certain degree - perhaps not as good as the thunking ones, but I consider it sufficient).
    Half a year ago or so, I've hardened it a bit more again, after DexWerx brought up the topic of IDE-safety in a comparison...
    (not sure what it was I was changing back then, I think it was "enforced entering of break-mode when caused by an error").

    Just play around with it - StopButton-safety should be there at least - break-point-handling should work too.

    Quote Originally Posted by AAraya View Post
    2) Your WindowProc parameters are different than "the tricks" and the previous one I worked with. In those when I wanted to override the default message handling with my own code, I would set a return value = 0 and set a DefCall/Default to False. When I wanted the default message handling, I would set DefCall/Default to True. Your class does have a Result param but does not have a DefCall/Default parameter. Please advise how I allow the default message handling and how I override it with my own.
    The following simple example (MouseEnter/MouseLeave) shows its usage ...
    In short, you need to put a line at the end of the Event-handler (as shown below in magenta).
    If you want to provide your own (non-default-handled) Results, you just set them and do an Exit Sub.

    Code:
    Option Explicit
    
    Private Declare Function TrackMouseEvent& Lib "user32" (lpTrack As Any)
    Private WithEvents SC As cSubClass, PB As VB.PictureBox
    
    Private Sub Form_Load()
      Set PB = Controls.Add("VB.PictureBox", "PB"): PB.Visible = True
      Set SC = New_c.SubClass: SC.Hook PB.hWnd
    End Sub
    
    Private Sub SC_WindowProc(Result As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long)
      Const WM_MOUSEMOVE = &H200, WM_MOUSELEAVE = &H2A3
     
      Select Case Msg
        Case WM_MOUSEMOVE:  HandleMouseEnterOn PB
        Case WM_MOUSELEAVE: HandleMouseLeaveOn PB
      End Select
      
      Result = SC.CallWindowProc(Msg, wParam, lParam)
    End Sub
    
    Private Sub HandleMouseEnterOn(Ctl As Object)
      Dim T&(0 To 3): T(0) = 16: T(1) = 2: T(2) = Ctl.hWnd
      TrackMouseEvent T(0)
      Ctl.BackColor = vbGreen
    End Sub
    Private Sub HandleMouseLeaveOn(Ctl As Object)
      Ctl.BackColor = vbRed
    End Sub
    HTH

    Olaf

  32. #32
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by AAraya View Post
    1) NO
    Nah - it can't be *that* bad...
    What's your RC5-version? (as said, half a year ago I've hardened the SubClasser a bit)...

    I'm using VB6-SP6 on an up-to-date Win10 - and within the SubClass-EventHandler:
    - can set my own breakpoints (and can also end the IDE from such a break-point via Stop-Button)
    - can put e.g. Dim a: a = 1 / 0 into the EventHandler (forcing an "error-break") and also call an IDE-Stop from there

    I have absolutely no AddIns running in my IDE though...


    Quote Originally Posted by AAraya View Post
    I had no success using your subclasser with a VBCCR ComboBox.
    Using "the Tricks" subclasser I am able to hook the combobox and receive all WM_COMMAND messages and CBN_SELCHANGED notifications.
    Just played that through with the newest "CCRP 1.6 OCX-download" - and it works without any problems:
    (the example prevents any change in the drop-down-selection of a ComboBoxW1-Control)
    Code:
    Option Explicit
    
    Private WithEvents SC As cSubClass
    
    Private Sub Form_Load()
      ComboBoxW1.AddItem "Item 1"
      ComboBoxW1.AddItem "Item 2"
      ComboBoxW1.AddItem "Item 3"
      
      Set SC = New_c.SubClass: SC.Hook ComboBoxW1.hWnd
    End Sub
     
    Private Sub SC_WindowProc(Result As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long)
      Const WM_COMMAND = &H111&, CBN_SELCHANGE = 1
      
      Select Case Msg
        Case WM_COMMAND: If wParam \ 65536 = CBN_SELCHANGE Then Exit Sub
      End Select
      
      Result = SC.CallWindowProc(Msg, wParam, lParam)
    End Sub
    HTH

    Olaf
    Last edited by Schmidt; Aug 8th, 2019 at 06:34 PM.

  33. #33

  34. #34
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by The trick View Post
    Thank you for the report. Can you provide an example that causes the error?
    As said, the error was not really caused by a concrete action (a click or something) -
    it happened "after some time working in the IDE" (IIRC when saving the project, which causes new Control-instancing) -
    but only after I worked with more than a single Form in the IDE - loading/closing those Extra-forms ...code-typing... and repeating that cycle
    (the secondary Forms shown as non-modal Windows atop a "leading form").

    I've uploaded such a multi-form-example a few hours ago into the Codebank-thread
    (although with cSubClass.cls now containing wqwetos code, only adapted to your Event-throwing mechanism).

    You should be able though, to switch to the original SubClassing which used your SubClasser by:
    - overwriting cSubClass.cls with the similarly named File from the original Zip in the Opener-Post of the Codebank-thread (containing your code)
    - overwriting the ucVirtualCombo.ctl in the same way (with the older version)
    - then adding the modCreateHook.bas from the old project into the newer project (which is now needed again)
    - and finally commenting out all the Combo-related Code in fTest.frm (which is the starting-form - only that forms Combo made use of some enhancements in the newer ucVirtualCombo.ctl)

    The last point above meaning, that in the new uploaded Projects fTest.frm,
    only the CommandButton-array should remain active, whit this EventHandler:
    Code:
    Private Sub cmdShowForms_Click(Index As Integer)
      With Forms.Add("fTest" & Index)
        .Show , Me
      End With
    End Sub
    The routine above is then able to start the 3 "older Forms" (which should work with the older ucVirtualCombo.ctl in conjunction with your cSubClass.cls).

    I hope the outlined steps above will give you a working project... the "additional Form-loading" is
    the very same thing I've done a few months ago, whilst still working with your SubClasser in the older Project
    (which I've overwritten with the new stuff, hence only the original Zip in the Codebank remains, to "restore things" in a roughly similar way).

    HTH

    Olaf

  35. #35

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by Schmidt View Post
    Nah - it can't be *that* bad...
    What's your RC5-version? (as said, half a year ago I've hardened the SubClasser a bit)...
    Olaf
    Hi Olaf,

    It didn't work for me at all. I used the same code as you did and as I used in both wqweto and trick's subclassers. Their subclassers caught the messages/notifications I wanted while yours didn't. I also crashed every time I used yours.

    I am using an older version of the vbRichClient5.dll however - I'm on version 5.0.0.67 dated 11/7/2018. I'll update my RC5 dlls. Thanks for your time and input.

  36. #36

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    293

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    My apologies Olaf. As I look more closely at your example I see that I wasn't coding this properly. This seems to be an operator error.

  37. #37
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: [RESOLVED] Is it possible to make a ComboBox item non-selectable?

    Quote Originally Posted by AAraya View Post
    My apologies Olaf. As I look more closely at your example I see that I wasn't coding this properly. This seems to be an operator error.
    Ah, Ok... well - despite that, I'd still recommend updating your current RC5-version
    (which - as said - should show more tolerant behaviour, when you run into unhandled VB6-errors,
    caused by UserCode within the SubClassing-EventHandler).

    Olaf

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width