BSOne.SFC/Tocsg.Module/WndMsgHook/EXE_WndMsgHook/DMainHook.pas

656 lines
19 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

unit DMainHook;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, CtrlWndActiveHook, Vcl.StdCtrls,
Vcl.Menus, VirtualTrees, Vcl.ExtCtrls, Vcl.ImgList;
type
PProcessWndEntry = ^TProcessWndEntry;
TProcessWndEntry = record
pNode: PVirtualNode;
WindowEntry: TWindowEntry;
nIcon: Integer;
end;
TDlgMainHook = class(TForm)
Memo1: TMemo;
mmMain: TMainMenu;
miFile: TMenuItem;
miExit: TMenuItem;
pnMain: TPanel;
vtWindowEntry: TVirtualStringTree;
Splitter1: TSplitter;
Splitter2: TSplitter;
vtLogEntry: TVirtualStringTree;
lstState: TImageList;
miDebug: TMenuItem;
miReloadDLL: TMenuItem;
miRemoveHook: TMenuItem;
procedure miExitClick(Sender: TObject);
procedure vtWindowEntryGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
procedure vtWindowEntryGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
procedure vtWindowEntryFocusChanged(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex);
procedure vtLogEntryGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
procedure vtLogEntryGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
procedure vtLogEntryFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure vtWindowEntryPaintText(Sender: TBaseVirtualTree;
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType);
procedure vtWindowEntryCompareNodes(Sender: TBaseVirtualTree; Node1,
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
procedure vtLogEntryHeaderClick(Sender: TVTHeader;
HitInfo: TVTHeaderHitInfo);
procedure vtWindowEntryHeaderClick(Sender: TVTHeader;
HitInfo: TVTHeaderHitInfo);
procedure vtLogEntryCompareNodes(Sender: TBaseVirtualTree; Node1,
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
procedure vtWindowEntryGetImageIndexEx(Sender: TBaseVirtualTree;
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
var Ghosted: Boolean; var ImageIndex: Integer;
var ImageList: TCustomImageList);
procedure vtLogEntryGetImageIndexEx(Sender: TBaseVirtualTree;
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
var Ghosted: Boolean; var ImageIndex: Integer;
var ImageList: TCustomImageList);
procedure miReloadDLLClick(Sender: TObject);
procedure miRemoveHookClick(Sender: TObject);
private
{ Private declarations }
WndHook_: TCtrlWndActiveHook;
lstShellImg_: TImageList;
CurrentViewEntry_: TWindowEntry;
RootNodeCreate_,
RootNodeDestroy_: PVirtualNode;
public
{ Public declarations }
Constructor Create(aOwner: TComponent); override;
Destructor Destroy; override;
procedure AddWindowLog(pLog: PWindowLogEntry);
procedure OutLog(const sLog: String); overload;
procedure OutLog(const Format: string; const Args: array of const); overload;
procedure AddWindowEntry(aEntry: TWindowEntry; bDestroy: Boolean = false);
procedure DeleteWindowEntry(aEntry: TWindowEntry);
procedure OnActiveWindow(Sender: TCtrlWndActiveHook; aWindowEntry: TWindowEntry);
procedure OnDeActiveWindow(Sender: TCtrlWndActiveHook; aWindowEntry: TWindowEntry);
procedure process_WM_WNDHOOK_RELOAD(var msg: TMessage); Message WM_WNDHOOK_RELOAD;
procedure process_WM_WNDHOOK_NOTIFY(var msg: TMessage); Message WM_WNDHOOK_NOTIFY;
end;
var
DlgMainHook: TDlgMainHook;
implementation
uses
Sunk.Shell, System.DateUtils, Sunk.DateTime, Sunk.Debug, Sunk.Process;
{$R *.dfm}
Constructor TDlgMainHook.Create(aOwner: TComponent);
procedure InitRootNode;
var
pData: PProcessWndEntry;
begin
RootNodeCreate_ := vtWindowEntry.AddChild(nil);
Include(RootNodeCreate_.States, vsInitialized);
Include(RootNodeCreate_.States, vsExpanded);
pData := vtWindowEntry.GetNodeData(RootNodeCreate_);
pData.nIcon := -1;
RootNodeDestroy_ := vtWindowEntry.AddChild(nil);
Include(RootNodeDestroy_.States, vsInitialized);
Include(RootNodeDestroy_.States, vsExpanded);
pData := vtWindowEntry.GetNodeData(RootNodeDestroy_);
pData.nIcon := -2;
end;
begin
Inherited Create(aOwner);
WndHook_ := TCtrlWndActiveHook.Create(Handle, true);
WndHook_.OnActive := OnActiveWindow;
WndHook_.OnDeActive := OnDeActiveWindow;
lstShellImg_ := TImageList.Create(self);
lstShellImg_.Handle := GetShellImageHandle;
lstShellImg_.ShareImages := true;
vtWindowEntry.Images := lstShellImg_;
vtLogEntry.Images := lstShellImg_;
CurrentViewEntry_ := nil;
InitRootNode;
end;
Destructor TDlgMainHook.Destroy;
begin
FreeAndNil(lstShellImg_);
FreeAndNil(WndHook_);
Inherited;
end;
procedure TDlgMainHook.AddWindowLog(pLog: PWindowLogEntry);
var
pNode: PVirtualNode;
pData: PWindowLogEntry;
begin
if CurrentViewEntry_ = pLog.OwnerWindow then
begin
pNode := vtLogEntry.AddChild(nil);
Include(pNode.States, vsInitialized);
pData := vtLogEntry.GetNodeData(pNode);
pData^ := pLog^;
end;
end;
procedure TDlgMainHook.miExitClick(Sender: TObject);
begin
Close;
end;
procedure TDlgMainHook.miReloadDLLClick(Sender: TObject);
begin
ShowMessage('<27><><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD>');
// WndHook_.LoadHookDll(Handle);
end;
procedure TDlgMainHook.miRemoveHookClick(Sender: TObject);
begin
WndHook_.UnHookDll;
end;
procedure TDlgMainHook.OutLog(const sLog: String);
begin
Memo1.Lines.Add(Format('[%s] %s', [DateTimeToStr(now), sLog]));
end;
procedure TDlgMainHook.OutLog(const Format: string; const Args: array of const);
var
str: String;
begin
FmtStr(str, Format, Args);
OutLog(str);
// test
vtWindowEntry.Repaint;
end;
procedure TDlgMainHook.AddWindowEntry(aEntry: TWindowEntry; bDestroy: Boolean = false);
var
pNode: PVirtualNode;
pData: PProcessWndEntry;
begin
if Assigned(aEntry) then
begin
if bDestroy then
pNode := vtWindowEntry.AddChild(RootNodeDestroy_)
else
pNode := vtWindowEntry.AddChild(RootNodeCreate_);
Include(pNode.States, vsInitialized);
pData := vtWindowEntry.GetNodeData(pNode);
pData.WindowEntry := aEntry;
pData.nIcon := GetShellImageIndex(aEntry.ModulePath);
end;
end;
procedure TDlgMainHook.DeleteWindowEntry(aEntry: TWindowEntry);
var
pNode: PVirtualNode;
pData: PProcessWndEntry;
begin
pNode := vtWindowEntry.GetFirst;
while pNode <> nil do
begin
pData := vtWindowEntry.GetNodeData(pNode);
if pData.WindowEntry = aEntry then
begin
vtWindowEntry.DeleteNode(pNode);
exit;
end;
pNode := vtWindowEntry.GetNext(pNode);
end;
end;
procedure TDlgMainHook.OnActiveWindow(Sender: TCtrlWndActiveHook; aWindowEntry: TWindowEntry);
begin
OutLog('(%s:%d) <20><><EFBFBD>α׷<CEB1> Ȱ<><C8B0>ȭ', [aWindowEntry.ModuleName, aWindowEntry.PID]);
vtWindowEntry.Repaint;
end;
procedure TDlgMainHook.OnDeActiveWindow(Sender: TCtrlWndActiveHook; aWindowEntry: TWindowEntry);
begin
OutLog('(%s:%d) <20><><EFBFBD>α׷<CEB1> <20><>Ȱ<EFBFBD><C8B0>ȭ (<28><> Ȱ<><C8B0>ȭ <20>ð<EFBFBD> = %d)',
[aWindowEntry.ModuleName, aWindowEntry.PID, aWindowEntry.ActiveSec]);
vtWindowEntry.Repaint;
end;
procedure TDlgMainHook.vtLogEntryCompareNodes(Sender: TBaseVirtualTree; Node1,
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var
pData1, pData2: PWindowLogEntry;
begin
pData1 := Sender.GetNodeData(Node1);
pData2 := Sender.GetNodeData(Node2);
case Column of
1 : Result := Integer(pData1.WindowLogState) - Integer(pData2.WindowLogState);
2 : Result := CompareDateTime(pData1.dtLog, pData2.dtLog);
3 : Result := CompareStr(pData1.OwnerWindow.ModuleName, pData2.OwnerWindow.ModuleName);
4 : Result := CompareText(pData1.sTitle, pData2.sTitle);
end;
end;
procedure TDlgMainHook.vtLogEntryFreeNode(Sender: TBaseVirtualTree;
Node: PVirtualNode);
var
pData: PWindowLogEntry;
begin
pData := Sender.GetNodeData(Node);
Finalize(pData^);
end;
procedure TDlgMainHook.vtLogEntryGetImageIndexEx(Sender: TBaseVirtualTree;
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
var Ghosted: Boolean; var ImageIndex: Integer;
var ImageList: TCustomImageList);
var
pData: PWindowLogEntry;
begin
pData := Sender.GetNodeData(Node);
case Kind of
ikNormal,
ikSelected:
case Column of
1 :
begin
ImageList := lstState;
ImageIndex := Integer(pData.WindowLogState);
end;
3 :
begin
ImageList := lstShellImg_;
ImageIndex := GetShellImageIndex(pData.OwnerWindow.ModulePath);
end;
end;
end;
end;
procedure TDlgMainHook.vtLogEntryGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
begin
NodeDataSize := SizeOf(TWindowLogEntry);
end;
procedure TDlgMainHook.vtLogEntryGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: string);
var
pData: PWindowLogEntry;
begin
pData := Sender.GetNodeData(Node);
case Column of
0 : CellText := IntToStr(Node.Index + 1);
1 :
case pData.WindowLogState of
wlUnknown : CellText := '<27>˼<EFBFBD><CBBC><EFBFBD><EFBFBD><EFBFBD>';
wlCreate : CellText := '<27><><EFBFBD><EFBFBD>';
wlDestroy : CellText := '<27>ݱ<EFBFBD>';
wlActive : CellText := 'Ȱ<><C8B0>';
wlMin : CellText := '<27>ּ<EFBFBD>ȭ';
wlMax : CellText := '<27>ִ<EFBFBD>ȭ';
wlRestore : CellText := '<27><><EFBFBD><EFBFBD>';
wlMoveSize : CellText := '<27>̵<EFBFBD><><C5A9>';
wlRedrawTitle : CellText := '<27><><EFBFBD>񺯰<EFBFBD>';
wlAttach : ;
wlDetach : CellText := '<27><><EFBFBD><EFBFBD>';
end;
2 : CellText := DateTimeToStr(pData.dtLog);
3 : CellText := pData.OwnerWindow.ModuleName;
4 : CellText := pData.sTitle;
5 : CellText := pData.sSubTitle;
end;
end;
procedure TDlgMainHook.vtLogEntryHeaderClick(Sender: TVTHeader;
HitInfo: TVTHeaderHitInfo);
begin
if HitInfo.Button = mbLeft then
begin
with Sender, Treeview, HitInfo do
begin
if HitInfo.Column < 0 then
exit;
if SortColumn > NoColumn then
Columns[SortColumn].Options := Columns[SortColumn].Options + [coParentColor];
if HitInfo.Column = 0 then
SortColumn := NoColumn
else begin
if (SortColumn = NoColumn) or (SortColumn <> Column) then
begin
SortColumn := Column;
SortDirection := sdAscending;
end else
if SortDirection = sdAscending then
SortDirection := sdDescending
else
SortDirection := sdAscending;
Columns[SortColumn].Color := $00F7F0F0;
vtLogEntry.BeginUpdate;
try
SortTree(SortColumn, SortDirection, False);
finally
vtLogEntry.EndUpdate;
end;
end;
end;
end;
end;
procedure TDlgMainHook.vtWindowEntryCompareNodes(Sender: TBaseVirtualTree;
Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var
pEntry1, pEntry2: PProcessWndEntry;
begin
pEntry1 := Sender.GetNodeData(Node1);
pEntry2 := Sender.GetNodeData(Node2);
if Assigned(pEntry1.WindowEntry) and Assigned(pEntry2.WindowEntry) then
case Column of
0 : Result := CompareText(pEntry1.WindowEntry.ModuleName, pEntry2.WindowEntry.ModuleName);
1 : Result := CompareDateTime(pEntry1.WindowEntry.CreateDateTime, pEntry2.WindowEntry.CreateDateTime);
2 : Result := CompareDateTime(pEntry1.WindowEntry.DestroyDateTime, pEntry2.WindowEntry.DestroyDateTime);
end;
end;
procedure TDlgMainHook.vtWindowEntryFocusChanged(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex);
procedure ClearSortHighlight;
begin
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̶<EFBFBD><CCB6><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>
with vtLogEntry.Header do
begin
if SortColumn <> -1 then
begin
Columns[SortColumn].Options := Columns[SortColumn].Options + [coParentColor];
SortColumn := -1;
end;
end;
end;
procedure FillLog(pNode: PVirtualNode);
var
i: Integer;
pEntry: PProcessWndEntry;
begin
pEntry := Sender.GetNodeData(pNode);
CurrentViewEntry_ := pEntry.WindowEntry;
vtLogEntry.BeginUpdate;
try
for i := 0 to pEntry.WindowEntry.CountLog - 1 do
AddWindowLog(pEntry.WindowEntry[i]);
finally
vtLogEntry.EndUpdate;
end;
end;
var
pNode: PVirtualNode;
begin
ClearSortHighlight;
vtLogEntry.Clear;
if not Assigned(Node) then
exit;
if (RootNodeCreate_ = Node) or (RootNodeDestroy_ = Node) then
begin
pNode := Node.FirstChild;
while pNode <> nil do
begin
FillLog(pNode);
pNode := pNode.NextSibling;
end;
vtLogEntry.Sort(vtLogEntry.RootNode, 2, sdAscending);
end else
FillLog(Node);
end;
procedure TDlgMainHook.vtWindowEntryGetImageIndexEx(Sender: TBaseVirtualTree;
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
var Ghosted: Boolean; var ImageIndex: Integer;
var ImageList: TCustomImageList);
var
pData: PProcessWndEntry;
begin
pData := Sender.GetNodeData(Node);
case Kind of
ikNormal,
ikSelected:
case Column of
0 :
if pData.nIcon < 0 then
begin
ImageList := lstState;
case pData.nIcon of
-1 : ImageIndex := 9;
-2 : ImageIndex := 10;
end;
end else begin
ImageList := lstShellImg_;
ImageIndex := pData.nIcon;
end;
end;
end;
end;
procedure TDlgMainHook.vtWindowEntryGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
begin
NodeDataSize := SizeOf(TProcessWndEntry);
end;
procedure TDlgMainHook.vtWindowEntryGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: string);
var
pData: PProcessWndEntry;
begin
pData := Sender.GetNodeData(Node);
if pData.WindowEntry = nil then
begin
case Column of
0 :
if Node = RootNodeCreate_ then
CellText := '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD>'
else
if Node = RootNodeDestroy_ then
CellText := '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD>';
end;
end else
case Column of
0 : CellText := Format('%s (%d)', [pData.WindowEntry.Description, pData.WindowEntry.CountLog]);
1 : CellText := GetTicktocktime(pData.WindowEntry.ActiveSec);
2 : CellText := GetTicktocktime(pData.WindowEntry.IdleSec);
3 :
if Node.Parent = RootNodeCreate_ then
CellText := Format('%s:%d', [pData.WindowEntry.ModuleName,
pData.WindowEntry.PID])
else
CellText := Format('%s', [pData.WindowEntry.ModuleName]);
4 : CellText := DateTimeToStr(pData.WindowEntry.CreateDateTime);
5 :
if pData.WindowEntry.DestroyDateTime = 0 then
CellText := '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..'
else
CellText := DateTimeToStr(pData.WindowEntry.DestroyDateTime);
end;
end;
procedure TDlgMainHook.vtWindowEntryHeaderClick(Sender: TVTHeader;
HitInfo: TVTHeaderHitInfo);
begin
exit;
if HitInfo.Button = mbLeft then
begin
with Sender, Treeview, HitInfo do
begin
if SortColumn > NoColumn then
Columns[SortColumn].Options := Columns[SortColumn].Options + [coParentColor];
if (SortColumn = NoColumn) or (SortColumn <> Column) then
begin
SortColumn := Column;
SortDirection := sdAscending;
end else
if SortDirection = sdAscending then
SortDirection := sdDescending
else
SortDirection := sdAscending;
Columns[SortColumn].Color := $00F7F0F0;
vtWindowEntry.BeginUpdate;
try
SortTree(SortColumn, SortDirection, False);
finally
vtWindowEntry.EndUpdate;
end;
end;
end;
end;
procedure TDlgMainHook.vtWindowEntryPaintText(Sender: TBaseVirtualTree;
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType);
var
pData: PProcessWndEntry;
begin
case Column of
0 :
begin
if (Node.Parent = RootNodeDestroy_) and not (vsSelected in Node.States) then
TargetCanvas.Font.Color := clGray;
pData := Sender.GetNodeData(Node);
if Assigned(pData.WindowEntry) and pData.WindowEntry.IsActive then
TargetCanvas.Font.Style := TargetCanvas.Font.Style + [fsBold]
else
TargetCanvas.Font.Style := TargetCanvas.Font.Style - [fsBold];
end;
end;
end;
procedure TDlgMainHook.process_WM_WNDHOOK_RELOAD(var msg: TMessage);
function CheckUnHook(dwPID: DWORD): Boolean;
var
dwTick: DWORD;
sOld, sCur: String;
begin
TSunkTrace.t('TDlgMainHook >> process_WM_WNDHOOK_RELOAD >> CheckUnHook()');
Result := true;
dwTick := GetTickCount;
while (GetTickCount - dwTick) < 1000 do
begin
sOld := GetProcessNameFromPID(dwPID);
Sleep(100);
sCur := GetProcessNameFromPID(dwPID);
if (sCur = '') or (sCur <> sOld) then
begin
Result := false;
exit;
end;
Application.ProcessMessages;
end;
end;
begin
// if Assigned(WndHook_) then
// begin
// TSunkTrace.t('TDlgMainHook >> process_WM_WNDHOOK_RELOAD >> PID = %d', [msg.WParam]);
// if CheckUnHook(msg.WParam) then
// begin
// TSunkTrace.t('TDlgMainHook >> process_WM_WNDHOOK_RELOAD >> CheckUnHook() >> UnHook!!!');
//// WndHook_.LoadHookDll(Handle);
// end;
// end;
end;
procedure TDlgMainHook.process_WM_WNDHOOK_NOTIFY(var msg: TMessage);
var
l: TWindowLogEntry;
e: TWindowEntry;
begin
if msg.WParamLo = WND_STATE_DETACH_HOOK then
begin
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> UI<55><49><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ư<><C6AF> <20><>Ȳ<EFBFBD>̴<EFBFBD>.
e := WndHook_[msg.WParamHi];
if Assigned(e) then
begin
l := e.AddWindowLog(msg.LParam, wlDetach);
if l.dtLog <> 0 then
AddWindowLog(@l);
OutLog('(%s:%d) <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD> <20><><EFBFBD><EFBFBD> (Begin = %s, End = %s)', [e.ModuleName, e.PID,
DateTimeToStr(e.CreateDateTime), DateTimeToStr(now)]);
DeleteWindowEntry(e);
end;
e := WndHook_.DeleteWindowEntry(msg.WParamHi);
if Assigned(e) then
AddWindowEntry(e, true);
exit;
end;
l := WndHook_.ProcessHookNotify(msg);
if l.dtLog <> 0 then
begin
AddWindowLog(@l);
case msg.WParamLo of
WND_STATE_ACTIVATE : OutLog('(%s:%d) Ȱ<><C8B0>ȭ - %s', [l.OwnerWindow.ModuleName, l.OwnerWindow.PID, l.sTitle]);
WND_STATE_WINDOW_MIN : OutLog('(%s:%d) <20>ּ<EFBFBD>ȭ - %s', [l.OwnerWindow.ModuleName, l.OwnerWindow.PID, l.sTitle]);
WND_STATE_WINDOW_MAX : OutLog('(%s:%d) <20>ִ<EFBFBD>ȭ - %s', [l.OwnerWindow.ModuleName, l.OwnerWindow.PID, l.sTitle]);
WND_STATE_WINDOW_MOVESIZE : OutLog('(%s:%d) <20>̵<EFBFBD> / ũ<><C5A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - %s', [l.OwnerWindow.ModuleName, l.OwnerWindow.PID, l.sTitle]);
WND_STATE_REDRAW_TITLE : OutLog('(%s:%d) ĸ<>Ǻ<EFBFBD><C7BA><EFBFBD> - %s', [l.OwnerWindow.ModuleName, l.OwnerWindow.PID, l.sTitle]);
WND_STATE_CREATE_MAIN : OutLog('(%s:%d) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> - %s', [l.OwnerWindow.ModuleName, l.OwnerWindow.PID, l.sTitle]);
WND_STATE_DESTROY_MAIN : OutLog('(%s:%d) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> - %s', [l.OwnerWindow.ModuleName, l.OwnerWindow.PID, l.sTitle]);
WND_STATE_WINDOW_NORMAL : OutLog('(%s:%d) <20>ּ<EFBFBD> / <20>ִ<EFBFBD>ȭ <20><><EFBFBD><EFBFBD> - %s', [l.OwnerWindow.ModuleName, l.OwnerWindow.PID, l.sTitle]);
end;
end else
if msg.WParamLo = WND_STATE_ATTACH_HOOK then
AddWindowEntry(WndHook_[msg.WParamHi]);
end;
end.