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?
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
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 >WindowPos
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 >WindowPos
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
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
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
No I didn’t, CB_SHOWDROPDOWN is enough for me to detect state change.