Delphi5學習筆記之五

uuxa發表於2007-05-05

153.使用函式GetWindowsDirectory時的常用方法:

var

Wdir: String;

Begin

SetLength(Wdir,144);

If GetWindowsDirectory(Pchar(Wdir),144) <> 0 then

SetLenth(Wdir,StrLen(Pchar(Wdir)))這裡要呼叫SetLength的目的:是因為在呼叫GetWindowsDirectory時傳遞給它的第一個引數是一個長字元型別的字串,在執行完GetWindowsDirectory後,Delphi不知道字串Wdir是否被修改,這樣就不能對字串進行及時的更新,所以這裡使用了SetLength手動設定一下字串,實現自動更新。

Else RaiseLastWin32Error;

End;

[@more@]

154.TSearchRec結構:

TSearchRecFindFirstFindNext函式的返回值型別,它定義如下:

TSearchRec = record

Time: Integer;//建立和修改檔案的時間

Size: Integer;//檔案大小(位元組數)

Attr: Integer;//檔案屬性(faOnlyRead,faHidden,faSysFile)

Name: TFileName;//檔名

ExcludeAttr: Integer;//FindFirstFindNext內部使用,不必關心

FindHandle: THandle; //FindFirstFindNext內部使用,不必關心

FindData: TWin32FindData;

End;

結構TWin32FindData包含了找到的檔案或子目錄的資訊,它的定義如下:

TWin32FindData = record

dwFileAttributes: DWORD;

ftCreationTime: TFileTime;

ftLastAccessTime: TFileTime;

ftLastWriteTime: TFileTime;

nFileSizeHigh: DWORD;

nFileSizeLow: DWORD;

dwReserved0: DWORD;//保留

dwReserved1: DWORD; //保留

cFileName: Array[0..MAX_PATH - 1] of AnsiChar;//null結尾的檔名

cAlternateFileName: Array[0..13] of AnsiChar;//8.3格式的檔名

End;

155.複製全目錄

Procedure CopyDirectoryTree(AHandle: THandle;const AFromDirectory,AToDirectory: String);

Var

SHFileOpStruct: TSHFileOpStruct;

FromDir: PChar;

ToDir: PChar;

Begin

GetMem(FromDir,Length(AFromDirectory) + 2);

Try

GetMem(ToDir,Length(AToDirectory) + 2);

try

FillChar(FromDir^,Length(AFromDirectory) + 2);

FillChar(ToDir^,Length(AToDirectory) + 2);

StrCopy(FromDir,PChar(AFromDirectory));

StrCopy(ToDir,PChar(AToDirectory));

With SHFileOpStruct do

Begin

Wnd := AHandle;

wFunc := FO_COPY;

pFrom := FromDir;

pTo := ToDir;

fFlags := FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION;

fAnyOperationsAborted := False;

hNameMappings := nil;

lpszProgressTitle := nil;

if SHFileOperation(SHFileOpStruct) <> 0 then

RaiseLastWin32Error;

End;

Finally

FreeMem(ToDir,Length(AToDirectory) + 2);

End;

Finally

FreeMem(FromDir,Length(AFromDirectory) + 2);

End;

End;

CopyDirectoryTree引數說明:

AHandle:是一個用來顯示源目錄和目標目錄的對話方塊的控制程式碼。

另外兩個引數是源目錄和目標目錄。

156.將檔案或目錄刪除到回收站

Procedure ToRecycle(AHandle: THandle;const ADirName: String);

Var

SHFileOpStruct: TSHFileOpStruct;

DirName: PChar;

BufferSize: Cardinal;

Begin

BufferSize := Length(ADirName) + 2;

GetMem(DirName,BufferSize);

Try

FillChar(DirName^,BufferSize,0);

StrCopy(DirName,PChar(ADirName));

With SHFileOpStruct do

Begin

Wnd := AHandle;

wFunc := FO_DELETE;

pFrom := DirName;

pTo := nil;

fFlags := FOF_ALLOWUNDO;

fAnyOperationsAborted := False;

hNameMappings := nil;

lpszProgressTitle := nil;

End;

If SHFileOperation(SHFileOpStruct) <> 0 then

RaiseLastWin32Error;

Finally

FreeMem(DirName,BufferSize);

End;

End;

過程ToRecycle中的wFunc成員為FO_DELETEpTo成員為nil。如果將FOF_ALLOWUNDO 標誌加入f Flags成員,函式將取消將檔案放入回收站的操作。

157.高階訊息處理

視窗過程是一種函式,當一個視窗收到訊息時由Windows來呼叫它。在每個應用程式物件中都包含一個視窗過程,應用程式物件利用它來接收所有被髮送到應用程式的訊息。

TApplication類利用OnMessage ()事件通知訊息的到來。TApplication.OnMessage只在應用程式的訊息佇列接收到一個訊息時才被觸發。一般應用程式接收到的訊息是與視窗管理有關的訊息 (例如WM_PAINTWM_SIZE) ,或由PostMessage()PostAppMessage()BroadcastSy stemMessage()API函式傳送出的訊息。但是,由於WindowsSendMessage()有可能會繞過訊息佇列直接將訊息傳送給視窗過程。當發生這種情況時,TApplication.OnMessage就不會被觸發。

