354 lines
9.7 KiB
Plaintext
354 lines
9.7 KiB
Plaintext
unit ManageWindowPage;
|
|
|
|
interface
|
|
|
|
uses
|
|
Tocsg.Obj, System.Classes, Winapi.Windows, Vcl.Forms, Vcl.ComCtrls,
|
|
System.Generics.Collections, System.SysUtils, Tocsg.Process, superobject,
|
|
Winapi.Messages;
|
|
|
|
const
|
|
DAT_WNDPAGES = 'WndPages.dat';
|
|
|
|
type
|
|
TWndTabSheet = class;
|
|
TWndFrame = class(TFrame)
|
|
protected
|
|
OwnerTabSheet_: TWndTabSheet;
|
|
public
|
|
Constructor Create(aOwner: TComponent); override;
|
|
property OwnerTabSheet: TWndTabSheet read OwnerTabSheet_;
|
|
end;
|
|
|
|
TWndFrameClass = class of TWndFrame;
|
|
|
|
TWndKind = (wkNormal);
|
|
PWndInfo = ^TWndInfo;
|
|
TWndInfo = record
|
|
WndKind: TWndKind;
|
|
ProcPath: String;
|
|
ProcID: NativeUInt;
|
|
WndHandle: HWND;
|
|
WndFrameClass: TWndFrameClass;
|
|
OrzWndRect: TRect; // 폼이 원상복구(폼이 포함되기 전) 될때의 위치/크기로 변하기 위해 사용 14_0421 22:21:37 sunk
|
|
OrzBorderStyle,
|
|
OrzBorderExStyle: NativeInt;
|
|
ProcInfo: TTgProcessInfo;
|
|
end;
|
|
|
|
TWndTabSheet = class(TTabSheet)
|
|
private
|
|
WndInfo_: TWndInfo;
|
|
WndFrame_: TWndFrame;
|
|
public
|
|
Constructor Create(aOwner: TComponent; aWndInfo: TWndInfo);
|
|
Destructor Destroy; override;
|
|
|
|
property WndInfo: TWndInfo read WndInfo_;
|
|
end;
|
|
|
|
TWndInfoEnumerator = TEnumerator<PWndInfo>;
|
|
|
|
TManagerWindowPage = class(TTgObject)
|
|
private
|
|
DcWndPages_: TDictionary<HWND,PWndInfo>;
|
|
// DcProcessTabSheet_: TDictionary<DWORD,TWndTabSheet>;
|
|
DcWndTabSheet_: TDictionary<HWND,TWndTabSheet>;
|
|
procedure OnWndPage(Sender: TObject; const Item: PWndInfo;
|
|
Action: TCollectionNotification);
|
|
|
|
procedure RemoveWndPage(WndHandle: HWND);
|
|
procedure SavePages;
|
|
procedure LoadPages;
|
|
|
|
// function GetWndTabSheetByPID(const dwPid: DWORD): TWndTabSheet;
|
|
function GetWndTabSheetByHWND(const hWindow: HWND): TWndTabSheet;
|
|
public
|
|
Constructor Create;
|
|
Destructor Destroy; override;
|
|
|
|
procedure ClearPages;
|
|
|
|
procedure AddWndPage(aWndInfo: TWndInfo);
|
|
function GetWndPage(aWndHandle: HWND): PWndInfo;
|
|
function GetWndTabSheet(aWndHandle: HWND): TWndTabSheet;
|
|
function GetWndInfoEnumerator: TWndInfoEnumerator;
|
|
|
|
procedure DeleteWndTabSheetFromHWND(const hWindow: HWND; bWndDestroyAfter: Boolean = false);
|
|
procedure DeleteWndTabSheetFromPid(const dwPid: DWORD);
|
|
|
|
// property WndTabSheet[const hWindow: HWND]: TWndTabSheet read GetWndTabSheetByHWND;
|
|
end;
|
|
|
|
var
|
|
gWndPage: TManagerWindowPage = nil;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Vcl.Controls, Tocsg.Safe, Tocsg.JSON, Tocsg.Path,
|
|
Define, Tocsg.WndUtil, Tocsg.Convert;
|
|
|
|
{ TWndFrame }
|
|
|
|
Constructor TWndFrame.Create(aOwner: TComponent);
|
|
begin
|
|
Inherited Create(aOwner);
|
|
ASSERT(aOwner is TWndTabSheet);
|
|
OwnerTabSheet_ := aOwner as TWndTabSheet;
|
|
end;
|
|
|
|
{ TWndTabSheet }
|
|
|
|
Constructor TWndTabSheet.Create(aOwner: TComponent; aWndInfo: TWndInfo);
|
|
begin
|
|
Inherited Create(aOwner);
|
|
WndInfo_ := aWndInfo;
|
|
WndFrame_ := WndInfo_.WndFrameClass.Create(Self);
|
|
WndFrame_.Parent := Self;
|
|
WndFrame_.Align := alClient;
|
|
if gWndPage <> nil then
|
|
gWndPage.DcWndTabSheet_.Add(WndInfo_.WndHandle, Self);
|
|
// gWndPage.DcProcessTabSheet_.Add(WndInfo_.ProcID, Self);
|
|
end;
|
|
|
|
Destructor TWndTabSheet.Destroy;
|
|
begin
|
|
if gWndPage <> nil then
|
|
begin
|
|
// gWndPage.DcProcessTabSheet_.Remove(WndInfo_.ProcID);
|
|
gWndPage.DcWndTabSheet_.Remove(WndInfo_.WndHandle);
|
|
|
|
// todo : 포함 윈도우(프로세스)를 같이 닫을건지 아님 뺄건지 묻기/옵션
|
|
|
|
// if (GetProcessPathFromPID(WndInfo_.ProcID) <> '') and
|
|
// (MessageBox(Handle, '하위 프로세스도 함께 종료하시겠습니까?',
|
|
// APP_NAME, MB_ICONQUESTION or MB_YESNO) = IDYES) then
|
|
// begin
|
|
// TerminateProcessFromPID(WndInfo_.ProcID);
|
|
// WndInfo_.ProcID := 0;
|
|
// end;
|
|
|
|
// if IsWindow(WndInfo_.WndHandle) and
|
|
//// (GetProcessPathFromPID(WndInfo_.ProcID) <> '') and
|
|
// (MessageBox(Handle, '하위 윈도우도 함께 종료하시겠습니까?',
|
|
// APP_NAME, MB_ICONQUESTION or MB_YESNO) = IDYES) then
|
|
// begin
|
|
// PostMessage(WndInfo_.WndHandle, WM_CLOSE, 0, 0);
|
|
//// WndInfo_.ProcID := 0;
|
|
// end;
|
|
|
|
if GetProcessNameByPid(WndInfo_.ProcID) <> '' then
|
|
gWndPage.RemoveWndPage(WndInfo_.WndHandle);
|
|
end;
|
|
|
|
Inherited;
|
|
end;
|
|
|
|
{ TManagerWindowPage }
|
|
|
|
Constructor TManagerWindowPage.Create;
|
|
begin
|
|
Inherited Create;
|
|
ASSERT(gWndPage = nil);
|
|
gWndPage := Self;
|
|
|
|
DcWndPages_ := TDictionary<HWND,PWndInfo>.Create;
|
|
DcWndPages_.OnValueNotify := OnWndPage;
|
|
|
|
// DcProcessTabSheet_ := TDictionary<DWORD,TWndTabSheet>.Create;
|
|
DcWndTabSheet_ := TDictionary<HWND,TWndTabSheet>.Create;
|
|
|
|
LoadPages;
|
|
end;
|
|
|
|
Destructor TManagerWindowPage.Destroy;
|
|
begin
|
|
gWndPage := nil;
|
|
FreeAndNil(DcWndTabSheet_);
|
|
|
|
// 정상 종료되면 기존 포함 폼을 정상으로 돌려주고, 비정상 종료로 보이지 않게 비워준다 14_0421 22:32:23 sunk
|
|
DcWndPages_.Clear;
|
|
SavePages;
|
|
FreeAndNil(DcWndPages_);
|
|
Inherited;
|
|
end;
|
|
|
|
procedure TManagerWindowPage.OnWndPage(Sender: TObject; const Item: PWndInfo;
|
|
Action: TCollectionNotification);
|
|
var
|
|
WndPlacement: TWindowPlacement;
|
|
begin
|
|
case Action of
|
|
cnAdded:
|
|
begin
|
|
ZeroMemory(@Item.OrzWndRect, SizeOf(Item.OrzWndRect));
|
|
if GetWindowPlacement(Item.WndHandle, WndPlacement) then
|
|
Item.OrzWndRect := WndPlacement.rcNormalPosition;
|
|
Item.OrzBorderStyle := GetWindowStyle(Item.WndHandle);
|
|
Item.OrzBorderExStyle := GetWindowExStyle(Item.WndHandle);
|
|
end;
|
|
cnRemoved:
|
|
begin
|
|
if GetProcessNameByPid(Item.ProcID) <> '' then
|
|
begin
|
|
Winapi.Windows.SetParent(Item.WndHandle, GetDesktopWindow);
|
|
if (Item.OrzWndRect.Width <> 0) and (Item.OrzWndRect.Height <> 0) then
|
|
MoveWindow(Item.WndHandle, Item.OrzWndRect.Left, Item.OrzWndRect.Top, Item.OrzWndRect.Width, Item.OrzWndRect.Height, true);
|
|
SetWindowLong(Item.WndHandle, GWL_STYLE, Item.OrzBorderStyle);
|
|
SetWindowLong(Item.WndHandle, GWL_EXSTYLE, Item.OrzBorderExStyle);
|
|
end;
|
|
if Item.ProcInfo <> nil then
|
|
FreeAndNil(Item.ProcInfo);
|
|
Dispose(Item);
|
|
end;
|
|
cnExtracted: ;
|
|
end;
|
|
end;
|
|
|
|
procedure TManagerWindowPage.ClearPages;
|
|
begin
|
|
DcWndPages_.Clear;
|
|
SavePages;
|
|
end;
|
|
|
|
procedure TManagerWindowPage.AddWndPage(aWndInfo: TWndInfo);
|
|
var
|
|
pInfo: PWndInfo;
|
|
begin
|
|
if (aWndInfo.WndHandle <> 0) and not DcWndPages_.ContainsKey(aWndInfo.WndHandle) then
|
|
begin
|
|
New(pInfo);
|
|
pInfo^ := aWndInfo;
|
|
DcWndPages_.Add(pInfo.WndHandle, pInfo);
|
|
SavePages;
|
|
end;
|
|
end;
|
|
|
|
function TManagerWindowPage.GetWndPage(aWndHandle: HWND): PWndInfo;
|
|
begin
|
|
if DcWndPages_.ContainsKey(aWndHandle) then
|
|
Result := DcWndPages_[aWndHandle]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TManagerWindowPage.GetWndTabSheet(aWndHandle: HWND): TWndTabSheet;
|
|
begin
|
|
if DcWndTabSheet_.ContainsKey(aWndHandle) then
|
|
Result := DcWndTabSheet_[aWndHandle]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
//function TManagerWindowPage.GetWndTabSheetByPID(const dwPid: DWORD): TWndTabSheet;
|
|
function TManagerWindowPage.GetWndTabSheetByHWND(const hWindow: HWND): TWndTabSheet;
|
|
begin
|
|
if DcWndTabSheet_.ContainsKey(hWindow) then
|
|
Result := DcWndTabSheet_[hWindow]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TManagerWindowPage.RemoveWndPage(WndHandle: HWND);
|
|
begin
|
|
if DcWndPages_.ContainsKey(WndHandle) then
|
|
begin
|
|
DcWndPages_.Remove(WndHandle);
|
|
SavePages;
|
|
end;
|
|
end;
|
|
|
|
function TManagerWindowPage.GetWndInfoEnumerator: TWndInfoEnumerator;
|
|
begin
|
|
Result := DcWndPages_.Values.GetEnumerator
|
|
end;
|
|
|
|
procedure TManagerWindowPage.DeleteWndTabSheetFromHWND(const hWindow: HWND; bWndDestroyAfter: Boolean = false);
|
|
var
|
|
WndTabSheet: TWndTabSheet;
|
|
begin
|
|
if DcWndTabSheet_.ContainsKey(hWindow) then
|
|
begin
|
|
WndTabSheet := DcWndTabSheet_[hWindow];
|
|
DcWndTabSheet_.Remove(hWindow);
|
|
if bWndDestroyAfter then
|
|
WndTabSheet.WndInfo_.WndHandle := 0;
|
|
WndTabSheet.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TManagerWindowPage.DeleteWndTabSheetFromPid(const dwPid: DWORD);
|
|
var
|
|
enum: TEnumerator<TWndTabSheet>;
|
|
begin
|
|
Guard(enum, DcWndTabSheet_.Values.GetEnumerator);
|
|
while enum.MoveNext do
|
|
begin
|
|
if enum.Current.WndInfo_.ProcID = dwPid then
|
|
begin
|
|
DcWndPages_.Remove(enum.Current.WndInfo_.WndHandle);
|
|
enum.Current.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TManagerWindowPage.SavePages;
|
|
var
|
|
WndPageList: TStringList;
|
|
enum: TWndInfoEnumerator;
|
|
begin
|
|
Guard(WndPageList, TStringList.Create);
|
|
Guard(enum, GetWndInfoEnumerator);
|
|
while enum.MoveNext do
|
|
WndPageList.Add(TTgJson.ValueToJsonAsString<TWndInfo>(enum.Current^));
|
|
WndPageList.SaveToFile(GetRunExePathDir + DAT_WNDPAGES);
|
|
end;
|
|
|
|
procedure TManagerWindowPage.LoadPages;
|
|
var
|
|
sPath: String;
|
|
WndPageList: TStringList;
|
|
i: Integer;
|
|
O: ISuperObject;
|
|
WndInfo: TWndInfo;
|
|
pInfo: PWndInfo;
|
|
begin
|
|
sPath := GetRunExePathDir + DAT_WNDPAGES;
|
|
if FileExists(sPath) then
|
|
begin
|
|
Guard(WndPageList, TStringList.Create);
|
|
WndPageList.LoadFromFile(GetRunExePathDir + DAT_WNDPAGES);
|
|
for i := 0 to WndPageList.Count - 1 do
|
|
begin
|
|
pInfo := nil;
|
|
try
|
|
O := SO(WndPageList[i]);
|
|
WndInfo.WndKind := TTgRtti.Int64ToSetType<TWndKind>(O.I['WndKind']);
|
|
WndInfo.ProcPath := O.S['ProcPath'];
|
|
WndInfo.ProcID := O.I['ProcID'];
|
|
WndInfo.WndHandle := O.I['WndHandle'];
|
|
WndInfo.WndFrameClass := TTgJson.GetDataAsType<TWndFrameClass>(O['WndFrameClass']);
|
|
|
|
if UpperCase(ExtractFileName(WndInfo.ProcPath)) = UpperCase(GetProcessNameByPID(WndInfo.ProcID)) then
|
|
begin
|
|
WndInfo.ProcInfo := TTgProcessInfo.Create(WndInfo.ProcID);
|
|
New(pInfo);
|
|
pInfo^ := WndInfo;
|
|
ShowWindow(pInfo.WndHandle, SW_SHOWNORMAL);
|
|
// pInfo.WndHandle := GetWndHandleFromPID(WndInfo.ProcID);
|
|
DcWndPages_.Add(pInfo.WndHandle, pInfo);
|
|
end else
|
|
WndInfo.ProcInfo := nil;
|
|
except
|
|
if pInfo <> nil then
|
|
Dispose(pInfo);
|
|
continue;
|
|
end;
|
|
end;
|
|
SavePages;
|
|
end;
|
|
end;
|
|
|
|
end.
|