Is a COMBO List Dropped?

I am aware of EVENT:DroppedDown but can’t find or remember how one can tell if a COMBO control was dropped when a selection is made or whether is was done with entry completion. Any ideas?

1 Like

Event: NewSelection is fired as they select items with the mouse…but the control still has focus to type over the picked value, also… they can use arrows to move down the list firing new selection events for each one then still type into the combo.

I would simply check in event accepted if the value is in the list and assume they picked it. To be more accurate maybe track you got event dropping down and new selection.

In my WndPreview class on Git I added an event logger to the Tricks menu. I’m on my phone. I’ll post log when Comcast fixes my Internet … they broke have to wait 2 days

Appreciate the thoughts and know all too well the never to be sufficiently cursed service of Comcast.

This would be for an extension to the FileDropComboClass that will handle a LIKE/CONTAINS Sql search. The basics are in place but I’m seeing a few situations that might require knowing if Accepted occurred when the combo was dropped or not.

I haven’t tried this… But you might check

IF (?MyCombo{PROP:ListFEQ}) {PROP:Visible}

Thought for sure this was to be the answer, but no such luck.
Visible always returned as true, even when the combo list is not dropped.
(I did also verify that ?MyCombo{PROP:ListFEQ} is returning a proper value.)

Keep wondering if there should be a counterpart to EVENT:DroppingDown - ie something like EVENT:PullingUp.

How about checking ?MyCombo{PROP:ListFEQ}{PROP:Height}
or PROP:Skip
or PROP:Disable

Will definitely do so. Perhaps most logical - PROP:Hide.

In the docs on EVENT:DroppedDown, this caught my attention:

“This is the event on which you can hide other controls that the droplist covers to prevent “screen clutter” from distracting the user.”

The natural question of course, what is the event on which to unhide the other controls? I suspect EVENT:Accepted could be a bad assumption.

I think in my testing I had arrowed down to a selection so it showed in the Entry, then I typed another value and the list remained dropped, then I tabbed out with the non-list value.

For me I know this Win32 message will Drop the Combo or roll it up.

ListDrop PROCEDURE(LONG F, BYTE U=0)  !0=Dn 1=Up
  CODE  !CB_SHOWDROPDOWN = &H14F
  PostMessage(PWnd$F{PROP:Handle},14Fh,U-1,0)

You may want to try State=SendMessage(Handle,CB_GETDROPPEDSTATE,0,0). It returns True if dropped

There probably are API messages for Dropping and UnDrop if you subclass.

Looks like PROP:Height might be useful.
When NOT dropped it returns 1 and an appropriately larger value when dropped.
Will give SendMessage a try too.

As always, your help is much appreciated.

Carl, you can use longer parameter names
What does F mean (guessing FEQ)
What does U mean (guessing Up or Down)
what happens if you don’t pass a 0 or a 1 ?
Looks like PWnd is side-effecting through …

and that’s not supposed to be an FU to you :wink:

I always make the MAP parameters very descriptive because that shows up in Intellisense

  MAP
