public Hotkeys in Visual foxpro
Inside Foxpro system can Assign easily Access Keys and Keyboard Shortcuts
As you create a menu system, you should consider ease of access to the system, and you
must assign tasks to the system.
You must give menus and menu items tasks to perform, such as displaying forms, toolbars, and other menu systems.
You should define access keys to permit entry to the menu system. You can also add
keyboard shortcuts and enable or disable menu items for more control.
To specify the access key for a menu or menu item
Type \< to the left of the letter you want as the access key.
For example, to set the access key to "u" in the Customer menu title, replace Customer
with C\<ustomer in the Prompt column.
Assigning Keybord shortcuts
In addition to assigning access keys, you can specify keyboard shortcuts for menus or
menu items. As with access keys, keyboard shortcuts let you choose a menu or menu item
by holding down one key while pressing another. The difference between access keys and
keyboard shortcuts is that you can use a keyboard shortcut to choose a menu item without
first displaying its menu.
Keyboard shortcuts for Visual FoxPro menu items are combinations of the CTRL or ALT key
and another key. For instance, you can create a new file in Visual FoxPro by pressing
CTRL+N
But outside of foxpro , there is no native method to build shortcuts or hotkeys to
access quickly to make actions in any application.
We present two methods to do this last job by:
1-shell environment (scripting shell) : can create shortcut and design a public hotkey
to access that app.
2-API registerHotkey: it registers into the windows environment hotkeys to access to
app....(and Unregister it).
Below 5 examples of hotkeys codes.
*Begin code
local oShell
oShell = CreateObject("Wscript.shell")
strDesktop = oShell.SpecialFolders("Desktop")
oShortcut = oShell.CreateShortcut(strDesktop + "\calc.lnk")
oShortcut.WindowStyle = 4 &&Maximized 7=Minimized 4=Normal
oShortcut.IconLocation = ADDBS(GETENV('windir'))+"system32\calc.exe" &&encapsuled in exe
OShortcut.TargetPath =ADDBS(GETENV('windir'))+"system32\calc.exe"
oShortCut.Hotkey = "ALT+CTRL+F"
oShortCut.Save
=null
oshell=null
retu
*End code
*Begin code
Publi yform
yform=Newobject("yhotkeys")
yform.Show
Read Events
Return
*
Define Class yhotkeys As Form
Top = 6
Left = 109
Height = 516
Width = 849
ShowWindow = 2
Caption = "WINCalc attached to a top level form"
KeyPreview = .T.
yhwnd = 0
Name = "Form1"
Add Object grid1 As Grid With ;
Anchor = 15, ;
Height = 295, ;
Left = 4, ;
Top = 29, ;
Width = 836, ;
Name = "Grid1"
Add Object edit1 As EditBox With ;
FontBold = .T., ;
FontSize = 11, ;
Anchor = 768, ;
Height = 111, ;
Left = 48, ;
ReadOnly = .T., ;
Top = 399, ;
Width = 529, ;
ForeColor = Rgb(255,0,0), ;
Name = "Edit1"
Add Object shape1 As Shape With ;
Top = 0, ;
Left = 398, ;
Height = 25, ;
Width = 36, ;
Curvature = 15, ;
BackColor = Rgb(0,255,0), ;
Name = "Shape1"
Add Object label1 As Label With ;
AutoSize = .T., ;
FontSize = 16, ;
Anchor = 768, ;
WordWrap = .T., ;
Alignment = 2, ;
BackStyle = 1, ;
Caption = "CTRl+F6 to fire calc- CTRL+F7 to hide it.", ;
Height = 98, ;
Left = 588, ;
Top = 408, ;
Width = 117, ;
ForeColor = Rgb(255,0,0), ;
BackColor = Rgb(255,255,0), ;
Name = "Label1"
Add Object label2 As Label With ;
FontBold = .T., ;
FontSize = 28, ;
Anchor = 768, ;
Alignment = 2, ;
BackStyle = 0, ;
Caption = "?", ;
Height = 37, ;
Left = 0, ;
MousePointer = 15, ;
Top = 432, ;
Width = 37, ;
ForeColor = Rgb(0,255,0), ;
Name = "Label2"
Procedure yprocess
Lparameters ytitle
#Define MOD_ALT 0x001 && Alt key
#Define MOD_CTRL 0x002 && Ctrl key
#Define MOD_SHIFT 0x004 && Shift key
#Define MOD_WIN 0x008 && Windows key
#Define vk_F6 0x75 &&Virtual key F6
#Define vk_F7 0x76 &&Virtual key F7
#Define WM_HOTKEY 0x312
#Define SW_hide 0
#Define SW_SHOW 5
#Define WM_CLOSE 0x0010
*Important: must be the EXACT Caption of the window depending on language used on system-place it in the form
Local i,fail
i=0
fail=.F.
Thisform.yhwnd=0
Do While Thisform.yhwnd=0
Thisform.yhwnd = FindWindow(Null, Allt(ytitle)) &&localized
sleep(300)
i=i+1
If i>5
m.fail=.T.
Exit
Endi
Enddo
If m.fail=.T.
Messagebox("Fail top find "+ytitle,16+4096,"error",1000)
Return .F.
Endi
If IsWindow(Thisform.yhwnd) <> 0
#Define GWL_STYLE -16
#Define WS_CAPTION 0x00C00000
#Define SW_SHOWNORMAL 1
#Define WS_SYSMENU 0x80000
= SetForegroundWindow(Thisform.yhwnd)
= SetParent(Thisform.yhwnd,Thisform.HWnd)
*Cut the titlebar
Local lnStyle, lnNewStyle
* Get the current style of the window
lnStyle = GetWindowLong(Thisform.yhwnd, GWL_STYLE)
* Remove the border of the window
lnNewStyle = Bitxor(lnStyle, WS_CAPTION)-0xCF0000-WS_SYSMENU
* Set the new style for the window
=SetWindowLong(Thisform.yhwnd, GWL_STYLE, lnNewStyle)
x=Thisform.shape1.Left+Thisform.shape1.Width/5
Y=Thisform.shape1.Top+Thisform.shape1.Height/2
#Define SWP_NOSIZE 0x0001
=SetWindowPos(Thisform.yhwnd,0,x,Y,0,0,SWP_NOSIZE)
Endif
=ShowWindow(Thisform.yhwnd,SW_hide)
TEXT to thisform.edit1.value noshow
This code tests sending registered system hotkeys to windows calculator
(HWND="+trans(thisform.yhwnd)+")
- Press CTRL+F6 or CTRL+F7 for this.
ENDTEXT
*RegisterHotKey;: If the function succeeds, the return value is nonzero...
*If the function fails, the return value is zero.
yresult1 = RegisterHotKey(Thisform.HWnd,1000,MOD_CTRL,vk_F6) && CTRL+F6
If yresult1=0
Messagebox("the hotkey CTRL+F6 is not registrered-Fail !"+Transform(yresult1))
SendMessage(Thisform.yhwnd,WM_CLOSE,0,0)
Return .F.
Endif
yresult2 = RegisterHotKey(Thisform.HWnd,1001,MOD_CTRL,vk_F7) && CTRL+F7
If yresult2=0
Messagebox("the hotkey CTRL+F7 is not registrered-Fail !"+Transform(yresult2))
SendMessage(Thisform.yhwnd,WM_CLOSE,0,0)
Return .F.
Endif
Bindevent(Thisform.HWnd,WM_HOTKEY,Thisform, "DispatchMessages")
Endproc
Procedure dispatchmessages
Lparameters HWnd As Integer,;
Msg As Integer, ;
wParam As Integer, ;
lParam As Integer
Do Case
Case wParam=1000
Set Bell To (Addbs(Getenv('windir')))+"MEDIA\DING.WAV"
?? Chr(7)
TEXT to thisform.edit1.value textmerge noshow
Hotkey CTRL+F6 is pressed -message received... !
At :<<Ttoc(Datetime())>>
-Message :<<Trans(Msg)>>
-Wparam :<<Trans(wParam)>> -lparam :<<Trans(Lparam)>>
ENDTEXT
#Define SW_SHOWNORMAL 1
ShowWindow(Thisform.yhwnd,SW_SHOWNORMAL)
#Define SWP_SHOWWINDOW 0x0040
x=Thisform.shape1.Left+Thisform.shape1.Width/5
Y=Thisform.shape1.Top+Thisform.shape1.Height/2
#Define SWP_NOSIZE 0x0001
=SetWindowPos(Thisform.yhwnd,0,x,Y,0,0,SWP_NOSIZE)
Case wParam=1001
Set Bell To (Addbs(Getenv('windir')))+"MEDIA\NOTIFY.WAV"
?? Chr(7)
TEXT to thisform.edit1.value textmerge noshow
Hotkey CTRL+F7 is pressed -message received... !
At :<<Ttoc(Datetime())>>
-Message :<<Trans(Msg)>>
-Wparam :<<Trans(wParam)>> -lparam :<<Trans(Lparam)>>
ENDTEXT
#Define SW_hide 0
ShowWindow(Thisform.yhwnd,SW_hide)
Endcase
If Isnull(Thisform.yhwnd)
Unbindevents(0)
Endi
Set Bell To
Endproc
Procedure Destroy
*this can be used to close the calculator if its not a form child window.
*LOCAL hWindow
*hWindow = FindWindow(Null, "Calculatrice")
* IF IsWindow(hWindow) <> 0
* #DEFINE WM_QUIT 18
* = PostMessage(hWindow, WM_QUIT, 0,0) &&release calculatore
* ENDIF
Clea Events
Endproc
Procedure QueryUnload
UnregisterHotKey(Thisform.yhwnd, 1000)
UnregisterHotKey(Thisform.yhwnd, 1001)
Endproc
Procedure Init
_Screen.WindowState=1
Thisform.WindowState=0
With Thisform.grid1
.RecordSource="ycurs"
.RecordSourceType=1
.GridLines=0
.DeleteMark=.F.
.SetAll("DynamicBackColor", "IIF(MOD(RECNO( ), 2)=0, RGB(255,255,255), RGB(220,200,180))", "Column")
Endwith
Local m.xtitle
m.xtitle="Calculatrice " &&warning ! localized (set the title depending on langage on use in system)
Thisform.yprocess (m.xtitle)
Endproc
Procedure Load
*APIS declarations
Declare Integer RegisterHotKey In user32;
integer HWnd,;
integer Id,;
integer fsModifiers,;
integer vk
Declare Integer UnregisterHotKey In user32;
INTEGER HWnd,;
INTEGER Id
Declare Integer Sleep In kernel32 Integer
Declare Integer ShellExecute In SHELL32.Dll Integer nWinHandle,;
STRING cOperation,;
STRING cFileName,;
STRING cParameters,;
STRING cDirectory,;
INTEGER nShowWindow
Declare Long FindWindow In "user32" String lpClassName, String lpWindowName
Declare Integer ShowWindow In user32;
INTEGER HWnd,;
INTEGER nCmdShow
Declare Integer SendMessage In Win32API;
INTEGER HWnd,;
INTEGER uMsg,;
INTEGER wParam,;
INTEGER Lparam
Declare Integer PostMessage In user32;
INTEGER hWindow, Integer Msg,;
STRING @wParam, Integer Lparam
Declare Integer IsWindow In user32 Integer hWindow
Declare Long SetWindowPos In "user32" Long HWnd, Long hWndInsertAfter, Long x, Long Y, Long cx, Long cy, Long wFlags
Declare Integer SetForegroundWindow In user32 Integer hWindow
Declare Integer GetWindowLong In User32 Integer HWnd, Integer nIndex
Declare Integer SetWindowLong In user32 Integer HWnd,;
INTEGER nIndex, Integer dwNewLong
Declare Integer SetParent In user32;
INTEGER hWndChild,;
INTEGER hWndNewParent
*cursor for grid as example only
Sele * From Home(1)+"samples\data\customer" Into Cursor ycurs
Sele ycurs
Locate
Run /n2 Calc.Exe &&lauch win calculator (dont minimize it !)
*shellexecute(0,"open","calc.exe","","",0) &&hidden( dont hide ??)
sleep(300)
Endproc
Procedure KeyPress
Lparameters nKeyCode, nShiftAltCtrl
If nKeyCode=27
Thisform.Release
Endi
Endproc
Procedure label2.Click
Local m.myvar
TEXT to m.myvar noshow
The sample makes the follow:
-Fire the windows calculator(title localized) ,cuts its titlebar,and position it on the form exactly
at the green shape.
-The calculator here is made as a child window of the form (as a form level 0,1)
-The calc menu stays accessible to chose the calc type (4 types: std,scientific,...)-The calculator memorize
automatically its last played window.
-Pressing the hotkey CTRL+F6 activates the calculator at the exact position wanted
-Pressing the hotkey CTRL+F7 hides the calculator.
-releasing the form, the calc autorelease as any child window
-The defined hotkeys are trapped as windows messages in form.dispatchemessages method.
ENDTEXT
Messagebox(m.myvar,0+32+4096,"Summary help")
Endproc
Enddefine
*
*Endcode
*3*-The hotkeys can be defined for any application with API RegisterHotKey to tell the system a public key can be applied from anywhere to launch this application.
In the example below the keys CTRL+ALT+C activate the visual foxpro calculator
the key CTRL+ALT+D desactivate it.
Must Unregister the keys set when exiting the application to tell the system that is no need to them.
Of course the hotkey must be registered to work.Otherwise the system registration fails (see the fail messagebox in code).
*begin code
&&some windows constants
#Define MOD_ALT 0x001 && Alt key
#Define MOD_CTRL 0x002 && Ctrl key
#Define MOD_SHIFT 0x004 && Shift key
#Define MOD_WIN 0x008 && Windows key
#Define vk_C 0x43 &&Virtual key C
#Define vk_D 0x44 &&Virtual key D
#Define WM_HOTKEY 0x312
&&APIs
Declare Integer RegisterHotKey In user32;
integer HWnd,;
integer Id,;
integer fsModifiers,;
integer vk
Declare Integer UnregisterHotKey In user32;
INTEGER HWnd,;
INTEGER Id
Public yForm
yForm = Createobject('asup')
If Vartype(yForm)='O' .And. !Isnull(yForm)
yForm.Show()
Endif
Return
Define Class asup As Form
Width=800
Height=600
MaxButton=.F.
AutoCenter=.T.
Caption="Test sending 2 system Hotkeys to VFP calculator---CTRL+ALT+C and CTRL+ALT+D"
ShowWindow=2 && top level form
Name="myForm"
Procedure Init
_Screen.Visible=.F.
Messagebox("This programm tests sending regitered system hotkeys to visual Foxpro.Press CTRL+ALT+C for activate VFP calculator and CTRL+ALT+D for deactivate.",0+32)
This.ForeColor=255
This.Print( " Press Hotkeys registered :CTRL+ALT+C and CTRL+ALT+D")
yresult1 = RegisterHotKey(This.HWnd,1000,MOD_CTRL+MOD_ALT,vk_C)
If yresult1=0 &&insuccess
Messagebox("the hotkey CTRL+ALT+C is not registrered-Fail !"+Transform(yresult1))
Return .F.
Endif
yresult2 = RegisterHotKey(This.HWnd,1001,MOD_CTRL+MOD_ALT,vk_D)
If yresult2=0 &&insuccess
Messagebox("the hotkey CTRL+ALT+C is not registrered-Fail !"+Transform(yresult2))
Return .F.
Endif
Bindevent(This.HWnd, WM_HOTKEY, This, "yBind")
Endproc
Procedure yBind
Lparameters HWnd As Integer,;
Msg As Integer, ;
wParam As Integer, ;
lParam As Integer
cr=Chr(13)
Do Case
Case wParam=1000
Set Bell To (Addbs(Getenv('windir')))+"MEDIA\DING.WAV"
?? Chr(7)
Activate Window calculator Top In "myform"
Case wParam=1001
Set Bell To (Addbs(Getenv('windir')))+"MEDIA\NOTIFY.WAV"
?? Chr(7)
Deactivate Window calculator
Endcase
Set Bell To
Endproc
Procedure Destroy
&&unregister the hotkeys registered
UnregisterHotKey(This.HWnd, 1000)
UnregisterHotKey(This.HWnd, 1001)
_Screen.Visible=.T.
Endproc
Enddefine
*End code
*4)*-
*Begin code
yform=Createobject('asup')
yform.Show
Read Events
Return
*
Define Class asup As Form
Top = 51
Left = 204
Height = 110
Width = 375
ShowWindow = 2
AutoCenter=.T.
BorderStyle = 2
Caption = "Test Hotkeys from system to Viisual Foxpro"
MaxButton = .F.
Name = "Form1"
Add Object label1 As Label With ;
AutoSize = .T., ;
BackStyle = 0, ;
Caption = "", ;
Height = 17, ;
Left = 6, ;
Top = 4, ;
Width = 2, ;
Name = "Label1"
Add Object command1 As CommandButton With ;
Top = 72, ;
Left = 108, ;
Height = 27, ;
Width = 132, ;
Caption = "Execute a Loop", ;
Name = "Command1"
Add Object label2 As Label With ;
AutoSize = .T., ;
FontBold = .T., ;
FontSize = 22, ;
Alignment = 2, ;
BackStyle = 0, ;
Caption = "", ;
Height = 37, ;
Left = 195, ;
Top = 28, ;
Width = 2, ;
ForeColor = Rgb(0,0,255), ;
Name = "Label2"
Procedure dispatchmessage
Lparameters HWnd As Integer,;
Msg As Integer, ;
wParam As Integer, ;
lParam As Integer
cr=Chr(13)
Do Case
Case wParam=1000
Set Bell To (Addbs(Getenv('windir')))+"MEDIA\DING.WAV"
?? Chr(7)
If Messagebox("Continue ?",4+48,"Pausing program") = 6
ystop=.F.
Else
ystop=.T.
Endif
Case wParam=1001
Set Bell To (Addbs(Getenv('windir')))+"MEDIA\NOTIFY.WAV"
?? Chr(7)
ystop=.T.
Clea
Thisform.Release
Endcase
Set Bell To
Endproc
Procedure Init
Publi ystop
ystop=.F.
#Define MOD_ALT 0x001 && Alt key
#Define MOD_CTRL 0x002 && Ctrl key
#Define MOD_SHIFT 0x004 && Shift key
#Define MOD_WIN 0x008 && Windows key
#Define vk_F6 0x75 &&Virtual key F6
#Define vk_F7 0x76 &&Virtual key F7
#Define WM_HOTKEY 0x312
_Screen.Visible=.F.
Messagebox("This programm tests sending regitered system hotkeys to visual Foxpro.Start the loop-Press CTRL+F6 (pause?) or CTRL+F7(release) ",0+32)
This.label1.ForeColor=255
This.label1.Caption=" pausing:CTRL+F6------Stop+release :CTRL+F7 "
yresult1 = RegisterHotKey(Thisform.HWnd,1000,MOD_CTRL,vk_F6) && ALT+F6
If yresult1=0
Messagebox("the hotkey CTRL+F is not registrered-Fail !"+Transform(yresult1))
Return .F.
Endif
yresult2 = RegisterHotKey(Thisform.HWnd,1001,MOD_CTRL,vk_F7) && ALT+F7
If yresult2=0
Messagebox("the hotkey CTRL+F7 is not registrered-Fail !"+Transform(yresult2))
Return .F.
Endif
Bindevent(Thisform.HWnd, WM_HOTKEY, Thisform, "DispatchMessage")
Endproc
Procedure Destroy
_Screen.Visible=.T.
UnregisterHotKey(This.HWnd, 1000)
UnregisterHotKey(This.HWnd, 1001)
Clea Events
Endproc
Procedure Load
Declare Integer RegisterHotKey In user32;
integer HWnd,;
integer Id,;
integer fsModifiers,;
integer vk
Declare Integer UnregisterHotKey In user32;
INTEGER HWnd,;
INTEGER Id
Endproc
Procedure command1.Click
ystop=.F.
i=0
Do While .T. &&execute a continue loop
i=i+1
Thisform.label2.Caption=Trans(i)
If ystop=.T.
Exit
Else
Loop
Endi
Enddo
Endproc
Enddefine
*End code
*5)*-Another example of hotkeys
*Begin code
#Define MOD_ALT 0x001 && Alt key
#Define MOD_CTRL 0x002 && Ctrl key
#Define MOD_SHIFT 0x004 && Shift key
#Define MOD_WIN 0x008 && Windows key
#Define vk_F6 0x75 &&Virtual key F6
#Define vk_F7 0x76 &&Virtual key F7
#Define WM_HOTKEY 0x312
Declare Integer RegisterHotKey In user32;
integer HWnd,;
integer Id,;
integer fsModifiers,;
integer vk
Declare Integer UnregisterHotKey In user32;
INTEGER HWnd,;
INTEGER Id
Public loForm
loForm = Createobject('formCapture')
If Vartype(loForm)='O' .And. !Isnull(loForm)
loForm.Show()
Else
*-- some trouble
Endif
Return
Define Class formCapture As Form
Width=350
Height=80
MaxButton=.F.
Caption="Test sending system Hotkeys to VFP"
ShowWindow=2 && top level form
WindowState=1 && reduced
Procedure Init
_Screen.Visible=.F.
Messagebox("This programm tests sending registered system hotkeys to visual Foxpro.Press CTRL+F6 or CTRL+F7 for this.The form is reduced.",0+32)
This.ForeColor=255
This.Print( " Press Hotkeys registered :CTRL+F6 or CTRL+F7 ")
yresult1 = RegisterHotKey(This.HWnd,1000,MOD_CTRL,vk_F6) && ALT+F6
If yresult1=0
Messagebox("the hotkey CTRL+F is not registrered-Fail !"+Transform(yresult1))
Return .F.
Endif
yresult2 = RegisterHotKey(This.HWnd,1001,MOD_CTRL,vk_F7) && ALT+F7
If yresult2=0
Messagebox("the hotkey CTRL+F7 is not registrered-Fail !"+Transform(yresult2))
Return .F.
Endif
Bindevent(This.HWnd, WM_HOTKEY, This, "DispatchMessages")
Endproc
Procedure DispatchMessages
Lparameters HWnd As Integer,;
Msg As Integer, ;
wParam As Integer, ;
lParam As Integer
cr=Chr(13)
Do Case
Case wParam=1000
Set Bell To (Addbs(Getenv('windir')))+"MEDIA\DING.WAV"
?? Chr(7)
Messagebox('Hotkey CTRL+F6 is pressed -message received...for doing somethings !'+cr+"At :"+Ttoc(Datetime())+cr+"-Message :"+Trans(Msg)+cr+"-Wparam :"+Trans(wParam)+cr+"-lparam :"+Trans(Lparam),0+32+4096)
Case wParam=1001
Set Bell To (Addbs(Getenv('windir')))+"MEDIA\NOTIFY.WAV"
?? Chr(7)
Messagebox('Hotkey CTRL+F7 is pressed -message received...for doing somethings !'+cr+"At :"+Ttoc(Datetime())+cr+"-Message :"+Trans(Msg)+cr+"-Wparam :"+Trans(wParam)+cr+"-lparam :"+Trans(Lparam),0+32+4096)
Endcase
&&the message received ,we can do any code on the form
Set Bell To
Endproc
Procedure Destroy
UnregisterHotKey(This.HWnd, 1000)
UnregisterHotKey(This.HWnd, 1001)
_Screen.Visible=.T.
Endproc
Enddefine
*End code