WINDOWS編程技巧之DELPHI篇
本文由lanyus收集整理,文中技術來源網路,部分摘自《奇思異想編程之DELPHI篇》,轉載請註明此處。
///* lanyus QQ:231221 greathjw@163.com *///
一、隱藏工作列
在WINDOWS中,系統的工作列本質上也是一個視窗,其視窗類別名為“Shell_TrayWnd"。要實現對它的操作,可通過API
函數FindWindow和ShowWindow來達到目的。
var
wndHandle:THandle;
wndClass:Array[0..50] of char;
begin
StrPCopy(@wndClass[0],'Shell_TrayWnd');
wndHandle:=FindWindow(@wndClass[0],nil);
ShowWindow(wndHandle,SW_HIDE); //sw_restore
end;
二、隱藏案頭上的捷徑
跟工作列一樣,案頭其實也是一個視窗,它的類名為“ProgMan”,同樣用FindWindow找到視窗控制代碼,再由
ShowWindow來決定是否顯示。
三、擷取工作列尺寸及位置
用FindWindow找到控制代碼,再用GetWindowRect擷取當前工作列尺寸大小。
GetWindowRect(HWND hWnd, //所求視窗的控制代碼
LPRECT lpRect //儲存視窗座標的結構體的地址
):Boolean;
四、擷取CPU資訊
CPU的相關資訊是儲存在一個結構體中的,這個結構體由DELPHI用TSYSTEMINFO進行了封裝,定義如下:
typedef struct_SYSTEM_INFO{
union{
DWORD dwOemId; //已改用如下結構體分支來代替這個變數的使用了
struct{
WORD wProcessorArchitecture; //表示處理器的架構
word wReserved; //保留字
};
};
DWORD swPageSiae; //分頁大小
LPVOID lpMinimumApplicationAddress; //應用程式和動態連結程式庫可以訪問的最小地址
LPVOID lpMaximumApplicationAddress; //應用程式和動態連結程式庫可以訪問的最大地址
DWORD swActiveProcessorMask; //活動處理器的掩碼
DWORD dwNumberOfProcessors; //處理器的數目
DWORD dwProcessorType; //處理器的類別
DWORD dwAllocationGranularity; //虛擬記憶體地址分配的間隔
WORD wProcessorLevel; //處理器的層級
WORD wProcessorRevision; //處理器修改資訊
}SYSTEM_INFO;
其中dwProcessorType由wProcessorArchitecture、wProcessorLevel和wProcessorRevision三個成員來確定
,其值為:
PROCESSOR_INTEL_386:INTEL80386系列;
PROCESSOR_ITNEL_486:INTEL80486系列;
PROCESSOR_INTEL_PENTIUM:INTEL PENTIUM系列;
PROCESSOR_MIPS_R4000:MIPS的4000系列(僅適用於WINDOWS NT);
PROCESSOR_ALPHA_21064:ALPHA的21064系列(僅適用於WINDOWS NT);
另外,獲得CPU資訊調用API函數GetSystemInfo即可。
五、擷取記憶體資訊。
與擷取CPU一樣,系統依然採用了一個結構體來儲存記憶體資訊。這個儲存內在狀態資訊的體定義下如:
typedef struct_MEMORYSTATUS{
DWORD dwLength; //SIZEOF(MEMORYSTATUS)即本結構體的大小
DWORD dwMemoryLoad; //當前使用記憶體與總內在的百分比
DWORD dwTotalPhys; //總實體記憶體大小
DWORD dwAvailPhys; //可用實體記憶體大小
DWORD dwTotalPageFile; //總分頁檔的大小
DWORD dwAvailPageFile; //可用分頁檔的大小
DWORD dwTotalVirtual; //總虛擬記憶體的大小
DWORD dwAvailVirtual; //可用虛擬記憶體的大小
}MEMORYSTATUS,*LPMEMORYSTATUS;
最後調用API函數GlobalMemoryStatus來擷取記憶體資訊。
六、擷取磁碟空間大小。 (測試發現不準)
使用API函數GetDiskFreeSpace。
BOOL GetDiskFreeSpace(
LPCTSTR lpRootPathName, //根目錄
LPDWORD lpSectorsPerCluster, //每簇的扇區數
LPDWORD lpBytesPerSector, //每個扇區的位元組數
LPDWORD lpNumberOfFreeClusters, //可用的簇數
LPDWORD lpTotalNumberOfClusters //總簇數
);
procedure TForm1.BitBtn1Click(Sender: TObject);
var
Secspclu,Bytespsec,Freeclu,Totalclu,Ts,Fs:DWORD;
begin
GetDiskFreeSpace('c:/',Secspclu,Bytespsec,Freeclu,Totalclu);
Fs:=Freeclu*Secspclu*Bytespsec;
Ts:=Totalclu*Secspclu*Bytespsec;
Edit1.text:=FormatFloat('###,###',Ts); //總空間
Edit2.text:=FormatFloat('###,###',Fs); //可用空間
end;
七、限制滑鼠移動範圍。
WINDOWS裡有一個現成的API函數ClipCursor可以限制游標移動地區。
BOOL ClipCursor(
CONST RECT *lpRect //指向一個儲存矩形範圍資料的結構體
);
有了這個函數就可以限制游標在螢幕的移動範圍了。但是,如果想控制滑鼠在某視窗的固定範圍內移動,則需要調用
咖一個函數MapWindowPoints,它可以將一個表單的座標轉化為另一個相關的表單座標。
int MapWindowPoints(
HWND hWndFrom, //源視窗控制代碼
HWND hWndTo, //目標表單控制代碼
LPPOINT lpPoints, //指向結構體數組,包含需要轉化的座標
UINT cPoints //數組中結構體的數量
);
參數hWndForm或hWndTo為NULL或HWND_DESKTOP時,表明所源表單或目標表單為螢幕表單。參數lpPoints可以指向一個
Rect結構體,此時cPoints的值將設為2。
procedure TForm1.BitBtn1Click(Sender: TObject);
var
sc:TRect;
begin
sc:=BitBtn2.BoundsRect;
MapWindowPoints(handle,0,sc,2);
ClipCursor(@sc);
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
var
sc:TRect;
begin
sc:=RECT(0,0,screen.Width,screen.Height);
ClipCursor(@sc);
end;
八、如何啟動螢幕保護裝置程式。
使用SendMessage或PostMessage函數。
procedure TForm1.BitBtn3Click(Sender: TObject);
begin
sendmessage(HWND_BROADCAST,WM_SYSCOMMAND,SC_SCREENSAVE,0);
end;
啟動螢幕保護裝置程式還有一個方法,調用函數SystemParametersInfo,能過其參數設定可以啟動或關閉螢幕保護裝置程式。
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,1,nil,0); //啟動屏保
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,0,nil,0); //關閉屏保
九、檢測磁碟機是否準備就緒。
在DELPHI中沒有提供專門的函數檢測磁碟機是否準備就緒,也不能直接調用一人API函數來實現這一操作。但是,我
們可以利用DiskSize來檢測磁碟容量,如果磁碟機不存在或沒有準備好,它會返回-1,其它情況下則返回該磁碟或光
盤的容量。
Function DiskSize(Drive:Byte):Int64;
參數為0時,表示指定當前磁碟機;為1時表示A盤,2表示B盤,依此類推。
十、隱藏滑鼠。
利用ShowCursor函數。
int ShowCursor(
BOOL bShow //游標是否可見的標誌
);
參數bShow為FALSE時表示游標不可見。注意,調用此函數僅僅隱藏了滑鼠,程式還是可以檢測到並激發滑鼠的單擊或
移動等事件的。
十一、串口操作。
在DELPHI中沒有提供專門的串口操作控制項,協助檔案裡介紹串口的資料也是廖廖無幾的。但是,我們可以通過調用一
系列的API來操作串口,spcomm串口操作控制項也是通過調用一系列API工作的。
開啟串口用API函數CreateFile,該函數可開啟、建立檔案或開啟裝置,其原形如下:
CreateFile(
lpFileName:PChar; //為檔案名稱或裝置名稱,串口用COM1,COM2表示。
dwDesiredAccess:DWORD; //訪問類型,Generic_Read為唯讀訪問,Generic_Write為寫訪問。Generic_Read or
Generic_Write為讀寫訪問。
dwShareMode:DWORD; //指定該檔案的共用屬性,該參數是為有許多應用程式共用的檔案提供的,串口不能共用,
必須設定為0。
lpSecurityAttributes:PSecurityAttributes; //引用安全性屬性SECURITY_ATTRIBUTES結構,該結構定義了一些
屬性,例如通訊控制代碼如何被 開啟連接埠的應用程式的子程式所繼承。設定為NULL將為該連接埠分配預設的安全性屬性。
dwCreationDisposition:DWORD; //指定如果CreateFile正在被已有的檔案調用時應做些什麼,串口是實物,必須
設定成OPEN_Existing,該標誌告訴WINDOWS不要建立新連接埠,而是開啟已存在的連接埠。
dwFlagsAndAttributes:DWORD; //描述了該連接埠的各種屬性。對串口來說,唯一有意義的設定是
File_Flag_Overlapped。
hTemplateFile:THandle //是指向檔案的控制代碼。串口沒有模板檔案,因而設定該參數為0。
):THANDLE;stdcall;
關閉串口使用API函數CloseHandle:CloseHandle(hObject:THandle):BOOL;stdccall; 控制代碼是CREATEFILE開啟串口時
返回的控制代碼。
初始化串口使用API函數SetupComm:SetupComm(hFile:Thandle; dwInQueue,dwOutQueue:DWORD):BOOL;stdcall;
dwInQueue,dwOutQueue分別定義接收緩衝區和發送緩衝區的大小(只是推薦的,實際大小由WINDOWS分配);
擷取串口當前配置:GetCommState(hFile:Thandle; varlpDCB:TDCB):BOOL;Stdcall; 調用成功返回非0值,
GetLastError函數可擷取錯誤資訊
。
配置串口:SetCommState(hFile:Thandle; const lpDCB:TDCB):BOOL;Stdcall;
擷取串口效能:GetCommProperties(hFile:Thandle; var lpCommProp:TCommProp):bool;stdcall;
通訊裝置配置:CommConfigDialog(lpszName:PChar;hWnd:HWND; var lpCC:TCommConfig);調用該函數將彈出一個配
置視窗
讀串口操作:ReadFile(hFile:THandle; var Buffer; nNumberOfBytesToRead:DWORD; var
lpNumberOfBytesRead:DWORD; lpOverlapped:POverlapped):BOOL;Stdcall;支援同步或非同步作業。
十二、列舉進程。
引用Tlhelp32單元。
利用API函數CreateToolhelp32Snapshot建立一個系統進程快照,用Process32First得到第一個系統進程,再用
Process32Next向後列舉。
procedure TForm1.BitBtn13Click(Sender: TObject); //進程操作
var
ProName:string; //進程名
ProID:integer; //進程ID號
ProTheard:integer; //進程線程數
goloop:boolean;
FSnapshothandle:Thandle; //系統進程快照控制代碼
FProcessEntry32:TProcessEntry32;//進程入口的結構資訊
begin
FSnapshothandle:=CreateToolHelp32Snapshot(TH32CS_SnapProcess,0); //建立一個系統進程快照
FProcessEntry32.dwSize:=sizeof(FProcessEntry32);
goloop:=Process32First(FSnapshothandle,FProcessEntry32); //得到第一個進程
while goloop do
begin
ProName:=FProcessEntry32.szExeFile;
ProID:=FProcessEntry32.th32ProcessID;
ProTheard:=FProcessEntry32.cntThreads;
ListBox1.Items.Add(ProName+' '+Inttostr(ProID)+' '+inttostr(ProTheard)); //進程全顯示在LISTBOX組
件裡
goloop:=Process32Next(FSnapshothandle,FProcessEntry32);
end;
十三、以其它身份運行程式(RUNAS)。
使用API函數CreateProcessWithLogonW。該函數在DELPHI並沒封裝完整,使用前需對其作出聲明與定義。
聲明:
function CreateProcessWithLogon(
lpUsername: PWChar; // 使用者乙的帳號(Account)
lpDomain: PWChar; //使用者乙的域(Domain)
lpPassword: PWChar; // 使用者乙的密碼(Password)
dwLogonFlags: DWORD; // logon option
lpApplicationName: PWChar; // 需要啟動並執行程式
lpCommandLine: PWChar; // command-line string
dwCreationFlags: DWORD; // creation flags
lpEnvironment: Pointer; // new environment block
lpCurrentDirectory: PWChar; // current directory name
const lpStartupInfo: TStartupInfo; // startup information
var lpProcessInfo: TProcessInformation // process information
): BOOL; stdcall;
定義:
function CreateProcessWithLogon; external advapi32 name 'CreateProcessWithLogonW';
十四、擷取當前登入使用者名稱。
使用API函數GetUserName.
procedure TForm1.XP_Button2Click(Sender: TObject); //擷取當前登入使用者名稱
var
users:array[0..255] of char;//使用者名稱
i:Dword; //緩衝區大小
begin
if GetUserName(users,i) then
Edit6.Text:=users;
end;
十五、修改檔案建立時間、修改時間和最後訪問時間。
利用API函數SetFileTime可直接修改檔案的建立時間、修改時間及最後訪問時間。而API函數GetFileTime則可以讀出
檔案的建立時間、修改時間及最後訪問時間。
這兩個函數原形如下:
function SetFileTime(
hFile: THandle; //檔案控制代碼,可由createFile函數開啟檔案獲得
lpCreationTime, //檔案建立時間
lpLastAccessTime, //最後訪問時間
lpLastWriteTime: PFileTime //最後修改時間
): BOOL;
function GetFileTime(
hFile: THandle; //檔案控制代碼,可由createFile函數開啟檔案獲得
lpCreationTime, //檔案建立時間
lpLastAccessTime, //最後訪問時間
lpLastWriteTime: PFileTime //最後修改時間
): BOOL;
//////////////////////////////////////////////////////////////////////
hFileOld :=createFile(srcFile,generic_read,file_share_read,nil,
open_existing,FILE_ATTRIBUTE_NORMAL,Cardinal(nil));
hFileNew :=createFile(destFile,generic_write,file_share_write,nil,
open_existing,FILE_ATTRIBUTE_NORMAL,Cardinal(nil));
GetMem(CreationTime,SizeOf(TFileTime));
GetMem(LastAccessTime,SizeOf(TFileTime));
GetMem(LastWriteTime,SizeOf(TFileTime));
GetFileTime(hFileOld,CreationTime,LastAccessTime,LastWriteTime);
SetFileTime(hFileNew,CreationTime,LastAccessTime,LastWriteTime);
十六、在系統托盤添加表徵圖。
在系統托盤區添加一個表徵圖可以通過發訊息的發送來實現。WINDOWS中有這樣一個API函數Shell_NotifyIcon可以用來
向托盤發送訊息。
WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(
DWORD dwMessage, //發送的訊息
PNOTIFYICONDATA pnid //指向結構體NOTIFYICONDATA
);
它發送的訊息參數如下:
NIM_ADD //向托盤中添加一個表徵圖
NIM_DELETE //刪除托盤中的某個表徵圖
NIM_MODIFY //修改托盤中的某個表徵圖
另一參數為指向結構體NOTIFYICONDATA的指標,結構體NOTIFYICONDATA則是用來儲存系統任務狀態列資訊的。
typedef struct_NOTIFYICONDATA{
DWORD cbSize; //結構體NOTIFYICONDATA的大小
HWND hWnd; //接收托盤滑鼠事件的視窗控制代碼
UINT uID; //表徵圖的ID(托盤滑鼠事件的wParam參數)
UINT uFlags; //訊息的有效範圍
UINT uCallbackMessage; //系統回送訊息的ID
HICON HIcon; //顯示在托盤中的表徵圖的控制代碼
char szTip[64]; //滑鼠移動到表徵圖上時的提示資訊
}NOTIFYICONDATA,*PNOTIFYICONDATA;
注意:在安裝表徵圖時需要對結構體NOTIFYICONDATA的每一個成員賦值,而更改或刪除時某些成員可不必賦值。
十七、使程式不在系統任務條上出現
procedure TForm1.FormCreate(Sender: TObject);
begin
SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
end;
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=493088