ListDrop   PROCEDURE(LONG ListFEQ, BYTE Down0_Up1=0),PRIVATE`

For the actual code I tend to be terse but that one was too terse. (FEQ, UpDn) would be better.

I did get a fantastic Comcast tech that really new what he was doing and explained a lot. Everything was done outside and now Web and TV are working the best ever. He admitted the other guy left it hooked up wrong and should have removed a splitter + other stuff. I stayed on the phone for 2 hours and kept asking for the next person up the chain, which did nothing because they made me wait 2 days. Maybe it got me a senior tech.

If you use lowercase f and u, you can make it a lot smaller.

Send me email [email protected]
Will send you a class with demo app to test and implement.

after a lot of hunting around
I have found a way to track if the list of a DropCombo is showing

(?MyCombo{PROP:ListFEQ}){PROP:WndProc} = ADDRESS( MyWndProc)

In MyWndProc, watch for WM_PosChanging
you’d think WM_PosChanged too, tests show that doesn’t fire when I press ESC to close listbox

When the xMsg = WM_PosChanging
Then the LParam is a pointer to a WindowPos structure

Then look at WindowPos.Flag
BAND(WindowPos.Flag, SWP_ShowWindow)
BAND(WindowPos.Flag, SWP_HideWindow)

The following code just sends info to OutputDebugString (ODS)
But it’s enough to show that you get the necessary info

IntWin32     EQUATE(SIGNED)

gtWindowPos  GROUP,TYPE ! https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-windowpos 
HWND             HWND 
HWNDInsertAfter  HWND 
X                IntWin32 ! Left
Y                IntWin32 ! Top  
CX               IntWin32 ! Width in pixels
Cy               IntWin32 ! height in pixels
FLAGS            UINT     ! SWP_* values 
             END 

!SetWindowPos Flags
SWP_NOSIZE          EQUATE(00001h) !
SWP_NOMOVE          EQUATE(00002h) !
SWP_NOZORDER        EQUATE(00004h) !
SWP_NOREDRAW        EQUATE(00008h) !
SWP_NOACTIVATE      EQUATE(00010h) !
SWP_FRAMECHANGED    EQUATE(00020h) !  /* The frame changed: send WM_NCCALCSIZE */
SWP_SHOWWINDOW      EQUATE(00040h) !
SWP_HIDEWINDOW      EQUATE(00080h) !
SWP_NOCOPYBITS      EQUATE(00100h) !
SWP_NOOWNERZORDER   EQUATE(00200h) !  /* Don't do owner Z ordering */
SWP_NOSENDCHANGING  EQUATE(00400h) !  /* Don't send WM_WINDOWPOSCHANGING */

SWP_DRAWFRAME       EQUATE(SWP_FRAMECHANGED )
SWP_NOREPOSITION    EQUATE(SWP_NOOWNERZORDER)

!#if(WINVER >= 0x0400)
SWP_DEFERERASE      EQUATE(02000h)
SWP_ASYNCWINDOWPOS  EQUATE(04000h)
!#endif /* WINVER >= 0x0400 */


WindowPos:ToString PROCEDURE(LONG xlpWindowPos)!,STRING 
WindowPosStructure &gtWindowPos
 CODE 
    WindowPosStructure &= ( xlpWindowPos ) 
    RETURN WindowPos:ToString( WindowPosStructure)

WindowPos:ToString PROCEDURE(*gtWindowPos xWindowPos)!,STRING 
 CODE 
    RETURN            ' HWND[' & xWindowPos.HWND            &']' |
          &' HWNDInsertAfter[' & xWindowPos.HWNDInsertAfter &']' |
          &              ' X[' & xWindowPos.X               &']' |
          &              ' Y[' & xWindowPos.Y               &']' |
          &              ' W[' & xWindowPos.CX              &']' |
          &              ' H[' & xWindowPos.Cy              &']' |
          &          ' FLAGS[' & xWindowPos.FLAGS           &']=' & WindowPosFlags:ToString( xWindowPos.Flags )


WindowPosFlags:ToString PROCEDURE(UINT xFlag)
Answer    ANY ! string of uknown length 
Remaining UINT
   CODE 
   Remaining = xFlag
                                              Answer = ''
   IF BAND( xFlag, SWP_NOSIZE         ) THEN  Answer = Answer & 'NoSize '         ; Remaining -= SWP_NOSIZE         END 
   IF BAND( xFlag, SWP_NOMOVE         ) THEN  Answer = Answer & 'NoMove '         ; Remaining -= SWP_NOMOVE         END 
   IF BAND( xFlag, SWP_NOZORDER       ) THEN  Answer = Answer & 'NoZOrder '       ; Remaining -= SWP_NOZORDER       END 
   IF BAND( xFlag, SWP_NOREDRAW       ) THEN  Answer = Answer & 'NoRedraw '       ; Remaining -= SWP_NOREDRAW       END 
   IF BAND( xFlag, SWP_NOACTIVATE     ) THEN  Answer = Answer & 'NoActivate '     ; Remaining -= SWP_NOACTIVATE     END 
   IF BAND( xFlag, SWP_FRAMECHANGED   ) THEN  Answer = Answer & 'FrameChanged '   ; Remaining -= SWP_FRAMECHANGED   END 
   IF BAND( xFlag, SWP_SHOWWINDOW     ) THEN  Answer = Answer & 'ShowWindow '     ; Remaining -= SWP_SHOWWINDOW     END 
   IF BAND( xFlag, SWP_HIDEWINDOW     ) THEN  Answer = Answer & 'HideWindow '     ; Remaining -= SWP_HIDEWINDOW     END 
   IF BAND( xFlag, SWP_NOCOPYBITS     ) THEN  Answer = Answer & 'NoCopybits '     ; Remaining -= SWP_NOCOPYBITS     END 
   IF BAND( xFlag, SWP_NOOWNERZORDER  ) THEN  Answer = Answer & 'NoOwnerZOrder '  ; Remaining -= SWP_NOOWNERZORDER  END 
   IF BAND( xFlag, SWP_NOSENDCHANGING ) THEN  Answer = Answer & 'NoSendChanging ' ; Remaining -= SWP_NOSENDCHANGING END 
  !IF BAND( xFlag, SWP_DRAWFRAME      ) THEN  Answer = Answer & 'DrawFrame '      ; Remaining -= SWP_DRAWFRAME      END  ! same as SWP_FrameChanged 
  !IF BAND( xFlag, SWP_NOREPOSITION   ) THEN  Answer = Answer & 'NoReposition '   ; Remaining -= SWP_NOREPOSITION   END  ! same as SWP_NoOwnerZOrder
   IF BAND( xFlag, SWP_DEFERERASE     ) THEN  Answer = Answer & 'DeferErase'      ; Remaining -= SWP_DEFERERASE     END 
   IF BAND( xFlag, SWP_ASYNCWINDOWPOS ) THEN  Answer = Answer & 'AsyncWindowpos ' ; Remaining -= SWP_ASYNCWINDOWPOS END 

   IF Answer = ''                       THEN Answer = 'Unknown['& xFlag &']'                END 
   IF Remaining                         THEN Answer = Answer & 'Remaining['& Remaining &']' END 

   RETURN Answer 

SharedWndProc   PROCEDURE(STRING xDescr, LONG xOrigWndProc, HWND xhwnd, UINT xMsg, WPARAM xW, LPARAM xL)!,LRESULT,PASCAL
Answer LRESULT,AUTO
W      GROUP,OVER(xW)
LoWord   SHORT 
HiWord   SHORT 
        END 
L      GROUP,OVER(xL)
LoWord   SHORT 
HiWord   SHORT 
        END 

WindowPosStructure &gtWindowPos
InterpretMsg       ANY
   CODE    

   CASE xMsg 
     OF WM_WindowPosChanging 
   OROF WM_WindowPosChanged  ; InterpretMsg = WindowPos:ToString( xL )
   ELSE InterpretMsg = ''
   END                                
                               
   Answer  = CallWindowProc( xOrigWndProc, xHWND, xMsg, xW, xL )

   DBG.ODS( xDescr & '_WndProc  Message['& dbg.GetEventDescr_WM(xMsg) &'] HWND['& xHWND &'] W.Hi['& W.HiWord &'] W.Lo['& W.LoWord &']   L.Hi['& L.HiWord &'] L.Lo['& L.LoWord &']   Answer['& Answer &'] ' & InterpretMsg )

   RETURN Answer
2 Likes

Does it really work? My respect. One question: why are you doing it in such strange way (WM_WindowPosChanging)? There is special message CB_SHOWDROPDOWN.

Yes, the WM_WindowPosChanging approach has worked in all my tests.

I’ve now written a ctQ_ComboTracker singleton with a syncobject around a queue. The class takes care of the hooking in a WndProc, and can send notification messages for show & hide, as well as tracking .IsShowing

I have read about CB_ShowDropDown, but it sounds like that used to ASK the combo to drop down. That said, I just wrote a quick testbed, and I did NOT get it to show the combo

The following works to show a combo,drop(n)

SETKEYCODE(DownKey)
FORWARDKEY(?UI:Combo) 

There is also doc on CBN_DropDown as part of a WM_COMMAND message
But I haven’t seen WM_COMMAND appear.

You recently showed a demo which shows when the drop down is hidden or visible
ANN: Combo drop-down state - marketplace / Templates - ClarionHub
May I ask what approach you took ?

In subclass procedure I receive CB_SHOWDROPDOWN message, wParam value indicates drop-down state (visible/hidden).

That’s odd, first the documentation seems to indicate that’s a message the application sends. What’s more is I only see the message, when I’ve sent it. The WndProc shows WParam is always 1, because that’s what I’m sending :slight_smile:

CB_SHOWDROPDOWN message (Winuser.h) - Win32 apps | Microsoft Docs

Clearly I must be subclassing the wrong control
I’ve tried subclassing

 ?Combo               {PROP:Handle} 
(?Combo{PROP:ListFEQ}){PROP:Handle}
(?Combo{PROP:Parent)  {PROP:Handle}
 0                    {PROP:Handle}

I just realized I never tested PROP:ButtonFEQ
adding that, I see CB_SHOWDROPDOWN come through, but only when I click on the button (vs. using a down arrow) and what’s more is the identical message and answer come through when I click on the button again to ‘hide’ the droplist. And no message at all when I hide the droplist in other ways.

Did you try working with CB_GetDroppedState ?
CB_GETDROPPEDSTATE message (Winuser.h) - Win32 apps | Microsoft Docs

1 Like

No I didn’t, CB_SHOWDROPDOWN is enough for me to detect state change.