{*******************************************************} { } { ApiHookPrint } { } { Copyright (C) 2023 kku } { } {*******************************************************} unit ApiHookPrint; interface uses System.SysUtils, System.Classes, Winapi.Windows, Vcl.Graphics; type // 프린트 TFun_StartDocA = function(dc: HDC; pDocInfo: PDocInfoA): Integer; stdcall; TFun_StartDocW = function(dc: HDC; pDocInfo: PDocInfoW): Integer; stdcall; TFun_HDC = function(dc: HDC): Integer; stdcall; TFun_CreateDC = function(lpszDriver, lpszDevice, lpszOutput: LPCWSTR; lpdvmInit: PDeviceMode): HDC; stdcall; TFun_CreateDCA = function(lpszDriver, lpszDevice, lpszOutput: LPCSTR; lpdvmInit: PDeviceModeA): HDC; stdcall; TFun_CreateDCW = function(lpszDriver, lpszDevice, lpszOutput: LPCWSTR; lpdvmInit: PDeviceModeW): HDC; stdcall; TFun_WritePrinter = function(hPrinter: THandle; pBuf: Pointer; cbBuf: DWORD; var pcWritten: DWORD): BOOL; stdcall; // 마스킹 // TFun_DrawTextA = function(hDC: HDC; lpString: LPCSTR; nCount: Integer; // var lpRect: TRect; uFormat: UINT): Integer; stdcall; // TFun_DrawTextW = function(hDC: HDC; lpString: LPCWSTR; nCount: Integer; // var lpRect: TRect; uFormat: UINT): Integer; stdcall; // TFun_DrawTextExA = function(DC: HDC; lpchText: LPCSTR; cchText: Integer; var p4: TRect; // dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; // TFun_DrawTextExW = function(DC: HDC; lpchText: LPCWSTR; cchText: Integer; var p4: TRect; // dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; // TFun_ExtTextOutA = function(DC: HDC; X, Y: Integer; Options: Longint; // Rect: PRect; Str: LPCSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; // TFun_ExtTextOutW = function(DC: HDC; X, Y: Integer; Options: Longint; // Rect: PRect; Str: LPCWSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; // TFun_TextOutA = function(DC: HDC; X, Y: Integer; Str: LPCSTR; Count: Integer): BOOL; stdcall; // TFun_TextOutW = function(DC: HDC; X, Y: Integer; Str: LPCWSTR; Count: Integer): BOOL; stdcall; // TFun_PolyTextOutA = function(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; // TFun_PolyTextOutW = function(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; // TFun_TabbedTextOutA = function(hDC: HDC; X, Y: Integer; lpString: LPCSTR; nCount, nTabPositions: Integer; // var lpnTabStopPositions; nTabOrigin: Integer): Longint; stdcall; // TFun_TabbedTextOutW = function(hDC: HDC; X, Y: Integer; lpString: LPCWSTR; nCount, nTabPositions: Integer; // var lpnTabStopPositions; nTabOrigin: Integer): Longint; stdcall; function CreateDCHook(lpszDriver, lpszDevice, lpszOutput: LPCWSTR; lpdvmInit: PDeviceMode): HDC; stdcall; function CreateDCAHook(lpszDriver, lpszDevice, lpszOutput: LPCSTR; lpdvmInit: PDeviceModeA): HDC; stdcall; function CreateDCWHook(lpszDriver, lpszDevice, lpszOutput: LPCWSTR; lpdvmInit: PDeviceModeW): HDC; stdcall; function StartDocAHook(dc: HDC; pDocInfo: PDocInfoA): Integer; stdcall; function StartDocWHook(dc: HDC; pDocInfo: PDocInfoW): Integer; stdcall; function StartPageHook(dc: HDC): Integer; stdcall; function EndPageHook(dc: HDC): Integer; stdcall; function EndDocHook(dc: HDC): Integer; stdcall; function WritePrinterHook(hPrinter: THandle; pBuf: Pointer; cbBuf: DWORD; var pcWritten: DWORD): BOOL; stdcall; //function DrawTextAHook(hDC: HDC; lpString: LPCSTR; nCount: Integer; // var lpRect: TRect; uFormat: UINT): Integer; stdcall; //function DrawTextWHook(hDC: HDC; lpString: LPCWSTR; nCount: Integer; // var lpRect: TRect; uFormat: UINT): Integer; stdcall; //function DrawTextExAHook(DC: HDC; lpchText: LPCSTR; cchText: Integer; var p4: TRect; // dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; //function DrawTextExWHook(DC: HDC; lpchText: LPCWSTR; cchText: Integer; var p4: TRect; // dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; //function ExtTextOutAHook(DC: HDC; X, Y: Integer; Options: Longint; // Rect: PRect; Str: LPCSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; //function ExtTextOutWHook(DC: HDC; X, Y: Integer; Options: Longint; // Rect: PRect; Str: LPCWSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; //function TextOutAHook(DC: HDC; X, Y: Integer; Str: LPCSTR; Count: Integer): BOOL; stdcall; //function TextOutWHook(DC: HDC; X, Y: Integer; Str: LPCWSTR; Count: Integer): BOOL; stdcall; //function PolyTextOutAHook(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; //function PolyTextOutWHook(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; //function TabbedTextOutAHook(hDC: HDC; X, Y: Integer; lpString: LPCSTR; nCount, nTabPositions: Integer; // var lpnTabStopPositions; nTabOrigin: Integer): Longint; stdcall; //function TabbedTextOutWHook(hDC: HDC; X, Y: Integer; lpString: LPCWSTR; nCount, nTabPositions: Integer; // var lpnTabStopPositions; nTabOrigin: Integer): Longint; stdcall; function DrawBitmapWater(aDestDC: HDC; nX, nY: Integer; aSrcBmp: TBitmap): Boolean; stdcall; procedure LogToReg(sVName, sLog: String); inline; //function WritePrinter( // hPrinter: THandle; // pBuf: Pointer; // cbBuf: DWORD; // var pcWritten: DWORD //): BOOL; stdcall; external 'winspool.drv' name 'WritePrinter'; var ozCreateDC: TFun_CreateDC = nil; ozCreateDCA: TFun_CreateDCA = nil; ozCreateDCW: TFun_CreateDCW = nil; ozStartDocA: TFun_StartDocA = nil; ozStartDocW: TFun_StartDocW = nil; ozStartPage: TFun_HDC = nil; ozEndPage: TFun_HDC = nil; ozEndDoc: TFun_HDC = nil; ozWritePrinter: TFun_WritePrinter = nil; // ozDrawTextA: TFun_DrawTextA = nil; // ozDrawTextW: TFun_DrawTextW = nil; // ozDrawTextExA: TFun_DrawTextExA = nil; // ozDrawTextExW: TFun_DrawTextExW = nil; // ozExtTextOutA: TFun_ExtTextOutA = nil; // ozExtTextOutW: TFun_ExtTextOutW = nil; // ozTextOutA: TFun_TextOutA = nil; // ozTextOutW: TFun_TextOutW = nil; // ozPolyTextOutA: TFun_PolyTextOutA = nil; // ozPolyTextOutW: TFun_PolyTextOutW = nil; // ozTabbedTextOutA: TFun_TabbedTextOutA = nil; // ozTabbedTextOutW: TFun_TabbedTextOutW = nil; var _bmpWater: TBitmap; _bmpWaterP: TBitmap; _sbmpWaterIf: String; _sLabelName: String; _bIgrPrtWater: Boolean; _PrtDC: HDC; _bDoStartProc: Boolean; _bDoEndProc: Boolean; _nFontSize: Integer; _sDrvName: String; _sDevName: String; _sPrtName: String; _sPrtDocId: String; gPrtWatering: Boolean; implementation uses {$IFDEF _BS1HP_} BS1Hook, DefineHelper, ProcessWM_JUVIS, ProcessWM_KBIZ, ProcessWM_HEC, ProcessWM_GEC, ProcessWM_KOCES, ProcessWM_SHSC, ProcessWM_SHCI, ProcessWM_Custom, ProcessWM_Def, ProcessWM_WINSTN, ProcessWM_SANKYO, ProcessWM_WELFND, ProcessWM_SERVE1, ProcessWM_DEMO, ProcessWM_SOLMIX, ProcessWM_KORENTAL, ProcessWM_SKEC, {$ELSE} AppHook, ProcessWM, {$ENDIF} Condition, ApiHookDraw, Tocsg.Safe, AppCtrlDefine, Vcl.Imaging.jpeg, Tocsg.Files, Tocsg.Shell, Winapi.WinSpool, Vcl.Imaging.pngimage, Tocsg.Network, Tocsg.Graphic, Tocsg.WndUtil, Tocsg.Path, Tocsg.Registry, superobject, Winapi.Messages, Tocsg.Strings, Tocsg.Process, Winapi.ActiveX, Winapi.GDIPOBJ, System.UIConsts, Winapi.GDIPAPI, Tocsg.Convert, Winapi.MultiMon, Tocsg.Printer; const CaptureBlt = $40000000; var _nPageCnt: Integer = 0; _sDocName: String = ''; procedure LogToReg(sVName, sLog: String); inline; begin // SetRegValueString(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', sVName, sLog, true); end; function DrawBitmapWater(aDestDC: HDC; nX, nY: Integer; aSrcBmp: TBitmap): Boolean; stdcall; //const // cTrMatrix: TColorMatrix = ( // (1.0, 0.0, 0.0, 0.0, 0.0), // (0.0, 1.0, 0.0, 0.0, 0.0), // (0.0, 0.0, 1.0, 0.0, 0.0), // (0.0, 0.0, 0.0, 0.5, 0.0), // (0.0, 0.0, 0.0, 0.0, 1.0)); var GPGraphics: TGPGraphics; ms: TMemoryStream; // GPStream: IStream; GPImg: TGPImage; ImageAttributes: TGPImageAttributes; GPRect: TGPRect; nWW, nHH: Integer; begin Result := true; try Guard(ms, TMemoryStream.Create); aSrcBmp.SaveToStream(ms); ms.Position := 0; // ms.SaveToFile('C:\Users\kku\Desktop\test111.bmp'); Guard(GPGraphics, TGPGraphics.Create(aDestDC)); // GPGraphics.SetSmoothingMode(SmoothingModeAntiAlias); GPGraphics.SetPageScale(0.33); // IStream 메모리 해제를 위해 여기에 변수 선언해야 함 24_0125 10:58:12 kku var GPStream: IStream := TStreamAdapter.Create(ms, soOwned) as IStream; Guard(GPImg, TGPImage.Create(GPStream)); Guard(ImageAttributes, TGPImageAttributes.Create); // 흰색 배경 투명처리 ImageAttributes.SetColorKey(System.UIConsts.MakeColor(255, 255, 255), System.UIConsts.MakeColor(255, 255, 255)); // 빨간색 배경 투명처리 // ImageAttributes.SetColorKey(System.UIConsts.MakeColor(255, 0, 0), System.UIConsts.MakeColor(255, 0, 0)); // ImageAttributes.SetColorMatrix(MakeColorMatrix(0.1, 0.1, 0.5, 0.2)); // Gray, 하늘색 // ImageAttributes.SetColorMatrix(MakeColorMatrix(0.1, 0.5, 0.5, 0.2)); // Gray, 녹색 // ImageAttributes.SetColorMatrix(MakeColorMatrix(0.1, 1.1, 0.5, 0.2)); // Gray, 연두색 // ImageAttributes.SetColorMatrix(MakeColorMatrix(0.2, 0.2, 0.2, 0.2)); // Gray, 실버 ImageAttributes.SetColorMatrix(MakeColorMatrix(0.2, 0.2, 0.2, 0.3)); // Gray, 회색 // ImageAttributes.SetColorMatrix(MakeTransparentMatrix(0.4)); // 그 외 mode, type 옵션 의미 없음.. nWW := GPImg.GetWidth; nHH := GPImg.GetHeight; // var GPUnit: TUnit := GPGraphics.GetPageUnit; GPRect.X := nX; GPRect.Y := nY; GPRect.Width := nWW; GPRect.Height := nHH; GPGraphics.DrawImage(GPImg, GPRect, 0, 0, Round(nWW), Round(nHH), UnitPixel, ImageAttributes); except Result := false; end; end; procedure GetPrinterName(sDriver, sDevice: String); begin _sDrvName := sDriver; _sDevName := sDevice; end; function GetScaleFactorFromDriverName(sDriverName: String): Double; var DC: HDC; nDPIW, nDPIH: Integer; nW, nH: Integer; begin Result := 0.0; try DC := CreateDC(nil, PChar(sDriverName), nil, nil); if DC <> 0 then begin nW := GetDeviceCaps(DC, HORZRES); // 세로모드 : 4961, 가로모드 : 7016, 크로미움 프린트 인쇄시 4760 nH := GetDeviceCaps(DC, VERTRES); // 가로모드 : 7016, 가로모드 : 4961, 크로미움 프린트 인쇄시 6814 LogToReg('DC=' + sDriverName, Format('W=%d, H=%d', [nW, nH])); try nDPIW := GetDeviceCaps(DC, LOGPIXELSX); nDPIH := GetDeviceCaps(DC, LOGPIXELSY); LogToReg('DC=' + sDriverName, Format('W=%d, H=%d, DPI_W=%d, DPI_H=%d', [nW, nH, nDPIW, nDPIH])); Result := nDPIW / 96.0; finally DeleteDC(DC); end; end; except // .. end; end; function GetMonitorScaleFactor: Double; var hMon: HMONITOR; MonInfo: MONITORINFOEX; DC: HDC; nDPI: Integer; begin Result := 0.0; try // LogToReg('GetMonitorScaleFactor() - 1', ''); if gAppHook = nil then exit; if gAppHook.Helper.CtrlOpt.hMainWnd = 0 then exit; // LogToReg('GetMonitorScaleFactor() - 2', ''); // DC := GetDC(gAppHook.Helper.CtrlOpt.hMainWnd); // if DC <> 0 then begin try // nDPI := GetDeviceCaps(DC, LOGPIXELSX); nDPI := GetDpiForWindow(gAppHook.Helper.CtrlOpt.hMainWnd); // LogToReg('GetMonitorScaleFactor() - 3', Format('DPI = %d', [nDPI])); Result := nDPI / 96.0; finally ReleaseDC(gAppHook.Helper.CtrlOpt.hMainWnd, DC); end; end; // hMon := MonitorFromWindow(gAppHook.Helper.CtrlOpt.hMainWnd, MONITOR_DEFAULTTONEAREST); // if hMon = 0 then // exit; // // ZeroMemory(@MonInfo, SizeOf(MonInfo)); // MonInfo.cbSize := SizeOf(MonInfo); // if GetMonitorInfo(hMon, @MonInfo) then // begin // DC := CreateDC(nil, MonInfo.szDevice, nil, nil); // if DC <> 0 then // begin // try // nDPI := GetDeviceCaps(DC, LOGPIXELSX); // LogToReg('GetMonitorScaleFactor() - 5', Format('MonName = %s, DPI = %d', [MonInfo.szDevice, nDPI])); // Result := nDPI / 96.0; // finally // DeleteDC(DC); // end; // end; // end; except // .. end; end; function GetMonitorWidth: Integer; var hMon: HMONITOR; MonInfo: MONITORINFOEX; DC: HDC; nDPI: Integer; begin Result := 0; try if gAppHook = nil then exit; if gAppHook.Helper.CtrlOpt.hMainWnd = 0 then exit; try hMon := MonitorFromWindow(gAppHook.Helper.CtrlOpt.hMainWnd, MONITOR_DEFAULTTONEAREST); MonInfo.cbSize := SizeOf(MonInfo); if GetMonitorInfo(hMon, @MonInfo) then begin Result := MonInfo.rcMonitor.Right - MonInfo.rcMonitor.Left; // Height := MonitorInfo.rcMonitor.Bottom - MonitorInfo.rcMonitor.Top; end; finally ReleaseDC(gAppHook.Helper.CtrlOpt.hMainWnd, DC); end; except // .. end; end; function CreateDCHook(lpszDriver, lpszDevice, lpszOutput: LPCWSTR; lpdvmInit: PDeviceMode): HDC; begin GetPrinterName(String(lpszDriver), String(lpszDevice)); Result := ozCreateDC(lpszDriver, lpszDevice, lpszOutput, lpdvmInit); end; function CreateDCAHook(lpszDriver, lpszDevice, lpszOutput: LPCSTR; lpdvmInit: PDeviceModeA): HDC; begin GetPrinterName(AnsiString(lpszDriver), AnsiString(lpszDevice)); Result := ozCreateDCA(lpszDriver, lpszDevice, lpszOutput, lpdvmInit); end; function CreateDCWHook(lpszDriver, lpszDevice, lpszOutput: LPCWSTR; lpdvmInit: PDeviceModeW): HDC; begin GetPrinterName(String(lpszDriver), String(lpszDevice)); Result := ozCreateDCW(lpszDriver, lpszDevice, lpszOutput, lpdvmInit); end; procedure SetAlphaBlend(var img: TPngImage; const Alpha: Byte); var mScanline, mPixel: Integer; mScanArray: pByteArray; begin try img.CreateAlpha; for mScanline := 0 to img.Height - 1 do begin mScanArray := img.AlphaScanline[mScanline]; for mPixel := 0 to img.Width - 1 do mScanArray[mPixel] := Alpha; end; except exit; end; end; function ProcessWartermarkCustomer(dwCustomer: DWORD; DC: HDC; bStartPage: Boolean): Boolean; begin if _bIgrPrtWater then begin Result := true; exit; end; gPrtWatering := true; try if (gAppHook <> nil) and gAppHook.Helper.CtrlOpt.PrtWaterCfg.bActive then begin {$IFDEF _BS1HP_} Result := ProcessWartermark_Custom(dc, bStartPage); {$ELSE} Result := false; {$ENDIF} end else case dwCustomer of {$IFDEF _BS1HP_} CUSTOMER_GEC : Result := ProcessWartermark_GEC(dc, bStartPage); CUSTOMER_HDENG : Result := ProcessWartermark_HEC(dc, bStartPage); CUSTOMER_JUVIS : Result := ProcessWartermark_JUVIS(dc, bStartPage); CUSTOMER_KOCES : Result := ProcessWartermark_KOCES(dc, bStartPage); CUSTOMER_KBIZ : Result := ProcessWartermark_KBIZ(dc, bStartPage); CUSTOMER_SHCI : Result := ProcessWartermark_SHCI(dc, bStartPage); CUSTOMER_SHSC : Result := ProcessWartermark_SHSC(dc, bStartPage); CUSTOMER_WINSTN : Result := ProcessWartermark_WINSTN(dc, bStartPage); CUSTOMER_SANKYO : Result := ProcessWartermark_SANKYO(dc, bStartPage); CUSTOMER_WELFNI, CUSTOMER_WELFND : Result := ProcessWartermark_WELFND(dc, bStartPage); CUSTOMER_SERVE1 : Result := ProcessWartermark_SERVE1(dc, bStartPage); CUSTOMER_SOLMIX : Result := ProcessWartermark_SOLMIX(dc, bStartPage); CUSTOMER_KORENTAL : Result := ProcessWartermark_KORENTAL(dc, bStartPage); CUSTOMER_SKEC : Result := ProcessWartermark_SKEC(dc, bStartPage); // CUSTOMER_DEMO : Result := ProcessWartermark_DEMO(dc, bStartPage); {$ENDIF} {$IFNDEF _BS1HP_} 113001 : Result := ProcessWartermark(dc, bStartPage); // DEV {$ENDIF} else Result := ProcessWartermark(dc, bStartPage); end; finally gPrtWatering := false; end; end; function FindPrintingFile(sDocName: String; bIgrRB: Boolean = false): String; var sDir, sChk: String; FList: TModFileList; i, n: Integer; // Plf: TParserLinkFile; begin Result := ''; if gAppHook = nil then exit; // Result := gAppHook.GetRFilePath(sDocName); // exit; sDir := GetWindowsDir; if sDir = '' then exit; sDir := sDir[1] + Format(':\Users\%s\AppData\Roaming\Microsoft\Windows\Recent\', [gAppHook.Helper.CtrlOpt.sAcName]); Guard(FList, TModFileList.Create(TModeFileComparer.Create)); ExtrModFilesFromDir(sDir, FList); if FList.Count > 0 then begin FList.Sort; if bIgrRB then sDocName := StrsReplace(sDocName, ['(', ')', '[', ']'], '0'); for i := 0 to FList.Count - 1 do begin if bIgrRB then sChk := StrsReplace(CutFileExt(FList[i].sFName), ['(', ')', '[', ']'], '0') else sChk := CutFileExt(FList[i].sFName); // 최근문서 파일처리 보완 24_0722 14:54:30 kku if (sChk.Length > 0) and (sChk[sChk.Length] = ')') then begin n := LastIndexOf(' (', sChk); if n > 0 then Delete(sChk, n, sChk.Length - n + 1); end; if Pos(sChk, sDocName) > 0 then begin Result := GetTargetExeFromLink(sDir + FList[i].sFName); if DirectoryExists(Result) then continue; // Guard(Plf, TParserLinkFile.Create); // if Plf.LoadFromFile(sDir + FList[i].sName) then // begin // Result := GetLfiValueFromCaption(Plf.LfiEntList, 'Base Path'); // if not FileExists(Result) then // Result := ''; // end; exit; end; end; // PDF의 경우... 문서 이름에 파일 이름이 안들어 가는 경우가 있다... // PDF 파일 최근파일 내역을 찾을 수 없다면 맨 첫번째 있는 PDF 파일을 넘겨준다.. 24_0418 15:10:27 kku if Pos('.PDF', sDocName.ToUpper) > 0 then begin for i := 0 to FList.Count - 1 do begin sChk := CutFileExt(FList[i].sFName); if GetFileExt(sChk).ToUpper = 'PDF' then begin Result := sChk; exit; end; end; end; end; end; function SendData(h: HWND; dwCmd: DWORD; const sData: String): LONGLONG; var CopyData: TCopyDataStruct; begin CopyData.dwData := dwCmd; CopyData.cbData := (Length(sData) + 1) * 2; CopyData.lpData := PChar(sData); Result := SendMessage(h, WM_COPYDATA, 0, NativeInt(@CopyData)); end; function FindAipMdWnd: HWND; var nTO: Integer; sPath, sFind, sFind2, sPName: String; begin sPath := gAppHook.Helper.CtrlOpt.sAipPath; if (sPath = '') or not FileExists(sPath) then begin Result := 0; exit; end; nTO := 0; sFind2 := 'BSOne-AIP-T140713'; sFind := sFind2 + '-' + ExtractFileName(sPath); Result := FindWindow(nil, PChar(sFind)); if Result = 0 then Result := FindWindow(nil, PChar(sFind2)); // todo : 업데이트가 바로 안될경우를 대비해서 이전 식별자로 한번더 해준다.. 나중에 정리 필요 if Result = 0 then begin var sAipDMail: String := gAppHook.Helper.CtrlOpt.sAccount + '@hec.co.kr'; sPName := ExtractFileName(sPath); while Result = 0 do begin if nTO > 40 then break; if GetProcessPidByName(sPName) = 0 then begin if not FileExists(sPath) then break; ExecutePath_hide(sPath, '-r ' + sAipDMail); // 차단으로 연결이 안되는 경우가 있다... Sleep(1000); end; Result := FindWindow(nil, PChar(sFind)); if Result = 0 then Result := FindWindow(nil, PChar(sFind2)); // todo : 업데이트가 바로 안될경우를 대비해서 이전 식별자로 한번더 해준다.. 나중에 정리 필요 Sleep(200); Inc(nTO); end; if Result = 0 then TerminateProcessByName(sPName); end; end; function ProcStartDoc(sDocName: String): Boolean; var sChkDoc: AnsiString; i: Integer; CtrlOpt: TAppCtrlOpt; sWText, sDept, sDocPath, sUName, sIpAddr: String; O: ISuperObject; begin Result := true; _nPageCnt := 0; _bDoStartProc := false; _sDocName := sDocName; CtrlOpt := gAppHook.Helper.CtrlOpt; // 필요 시 문서 식별 번호 생성, 저장 case CtrlOpt.dwCustomerType of CUSTOMER_DEMO, CUSTOMER_WELFND, CUSTOMER_WELFNI : begin _sPrtDocId := StrsReplace(TGUID.NewGuid.ToString, ['{', '}'], ''); SetRegValueString(HKEY_CURRENT_USER, 'Software\eCrmHomeEdition', 'PrtDocId', _sPrtDocId, true); end; else _sPrtDocId := ''; end; // if not SetRegValueString(HKEY_CURRENT_USER, 'Software\eCrmHomeEdition', 'PrtPName', gAppHook.ModuleName, true) then // SaveStrToFile('C:\ProgramData\HE\PrtPName.txt', Format('ProcStartDoc() ... PName=%s', [gAppHook.ModuleName])); // SetRegValueString(HKEY_CURRENT_USER, 'Software\eCrmHomeEdition', 'PrtPName1', '11111', true); // SaveStrToFile('C:\ProgramData\HE\test.txt', Format('ProcStartDoc() ... PName=%s', [gAppHook.ModuleName])); sUName := CtrlOpt.sUName; if sUName = '' then sUName := CtrlOpt.sEmpNo; sDept := gAppHook.Helper.CtrlOpt.sDeptName; sIpAddr := GetHostIP; case CtrlOpt.dwCustomerType of CUSTOMER_GEC, CUSTOMER_HDENG : sWText := sIpAddr{CtrlOpt.sIpAddr}; // Result.sPrintWaterTxt := Result.sDeptName + '/' + gMgSvc.EmpNo + '/' + gMgSvc.NicService.GetIP + '/' + FormatDateTime('yyyy-mm-dd', Now); CUSTOMER_INZENT : sWText := {Result.sDeptName + '/' + } CtrlOpt.sEmpNo + '/' + FormatDateTime('yyyy-mm-dd', Now) + '/INZENT'; CUSTOMER_SOLIDEO : begin if sDept <> '' then begin sDept := ExtrLastDelimiterStr(sDept, ';'); sWText := Format('(주)솔리데오 / %s / %s / %s', [sDept, sUName, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now)]); end else sWText := Format('(주)솔리데오 / %s / %s', [sUName, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now)]); end; CUSTOMER_CJONS : begin if sDept <> '' then begin sDept := ExtrLastDelimiterStr(sDept, ';'); sWText := Format('%s/%s/%s', [sUName, sDept, FormatDateTime('yyyy-mm-dd hh:nn', Now)]); end else sWText := Format('%s/%s', [sUName, FormatDateTime('yyyy-mm-dd hh:nn', Now)]); end; CUSTOMER_UNITUS, CUSTOMER_MOTRAS : begin if sUName <> '' then sWText := Format('%s / %s / %s / %s / %s', [sUName, sDept, gAppHook.Helper.CtrlOpt.sEmpNo, sIpAddr, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) else if sDept <> '' then sWText := Format('%s / %s / %s / %s', [sDept, gAppHook.Helper.CtrlOpt.sEmpNo, sIpAddr, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) else sWText := Format('%s / %s / %s', [gAppHook.Helper.CtrlOpt.sEmpNo, sIpAddr, FormatDateTime('yyyy-mm-dd hh:nn', Now)]); end; CUSTOMER_SHCI : begin if sUName <> '' then begin if sUName.Length > 1 then sUName[2] := '*'; sWText := Format('%s / %s / %s / %s', [gAppHook.Helper.CtrlOpt.sEmpNo, sUName, sDept, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now)]) end else if sDept <> '' then sWText := Format('%s / %s / %s', [gAppHook.Helper.CtrlOpt.sEmpNo, sDept, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now)]) else sWText := Format('%s / %s', [gAppHook.Helper.CtrlOpt.sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now)]); end; CUSTOMER_SHSC : begin var sEmpNo: String := gAppHook.Helper.CtrlOpt.sEmpNo; if sEmpNo.Length > 2 then sEmpNo[3] := '*'; if sEmpNo.Length > 3 then sEmpNo[4] := '*'; if sUName <> '' then begin if sUName.Length > 1 then sUName[2] := '*'; sWText := Format('%s / %s / %s', [sUName, sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) end else sWText := Format('%s / %s', [sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn', Now)]); end; CUSTOMER_SANKYO : begin sUName := CtrlOpt.sUName; if sUName <> '' then sWText := Format('%s / %s / %s', [sUName, gAppHook.Helper.CtrlOpt.sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) else sWText := Format('%s / %s', [gAppHook.Helper.CtrlOpt.sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn', Now)]); end; CUSTOMER_WELFND, CUSTOMER_WELFNI : begin var sTemp: String := _sPrtDocId; if sTemp.Length > 20 then SetLength(sTemp, 20); sWText := gAppHook.Helper.CtrlOpt.sEmpNo + '/' + sTemp; end; CUSTOMER_SERVE1 : begin if sDept <> '' then begin sDept := ExtrLastDelimiterStr(sDept, ';'); sWText := Format('%s / %s / %s / %s / %s', [sDept, sUName, gAppHook.Helper.CtrlOpt.sEmpNo, gAppHook.Helper.CtrlOpt.sIpAddr, FormatDateTime('yyyy-mm-dd hh:nn', Now)]); end else sWText := Format('%s / %s / %s', [gAppHook.Helper.CtrlOpt.sEmpNo, gAppHook.Helper.CtrlOpt.sIpAddr, FormatDateTime('yyyy-mm-dd hh:nn', Now)]); end; CUSTOMER_SOLMIX : begin sWText := Format('%s / %s / ', [gAppHook.Helper.CtrlOpt.sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now)]); end; // CUSTOMER_DEMO : // begin // sWText := _sPrtDocId; // end; CUSTOMER_KORENTAL : begin if gAppHook.Helper.CtrlOpt.sUName <> '' then sWText := Format('%s/%s/%s/%s/%s', [gAppHook.Helper.CtrlOpt.sEmpNo, gAppHook.Helper.CtrlOpt.sDeptName, gAppHook.Helper.CtrlOpt.sUName, gAppHook.Helper.CtrlOpt.sIpAddr, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) else if gAppHook.Helper.CtrlOpt.sDeptName <> '' then sWText := Format('%s/%s/%s/%s', [gAppHook.Helper.CtrlOpt.sEmpNo, gAppHook.Helper.CtrlOpt.sDeptName, gAppHook.Helper.CtrlOpt.sIpAddr, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) else sWText := Format('%s/%s/%s', [gAppHook.Helper.CtrlOpt.sEmpNo, gAppHook.Helper.CtrlOpt.sIpAddr, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) end; CUSTOMER_SKEC : begin if gAppHook.Helper.CtrlOpt.sUName <> '' then sWText := Format('%s / %s / %s / %s', [FormatDateTime('yyyy-mm-dd hh:nn', Now), gAppHook.Helper.CtrlOpt.sDeptName, gAppHook.Helper.CtrlOpt.sUName, gAppHook.Helper.CtrlOpt.sEmpNo]) else if gAppHook.Helper.CtrlOpt.sDeptName <> '' then sWText := Format('%s / %s / %s', [FormatDateTime('yyyy-mm-dd hh:nn', Now), gAppHook.Helper.CtrlOpt.sDeptName, gAppHook.Helper.CtrlOpt.sEmpNo]) else sWText := Format('%s / %s', [FormatDateTime('yyyy-mm-dd hh:nn', Now), gAppHook.Helper.CtrlOpt.sEmpNo]); end; else begin if sUName <> '' then sWText := Format('%s / %s / %s / %s', [sUName, sDept, gAppHook.Helper.CtrlOpt.sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) else if sDept <> '' then sWText := Format('%s / %s / %s', [sDept, gAppHook.Helper.CtrlOpt.sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn', Now)]) else sWText := Format('%s / %s', [gAppHook.Helper.CtrlOpt.sEmpNo, FormatDateTime('yyyy-mm-dd hh:nn', Now)]); end; end; gAppHook.Helper.CtrlOpt := CtrlOpt; gAppHook.Helper.sPrintWaterTxt := sWText; // LogToReg('PrintWaterTxt', gAppHook.Helper.sWText); if _bmpWater <> nil then FreeAndNil(_bmpWater); if _bmpWaterP <> nil then FreeAndNil(_bmpWaterP); _nFontSize := 0; // 웹브라우저의 경우 CreateDC를 디스플레이로 한번 더 하기 때문에 // _sDevName에 프린터 이름이 사라지는 현상이 있다 그래서 아래처럼 추가 처리 24_0627 14:19:34 kku if _sDevName <> '' then _sPrtName := _sDevName; // SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE); // SetProcessDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE); // DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'Step0'); // DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'Step1'); // DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'Step2'); // DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'Step3'); // DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'Step4'); // DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'Step5'); // DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'Step6'); // DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'Step7'); // LogToReg('Step1', Format('StartDocAHook, Cnt=%d', [gAppHook.PrtMaskList.Count])); gAppHook.Helper.bIsPrinting_ := true; (* if gAppHook.Helper.CtrlOpt.bPrintMasking and (gAppHook.PrtMaskList.Count = 0) then begin // LogToReg('Step2', Format('StartDocAHook, Cnt=%d', [gAppHook.PrtMaskList.Count])); // var sMskPath: String := 'C:\ProgramData\HE\Task\$mk.dat'; // if FileExists(sMskPath) then // begin // LogToReg('Step3', Format('StartPageHook, Cnt=%d', [gAppHook.PrtMaskList.Count])); // var StrList: TStringList; // Guard(StrList, TStringList.Create); // StrList.LoadFromFile(sMskPath, TEncoding.UTF8); // SplitString(StrList.Text, ',', gAppHook.PrtMaskList, false, true); // DeleteFile(PChar(sMskPath)); // LogToReg('Step4', Format('StartPageHook, Cnt=%d', [gAppHook.PrtMaskList.Count])); // end; var sVal: String := GetRegValueAsString(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'PrtMk'); // LogToReg('Step3', Format('StartDocAHook, Val=%s', [sVal])); SplitString(sVal, ',', gAppHook.PrtMaskList, false, true); // LogToReg('Step4', Format('StartDocAHook, Cnt=%d', [gAppHook.PrtMaskList.Count])); end; *) // LogToReg('Step0', 'PrintWater .. 0'); if gAppHook.Helper.CtrlOpt.bPrintSecu or gAppHook.Helper.CtrlOpt.bPrintWater then begin _bIgrPrtWater := sDocName.EndsWith(' *BSOne-'); _sLabelName := ''; // LogToReg('Step1', 'PrintWater .. 1 : ' + sDocName); case gAppHook.Helper.CtrlOpt.dwCustomerType of // CUSTOMER_CJONS, CUSTOMER_SOLIDEO : begin // LogToReg('Step00', '_sPrtName : ' + _sPrtName); if _sPrtName <> '' then begin var sChk: String := gAppHook.Helper.CtrlOpt.sPrintWaterImg; if sChk.StartsWith('*HB*|') then begin _bIgrPrtWater := true; var StrList: TStringList; Guard(StrList, TStringList.Create); SplitString(UpperCase(sChk), '|', StrList); sChk := UpperCase(_sPrtName); for i := 0 to StrList.Count - 1 do begin if Pos(StrList[i], sChk) > 0 then begin _bIgrPrtWater := false; break; end; end; end; end; end; CUSTOMER_GEC, CUSTOMER_HDENG : begin // 프린터에 따라 출력 처리 // if (gAppHook.Helper.CtrlOpt.dwCustomerType = CUSTOMER_GEC) and (_sPrtName <> '') then // begin // if (Pos('CANON', UpperCase(_sPrtName)) = 0) then // begin // _sLabelName := 'NoPrt'; // _bIgrPrtWater := true; // end; // end; if _sLabelName = '' then begin sDocPath := sDocName; if not FileExists(sDocPath) then begin // 엑셀에서 대괄호 [ 를 모두 괄호 ( 로 인식하는 문제가 있어서 아래처럼 처리 23_1218 10:44:27 kku sDocPath := FindPrintingFile(sDocPath, CompareText('excel.exe', gAppHook.ModuleName) = 0); end; // LogToReg('Step2', 'PrintWater .. 2 : ' + sDocPath); if (sDocPath = '') and (CompareText('notepad.exe', gAppHook.ModuleName) = 0) then begin // Windows 11 메모장에서 문서 이름이 현재 파일이 아닌 단순 "메모장"으로 뜨게된다. 23_0322 10:57:54 kku sDocPath := GetWindowCaption(GetForegroundWindow); sDocPath := FindPrintingFile(sDocPath); end; SetRegValueString(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'PrtPath', sDocPath, true); if FileExists(sDocPath) then begin // LogToReg('Step3', 'PrintWater .. 3 : ' + sDocPath); // _sLabelName := ExtractFileName(sDocPath); // _sLabelName := sDocPath; // 오피스 파일은 열려 있는 상태에서 레이블 확인이 불가능하다. 복사해서 처리 23_1018 17:28:11 kku var sTaskDir: String := 'C:\ProgramData\HE\HEC\'; if ForceDirectories(sTaskDir) then begin // LogToReg('Step4', 'PrintWater .. 4 : ' + sDocPath); var sDest: String := sTaskDir + ExtractFileName(sDocPath); if CopyFile(PChar(sDocPath), PChar(sDest), false) then begin // LogToReg('Step5', 'PrintWater .. 5 : ' + sDocPath); var h := FindWindow(nil, 'BSOne-AIP-T140713-BSOne-AIP-Decrypt.exe'); // if h = 0 then // h := FindAipMdWnd; if h <> 0 then begin // LogToReg('Step6', 'PrintWater .. 6 : ' + gAppHook.Helper.CtrlOpt.sAcSSid); O := SO; O.S['src'] := sDest; O.S['dst'] := sDest + '.tmp'; O.S['ssid'] := gAppHook.Helper.CtrlOpt.sAcSSid; DelRegValue(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'ALabel'); if SendData(h, 4, O.AsString) = 10 then begin _sLabelName := GetRegValueAsString(HKEY_CURRENT_USER, 'SOFTWARE\eCrmHomeEdition', 'ALabel'); // LogToReg('Step7', 'PrintWater .. 7 : ' + _sLabelName); if gAppHook.Helper.CtrlOpt.dwCustomerType = CUSTOMER_HDENG then begin i := Pos('(', _sLabelName); if i > 0 then SetLength(_sLabelName, i - 1); end; _bIgrPrtWater := (_sLabelName = '') or (Pos('일반', _sLabelName) > 0) or (Pos('ANYUSER', _sLabelName.ToUpper) > 0); if _bIgrPrtWater then _sLabelName := ''; end; // else // LogToReg('Step6', 'PrintWater .. 6 : ' + gAppHook.Helper.CtrlOpt.sAcSSid + ' Code : ' + IntToStr(i)); end; DeleteFile(PChar(sDest)); end; end; end else // 파일을 찾을 수 없을 경우 무조건 워터마크 찍도록 변경 23_1110 12:43:01 kku // if CompareText(gAppHook.ModuleName, 'MSIP.Viewer.exe') = 0 then begin // AIP 뷰어로 보는 파일은 파일 이름을 알아낼 방법이 없다.. // 그래서 강제 지정.. 23_1019 15:37:40 kku if gAppHook.Helper.CtrlOpt.dwCustomerType = CUSTOMER_HDENG then _sLabelName := '대외비' else _sLabelName := '대외비(Restricted)'; _bIgrPrtWater := false; end; end; if _sLabelName = '' then _bIgrPrtWater := true; end; CUSTOMER_TMAP : begin sDocPath := sDocName; if not FileExists(sDocPath) then begin // 엑셀에서 대괄호 [ 를 모두 괄호 ( 로 인식하는 문제가 있어서 아래처럼 처리 23_1218 10:44:27 kku sDocPath := FindPrintingFile(sDocPath, CompareText('excel.exe', gAppHook.ModuleName) = 0); end; if (sDocPath = '') and (CompareText('notepad.exe', gAppHook.ModuleName) = 0) then begin // Windows 11 메모장에서 문서 이름이 현재 파일이 아닌 단순 "메모장"으로 뜨게된다. 23_0322 10:57:54 kku sDocPath := GetWindowCaption(GetForegroundWindow); sDocPath := FindPrintingFile(sDocPath); end; {$IFDEF _BS1HP_} if FileExists(sDocPath) then begin if SendCopyData(gAppHook.Helper.CtrlOpt.hRcvWnd, HPCMD_CHECK_PRINTWATER_EXCEPT, sDocPath) = 300 then _bIgrPrtWater := true; end; {$ENDIF} end; end; {$IFDEF _BS1HP_} // 워터마크 예외 처리 추가 25_1014 14:12:19 kku if not _bIgrPrtWater then begin O := SO; O.S['PrtName'] := _sPrtName; if sDocPath = '' then begin sDocPath := sDocName; sDocPath := FindPrintingFile(sDocPath, CompareText('excel.exe', gAppHook.ModuleName) = 0); end; O.S['DocName'] := sDocPath; O.S['AppName'] := gAppHook.Helper.AppName; if SendCopyData(gAppHook.Helper.CtrlOpt.hRcvWnd, HPCMD_CHECK_PRINTWATER_EXCEPT_EX, O.AsJSon) = 300 then _bIgrPrtWater := true; end; {$ENDIF} // gAppHook.Helper.CopyPrintDC(dc); if gAppHook <> nil then begin {$IFDEF _BS1HP_} // if (gAppHook.Helper.CtrlOpt.hRcvWnd <> 0) and (gAppHook.Helper.sCurDocName_ <> sDocName) then // 다른 프로그램에서 출력하고 다시 동일 문서 출력 시 감지 안됨 25_0917 17:29:13 kku if gAppHook.Helper.CtrlOpt.hRcvWnd <> 0 then begin O := SO; O.S['PrtName'] := _sPrtName; O.S['DocName'] := sDocName; O.S['PrtDocId'] := _sPrtDocId; O.S['PName'] := gAppHook.ModuleName; O.I['PID'] := gAppHook.PID; var nRst: Integer := SendCopyData(gAppHook.Helper.CtrlOpt.hRcvWnd, HPCMD_PRINT_DOCNAME, O.AsJSon); if nRst = 300 then // 차단 25_1127 14:38:24 kku Result := false; // if (gAppHook.Helper.CtrlOpt.dwCustomerType = CUSTOMER_HDENG) and _bIgrPrtWater then // SendCopyData(gAppHook.Helper.CtrlOpt.hRcvWnd, HPCMD_PRINT_DOCNAME, 'NoWater') // else // SendCopyData(gAppHook.Helper.CtrlOpt.hRcvWnd, HPCMD_PRINT_DOCNAME, sDocName); end; {$ENDIF} // _nRecentPage := 0; gAppHook.Helper.nPtrCnt_ := 0; gAppHook.Helper.sCurDocName_ := sDocName; end; // _bIgrPrtWater := false; gAppHook.Log('StartDocWHook() - lpszDocName = ' + sDocName); if FileExists(gAppHook.sLogPath_) then DeleteFile(PChar(ExtractFilePath(gAppHook.sLogPath_) + 'PrintText.txt')); end; end; function CreateWatermarkBitmap(dc: HDC; sTxt: String): HBITMAP; var BmpDC: HDC; Bmp: HBITMAP; Font: HFONT; Text: string; begin BmpDC := CreateCompatibleDC(dc); Bmp := CreateCompatibleBitmap(dc, 800, 200); // 워터마크 영역 크기 SelectObject(BmpDC, Bmp); Font := CreateFont(48, 0, 0, 0, FW_BOLD, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, 'Arial'); SelectObject(BmpDC, Font); SetBkMode(BmpDC, TRANSPARENT); SetTextColor(BmpDC, RGB(150, 150, 150)); Text := sTxt; TextOut(BmpDC, 100, 50, PChar(Text), Length(Text)); DeleteDC(BmpDC); Result := Bmp; end; function StartDocAHook(dc: HDC; pDocInfo: PDocInfoA): Integer; stdcall; begin // SaveStrToFile('C:\ProgramData\HE\test1.txt', Format('StartDocAHook() ... PName=%s', [gAppHook.ModuleName])); if not ProcStartDoc(AnsiString(pDocInfo.lpszDocName)) then begin Result := 0; exit; end; Result := ozStartDocA(dc, pDocInfo); // CreateWatermarkBitmap(dc, 'StartDocAHook'); // if gAppHook.Helper.CopyPtrBmp_ <> nil then // Result := ozStartDocW(gAppHook.Helper.CopyPtrBmp_.Canvas.Handle, pDocInfo) // else // Result := ozStartDocW(dc, pDocInfo); end; function StartDocWHook(dc: HDC; pDocInfo: PDocInfoW): Integer; stdcall; var sChkDoc, sDocName: String; i: Integer; begin // SaveStrToFile('C:\ProgramData\HE\test2.txt', Format('StartDocWHook() ... PName=%s', [gAppHook.ModuleName])); if not ProcStartDoc(String(pDocInfo.lpszDocName)) then begin Result := 0; exit; end; Result := ozStartDocW(dc, pDocInfo); // CreateWatermarkBitmap(dc, 'StartDocWHook'); // if gAppHook.Helper.CopyPtrBmp_ <> nil then // Result := ozStartDocW(gAppHook.Helper.CopyPtrBmp_.Canvas.Handle, pDocInfo) // else // Result := ozStartDocW(dc, pDocInfo); end; function StartPageHook(dc: HDC): Integer; stdcall; begin _PrtDC := dc; _bDoEndProc := false; // _CopyXfInit := false; // if gAppHook.Helper.CtrlOpt.bPrintMasking then // gAppHook.Helper.PrtDC := DC // else // gAppHook.Helper.PrtDC := 0; // LogToReg('Step-', Format('StartPageHook, DC=%d, Cnt=%d', [DC, gAppHook.PrtMaskList.Count])); Inc(_nPageCnt); if gAppHook.Helper.CtrlOpt.bPrintSecu or gAppHook.Helper.CtrlOpt.bPrintWater then begin gAppHook.Log('StartPageHook()'); if not _bIgrPrtWater and (_sPrtName <> '') and (gAppHook.Helper.CtrlOpt.sPrintWaterExp <> '') then begin var ExpList: TStringList; var sChkName: String := UpperCase(_sPrtName); var i: Integer; Guard(ExpList, TStringList.Create); SplitString(UpperCase(gAppHook.Helper.CtrlOpt.sPrintWaterExp), '|', ExpList); for i := 0 to ExpList.Count - 1 do begin if Pos(ExpList[i], sChkName) > 0 then begin _bIgrPrtWater := true; break; end; end; end; Inc(gAppHook.Helper.nPtrCnt_); if gAppHook.Helper.CtrlOpt.bPrtCollect and (gAppHook.Helper.CtrlOpt.sPrtEmfOutDir <> '') then begin // gAppHook.Log('sTextOutDir = %s', [gAppHook.Helper.CtrlOpt.sTextOutDir]); CreateCopyDC(DC, GetValidFileName(_sDocName, '#'), _nPageCnt); end; Result := ozStartPage(dc); // 별도 프로시저 만들어서 사용하면 안된다.. 그래서 StartPageHook(), EndPageHook() 각각 구현 22_0907 15:06:14 kku if gAppHook.Helper.CtrlOpt.bPrintWater and (Result = 1) and ( not gAppHook.Helper.bEndDocProc_ or gAppHook.Helper.bBothDocProc_) then begin gAppHook.Log('StartPageHook() .. ProcessWartermark()'); if not ProcessWartermarkCustomer(gAppHook.Helper.CtrlOpt.dwCustomerType, dc, true) then Result := -1; end; end else begin Result := ozStartPage(dc); end; end; function EndPageHook(dc: HDC): Integer; stdcall; begin if gAppHook.Helper.CtrlOpt.bPrintWater and (gAppHook.Helper.bEndDocProc_ or gAppHook.Helper.bBothDocProc_) then begin gAppHook.Log('EndPageHook() .. ProcessWartermark()'); if not ProcessWartermarkCustomer(gAppHook.Helper.CtrlOpt.dwCustomerType, dc, false) then Result := -1; end; gAppHook.Log('EndPageHook()'); DeleteCopyDC; gAppHook.Helper.sPtrText_ := ''; _bDoStartProc := false; Result := ozEndPage(dc); _PrtDC := 0; end; function EndDocHook(dc: HDC): Integer; begin // CreateWatermarkBitmap(dc, 'EndDocHook'); Result := ozEndDoc(dc); try if gAppHook <> nil then begin // SetRegValueString(HKEY_CURRENT_USER, 'Software\eCrmHomeEdition', 'PrtPageCnt', IntToStr(_nPageCnt), true); gAppHook.Helper.bIsPrinting_ := false; // gAppHook.PrtMaskList.Clear; // Word에서는 부수 정보를 제대로 가져올 수 없어서 // 이렇게 전체 출력되는 페이지 정보를 별도 가져와서 계산한다 25_0813 14:48:40 kku // if CompareText('winword.exe', gAppHook.ModuleName) = 0 then // begin // var O: ISuperObject := SO; // O.S['MdPath'] := gAppHook.ModulePath; // O.S['PrtName'] := _sPrtName; // O.S['DrvName'] := _sDrvName; // O.S['DevName'] := _sDevName; // O.S['DocName'] := _sDocName; // O.I['PageCnt'] := _nPageCnt; // SendCopyData(gAppHook.Helper.CtrlOpt.hRcvWnd, HPCMD_PRINT_ENDDOC_INFO, O.AsJSon); // end; end; _bIgrPrtWater := false; _sLabelName := ''; if _bmpWater <> nil then FreeAndNil(_bmpWater); if _bmpWaterP <> nil then FreeAndNil(_bmpWaterP); except // .. end; end; function WritePrinterHook(hPrinter: THandle; pBuf: Pointer; cbBuf: DWORD; var pcWritten: DWORD): BOOL; stdcall; begin // gAppHook.Log('WritePrinterHook()'); // var fs: TFileStream; // Guard(fs, TFileStream.Create('c:\WritePrinterHook.dat', fmCreate)); // fs.Write(pBuf^, cbBuf); Result := ozWritePrinter(hPrinter, pBuf, cbBuf, pcWritten); end; // 이렇게 하면 Release 빌드 시 프린트가 실패한다;; 이유는 몰라, 귀찮아서 넘어감 22_1013 16:12:53 kku //function EndDocHook(dc: HDC): Integer; stdcall; //begin // if gAppHook.PrintMarkActive and (gAppHook.sRecentPtrDoc_ <> '') then // gAppHook.ProcessNoti(NOTI_HOOK_MONITOR_PRINT_WATER, gAppHook.sRecentPtrDoc_); //end; //procedure ReplaceTextA(sStr: LPCSTR); inline; stdcall; //var // sData: AnsiString; // bMod: Boolean; // i: Integer; //begin // try // if gAppHook = nil then // exit; // // if not gAppHook.Helper.bIsPrinting_ or (gAppHook.PrtMaskList.Count = 0) then // exit; // // bMod := false; // sData := AnsiString(sStr); // // for i := 0 to gAppHook.PrtMaskList.Count - 1 do // begin // if Pos(gAppHook.PrtMaskList[i], sData) > 0 then // begin // sData := StringReplace(sData, gAppHook.PrtMaskList[i], // MakeCharStr('*', Length(gAppHook.PrtMaskList[i])), [rfReplaceAll]); // bMod := true; // end; // end; // // if bMod then // CopyMemory(@sStr[0], @sData[1], Length(sData)); // except // // .. // end; //end; function LPCWSTRToString(const ws: LPCWSTR): UTF8String; var len: Integer; begin // WideChar (UTF-16)에서 UTF-8로 변환 len := WideCharToMultiByte(CP_UTF8, 0, ws, -1, nil, 0, nil, nil); SetLength(Result, len - 1); if len > 1 then begin WideCharToMultiByte(CP_UTF8, 0, ws, -1, PAnsiChar(Result), len - 1, nil, nil); end; end; //procedure ReplaceTextW(sStr: LPCWSTR); inline; stdcall; //var // sData: String; // bMod: Boolean; // i: Integer; //begin // try // if gAppHook = nil then // exit; // //// LogToReg('Step8', Format('ReplaceTextW, Cnt=%d, DC=%d', [gAppHook.PrtMaskList.Count, gAppHook.Helper.PrtDC])); // //// if not gAppHook.Helper.bIsPrinting_ or (gAppHook.PrtMaskList.Count = 0) then //// exit; // // LogToReg('Step9', Format('ReplaceTextW, Cnt=%d', [gAppHook.PrtMaskList.Count])); // // bMod := false; // sData := WideString(sStr); // //// if Pos('로그', sData) > 0 then //// begin //// sData := StringReplace(sData, '로그', '**', [rfReplaceAll]); //// bMod := true; //// end; // //// LogToReg(Format('Step10-%d, PName=%s', [_nTest, gAppHook.ModuleName]), sData); // for i := 0 to gAppHook.PrtMaskList.Count - 1 do // begin // if Pos(gAppHook.PrtMaskList[i], sData) > 0 then // begin // sData := StringReplace(sData, gAppHook.PrtMaskList[i], // MakeCharStr('*', Length(gAppHook.PrtMaskList[i])), [rfReplaceAll]); // LogToReg('Step10', Format('ReplaceTextW, Match=%s', [sData, gAppHook.PrtMaskList[i]])); // bMod := true; // end; // end; // // if bMod then // CopyMemory(@sStr[0], @sData[1], Length(sData) * 2); // except // // .. // end; //end; { // nX := 0; nX := GetDeviceCaps(DC, ASPECTX); // nY := GetDeviceCaps(DC, ASPECTY); // for i := 0 to 3 do // sOut := sOut + WORD_GAP + sOut; i := GetDeviceCaps(DC, ASPECTY) - 300; // 0; nRepeat := 2; // gAppHook.Helper.CtrlOpt.nLineCount; nGapH := nH div nRepeat; // (nRepeat - 1); if gAppHook.Helper.bSmallFont_ then nGapH := nGapH div 7; while i < nH do // + nGapH do begin MemCanvas.TextOut(nX, i, sOut); Inc(i, nGapH); Dec(nRepeat); if nRepeat = 0 then break; end; if bStartPage then begin BitBlt(DC, 0, 0, nW, nH, MemCanvas.Handle, 0, 0, SRCCOPY); // var bf: BLENDFUNCTION; // ZeroMemory(@bf, SizeOf(bf)); // bf.AlphaFormat := 0; // 일반 비트맵 0, 32비트 비트맵 AC_SRC_ALPHA // bf.BlendFlags := 0; // 무조건 0 // bf.BlendOp := AC_SRC_OVER; // AC_SRC_OVER // bf.SourceConstantAlpha := 100; // 투명도(투명 0 - 불투명 255) // AlphaBlend(DC, 0, 0, nW, nH, MemCanvas.Handle, 0, 0, nW, nH, bf); end; } // //function DrawTextAHook(hDC: HDC; lpString: LPCSTR; nCount: Integer; // var lpRect: TRect; uFormat: UINT): Integer; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = hDC) then // ReplaceTextA(lpString); // Result := ozDrawTextA(hDc, lpString, nCount, lpRect, uFormat); //end; // //function DrawTextWHook(hDC: HDC; lpString: LPCWSTR; nCount: Integer; // var lpRect: TRect; uFormat: UINT): Integer; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = hDC) then // ReplaceTextW(lpString); // Result := ozDrawTextW(hDc, lpString, nCount, lpRect, uFormat); //end; // //function DrawTextExAHook(DC: HDC; lpchText: LPCSTR; cchText: Integer; var p4: TRect; // dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = DC) then // ReplaceTextA(lpchText); // Result := ozDrawTextExA(DC, lpchText, cchText, p4, dwDTFormat, DTParams); //end; // //function DrawTextExWHook(DC: HDC; lpchText: LPCWSTR; cchText: Integer; var p4: TRect; // dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = DC) then // ReplaceTextW(lpchText); // Result := ozDrawTextExW(DC, lpchText, cchText, p4, dwDTFormat, DTParams); //end; // //function ExtTextOutAHook(DC: HDC; X, Y: Integer; Options: Longint; // Rect: PRect; Str: LPCSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = DC) then // ReplaceTextA(Str); // Result := ozExtTextOutA(DC, X, Y, Options, Rect, Str, Count, Dx); //end; // //function ExtTextOutWHook(DC: HDC; X, Y: Integer; Options: Longint; // Rect: PRect; Str: LPCWSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = DC) then // ReplaceTextW(Str); // Result := ozExtTextOutW(DC, X, Y, Options, Rect, Str, Count, Dx); //end; // //function TextOutAHook(DC: HDC; X, Y: Integer; Str: LPCSTR; Count: Integer): BOOL; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = DC) then // ReplaceTextA(Str); // Result := ozTextOutA(DC, X, Y, Str, Count); //end; // //function TextOutWHook(DC: HDC; X, Y: Integer; Str: LPCWSTR; Count: Integer): BOOL; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = DC) then // ReplaceTextW(Str); // Result := ozTextOutW(DC, X, Y, Str, Count); //end; // //function PolyTextOutAHook(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; //type // TArrayLPCSTR = array [0..0] of LPCSTR; //var // i: Integer; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = DC) then // begin // try // for i := 0 to Strings - 1 do // ReplaceTextA(TArrayLPCSTR(PolyTextArray)[i]); // except // // .. // end; // end; // Result := ozPolyTextOutA(DC, PolyTextArray, Strings); //end; // //function PolyTextOutWHook(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; //type // TArrayLPCWSTR = array [0..0] of LPCWSTR; //var // i: Integer; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = DC) then // begin // try // for i := 0 to Strings - 1 do // ReplaceTextW(TArrayLPCWSTR(PolyTextArray)[i]); // except // // .. // end; // end; // Result := ozPolyTextOutW(DC, PolyTextArray, Strings); //end; // //function TabbedTextOutAHook(hDC: HDC; X, Y: Integer; lpString: LPCSTR; nCount, nTabPositions: Integer; // var lpnTabStopPositions; nTabOrigin: Integer): Longint; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = hDC) then // ReplaceTextA(lpString); // Result := ozTabbedTextOutA(hDC, X, Y, lpString, nCount, nTabPositions, // lpnTabStopPositions, nTabOrigin); //end; // //function TabbedTextOutWHook(hDC: HDC; X, Y: Integer; lpString: LPCWSTR; nCount, nTabPositions: Integer; // var lpnTabStopPositions; nTabOrigin: Integer): Longint; stdcall; //begin // if (gAppHook <> nil) and (gAppHook.Helper.PrtDC = hDC) then // ReplaceTextW(lpString); // Result := ozTabbedTextOutW(hDC, X, Y, lpString, nCount, nTabPositions, // lpnTabStopPositions, nTabOrigin); //end; initialization _bmpWater := nil; _bmpWaterP := nil; _sbmpWaterIf := ''; _sLabelName := ''; _bIgrPrtWater := false; _PrtDC := 0; _bDoStartProc := false; _bDoEndProc := false; _nFontSize := 0; _sDrvName := ''; _sDevName := ''; _sPrtName := ''; gPrtWatering := false; end.