Subject Re: pushbutton
From Mervyn Bick <invalid@invalid.invalid>
Date Wed, 30 Nov 2022 10:15:30 +0200
Newsgroups dbase.getting-started
Attachment(s) ghor_mb.wfmpb_one_press.cc

On 2022/11/28 20:42, Mustansir Ghor wrote:
> Dear All
>
> When Pushputton gets focus in dbase 2019, I need to press Enter button twice to execute the push button whereas same form if I run in dbase 11 plus the pushbutton executes with focus on it by pressing it only once.
>
> If anybody has any clue where I need to correct pls advice me.

This is a bug that first appeared in dBASE 12 and has continued on into
dBASE 2019.

I have created a custom pushbutton (pb_one_press.cc) that uses the
CALLBACK command to trap when the user presses the Enter key while the
pushbutton has focus.  This immediately triggers the pushbutton's
onClick event.

Ken, you may want to consider this control for inclusion in the dUFLP.

An example form and the custom control are attached.

Mervyn.



clear
** END HEADER -- do not remove this line
//
// Generated on 2022-11-30
//
parameter bModal
local f
f = new ghor_mbForm()
if (bModal)
   f.mdi = false // ensure not MDI
   f.readModal()
else
   f.open()
endif

class ghor_mbForm of FORM
   set procedure to pb_one_press.cc additive
   with (this)
      onOpen = class::FORM_ONOPEN
      metric = 0        // Chars
      height = 8.5455
      left = -3.4286
      top = 1.3182
      width = 122.2857
      text = ""
   endwith

   this.CBCUSTOMER = new COMBOBOX(this)
   with (this.CBCUSTOMER)
      height = 1.5
      left = 6.0
      top = 3.5
      width = 39.0
      fontSize = 14.0
      dataSource = 'array {"MUSTANSIR","GHOR","DAR","TZ"}'
      style = 1        // DropDown
   endwith

   this.EAMOUNT = new ENTRYFIELD(this)
   with (this.EAMOUNT)
      height = 1.5
      left = 51.0
      top = 3.5
      width = 18.0
      fontSize = 14.0
      value = ""
      validRequired = true
   endwith

   this.PBSAVE = new PB_ONE_PRESS(this)
   with (this.PBSAVE)
      onClick = class::PBSAVE_ONCLICK
      height = 1.5
      left = 77.0
      top = 3.5
      width = 14.0
      text = "Display It"
   endwith

   this.TEXT1 = new TEXT(this)
   with (this.TEXT1)
      height = 1.0
      left = 7.0
      top = 6.0
      width = 54.0
      text = "Text1"
   endwith


   function PBSAVE_onClick()
         form.text1.text=""
         form.text1.text=form.cbcustomer.value+" has following balance "+form.eamount.value
      return

   function form_onOpen()
         with(this)
          height = 8.5
     left = 20.0
     top = 3.0
     width = 120.0
         endwith
     return


endclass



class pb_one_press(parentObj) of pushbutton(parentObj) custom

   /*

   Filename:   pb_one_press.cc

   Date:       2022-11-30

   Author:     Mervyn Bick

  

   Description:

      Starting with dBASE 12 and continuing in dBASE 2019, if a user Tabs
                to a pushbutton control it takes two presses of the Enter key to trigger
                the pushbutton's onClick event.   If the user uses the mouse to click on
                the pushbutton the onClick event fires immediately.
                
                This custom pushbutton triggers the object's onClick event immediately
                if the user tabs to the control and then preses the Enter key.  
                
                The custom control works without a problem in dBASE 11 so there should
                be no adverse effects if this bug is ever fixed for dBASE 2019.

      This custom control will only work with dBASE Plus 8 and later as the
      CALLBACK feature in not avaiable in earlier versions of dBASE.

   */
  
   with (this)
      onOpen = CLASS::onOpen
      onClose = CLASS::onClose
   endwith

   function onOpen()
      #include winuser.h
      if type("GetWindowLongA") # "FP"
         extern CLONG GetWindowLongA(CHANDLE, CINT) user32
      endif
      if type("SetWindowLongA") # "FP"
         extern CLONG SetWindowLongA(CHANDLE, CINT, CLONG) user32
      endif
      if type("CallWindowProcA") # "FP"
         extern CLONG CallWindowProcA(CPTR, CHANDLE, CUINT, CUINT, CUINT) user32
      endif
           if type("this.oldproc") = 'U'
                        this.oldproc = GetWindowLongA(this.hwnd, GWL_WNDPROC)
                        CALLBACK CLONG wndproc(CHANDLE, CUINT, CUINT, CUINT) OBJECT this
                        this.newproc = GetCallAddress(class::wndproc)
                        SetWindowLongA(this.hwnd, GWL_WNDPROC, this.newproc)
                endif                
      return

   function onClose
      if type("this.oldproc") = "FP"
         if this.oldproc <> null and not empty(this.oldproc)
         // must restore original window procedure for pushbutton
         SetWindowLongA(this.hwnd, GWL_WNDPROC, this.oldproc)      
         RELEASE CALLBACK wndproc OBJECT this
         endif            
      endif
      return

   function wndproc(hwnd,umsg,wparam,lparam)
                  if umsg = WM_CHAR  and wParam = VK_RETURN
                     //Enter key pressed while object has focus
                                this.onClick()                
            endif
       return CallWindowProcA(this.oldproc, hwnd, uMsg, wParam, lParam)

endclass