Proposed Better Solution to Itembox Selection AND Double Click Processing

Started by galaara98, February 10, 2014, 02:48:03 PM

Previous topic - Next topic

galaara98

recently I began having problems with Dialogs that Process Both Itembox Selection and ItemBox Dbl-Click loosing my Dbl-Click unless the item was already selected.  I searched the Winbatch Support and found an article at http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/Dialog~Editor/Dialog~Editor~version~6.2+Handle~Both~Itembox~Select~and~Itembox~Double-Click.txt but this article helps the Double Clicks for sure work when the item is already selected (honestly not useful to me)

so I did figure out how to accomplish this (very consistently, at least in my environment)

Basically, "the" issue is that when you dbl-click, the dialog first handles the "first click", or the selection event, and then if Windows still thinks there is a Double-Click in the queue, your dialog will have an opportunity to process that.  Windows can loose the "Double-Click" event if the Itembox Selection routine does certain behaviors (I am not sure i could precisely list all the reasons Windows discards the queued event, however for simplicity of the explanation, lets just say the more complex the selection routine is, and the longer it takes to return control to the dialog, the more likely you are going to loose the dbl-click)

So here is a way to never loose either events. 
NOTE: It relies on a timer event to "cleanup", and your code may already have a timer event and you may not want to mess with the timing...

Code (winbatch) Select

; Force Single Selection Only
IntControl(33,0,0,0,0)

;Create a list of "Fake" stuff to List
items = ''
For i = 10 To 50
   items = ItemInsert(i, -1, items, @TAB)
Next

MSG_INIT              =0    ; The one-time initialization
MSG_TIMER             =1    ; Call DialogCallback on "heartbeat" timer
MSG_BUTTONPUSHED      =2    ; Pushbutton or Picturebutton
MSG_ITEMSELECT        =7    ; Itembox
MSG_ITEMBOXDOUBLECLICK=13   ; Get double-click message on an ItemBox
RET_DO_DEFAULT        =-1   ; Continue with default processing for control
DCSTATE_SETFOCUS      =1
DPO_DISABLESTATE      =1000 ; codes -1=GetSetting 0=EnableDialog 1=DisableDialog


;**************************************************************************************************
; CHANGE ME to TRUE if a DBL-CLICK in Itembox should FIRST Execute the SELECTION in ItemBox Routine
DO_ITEMBOX_SELECTION_AND_DBL  = @FALSE
;**************************************************************************************************

#DefineSubRoutine MyDialogCallbackProc(MyDialog_Handle,MyDialog_Message,MyDialog_Name,MyDialog_EventInfo,MyDialog_ChangeInfo)
   Switch MyDialog_Message
      Case MSG_INIT
            DialogProcOptions(MyDialog_Handle,MSG_TIMER,250) ;max # of ms your dialog can appropriately wait to show the results of the Item Selection 
            DialogProcOptions(MyDialog_Handle,MSG_ITEMSELECT,@TRUE)
            DialogProcOptions(MyDialog_Handle,MSG_ITEMBOXDOUBLECLICK,@TRUE)
            ItemBoxSelectionNeedsHelp=@FALSE          ; <--- A FLAG TO KNOW WHEN AN UNPROCESSED SINGLE CLICK HAS HAPPENED
            WhichItemBoxNeedsHelp = ""                      ; In-case we have More than one Item Box
         Return(RET_DO_DEFAULT)

        Case MSG_TIMER
            if ItemBoxSelectionNeedsHelp then
                ItemBoxSelectionNeedsHelp = @FALSE ; I, as the Timer, will be handling the ItemBox Selection Needs
                ;Do whatever needs to be done when we select an item
                Selection = DialogControlGet(MyDialog_Handle, WhichItemBoxNeedsHelp, 6)
                pause('Item Selected' , selection)
            end if
            ; Do other Timer Tasks you were already doing
            Return(RET_DO_DEFAULT)

      Case MSG_ITEMSELECT
            ;Get in, get Out... We will deal with the Procedure to process this soon
            ItemBoxSelectionNeedsHelp=@TRUE
            WhichItemBoxNeedsHelp = MyDialog_Name
            Return(RET_DO_DEFAULT)

      Case MSG_ITEMBOXDOUBLECLICK
            if ItemBoxSelectionNeedsHelp then
                ItemBoxSelectionNeedsHelp = @FALSE ; I, as the ItemBox_DblClick routine, will be handling the ItemBox Selection Needs
                if DO_ITEMBOX_SELECTION_AND_DBL then
                    ;Do whatever needs to be done when we select an item
                    Selection = DialogControlGet(MyDialog_Handle, WhichItemBoxNeedsHelp, 6)
                    pause('Item Selected' , selection); and YES you dbl-clicked, and we will get to that in a moment
                end if
            end if
            selection = DialogControlGet(MyDialog_Handle, MyDialog_Name, 6)
            Pause('Item Double Clicked', selection)
            Return(RET_DO_DEFAULT)

   EndSwitch
   Return(RET_DO_DEFAULT)
#EndSubRoutine


MyDialogFormat=`WWWDLGED,6.2`

MyDialogCaption=`WIL Dialog 1`
MyDialogX=120
MyDialogY=241
MyDialogWidth=164
MyDialogHeight=176
MyDialogNumControls=003
MyDialogProcedure=`MyDialogCallbackProc`


MyDialogFont=`DEFAULT`
MyDialogTextColor=`DEFAULT`
MyDialogBackground=`DEFAULT,DEFAULT`
MyDialogConfig=0

MyDialog001=`057,149,036,012,PUSHBUTTON,"PushButton_OK",DEFAULT,"OK",1,10,0,DEFAULT,DEFAULT,DEFAULT`
MyDialog002=`105,149,036,012,PUSHBUTTON,"PushButton_Cancel",DEFAULT,"Cancel",0,20,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog003=`051,019,062,110,ITEMBOX,"ItemBox_1",Items,DEFAULT,DEFAULT,30,DEFAULT,DEFAULT,DEFAULT,DEFAULT`

ButtonPushed=Dialog("MyDialog", 1)

Exit


To be absolutely fair, it is possible to get the ItemBox Selection event out of order if you select an item and quickly interact with another control
If you want robust ItemBox Selection detection and your dialog is handling many types of events I would propose:

You create a User Subroutine for the procedure you normally would run in the ItemBox event (Dialog Message MSG_ITEMSELECT or 7)
For each Message Case, that is not the Init, or the ItemSelect event itself, check for the presence of the ItemBoxSelectionNeedsHelp flag, and run your User Sub.
(ItemBox Double Click may have special logic, while all others would just "Do It")

If it is very important that you process each and every selection event but you find your users are rapidly selecting items in your itembox before the timer event can handle them
you will need to develop a queue [FIFO].  ItemBoxSelectionNeedsHelp becomes a list (storing the actual content of the selections), and MSG_ITEMSELECT (7) adds to the list while all other message handlers drain the list.

Deana

Excellent. Thank you for sharing your solution. I will add this code to the above mentioned article, for the next user.
Deana F.
Technical Support
Wilson WindowWare Inc.

kdmoyers

The mind is everything; What you think, you become.