Page 1 of 1

A window can be opened unlimited times by hotkeys

Posted: Wed Jun 29, 2016 2:31 pm
by zolifree
Hi Roger!

My program is used by many customers, and the program sends error log to me over interet.
I saw a lot of unexplainable error messages logged, that I was never able to reproduce until now.
The problem is that if I have a window which has hotkey like pusbuttons, and if I open a subwindow over this window I can use the hotkey of the window below the active window.
And I can use it unlimited times. It is possible to open a subwindows as many times as You want be pressing a hotkey opening that window.
In my programs there are hundreds of windows with more than 10 hotyes in each of them, and many opens a subwindow.
I never tried to use a hotkey twice, or use a hotkey which is on the window that is not active.
But it seems customers do this many times.
So it is a very serious problem for me, and I was not able to find a way to stop this.
I using the latest express++ and xbase++ but I tried with 1.9 alaska and older express, and each has this problem.

This is a test program:
FUNCTION Main()
LOCAL GetList[0], wget:=space(20),wget2:=space(20)
@0,0 DCPUSHBUTTON CAPTION "&Test" ;
SIZE 10,1 ;
ACTION {||test()}

@2,0 dcsay "Get1:" get wget
@3,0 dcsay "Get2:" get wget2

DCREAD GUI FIT ADDBUTTONS TITLE 'Main';
EVAL {|o|SetAppWindow(o)}

RETURN nil

function test()
LOCAL GetList[0], wg:=space(10)
@0,0 dcsay "Alt+T will open this windows again :" get wg saysize 0

DCREAD GUI FIT ADDBUTTONS TITLE 'Test';
EVAL {|o|dc_centerobject(o,SetAppWindow(o))} ;
MODAL to wlok addbuttons
RETURN nil

If you press Alt+T on the main window it opens a new over it, and in that subwindow you can press the Alt+T again in the get object, and it opens the window again and again.

Best regards,
Zoltan

Re: A window can be opened unlimited times by hotkeys

Posted: Wed Jun 29, 2016 3:42 pm
by rdonnay
I am surprised that nobody has reported this problem before now.

Many years ago, when I first started with Xbase++, Alaska Software recommended that hot-keys on pushbuttons should be marked with an ampersand & and that the function SetAppEvent() should be used to cause the action. eXpress++ uses SetAppEvent() whenever an ampersand is in the caption of a pushbutton.
Unfortunately, spawned windows in the same thread will respond to the same hot-key.

To suppress this behavior, I recommend using the tilde ~ to underline the character and the ACCELKEY clause of the DCPUSHBUTTON command to force the action. This will make the Alt-T action local only to the GUI window where it is declared.

Code: Select all

Change this:

@0,0 DCPUSHBUTTON CAPTION "&Test" ;
SIZE 10,1 ;
ACTION {||test()} 

to this:

#include "appevent.ch"
@0,0 DCPUSHBUTTON CAPTION "~Test" ;
SIZE 10,1 ;
ACTION {||test()} ;
ACCELKEY xbeK_ALT_T

Re: A window can be opened unlimited times by hotkeys

Posted: Thu Jun 30, 2016 7:32 am
by rdonnay
I have corrected this problem in eXpress++.

If you make the below code changes, you will not need to make any changes to your source code.
These changes are made in \exp20\source\dclipx\_DCXBUTT.PRG.

Replace the methods DC_XbpPushButton:SetShortCut() and DC_XbpPushButtonXP:SetShortCut()
with the below code:

Run BUILD20.BAT or BUILD19_SL1.BAT to rebuild DCLIPX.DLL.

This change will be in build 265.

Code: Select all

METHOD DC_XbpPushButton:SetShortCut()

IF ( ::nShortCut := ::GetShortCut()) != NIL
  ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] := ::nShortCut
ENDIF

METHOD DC_XbpPushButtonXP:SetShortCut()

IF ( ::nShortCut := ::GetShortCut()) != NIL
  ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] := ::nShortCut
ENDIF

Re: A window can be opened unlimited times by hotkeys

