在程式中添加一些熱鍵可以讓使用者更加快速實作某些功能,對于一些熟練的操作人員,他們更容易接受快捷鍵的操作方式。例如大家熟悉的金山詞霸,一般情況下程式處在系統光标區,使用者可以通過Ctrl+Alt+F1組合鍵來切換是否進行螢幕取詞。
首先來說一下如何讓我們用PowerBuilder編寫的程式也能實作這個功能呢?有兩種方法:
方法一、本方法在視窗獲得焦點的時候,使用者按下熱鍵,就可以觸發視窗中的事件。
Send ( handle, message#, lowword, long )
參數說明:
handle:長整型,表示一個視窗的系統句柄,可以從handle()函數獲得。
message#:就是對應的系統消息,為十進制表示,如:WM_PASTE為0x0302,換算為十進制就是770。
longword:十進制,表示熱鍵的值,具體是由程式員自定義的。
算法是這樣的:
??? 高8位位元組與低8位位元組組成16位位元組,然後将它換算成十進制數,即得到所需的熱鍵值。高8位位元組值為一些輔助鍵(Control-0x02、Alt-0x04、Shift-0x01等),低8位位元組為使用鍵的ASCII碼,例如F1的ASCII碼為112。如果我們定義一個系統熱鍵是Ctrl+Alt+F1,那麼該值就是:高八位為輔助鍵,Ctrl+Alt=0x06,低八位為112,換算成十六進制是0x70,組合得到:0x670,再換算成十進制是1648。同理:Ctrl+Alt+A就是:1601。
long:該數值可以設定為0。
當然,也可以使用外部的API函數,是一樣的。該對應的API函數的聲明如下:
Function long SendMessageA(long lhWnd,uint uiMsg,long lwMsg,long lwParam) library? "user32.dll"
舉例說明:
為視窗上的一個按鈕(cb_1)聲明一個熱鍵:Ctrl+Alt+F1。查閱winuser.h可以得到:WM_SETHOTKEY為0x0032,換算成十進制就是50。然後為該按鈕所在的視窗的open事件寫入代碼:
long ll_rc
ll_rc=Send(Handle(this), 50, 1648, 0)
if ll_rc<>1 then
? messagebox("Error","Can not register hotkey!")
end if
然後在視窗的Other事件中寫入:
IF wparam =61776 THEN //61776為PB中的熱鍵消息,對應windows的SC_HOTKEY
??? cb_1.event clicked()
END IF
此時按下CTRL+Alt+F1就可以觸發cb_1的click事件。定義系統熱鍵成功。
又比如:
Send(Handle(dw_whatever), 274, 61472, 0)//最大化dw_whatever,SC_MINIMIZE
Send(Handle(dw_whatever), 274, 61488, 0)//最小化dw_whatever,SC_MAXIMIZE
Send(Handle(dw_whatever), 274, 61728, 0)//恢複原來的狀态,SC_RESTORE
方法二、本方法可以實作無論在任何時候,隻要使用者按下熱鍵,都将觸發視窗中的事件。
首先聲明如下的外部函數:
FUNCTION Integer GlobalAddAtom(ref string lpString) LIBRARY "kernel32.dll" ALIAS FOR? "GlobalAddAtomA"
參數說明:
lpString是任意的字元串,根據該字元串得到唯一的ID,進而不和其他的應用程式沖突。
FUNCTION ulong RegisterHotKey(ulong hwnd,ulong id,ulong fsModifiers,ulong vk) LIBRARY ??"user32.dll"
參數說明:
hwnd是定義熱鍵的視窗的句柄,由handle()得到。
id是有函數GlobalAddAtom傳回的數值(ulong)類型。
fsModifiers是輔助鍵的編碼和。Ctrl為2,Alt為1,Shift為4
vk是虛拟鍵的ASCII碼,如A為65
舉例說明:
在視窗中聲明一個執行個體變量ll_mod,儲存從GlobalAddAtom獲得的唯一ID。
在視窗的Open事件中寫入如下的代碼:
long ll_rc
string ls_mod
ls_mod="my id"//可以任意定義,是識别這個ID的關鍵字
ll_mod=GlobalAddAtom(ls_mod)//獲得注冊成功的唯一ID
ll_rc=RegisterHotKey(Handle(this), ll_mod, 3, 65) //定義熱鍵:Ctrl+Shift+A
if ll_rc=0 then
??? messagebox("Error","Unable to register hotkey!")
end if
在視窗的Other事件中加入如下的代碼:
if wparam=ll_mod then
//Do something
end if
如何模拟鍵盤按鍵
??? 另外,我們還可以想到,如果我截獲使用者的按鍵事件,在該事件中發送特殊意義的按鍵的代碼,就好像替使用者按了另外的按鍵一樣,比如,在Excel中按Shift+TAb可以實作和TAB相反方向的移動,我讓使用者按F12,然後我模拟按Shift+Tab,不也是“熱鍵”嗎?嗯,想法不錯,我們該如何實作呢?這就要用到一個Api函數,它可以用來模拟按鍵,是這樣聲明的:
SUBROUTINE keybd_event(int bvk,int bscan,int dwflags,int dwextrainfo) library? "user32.dll"
參數說明:
bvk:虛拟按鍵的ASCII碼值。
bscan:取值為0即可。
dwflags:取值為0表示按鍵按下,取值為2表示按鍵釋放。
dwextrainfo:取值為0即可。
舉例說明:
keybd_event(44,0,0,0)将目前螢幕上的内容存入到剪貼闆中。//44為PrintScreen的ASCII碼。
下面幾句相當于按下了Ctrl+Alt+F1:
keybd_event(18,0,0,0)//按下了Alt
keybd_event(17,0,0,0)//按下了Ctrl
keybd_event(65,0,0,0)//按下了F1
keybd_event(18,0,2,0)//釋放了Alt
keybd_event(17,0,2,0)//釋放了Ctrl
keybd_event(65,0,2,0)//釋放了F1
現在回過頭來看看我們的“熱鍵”的事情。我們已經有了解決的辦法,舉個例子吧:
在自定義的事件中寫入下面的代碼(事件的ID為pbm_dwnkey)
Choose Case key
Case KeyF4!
// 模拟按下Shift+Tab鍵,然後釋放
keybd_event(16,0,0,0) // SHIFT Depressed
keybd_event(9,0,0,0) // TAB Depressed
keybd_event(16,0,2,0) // SHIFT Released (CANNOT BE OMITTED)
keybd_event(9,0,2,0) // TAB Released (Can be omitted)
Case KeyF5!
// 模拟按下和釋放Tab鍵
keybd_event(9,0,0,0) // TAB Depressed
keybd_event(9,0,2,0) // TAB Released (Can be omitted)
End Choose
好了,到這裡,我們的所有的目标都達到了,現在問題又來了:我現在很難找到某個按鍵的AScii值,怎麼辦?這有兩個解決辦法。
1、使用PowerBuilder提供的asc()函數
2、使用下面的表格查找。