A window can be opened unlimited times by hotkeys
A window can be opened unlimited times by hotkeys
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
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
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.
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.
Re: A window can be opened unlimited times by hotkeys
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.
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.
Re: A window can be opened unlimited times by hotkeys
One little change needed.
I use 2 hotkeys with buttons many times like this:
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:
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()}
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
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.
Re: A window can be opened unlimited times by hotkeys
Thanks Roger, it is perfect!
Re: A window can be opened unlimited times by hotkeys
is this the same code for "METHOD DC_XbpPushButton" ?
best regards
Hans
Hans
Re: A window can be opened unlimited times by hotkeys
YES !!!!is this the same code for "METHOD DC_XbpPushButton" ?
The eXpress train is coming - and it has more cars.
Re: A window can be opened unlimited times by hotkeys
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.
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
Roger,
this works well:Please put it in _dcxbutt.prg
METHOD DC_XbpPushButton:SetShortCut() is the same.
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
METHOD DC_XbpPushButton:SetShortCut() is the same.