天天看點

PB熱鍵

在程式中添加一些熱鍵可以讓使用者更加快速實作某些功能,對于一些熟練的操作人員,他們更容易接受快捷鍵的操作方式。例如大家熟悉的金山詞霸,一般情況下程式處在系統光标區,使用者可以通過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、使用下面的表格查找。

繼續閱讀