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;
154.TSearchRec结构:
TSearchRec是FindFirst和FindNext函数的返回值类型,它定义如下:
TSearchRec = record
Time: Integer;//创建和修改文件的时间
Size: Integer;//文件大小(字节数)
Attr: Integer;//文件属性(faOnlyRead,faHidden,faSysFile等)
Name: TFileName;//文件名
ExcludeAttr: Integer;//由FindFirst和FindNext内部使用,不必关心
FindHandle: THandle; //由FindFirst和FindNext内部使用,不必关心
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_DELETE,pTo成员为nil。如果将FOF_ALLOWUNDO 标志加入f Flags成员,函数将取消将文件放入回收站的操作。
157.高级消息处理
窗口过程是一种函数,当一个窗口收到消息时由Windows来调用它。在每个应用程序对象中都包含一个窗口过程,应用程序对象利用它来接收所有被发送到应用程序的消息。
TApplication类利用OnMessage ()事件通知消息的到来。TApplication.OnMessage只在应用程序的消息队列接收到一个消息时才被触发。一般应用程序接收到的消息是与窗口管理有关的消息 (例如WM_PAINT和WM_SIZE) ,或由PostMessage()、PostAppMessage()或BroadcastSy stemMessage()等API函数发送出的消息。但是,由于Windows或SendMessage()有可能会绕过消息队列直接将消息发送给窗口过程。当发生这种情况时,TApplication.OnMessage就不会被触发。
1.子类化窗口(也就是“截取应用程序窗体消息”)
为了知道什么时候一个消息被发送到应用程序,必须用自己的窗口过程代替Application的窗口过程。当在自己的窗口过程中对消息处理完后,要把消息再传递给原窗口过程。这样的过程就叫做子类化窗口。
可以传递一个常量GWL_WNDPROC给Win32API函数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是一个消息;wParam、lpParam参数含有消息的附加信息。函数的返回值要依靠收到的消息确定。需要特别注意,此函数必须用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
使用TApplication的HookMainWindow()方法也可以截取窗体消息。这种方法可以把一个自定义的方法放到TApplication的WndProc前面执行。
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