A window can be opened unlimited times by hotkeys

This forum is for eXpress++ general support.
Post Reply
Message
Author
zolifree
Posts: 35
Joined: Sun Sep 19, 2010 6:55 am

A window can be opened unlimited times by hotkeys

#1 Post 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

User avatar
rdonnay
Site Admin
Posts: 4733
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

Re: A window can be opened unlimited times by hotkeys

#2 Post 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
The eXpress train is coming - and it has more cars.

User avatar
rdonnay
Site Admin
Posts: 4733
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

Re: A window can be opened unlimited times by hotkeys

#3 Post 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
The eXpress train is coming - and it has more cars.

zolifree
Posts: 35
Joined: Sun Sep 19, 2010 6:55 am

Re: A window can be opened unlimited times by hotkeys

#4 Post 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


User avatar
rdonnay
Site Admin
Posts: 4733
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

Re: A window can be opened unlimited times by hotkeys

#5 Post 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
The eXpress train is coming - and it has more cars.

zolifree
Posts: 35
Joined: Sun Sep 19, 2010 6:55 am

Re: A window can be opened unlimited times by hotkeys

#6 Post by zolifree »

Thanks Roger, it is perfect!

User avatar
hz_scotty
Posts: 107
Joined: Thu Jan 28, 2010 8:20 am
Location: Wr.Neustadt / Österreich

Re: A window can be opened unlimited times by hotkeys

#7 Post by hz_scotty »

is this the same code for "METHOD DC_XbpPushButton" ?
best regards
Hans

User avatar
rdonnay
Site Admin
Posts: 4733
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

Re: A window can be opened unlimited times by hotkeys

#8 Post by rdonnay »

is this the same code for "METHOD DC_XbpPushButton" ?
YES !!!!
The eXpress train is coming - and it has more cars.

zolifree
Posts: 35
Joined: Sun Sep 19, 2010 6:55 am

Re: A window can be opened unlimited times by hotkeys

#9 Post 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.

zolifree
Posts: 35
Joined: Sun Sep 19, 2010 6:55 am

Re: A window can be opened unlimited times by hotkeys

#10 Post 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.

Post Reply