一、概述
Delphi作為一種面向對象的可視化開發工具,以其開發程序的高速度和編譯代碼的高效率越來越受到廣大編程人員的喜愛。Delphi本身提供了包括界面設計、數據庫操作、報表打印和Internet等在內的數十個組件,開發者使用它們可以非常容易、快速地制作出所要的應用系統,同時所需要的編程量卻非常地小。除此之外,delphi同時秉承了borland公司產品一貫的編譯效率高,速度快特色。
Delphi2.0版本以上的產品完全支持32位應用程序的開發,完全支持windows95和WindowsNT提供的所有API函數。應用程序接口(API)是windows提供的任何Windows應
用可以訪問的函數的集合。盡管Delphi已經提供了非常強大的開發組件(VCL),但靈活使用API函數一定可以使你的程序增色不少。
二、狀態鍵的檢查
當今不少流行軟件的編輯窗口(包括Delphi的代碼編輯窗口)的底部都有一個狀態條用來顯示一些狀態信息,比如當前光標的位置、頁碼消息和狀態鍵的狀態。什么是狀態鍵呢?我們知道鍵盤上大多數按鍵只有在按下時才能為系統所識別,而狀態鍵的共同特點就是他們好似一個開關,每按一次就切換到相反狀態直至下一次按鍵為止。通常鍵盤的狀態鍵包括[NumLock],[ScrollLock],[CapsLock]和[Insert]這四個鍵,在編輯窗口中顯示狀
態鍵的狀態可以使你的界面更友好,更有利於方便用戶。
使用delphi強大的開發功能和API提供的GetKeyboardState()函數,你可以輕松地在你的程序中實現狀態鍵檢測這一功能。
也許有些讀者要問:我可以使用delphi提供的OnKeyPress函數捕捉按鍵動作來完成這一功能,又有什么必要調用API函數呢?這就涉及到狀態鍵的另一個特點:即它的狀態與程序運行無關。比如說你在word中按下insert鍵后再切換到delphi中輸入代碼,這個鍵的狀態仍然保持不
變。而如果只使用OnKeyPress函數,那么當你的程序在后台運行時就無法捕捉到在前台程序中發生的按鍵動作,所以當切換到你程序時也就無法正確反映狀態鍵的狀態。因此需要使用API的GetKeyboardState()函數來檢查鍵盤狀態。當調用GetKeyboardState()函數時,你需要在程序中開辟一個256字節的緩沖區用來存儲鍵盤上各個鍵的狀態(最簡單的方法你可以聲明一個TKeyboardState變量)你可以根據緩沖區中相應位置的值來判斷鍵盤狀態,下表顯示了系統常量和其相應的按鍵。(你如果想查看所有的鍵值列表可以在help菜單選擇WindowsAPI中輸入關鍵字virtualkeycodes,然后按下Show鍵)
常量按鍵名稱
VK—INSERT[Insert]鍵
VK—NUMLOCK[NumLock]鍵
VK—CAPITAL[CapsLock]鍵
VK—SCROLL[ScrollLock]鍵
鍵盤緩沖區每一位都有特定的格式,對於狀態鍵來說,最低位是1時表示狀態鍵處於ON狀態,你可以使用delphi提供的Odd()函數來確定這一位的狀態。為了使程序顯示正確的狀態鍵的狀態,你需要定期調用GetKeyboardState()函數來不斷的查詢鍵盤狀態,實現這一功能最簡單的方法是使用Timer組件。
下面舉一個小例子來說明如何具體實現這一調用功能,在這個例子中我們將檢查[NumLock]鍵的狀態並把它顯示在屏幕底部的狀態欄。
從Component模板Win95頁中選擇StatusBar組件,按如下所示設置它的屬性
AlignalBottom Height20
從system頁中的選擇Timer組件並把它放入窗體,雙擊Timer組件彈出OnTimer事件的代碼編輯窗口,按如下所示添加代碼:
procedureTForm1.Timer1Timer(Sender:TObject);
varKeyStates:TKeyboardState;
begin
GetKeyboardState(KeyStates);
begin
if Odd(KeyStates[VK—NUMLOCK])then
StatusBar1.Panels.Items[0].Text:=′NUM′
else
StatusBar1.Panels.Items[0].Text:=″
end;
end;
我們可以檢驗一下程序的運行結果。運行程序,可以看到狀態條中正確顯示了當前的狀態,切換到另一個程序改變[numlock]鍵的狀態再切換回運行程序,可以看到狀態條的狀態已經改變。一般說來,在程序中加入狀態條顯示相應信息對於用戶來說是十分方便的。
三、改變提示框(hint)的特性
許多程序在特定的控件上都有提示框,當鼠標在這些控件上停一定時間以后就可以顯示提示框。在Delphi中實現提示框是非常容易的,只要設定相應的屬性即可,這里就不詳細討論了。但通常的提示框都是以黃色矩形框的形式顯示在對應控件的左下角,以下這段代碼說明了如何使用API改變delphi中提示屬性的一些特性。有一點需要聲明的是代碼中使用到的GetIconInfo函數只適用win32(也就是說你只能在delphi2.0以上的版本中使用以下代碼)
。
把以下代碼加入到主窗體的Oncreate事件中,加入代碼后的主窗體的formcreate過程的代碼如下所示:
procedureTMainForm.FormCreate(Sender:TObject);
begin
...
Application.OnShowHint:=GetHintInfo;
end;
然后把以下過程聲明加入到主窗體的public段
procedureGetHintInfo(VarHintStr:sting;VarCanShow:boolean;varHintInfo:
THintInfo);
最后,在主窗體的implementation部分加入過程的實現代碼,加入完代碼的過程如下所示:
procedureTMainForm.GetHintInfo(varHintStr:string;varCanShow:boolean;
varHintInfo:THintInfo);
var
II:TlconInfo;
Bmp:Windows.TBitmap;
begin
with HintInfo do
begin
//應該保證有控件使用定義了Hint屬 性
if HintControl=NIL then exit;
HintPos:=HintControl.ClientToScreen(CursorPos);
//把光標坐標系由相對於提示改為相對於屏幕
GetIconInto(Screen.Cursors[HintControl.Cursor],II);
//獲得有關提示控制使用的有關光標的信息
GetObject(II.hbmMask,SizeOf(Windows.TBitmap),&Bmp);
//獲得有關光標的位圖(bitmap)信息
if II.hbmColor=0 then
inc(HintPos.Y,Bmp.bmHeightdiv2)
//如果光標不包括彩色位圖,增加Y方向
else
inc(HintPos.Y,Bmp.bmHeight);
dec(HintPos.Y,II.yHotSpot);
//減掉y方向的熱點位置
DeleteObject(II.hbmMask);
DeleteObject(II.hbmColor);
//清除位置句柄
end;
end;
通過改變HintPos.X和Y的值可以在任意位置顯示提示框。Word7.0中滾動縱向滾動條時頁碼序號總是顯示鼠標在左方,用以上代碼實現這一功能可以說是易如反掌。
*******************************************************************
Delphi以其優良的可視化編程,靈活的Windows API接口,豐富的底層操作越來越受到編程愛好者的青睞。
在Delphi中,通過調用Windows API,可以很方便地獲取系統信息,這有助於我們編寫出更好的Windows應用程序。以下程序在Delphi3.0 For Windows 9x下編譯通過。
一、 用GetDriveType函數獲取磁盤信息
Lbl_DriveType:Tlabel;
DriveType:WORD; //定義驅動器類型變量
DriveType:=GetDriveType(RootPathName); //獲得RootPathName所對應的磁盤驅動器信息
case DriveType of
DRIVE_REMOVABLE:Lbl_DriveType.Caption:= '軟盤驅動器';
DRIVE_FIXED : Lbl_DriveType.Caption:= '硬盤驅動器';
DRIVE_REMOTE: Lbl_DriveType.Caption:= '網絡驅動器';
DRIVE_CDROM: Lbl_DriveType.Caption:= '光盤驅動器';
DRIVE_RAMDISK: Lbl_DriveType.Caption:= '內存虛擬盤';
end; //將該磁盤信息顯示在Lbl_DriveType中
二、 用GlobalMemoryStatus函數獲取內存使用信息
MemStatus: TMEMORYSTATUS; //定義內存結構變量
Lbl_Memory:Tlabel;
MemStatus.dwLength := size of(TMEMORYSTATU
S);
GlobalMemoryStatus(MemStatus); //返回內存使用信息
Lbl_Memory.Caption := format('共有內存: %d KB 可用內存: %dKB',[MemStatus.dwAvailPhys div 1024,MemStatus.dwTotalPhys div 1024]);
//將內存信息顯示在Lbl_Memory中
三、 用GetSystemInfo函數獲取CPU信息
SysInfo: TSYSTEMINFO;
Lbl_CPUName:Tlabel;
GetSystemInfo(SysInfo);//獲得CPU信息
case SysInfo.dwProcessorType of
PROCESSOR_INTEL_386:Lbl_CPUName.Caption:=format('%d%s',[SysInfo.dwNumber Of Processors,'Intel80386']);
PROCESSOR_INTEL_486:Lbl_CPUName.Caption:=format('%d%s',[SysInfo.dwNumber Of Processors, 'Intel 80486']);
PROCESSOR_INTEL_PENTIUM:Lbl_CPUName.Caption:=format('%d%s',[SysInfo.dwNum
berOfProcessors, 'Intel Pentium']);
PROCESSOR_MIPS_R4000:Lbl_CPUName.Caption:=format('%d%s', [SysInfo.dwNumberOfProcessors,'MIPS R4000']);
PROCESSOR_ALPHA_21064:Lbl_CPUName.Caption:=format('%d%s', [SysInfo.dwNumberOfProcessors,'ALPHA 21064']);
end;//把CPU信息顯示在Lbl_CPUName中。
****************************************************************** 生成非矩形窗口
利用win32 API函數setwindowrgn可以將窗口定義為任何形狀,以下是將窗口定義為園角矩形的例子:
procedure TPortForm.FormCreate(Sender: TObject);
var hr :thandle;
begin
hr:=createroundrectrgn(0,0,width,height,20,20);//定義園角矩形(win API函數)
setwindowrgn(handle,hr,true); //設置園角窗口
end;
為了使該窗口更好,應在onResize事件處理程序放相同的代碼。
********************************************************************** 程序不出現在任務欄
一般Windows 95運行程序時都會在任務欄上出現按鈕,如果你的程序是一個監視程序,那么出現按鈕就不是明智之舉了。要實現該功能就要在OnCreate事件里利用到API函數SetWindowLong
procedure TForm1.FormCreate(sender:TObject);
begin
SetWindowLong(Application,Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW);
end;
關閉Windows
控制WINDOWS的開關:如關閉WINDOWS,重新啟動WINDOWS等, ExitWindowsEx(UINT uFlags,DWORD dwReserved);是實現這一功能的API函數
首先定義常數
const
EWX_FORCE=4; //關閉所有程序並以其他用戶身份登錄
EWX_LOGOFF=0; //重新啟動計算機並切換到MS-DOS方式
EWX_REBOOT=2; //重新啟動計算機
EWX_SHUTDOWN=1;//關閉計算機
運行時給How賦值,讓他等於EWX_SHUTDOWN或其他,調用以下語句
ExitWindowsEx(How,0);
隱藏桌面上的圖標
使桌面上的圖標消失,連桌面上的右鍵功能也不能使用如果不讓初學者亂用“我的電腦”的話,那么把程序放到“啟動”里,順便把“Windows資源管理器”也去掉,再加上個多用戶密碼,那么想破壞電腦文件也無從下手了。該程序Delphi 4里通過
var
hDesktop : THandle;
begin
hDesktop := FindWindow('Progman', nil);
ShowWindow(hDesktop, SW_HIDE);
end;
模擬按下某鍵
讓 WIN95 模擬按了一個按鍵,就向某窗體發送按鍵一樣,例如按下 ENTER 或者 TAB 鍵,或者按 7 鍵
PostMessage(Object.Handle, WM_KEYDOWN, VK_TAB, 0);
{Object表示窗體名,WM_KEYDOWN是按下,VK_TAB是發送的按鍵}
PostMessage(edit1.Handle, WM_KEYDOWN, 55, 0);
{向edit1發送一個7字}
動態修改顯示器分辨率
Windows提供給我們兩個API函數,可以動態調整顯示器的分辨率,他們是EnumDisplaySettings() 和ChangeDisplaySettings(),下面這個例子就是了
function DynamicResolution(X, Y: word): BOOL;
var
lpDevMode: TDeviceMode;
begin
Result := EnumDisplaySettings(nil, 0, lpDevMode);
if Result then
begin
lpDevMode.dmFields := DM_PELSWIDTH Or DM_PELSHEIGHT;
lpDevMode.dmPelsWidth := X;
lpDevMode.dmPelsHeight := Y;
Result := ChangeDisplaySettings(lpDevMode, 0) = DISP_CHANGE_SUCCESSFUL;
end
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if DynamicResolution(640, 480) then
ShowMessage('Now is 640*480');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if DynamicResolution(800, 600) then
ShowMessage('Now is 800*600');
end;
限制FORM的大小
使用過DELPHI的朋友都會注意到DELPHI本身最上面的窗口,當它極大時只占屏幕的一小部分,它是如何實現的呢,請看下面的說明:
1)在FORM私有聲明部分加上如下一行:
procedure WMGetMinMaxInfo( var Message:TWMGetMinMaxInfo ); message WM_GETMINMAXINFO;
2)在聲明部分加上如下幾行:
procedure TForm1.WMGetMinMaxInfo( var Message :TWMGetMinMaxInfo );
begin
with Message.MinMaxInfo^ do
begin
ptMaxSize.X := 200; {最大化時寬度}
ptMaxSize.Y := 200; {最大化時高度}
ptMaxPosition.X := 99; {最大化時左上角橫坐標}
ptMaxPosition.Y := 99; {最大化時左上角縱坐標}
end;
Message.Result := 0; {告訴Windows你改變了 minmaxinfo}
inherited;
end;
控制窗體
如何在 Delphi 中把 Form 控制成不能放大/縮小/移動/關閉?
1、把 Form 的 BorderIcons 下的幾個子屬性值全改為 False;
2、修改 Form 的 BorderStyle 的值為bsSingle ;
3、為了讓窗口不能移動,可以自已攔下 WM_NCHITTEST 消息, 對該消息的處理為:一概回應鼠標點在窗口的 Client 區域, 相信這個視窗就呆呆的不會動了。
詳情可以查一下 Win32API Help 的 CreateWindow() 與 WM_NCHITTEST 的說明。
下面是一個例子, 請參考看看:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure WMNCHitTest(var Msg: TMessage); message WM_NCHITTEST;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
Close; // 不可少, 因為已經沒有其他方法能關閉此窗口了
end;
procedure TForm1.WMNCHitTest(var Msg: TMessage);
begin
inherited; // 這樣,移動就不可能了...
Msg.Result := HTCLIENT;
end;
end.
快速將某一區域的顏色取反
快速將某一區域的顏色取反,主要應用在制作表格時的選擇區域.
API函數:PatBlt(MyHDC:HDC;X,Y,WIDTH,HEIGHT:INTEGER;MODE);
例如:
var
MyDC:HDC;
Begin
MyDC:HDC;
MyDC:=GetDC(Form1.Handle);
if not PatBlt(MyDC,
1,
1,
100,
100,
DSTINVERT) then
ShowMessage('ERROR :~(');
End;
得到WINDOWS的SYSTEM路徑
方法:
var
MySysPath : PCHAR ;
begin
GetMem(MySysPath,255);
GetSystemDirectory(MySysPath,255);
end;
注:MySysPath為SYSTEM路徑.。
Delphi下編程實現中文輸入法
江 蘇 省 電 信 傳 輸 局
周曉
---- Borland Delphi 以 其 強 大 的 功 能 及 和 高 效 的 可 視 化 開 發 環 境為 廣 大 程 序 設 計 員 所 青 睞 。 尤 其 是 它 封 裝 了WINDOWS API 函數, 能 方 便 地 利 用WINDOWS 資 源, 大 大 加 快 了 程 序 開 發 速度。
---- 在 平 時 的 計 算 機 操 作 中, 中 文 輸 入 是 不 可 避 免 的。 使用 者 可 能 喜 歡 不 同 的 中 文 輸 入 法(inputmethod editor, 簡 稱IME), 這 就 不 得 不 經 常 點 擊 任 務 欄 中 的 中 文 圖 標 或 用CTRL+Space,CTRL+Shift 熱 鍵 切 換, 初 學 者 用 起 來 很 不 方 便。 針 對 這 一 問 題, 可以 在 開 發 軟 件 時, 在 程 序 中 設 置 用 戶 喜 歡 的 中 文 輸 入法, 方 便 用 戶 的 使 用。Delphi 中 只 有 少 數 控 件 如TEdit 支 持IME, 而 且 該 功 能 不 強, 不 能 在 運 行 時 更 改 輸 入 法。
---- 筆 者 通 過 實 踐 和 摸 索, 查 找 了 相 關 的IME 資 料, 利 用 了WINDOWS API 函 數, 實 現 了IME 的 功 能。
---- 常 用 函 數 有:
API函數:BOOL ImmSimulateHotKey
(HWND hWnd,DWORD dwHotKeyID);//模擬熱鍵
其中Hwnd為程序窗口的句柄,dwHotHKeyID
為模擬的熱鍵,若成功則返回True
HKL GetKeyboardLayout(DWORD dwLayout);
//獲得當前鍵盤狀態
BOOL ImmIsIME(HKL hKL);
//判斷當前是否處於中文輸入狀態,若是則返回True
自定義函數:
打開相應輸入法:OpenIme(imename:string),
例OpenIme('全拼輸入法');
關閉中文輸入法:CloseIme;
以下是一個簡單的例子,僅起參考作用。
使用時uses中加上imm
具體的實現方法及源代碼如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons,imm;
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
procedure FormShow(Sender: TObject);
procedure OpenIme(imename:string);
procedure closeIme;
procedure ComboBox1Change(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormShow(Sender: TObject);
var
j:integer;
begin
for j:=0 to screen.imes.count-1 do
begin
ComBoBox1.Items.Add(screen.Imes.strings[j]);
//獲取系統中已安裝的中文輸入法
end;
end;
procedure Tform1.OpenIme(imename:string);
var
I:integer;
myhkl:hkl;
begin
if ImeName<>'' then
begin
if Screen.Imes.Count<>0 then
begin
I:=screen.Imes.indexof(imename);
if I>=0 then
myhkl:=hkl(screen.Imes.objects[i]);
activatekeyboardlayout(myhkl,
KLF_ACTIVATE);//設置相應的輸入法
end;
end;
end;
procedure TForm1.closeime;
var
myhkl:hkl;
begin
myhkl:=GetKeyBoardLayOut(0);
if ImmIsIME(myhkl) then
//判斷是否在中文狀態,若是則關閉它
immsimulateHotkey(handle,
IME_CHotKey_IME_NonIME_Toggle);
end;
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
OpenIme(ComboBox1.Text);
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
immsimulateHotkey(handle,
IME_CHotKey_shape_Toggle);//切換半角和全角模式
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
begin
immsimulateHotkey(handle,
IME_CHotKey_symbol_Toggle);
//切換中文標點模式和英文標點模式
end;
procedure TForm1.BitBtn3Click(Sender: TObject);
begin
closeime;
end;
end.
閃動標題欄
在你的應用程序中,你可能會希望將應用程序的標題欄進行閃動,以提醒用戶進行某種操作,本文介紹了如何使一個窗口的標題欄進行閃動。
閃動標題欄
閃動一個窗口的標題欄意味着改變它的標題欄的外觀,例如它從活動變為不活動,或是從不活動變為活動等等。只要你能在Delphi 或者 C++ Builder 中得到窗口的句柄,你就可以使用Windows 應用程序編程接口(API)函數來使該窗口的標題欄進行閃動。函數FlashWindows可以被用使一個特定的窗口閃動一次。
函數原形:
function FlashWindow(const hwnd:Integer;const bInvert:LongBool):LongBool;
該函數需要2個參數,第一個參數是要閃動標題欄的窗口的句柄,第二個參數用於指定是設置窗口的閃動狀態,還是恢復其原始狀態。如果該bInvert參數為True,則表明窗口的標題欄被閃動,如果該參數為False,則表明窗口的標題欄被恢復為原始狀態。
該函數所返回的值用於指定調用該函數前窗口的狀態,如果該返回值True,則表明窗口在調用該函數之前是活動的,否則,如果返回值為False,則表明調用函數前窗口是非活動的。
當使用該FlashWindow函數時,一個較好的方法是將標題欄閃動的頻率設置為同脫字符(也即閃動的光標)相同,脫字符的閃動頻率可以通過調用函數GetCaretBlinkTime來獲得。要使用該函數,需要將如下的聲明語句包含在你的窗體的通用聲明部分中:
function GetCaretBlinkTime:Integer;
該函數返回用毫秒值表示的時間。 例程: 建立新的Project,並新建一From(包括New Project建立的Form,共兩個),在Form1中加入一Button和Timer,按下面的方法建立程序.
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Show;
Form1.BringToFront;
Timer1.Interval:=GetCaretBlinkTime;
Timer1.Enabled:=Not Timer1.Enabled;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
FlashWindow(Form2.Handle,TRUE);
end;
應用程序敏感鍵的實現
---- 在一個應用程序內部菜單、部件都可以設置敏感鍵。如在菜單中一般用Alt+F進入“文件”之類的子菜單。另外我們在桌面上設置的快捷方式里的快捷鍵,無論你任何時候按下你所設置的快捷鍵就會啟動相應的應用程序。在多個正在運行的應用程序中如何利用一個按鍵動作迅速地回到你所需要的應用程序呢?這就需要利用敏感鍵(HOTKEY)的技術來實現。本文利用Delphi3.0開發工具來闡述該技術在應用程序的實現方法。
一、敏感鍵的設置
---- 在windows Api中有一個函數RegisterHotKey用於設置敏感鍵,它的調用方式如下:
BOOL RegisterHotKey(HWND hWnd, //響應該敏感鍵的窗口句柄Int id, //該敏感鍵的唯一標示符UINT fsModifiers, //該敏感鍵的輔助按鍵UINT vk //該敏感鍵的鍵值);
---- 其中敏感鍵的唯一標示符在Window中規定應用程序的取值范圍為0x0000到0xBFFF之間,動態鏈接庫的取值范圍為0xC000到0xFFFF之間。為了保證其唯一性建議使用GlobalAddAtom函數來設置敏感鍵的唯一標示符。需要注意的是GlobalAddAtom還回的值是在0xC000到0xFFFF范圍之間,為滿足RegisterHotKey的調用要求,如果是在應用程序中設置敏感鍵可以利用GlobalAddAtom還回值減去0xC000。
---- 敏感鍵的輔助按鍵包括Mod_Ctrl 、Mod_Alt、Mod_Shift,對於Windows兼容鍵盤還支持Windows鍵,即其鍵面上有Windows標志的那個鍵,其值為Mod_win。
---- 在Delphi中建立一個“New Application”,在Tform1中的Private段中加入如下代碼
private{ Private declarations }hotkeyid :integer;procedure WMhotkeyhandle(var msg:Tmessage);message wm_hotkey; //響應敏感鍵按鍵消息在FormCreate事件中加入如下代碼…hotkeyid:=GlobalAddAtom(pchar(“UserDefineHotKey”))-$C000;//減去$C000是為了保證取值范圍的限制registerhotkey(handle,hotkeyid,MOD_CONTROL or mod_Altt,$41);//敏感鍵為ctrl+Alt+A…
二、敏感鍵的響應
---- 一旦敏感鍵設置成功,在程序應用過程中如果有相應敏感鍵被按下,Windows系統都會給你的應用程序發送一個消息WM_HOTKEY,不管你的應用程序是否為當前活動的。其中WM_HOTKEY消息的格式為:
idHotKey = (int) wParam;// 該參數在設置系統級的敏感鍵有用,一般不予使用fuModifiers = (UINT) LOWORD(lParam);//敏感鍵的輔助按鍵uVirtKey = (UINT) HIWORD(lParam);//敏感鍵的鍵值
---- 因為Windows系統只是把一個WM_HotKey的消息發送給應用程序,要完成具體的事情需要一個消息處理程序,也就是上面Private段里的procedure WMhotkeyhandle(var msg:Tmessage); message wm_hotkey; 過程, 它的代碼如下(這里只是簡單地把窗口最前面顯示)
procedure TForm1.Wmhotkeyhandle(var msg:Tmessage);beginif (msg.LParamHi=$41) and(msg.lparamLo=MOD_CONTROL or mod_Alt) thenbeginmsg.Result:=1; //該消息已經處理application.BringToFront;//把窗口最前面顯示end;end;
三、敏感鍵的釋放
---- 在應用程序退出來之前應當把你所設置的敏感鍵釋放掉,以釋放其所占有的系統資源,這里需要調用兩個Windows API函數UNREGISTERHOTKEY,它的調用格式如下:
BOOL UNREGISTERHOTKEY(HWND HWND, //與敏感鍵關聯的窗口句柄INT ID //敏感鍵的標示符);也就是說只要在FormClose事件中加入如下代碼…unregisterhotkey(handle,hotkeyid);DeleteAtom(HotKeyID);…
---- 到這里為止,你應當對敏感鍵技術有了全面的了解, 以上的例子相當簡單同時也沒有提供必要的調用成功檢測,可以根據具體情況加以完善,希望對你的開發過程會有所幫助.
在Delphi中使用動態圖標
在應用程序的編寫中,組合框(ComboBox)、列表框(ListBox)、等常見的部件,通常不僅要用於顯示文字,而且還要顯示其與文字相關的圖標。在一般的Windows應用程序中,這些圖標的顯示都要隨列出的顯示文本的變化而變化,例如在組合框中列出當前目錄下的所有文件時,在組合框左邊就顯示與文件名相關聯的圖標,這就是所謂的動態圖標。在Delphi中使用動態圖標的步驟如下:
一、圖標的獲取
要使用動態圖標,首先要解決的是如何獲得顯示文本和與其相關聯的圖標句柄。該圖標通過文件關聯由系統注冊表決定,並且在Windows編程中同一文件(或子目錄,或文件夾)在桌面上也可能有兩種顯示結果,這就是DOS文件名與顯示名(Display Name)。如果我們的應用程序不需要有像Windows資源瀏覽器那樣的效果,則可以使用FindFirst()和FindNext()二個函數以及FindClose()過程來獲得DOS文件名,否則我們就應當使用WindowsAPI來獲得顯示名。在獲得文件名的同時可通過使用ShellAPI.pas中的SHGetFileInfo()函數來獲得其圖標句柄HICON,說明如下:
function SHGetFileInfo(pszPath: PAnsiChar; dwFileAttributes: DWORD;var psfi: TSHFileInfo; cbFileInfo,uFlags: UINT): DWORDl;
pszPath 參數:指定的文件名。當uFlags的取值中不包含 SHGFI_PIDL時,可直接指定;否則pszPath要通過計算獲得,不能直接指定;
dwFileAttributes參數:文件屬性,僅當uFlags的取值中包含SHGFI_USEFILEATTRIBUTES時有效,一般不用此參數;
psfi 參數:返回獲得的文件信息,是一個記錄類型,有以下字段:
hIcon: HICON; //文件的圖標句柄
iIcon: Integer; //圖標的系統索引號
dwAttributes: DWORD; //文件的屬性值
szDisplayName: array [0..MAX_PATH-1] of AnsiChar; //文件的顯示名
szTypeName: array [0..79] of AnsiChar; //文件的類型名
cbFileInfo 參數:psfi的比特值;
uFlags 參數:指明需要返回的文件信息標識符,常用的有以下常數:
SHGFI_ICON; //獲得圖標
SHGFI_DISPLAYNAME; //獲得顯示名
SHGFI_TYPENAME; //獲得類型名
SHGFI_ATTRIBUTES;//獲得屬性
SHGFI_LARGEICON; //獲得大圖標
SHGFI_SMALLICON; //獲得小圖標
SHGFI_PIDL;// pszPath是一個標識符
函數SHGetFileInfo()的返回值也隨uFlags的取值變化而有所不同。通過調用SHGetFileInfo()可以由psfi參數得到文件的圖標句柄,但要注意在uFlags參數中不使用SHGFI_PIDL時,SHGetFileInfo()不能獲得"我的電腦"等虛似文件夾的信息。
二、圖標的加載
使用Delphi提供的TImageList組件,通過調用CommCtrl .pas中的函數ImageList_AddIcon()來加載得到的圖標,並要保證其索引號與顯示文本相對應。說明如下:
function ImageList_AddIcon(ImageList: HIMAGELIST; //加載圖標的ImageList句柄
Icon: Hicon //加載的圖標句柄 ): Integer; //返回圖標在ImageList中的索引號
在需要指明圖標索引號時可使用ImageList_AddIcon()的返回值。
三、圖標和文本的繪圖式輸出
對於組合框、列表框等不能直接顯示圖標的組件,由於要求顯示圖標的同時又要同時顯示文本,可通過設置其相應的Style屬性達到目的,示例如下:
組合框:ComboBox1.Style:=csOwnerDrawVariable根據實際使用經驗最好不要在ObjectInspector窗體中直接設置,而應將代碼添加在程序的適當位置,否則可能出現繪圖區域高度不規則變化
列表框:ListBox1.Style:=lbOwnerDrawVariable
狀態欄:StatusBar1.Panels[i].Style:= psOwnerDraw 不能使用簡單狀態欄,i是狀態欄中要繪制圖標的某一窗格索引號,圖形輸出可使用TImageList的ImageList1.Draw()方法,而文本輸出則可使用TCanvas的TextOut()方法,它由組件的Canvas屬性繼承得到,顯然沒有Canvas屬性的組件不能使用此方法顯示圖標。
對於可直接顯示圖標的組件,直接指定其Images、StateImages等需要的圖標屬性為相應的TimageList組件名,並通過指定圖標的索引號則可顯示圖標。需要注意的是:在使用大圖標時,必須先調用TImageList的CreateSize()方法指定可加載圖標的尺寸,並且在每次調用TImageList的Clear方法后都要重新調用CreateSize()。
使用TImageList的ImageList1.Clear方法清除已加載的圖標,常在需要刷新時使用