unit DPerfectDel; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Menus, System.Generics.Collections, superobject; const WM_CLICK_DECRYPT = WM_USER + 8548; type PDelEnt = ^TDelEnt; TDelEnt = record sDir, sExt, sFName: String; bDrm: Boolean; nImgIdx: Integer; end; TDlgPerfectDel = class(TForm) pnTop: TPanel; pnClient: TPanel; vtList: TVirtualStringTree; btnDelete: TButton; Label1: TLabel; popFun: TPopupMenu; miDelFile: TMenuItem; miClear: TMenuItem; btnAddFile: TButton; btnAddDir: TButton; OpenDialog: TOpenDialog; FileOpenDialog: TFileOpenDialog; procedure vtListGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); procedure vtListGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string); procedure vtListGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); procedure vtListPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType); procedure vtListGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); procedure vtListAfterPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); procedure vtListFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure miDelFileClick(Sender: TObject); procedure vtListContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); procedure miClearClick(Sender: TObject); procedure btnAddFileClick(Sender: TObject); procedure btnAddDirClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure btnDeleteClick(Sender: TObject); private { Private declarations } FileImageList_: TImageList; vtListOldWndProc_: TWndMethod; CheckFList_: TStringList; DcNDrvIps_: TDictionary; sUName_, sDept_, sEmpNo_, sPoName_: String; procedure vtListWndProc(var msg: TMessage); function CountEncFile: Integer; function CheckNetPath(sPath: String): String; procedure AddFile(sPath: String); public { Public declarations } Constructor Create(aOwner: TComponent); override; procedure CreateParams(var Params: TCreateParams); override; // 작업표시줄에 표시 Destructor Destroy; override; procedure AddFiles(aList: TStringList); procedure process_WM_COPYDATA(var msg: TMessage); Message WM_COPYDATA; end; var DlgPerfectDel: TDlgPerfectDel; implementation uses ManagerService, ManagerModel, Tocsg.Convert, Tocsg.Shell, Winapi.ShellAPI, Tocsg.Path, Tocsg.DRM.Encrypt, Tocsg.Encrypt, GlobalDefine, Condition, Tocsg.Files, Tocsg.Strings, Tocsg.VTUtil, DefineHelper, Define, Tocsg.Exception, Tocsg.Process, Tocsg.User32, Tocsg.Network, Tocsg.Trace, Tocsg.Hash, DProgCttSchTask, Tocsg.Safe; resourcestring RS_MsgAddFile = '먼저 파일을 추가해 주십시오.'; RS_NoTgFile = '삭제 할 파일이 없습니다.'; RS_FileDec = '파일 복호화'; RS_Q_Delete = '선택된 파일들을 완전삭제 하시겠습니까?'; RS_MsgError = '작업을 준비하는 중 오류가 발생했습니다.'; RS_CompleteWork1 = '작업을 완료했습니다.'; RS_CompleteWork2 = '(성공 : %d, 실패 : %d)'; RS_Q_Clear = '목록을 초기화 하시겠습니까?'; RS_SelExceptFile = '제외 할 파일을 선택해 주십시오.'; RS_Q_ExceptFile = '선택한 파일들을 제외 하시겠습니까?'; RS_NoExceptFile = '제외 할 파일이 없습니다.'; RS_DrmFileDragDrop = '파일을 드래그/드롭 해주십시오.'; RS_Ok = '확인'; {$R *.dfm} Constructor TDlgPerfectDel.Create(aOwner: TComponent); var hSysIcons: THandle; begin Inherited Create(aOwner); sUName_ := gMgSvc.UName; sDept_ := gMgSvc.DeptName; if sDept_ = '' then sDept_ := gMgSvc.ModePolicy.DeptName; sEmpNo_ := gMgSvc.EmpNo; sPoName_ := gMgSvc.ModePolicy.PolicyName; FileImageList_ := TImageList.Create(Self); FileImageList_.ShareImages := true; FileImageList_.BlendColor := clHighlight; hSysIcons := GetShellImageHandle; if hSysIcons <> 0 then begin FileImageList_.Handle := hSysIcons; vtList.Images := FileImageList_; end; CheckFList_ := TStringList.Create; CheckFList_.CaseSensitive := false; vtListOldWndProc_ := vtList.WindowProc; vtList.WindowProc := vtListWndProc; DragAcceptFiles(vtList.Handle, true); ChangeWindowMessageFilter(WM_COPYDATA, MSGFLT_ADD); ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD); ChangeWindowMessageFilterEx(vtList.Handle, WM_DROPFILES, MSGFLT_ALLOW, nil); ChangeWindowMessageFilter(WM_COPYGLOBALDATA, MSGFLT_ADD); end; procedure TDlgPerfectDel.CreateParams(var Params: TCreateParams); begin Inherited CreateParams(Params); {$IFDEF _HE_} Params.ExStyle := WS_EX_APPWINDOW; {$ENDIF} end; Destructor TDlgPerfectDel.Destroy; begin FreeAndNil(CheckFList_); Inherited; end; procedure TDlgPerfectDel.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := TCloseAction.caFree; end; function TDlgPerfectDel.CountEncFile: Integer; var pData: PDelEnt; pNode: PVirtualNode; begin Result := 0; vtList.BeginUpdate; try pNode := vtList.GetFirst; while pNode <> nil do begin pData := vtList.GetNodeData(pNode); if pData.bDrm then Inc(Result); pNode := vtList.GetNext(pNode); end; finally vtList.EndUpdate; end; end; function TDlgPerfectDel.CheckNetPath(sPath: String): String; var sDrive, sExe, sIpAddr: String; dwExecuteTick, dwWaitResult: DWORD; begin Result := sPath; try sDrive := IncludeTrailingPathDelimiter(ExtractFileDrive(sPath)); if not DirectoryExists(sDrive) then begin sIpAddr := ''; if not DcNDrvIps_.ContainsKey(sDrive) then begin sIpAddr := NetDriveToRemoteAddr(sDrive); DcNDrvIps_.Add(sDrive, sIpAddr); end else sIpAddr := DcNDrvIps_[sDrive]; if sIpAddr = '' then exit; // TTgTrace.T('TDlgEncryptDrm.AddFile() .. 7, IP=%s', [sIpAddr]); sIpAddr := IncludeTrailingPathDelimiter(sIpAddr); Result := StringReplace(sPath, sDrive, sIpAddr, [rfReplaceAll, rfIgnoreCase]); // TTgTrace.T('TDlgEncryptDrm.AddFile() .. 8, Path=%s', [Result]); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. CheckNetPath()'); end; end; procedure TDlgPerfectDel.AddFile(sPath: String); var pData: PDelEnt; begin try if CheckFList_.IndexOf(sPath) <> -1 then exit; CheckFList_.Add(sPath); pData := VT_AddChildData(vtList); pData.sDir := ExtractFilePath(sPath); pData.sFName := ExtractFileName(sPath); pData.sExt := GetFileExt(pData.sFName).ToUpper; pData.nImgIdx := -1; try pData.bDrm := TTgEncrypt.CheckSign(sPath, SIG_DRM); except pData.bDrm := false; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. AddFile()'); end; end; procedure TDlgPerfectDel.AddFiles(aList: TStringList); var sPath: String; i: Integer; begin vtList.BeginUpdate; try for i := 0 to aList.Count - 1 do begin sPath := aList[i]; if not FileExists(sPath) then continue; AddFile(sPath); end; finally vtList.EndUpdate; end; end; procedure TDlgPerfectDel.btnAddDirClick(Sender: TObject); procedure ExtrctFilesFromDir(sDir: String); var wfd: TWin32FindData; hSc: THandle; sPath: String; begin sDir := IncludeTrailingPathDelimiter(sDir); sPath := sDir + '*.*'; hSc := FindFirstFile(PChar(sPath), wfd); if hSc = INVALID_HANDLE_VALUE then exit; try Repeat if (String(wfd.cFileName) <> '.') and (String(wfd.cFileName) <> '..') then if ((wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0) then begin ExtrctFilesFromDir(sDir + wfd.cFileName); end else begin AddFile(sDir + wfd.cFileName); end; Until not FindNextFile(hSc, wfd); finally WinApi.Windows.FindClose(hSc); end; end; begin {$IFDEF _HE_} if FileOpenDialog.FileName = '' then FileOpenDialog.DefaultFolder := Format('C:\Users\%s\Desktop', [gMgSvc.UserName]); {$ENDIF} if FileOpenDialog.Execute then begin ExtrctFilesFromDir(FileOpenDialog.FileName); end; end; procedure TDlgPerfectDel.btnAddFileClick(Sender: TObject); var i: Integer; begin {$IFDEF _HE_} if (OpenDialog.Files.Count = 0) or (OpenDialog.FileName = '') then OpenDialog.InitialDir := Format('C:\Users\%s\Desktop', [gMgSvc.UserName]); {$ENDIF} if OpenDialog.Execute(Handle) then begin vtList.BeginUpdate; try for i := 0 to OpenDialog.Files.Count - 1 do AddFile(OpenDialog.Files[i]); finally vtList.EndUpdate; end; end; end; procedure TDlgPerfectDel.btnDeleteClick(Sender: TObject); var pNode: PVirtualNode; EntList: TRstEntList; pEnt: PRstEnt; pData: PDelEnt; dlg: TDlgProgCttSchTask; i, nCnt, nFail: Integer; begin if vtList.RootNodeCount = 0 then begin MessageBox(Handle, PChar(RS_MsgAddFile), PChar(Caption), MB_ICONWARNING or MB_OK); exit; end; if (MessageBox(Handle, PChar(RS_Q_Delete), PChar(Caption), MB_ICONQUESTION or MB_YESNO) = IDNO) then exit; Guard(EntList, TRstEntList.Create); vtList.BeginUpdate; try pNode := vtList.GetFirst; while pNode <> nil do begin pData := vtList.GetNodeData(pNode); if FileExists(pData.sDir + pData.sFName) then begin New(pEnt); ZeroMemory(pEnt, SizeOf(TRstEnt)); pEnt.sDir := pData.sDir; pEnt.sFName := pData.sFName; EntList.Add(pEnt); end; pNode := vtList.GetNext(pNode); end; if EntList.Count = 0 then exit; Guard(dlg, TDlgProgCttSchTask.Create(Self, cstkPerDelete, EntList)); dlg.ShowModal; nCnt := 0; nFail := 0; for i := 0 to EntList.Count - 1 do begin pEnt := EntList[i]; if pEnt.State = resDel then Inc(nCnt) else Inc(nFail); end; finally vtList.EndUpdate; end; MessageBox(Handle, PChar(Format(RS_CompleteWork1+#13+#10+RS_CompleteWork2, [nCnt, nFail])), PChar(Caption), MB_ICONINFORMATION or MB_OK); end; procedure TDlgPerfectDel.miClearClick(Sender: TObject); begin if MessageBox(Handle, PChar(RS_Q_Clear), PChar(Caption), MB_ICONQUESTION or MB_YESNO) = IDNO then exit; CheckFList_.Clear; VT_Clear(vtList); end; procedure TDlgPerfectDel.miDelFileClick(Sender: TObject); var pNode: PVirtualNode; pData: PDelEnt; nIdx: Integer; begin pNode := vtList.GetFirstSelected; if pNode = nil then begin MessageBox(Handle, PChar(RS_SelExceptFile), PChar(Caption), MB_ICONWARNING or MB_OK); exit; end; if MessageBox(Handle, PChar(RS_Q_ExceptFile), PChar(Caption), MB_ICONQUESTION or MB_YESNO) = IDNO then exit; vtList.BeginUpdate; try while pNode <> nil do begin pData := vtList.GetNodeData(pNode); nIdx := CheckFList_.IndexOf(pData.sDir + pData.sFName); if nIdx <> -1 then CheckFList_.Delete(nIdx); pNode := vtList.GetNextSelected(pNode); end; vtList.DeleteSelectedNodes; finally vtList.EndUpdate; end; end; procedure TDlgPerfectDel.vtListWndProc(var msg: TMessage); procedure ExtrctFilesFromDir(sDir: String); var wfd: TWin32FindData; hSc: THandle; sPath: String; begin sDir := IncludeTrailingPathDelimiter(sDir); sPath := sDir + '*.*'; hSc := FindFirstFile(PChar(sPath), wfd); if hSc = INVALID_HANDLE_VALUE then exit; try Repeat if (String(wfd.cFileName) <> '.') and (String(wfd.cFileName) <> '..') then if ((wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0) then begin ExtrctFilesFromDir(sDir + wfd.cFileName); end else begin AddFile(sDir + wfd.cFileName); end; Until not FindNextFile(hSc, wfd); finally WinApi.Windows.FindClose(hSc); end; end; var sPath: String; nCnt: Integer; i, nLen: Integer; pNode: PVirtualNode; pData: PDelEnt; begin if msg.Msg = WM_DROPFILES then begin nCnt := DragQueryFile(msg.WParam, DWORD(-1), nil, MAX_PATH); vtList.BeginUpdate; try for i := 0 to nCnt - 1 do begin nLen := DragQueryFile(msg.WParam, i, nil, 0) + 1; SetLength(sPath, nLen); DragQueryFile(msg.WParam, i, PChar(sPath), nLen); sPath := DeleteNullTail(sPath); if FileExists(sPath) then AddFile(sPath) else if DirectoryExists(sPath) then ExtrctFilesFromDir(sPath); end; finally vtList.EndUpdate; end; DragFinish(msg.WParam); exit; end; vtListOldWndProc_(msg); end; procedure TDlgPerfectDel.vtListAfterPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); var nX, nY, nW, nH: Integer; msg: String; begin if CUSTOMER_TYPE <> CUSTOMER_SERVE1 then // 서브원은 권한때문에 드래그드롭을 못함 24_0711 08:47:40 kku begin if TVirtualStringTree(Sender).RootNodeCount = 0 then begin TargetCanvas.Font.Color := clGray; msg := RS_DrmFileDragDrop; nW := TargetCanvas.TextWidth(msg); nH := TargetCanvas.TextHeight(msg); if Sender.Width > nW then nX := (Sender.Width div 2) - (nW div 2) else nX := 0; if Sender.Height > nH then nY := (Sender.Height div 2) - (nH div 2) - 20 else nY := 0; TargetCanvas.TextOut(nX, nY, msg); end; end; end; procedure TDlgPerfectDel.vtListContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); var pNode: PVirtualNode; begin pNode := vtList.GetNodeAt(MousePos); miDelFile.Visible := pNode <> nil; miClear.Visible := vtList.RootNodeCount > 0; end; procedure TDlgPerfectDel.vtListFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var pData: PDelEnt; begin pData := Sender.GetNodeData(Node); Finalize(pData^); end; procedure TDlgPerfectDel.vtListGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string); begin HintText := vtList.Text[Node, Column]; end; procedure TDlgPerfectDel.vtListGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); var pData: PDelEnt; begin case Kind of ikNormal, ikSelected: begin if Column = 1 then begin pData := Sender.GetNodeData(Node); if pData.nImgIdx = -1 then pData.nImgIdx := GetShellImageIndex_path(pData.sDir + pData.sFName); ImageIndex := pData.nImgIdx; end; end; end; end; procedure TDlgPerfectDel.vtListGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); begin NodeDataSize := SizeOf(TDelEnt); end; procedure TDlgPerfectDel.vtListGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); var pData: PDelEnt; begin pData := Sender.GetNodeData(Node); case Column of 0 : CellText := IntToStr(Node.Index + 1); 1 : CellText := pData.sFName; 2 : CellText := pData.sExt; 3 : CellText := pData.sDir; end; end; procedure TDlgPerfectDel.vtListPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType); var pData: PDelEnt; begin if not (vsSelected in Node.States) then begin pData := Sender.GetNodeData(Node); if not FileExists(pData.sDir + pData.sFName) then TargetCanvas.Font.Color := clGray; end; end; procedure TDlgPerfectDel.process_WM_COPYDATA(var msg: TMessage); var dwData: DWORD; pCpData: PCopyDataStruct; O: ISuperObject; sTemp: String; begin msg.Result := 0; dwData := 0; pCpData := PCopyDataStruct(msg.LParam); try // dwData := pCpData.dwData; // case dwData of // HPCMD_INPUT_EXCEPT_REASON : // begin // btnDecrypt.Enabled := true; // sTemp := Copy(PChar(pCpData.lpData), 1, pCpData.cbData); // if sTemp = '' then // exit; // // sExceptReason_ := sTemp; // PostMessage(Handle, WM_CLICK_DECRYPT, 0, 0); // end; // end; except on E: Exception do ETgException.TraceException(Self, E, Format('Fail .. process_WM_COPYDATA(), dwData=%d', [dwData])); end; end; end.