1.子類化視窗(也就是“擷取應用程式窗體訊息”)

為了知道什麼時候一個訊息被髮送到應用程式,必須用自己的視窗過程代替Application的視窗過程。當在自己的視窗過程中對訊息處理完後,要把訊息再傳遞給原視窗過程。這樣的過程就叫做子類化視窗

可以傳遞一個常量GWL_WNDPROCWin32API函式SetWindowLong()來指定一個新的視窗過程。

視窗過程可以是以下兩種格式:

一是利用A P I定義;

二是利用D e l p h i使視窗方法作為視窗過程。

1. 一個Win32 API的視窗過程

一個A P I的視窗過程必須像這樣宣告:

Function AWndProc(AHandle: hWnd;Msg,wParam,lParam: Longint): Longint;stdcall;

宣告中,Handle引數用於標識目標視窗;Msg是一個訊息;wParamlpParam引數含有訊息的附加資訊。函式的返回值要依靠收到的訊息確定。需要特別注意,此函式必須用stdcall作為呼叫約定。

可以這樣使用SetWindowLong()函式給應用程式的視窗指定視窗過程:

Var

WProc: Pointer;

Begin

WProc := Pointer(SetWindowLong(Application.Handle,GWL_WNDPROC,Integer(@NewWndProc)));

End;

在此呼叫後,返回一個指標型別的WProc指向舊的視窗過程。對這個值的保留是很必要的,因為有些訊息可能需要傳遞給舊的視窗過程。下面是一個視窗過程的實現示例:

Function NewWndProc(AHandle: hWnd;Msg,wParam,lParam: Longint): Longint; stdcall;

Begin

Result := CallWindowProc(WProc,Application.Handle,Msg,wParam,lParam);

End;

一定要把SetWindowLong()函式值儲存起來。如果你在自定義的視窗過程中不把該值返還給舊視窗過程,有可能導致應用程式甚至作業系統的崩潰。

下面是具體使用示例:

unit ScWndPrc;

interface

uses Forms,Messages;

Const

DDGM_FOOMGM = WM_USER;

implementation

uses Windows,SysUtils,Dialogs;

var

WProc: Pointer;

function NewWndProc(AHandle: hWnd;Msg,wParam,lParam: Longint): Longint; stdcall;

begin

if Msg = DDGM_FOOMGM then

ShowMessage(Format('Message seen by WndProc! Value is: $%x',[Msg]));

Result := CallWindowProc(WProc,AHandle,Msg,wParam,lParam);

end;

initialization

WProc := Pointer(SetWindowLong(Application.Handle,

GWL_WNDPROC,Integer(@NewWndProc)));

end.

2). Delphi的視窗方法 此方法不好,暫不記錄。

2.HookMainWindow

使用TApplicationHookMainWindow()方法也可以擷取窗體訊息。這種方法可以把一個自定義的方法放到TApplicationWndProc前面執行。

HookMainWindow的宣告:

Procedure HookMainWindow(Hook: TWinowHook);

其中的引數Hook的型別TWindowHook是一個方法,它是如下宣告的,

Type

TWindowHook = function (var Message: TMessage): Boolean of Object;

如果此方法返回True,表示訊息已經處理,WndProc會立即返回。

在處理訊息時,可以使用UnHookMainWindow,它的宣告如下,

Procedure UnHookMainWindow(Hook: TWindowHook);

下面是一個小小例子:

unit MainFrm;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

THookForm = class(TForm)

cbDoLog: TCheckBox;

lstBoxLog: TListBox;

btnSend: TButton;

btnClose: TButton;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure btnCloseClick(Sender: TObject);

procedure btnSendClick(Sender: TObject);

private

{ Private declarations }

function AppWindowHook(var Message: TMessage): Boolean;

public

{ Public declarations }

end;

var

HookForm: THookForm;

implementation

{$R *.dfm}

function THookForm.AppWindowHook(var Message: TMessage): Boolean;

const

LogStr = 'Message ID: $%x,wParam: $%x,lParam: $%x';

begin

Result := true;

if cbDoLog.Checked then

with Message do

begin

lstBoxLog.Items.Add(Format(LogStr,[Msg,wParam,lParam]));

end;

end;

procedure THookForm.FormCreate(Sender: TObject);

begin

Application.HookMainWindow(AppWindowHook);

end;

procedure THookForm.FormDestroy(Sender: TObject);

begin

Application.UnhookMainWindow(AppWindowHook);

end;

procedure THookForm.btnCloseClick(Sender: TObject);

begin

Close;

end;

procedure THookForm.btnSendClick(Sender: TObject);

begin

SendMessage(Application.Handle,WM_CLOSE,0,0);

end;

end.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7416120/viewspace-913387/,如需轉載,請註明出處,否則將追究法律責任。

相關文章