Posted: Thu Jun 30, 2016 4:24 pm
by zolifree
One little change needed.

I use 2 hotkeys with buttons many times like this:

Code: Select all

@0, 0 DCPUSHBUTTONXP CAPTION tny("&Bizonylat") ;
   SIZE 10,1 ;
   ACCELKEY xbeK_F2 ;
   ACTION {||f_tartalom()} 
Now the ACCELKEY hotkey is not working, only the Alt+& letter with the modification that You sent.
I know I can use an array with hotkeys at ACCELKEY, but if it is possible to solve it without code change, would be the perfect solution. I think I have more than 1000 buttons that has this problem, so it is a long time to manually correct each.

I tried this, but it is generating errors:

Code: Select all

IF ( ::nShortCut := ::GetShortCut()) != NIL
 if ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] = NIL
   ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] := ::nShortCut
 else
  private wuto:={}
  aadd(wuto,::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY])
  aadd(wuto,::nShortCut)
  ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] := wuto
 endif
ENDIF


Re: A window can be opened unlimited times by hotkeys

Posted: Thu Jun 30, 2016 6:04 pm
by rdonnay
This will work:

Code: Select all

METHOD DC_XbpPushButtonXP:SetShortCut()

LOCAL xAccelKey := ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY]

::nShortCut := ::GetShortCut()
IF Valtype(::nShortCut) == 'N'
  IF Valtype(xAccelKey) == 'N'
    ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] := { xAccelKey, ::nShortCut }
  ELSEIF Valtype(xAccelKey) == 'A'
    AAdd( xAccelKey, ::nShortCut )
  ELSEIF Valtype(xAccelKey) == 'U'
    ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] := ::nShortCut
  ENDIF
ENDIF

RETURN self

Re: A window can be opened unlimited times by hotkeys

Posted: Thu Jun 30, 2016 7:22 pm
by zolifree
Thanks Roger, it is perfect!

Re: A window can be opened unlimited times by hotkeys

Posted: Fri Jul 01, 2016 2:03 am
by hz_scotty
is this the same code for "METHOD DC_XbpPushButton" ?

Re: A window can be opened unlimited times by hotkeys

Posted: Fri Jul 01, 2016 7:08 am
by rdonnay
is this the same code for "METHOD DC_XbpPushButton" ?
YES !!!!

Re: A window can be opened unlimited times by hotkeys

Posted: Sat Jul 02, 2016 5:28 pm
by zolifree
Roger,

there is one more thing need to be fixed:
Now the Alt+O hotkey does not working for the Ok button, when I use the addbuttons.

The customers want this function back.
I had this problem before, and You solved that, but with this fix for the hotkeys bring this problem back.

Re: A window can be opened unlimited times by hotkeys

Posted: Thu Jul 07, 2016 1:34 pm
by zolifree
Roger,
this works well:

Code: Select all

METHOD DC_XbpPushButtonXP:SetShortCut()
LOCAL xAccelKey := ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY]
::nShortCut := ::GetShortCut()
if  Valtype(::caption) == 'C'.and. ::caption="&Ok".and.::nShortCut != NIL 
  ::oldShortCut := SetAppEvent( ::nShortCut, { | uNil1, uNil2, o| ;
               IIF(::isVisible(),(SetAppFocus(self), ;
                                  PostAppEvent( xbeP_Activate,,, self)),nil)})
 RETURN self
endif

IF Valtype(::nShortCut) == 'N'
  IF Valtype(xAccelKey) == 'N'
    ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] := { xAccelKey, ::nShortCut }
  ELSEIF Valtype(xAccelKey) == 'A'
    AAdd( xAccelKey, ::nShortCut )
  ELSEIF Valtype(xAccelKey) == 'U'
    ::getList:getListArray[::getListPointer,nGETLIST_ACCELKEY] := ::nShortCut
  ENDIF
ENDIF
RETURN self

Please put it in _dcxbutt.prg
METHOD DC_XbpPushButton:SetShortCut() is the same.