BSOne.SFC/eCrmHE/DLL_eCrmHeHelper/PrintWatermark/ProcessWM_GEC.pas

523 lines
21 KiB
Plaintext

{*******************************************************}
{ }
{ ProcessWatermark }
{ }
{ Copyright (C) 2025 kku }
{ }
{*******************************************************}
unit ProcessWM_GEC;
interface
uses
Winapi.Windows, System.Classes, Vcl.Graphics;
function ProcessWartermark_GEC(DC: HDC; bStartPage: Boolean = true): Boolean;
implementation
uses
AppCtrlDefine, ApiHookPrint, BS1Hook, Tocsg.Safe, System.SysUtils, Condition,
Tocsg.Graphic, Winapi.GDIPAPI, Tocsg.Strings, Vcl.Imaging.jpeg;
function ProcessWartermark_GEC(DC: HDC; bStartPage: Boolean = true): Boolean;
var
nW, nH, i, nX, nY, nWW, nHH, nXX, nYY,
nGapW, nGapH: Integer;
sText, sOut, sImgPath: String;
MemCanvas: TCanvas;
hbmp, hOldBmp: HBITMAP;
pen: HPEN;
CtrlOpt: TAppCtrlOpt;
oldColor: TColor;
hOldFont: HFONT;
nDPI, nFontH, nFontHmax: Integer;
// 만들어 놓은 BMP를 재사용하면 배경 투명처리가 안되서 이렇게 사용 23_1221 08:15:33 kku
function CreateTextBmp(sOutText: String): TBitmap;
begin
Result := TBitmap.Create;
Result.PixelFormat := pf4bit;
Result.Canvas.Font.Assign(MemCanvas.Font);
// Result.Canvas.Font.Color := clSilver;
// if nFontSize <> -1 then
// Result.Canvas.Font.Size := nFontSize;
Result.SetSize(Result.Canvas.TextWidth(sOutText), Result.Canvas.TextHeight(sOutText));
// Result.Canvas.Brush.Color := clWhite;
// Result.Canvas.Brush.Style := bsSolid;
// SetBkMode(Result.Canvas.Handle, TRANSPARENT);
SetBkColor(Result.Canvas.Handle, RGB(255, 255, 255));
Result.Canvas.TextOut(0, 0, sOutText);
Result.TransparentColor := clWhite;
Result.Transparent := true;
end;
begin
Result := true;
// if _nRecentPage < gAppHook.Helper.nPtrCnt_ then
// _nRecentPage := gAppHook.Helper.nPtrCnt_
// else exit;
// if _nRecentPage > 0 then
// exit;
// _nRecentPage := 1;
// 엑셀 (excel.exe)의 경우 이렇게 안하면 다음 페이지로 밀리는 현상 있음.
// 아마도 DC를 별도 추가 처리 하는 듯 함 23_1024 11:00:13 kku
if _PrtDC <> DC then
exit;
if _bIgrPrtWater then
exit;
// if gAppHook.Helper.IsExcel then
// begin
// if bStartPage then
// LogToReg(Format('WATER_Excel_ST_%d', [_nTest]), Format('DC=%d, W=%d, H=%d', [DC, GetDeviceCaps(DC, HORZRES), GetDeviceCaps(DC, VERTRES)]))
// else
// LogToReg(Format('WATER_Excel_ED_%d', [_nTest]), Format('DC=%d, W=%d, H=%d', [DC, GetDeviceCaps(DC, HORZRES), GetDeviceCaps(DC, VERTRES)]));
// Inc(_nTest);
// end;
bStartPage := false;
SaveDC(DC);
gAppHook.Helper.bIsWaterMaking_ := true;
try
try
// nW := GetDeviceCaps(DC, PHYSICALWIDTH); // 세로모드 : 4961, 가로모드 : 7016, 크로미움 프린트 인쇄시 4760
// nH := GetDeviceCaps(DC, PHYSICALHEIGHT); // 가로모드 : 7016, 가로모드 : 4961, 크로미움 프린트 인쇄시 6814
nW := GetDeviceCaps(DC, HORZRES); // 세로모드 : 4961, 가로모드 : 7016, 크로미움 프린트 인쇄시 4760
nH := GetDeviceCaps(DC, VERTRES); // 가로모드 : 7016, 가로모드 : 4961, 크로미움 프린트 인쇄시 6814
nX := GetDeviceCaps(DC, ASPECTX);
nY := GetDeviceCaps(DC, ASPECTY);
// 인도현지 프린터 종류
// 캐논 IRC3326, 쿄세라(kyocera) M8124
nDPI := GetDeviceCaps(DC, LOGPIXELSX);
// LogToReg('PrinterDPI', IntToStr(nDPI));
if nDPI < 600 then
begin
// 인도 현지 캐논 프린트 최대 DPI가 300이다 24_0621 10:22:10 kku
nFontH := 70;
nFontHmax := 80;
end else begin
nFontH := 180;
nFontHmax := 200;
end;
// 작업 후 폰트 롤백을 위한 백업 23_1018 11:21:29 kku
hOldFont := GetCurrentObject(DC, OBJ_FONT);
Guard(MemCanvas, TCanvas.Create);
if bStartPage then // 필요없음
MemCanvas.Handle := CreateCompatibleDC(DC)
else
MemCanvas.Handle := DC; //CreateCompatibleDC(DC);
hbmp := CreateCompatibleBitmap(MemCanvas.Handle, nW, nH);
hOldBmp := SelectObject(MemCanvas.Handle, hbmp);
gAppHook.Log(Format('ProcessWartermark_GEC() - DocSize X=%d, Y=%d, W=%d, H=%d, dc=%d', [nX, nY, nW, nH, DC]));
if bStartPage then
PatBlt(MemCanvas.Handle, 0, 0, nW, nH, WHITENESS);
nGapW := 0;
nGapH := 0;
// SetBkMode(MemCanvas.Handle, TRANSPARENT);
oldColor := GetTextColor(MemCanvas.Handle);
// 폰트색 지정... 프로그램에 따라 지정되는 설정이 다르다
MemCanvas.Font.Color := clGray; // 메모장등
SetTextColor(MemCanvas.Handle, clGray); // 엑셀등
// MemCanvas.Font.Name := 'Tahoma';
// MemCanvas.Font.Name := '돋음';
if gAppHook.Helper.bEndDocProc_ then
begin
if (CompareText(gAppHook.ModuleName, 'winword.exe') = 0) or
(CompareText(gAppHook.ModuleName, 'MSIP.Viewer.exe') = 0) then
nGapH := 85;
end;
MemCanvas.Font.Size := 60;
// sOut := gAppHook.Helper.CtrlOpt.sPrintWaterTxt;
sOut := '';
if gAppHook.Helper.CtrlOpt.sDeptName <> '' then
SumString(sOut, gAppHook.Helper.CtrlOpt.sDeptName, '/');
if gAppHook.Helper.CtrlOpt.sEmpNo <> '' then
SumString(sOut, gAppHook.Helper.CtrlOpt.sEmpNo, '/');
if gAppHook.Helper.sPrintWaterTxt <> '' then
SumString(sOut, gAppHook.Helper.sPrintWaterTxt, '/');
SumString(sOut, FormatDateTime('yyyy-mm-dd', Now), '/');
if _sbmpWaterIf <> sOut then
begin
// 이미지 캐시 초기화 추가 24_1213 14:05:40 kku
_sbmpWaterIf := sOut;
if _bmpWater <> nil then
FreeAndNil(_bmpWater);
if _bmpWaterP <> nil then
FreeAndNil(_bmpWater);
end;
if _nFontSize = 0 then
begin
_nFontSize := MemCanvas.Font.Size;
while True do
begin
if _nFontSize > nFontHmax then
break;
// if MemCanvas.TextWidth(sOut) > 3000 then // 부서명이 들어간 후 2000에서 변경
if MemCanvas.TextHeight(sOut) > nFontH then // 부서명이 들어간 후 2000에서 변경
begin
Dec(_nFontSize);
break;
end;
Inc(_nFontSize);
MemCanvas.Font.Size := _nFontSize;
end;
end;
if nDPI < 600 then
MemCanvas.Font.Size := _nFontSize - Round(_nFontSize / 2.5)
else
MemCanvas.Font.Size := _nFontSize - (_nFontSize div 3);
// sOut := IntToStr(MemCanvas.Font.Size) + ' - ' + sOut;
try
if gAppHook.Helper.bSmallFont_ then
begin
// 브라우저등의 경우... 폰트 크기를 가늠할수가 없다.
// 그래서 아래처럼 이미지로 처리 23_1017 13:10:40 kku
// var bmpText: TBitmap;
// Guard(bmpText, TBitmap.Create);
// bmpText.PixelFormat := pf4bit;
// bmpText.Canvas.Font.Assign(MemCanvas.Font);
// bmpText.Canvas.Font.Size := 12;
// bmpText.Canvas.Brush.Color := clWhite;
//// bmpText.Canvas.Brush.Style := bsClear;
//// bmpText.font
// sText := '작은 습관으로 시작되는 보안';
// bmpText.SetSize(bmpText.Canvas.TextWidth(sText), bmpText.Canvas.TextHeight(sText));
// bmpText.Canvas.TextOut(0, 0, sText);
// MemCanvas.Draw(nW - bmpText.Width + nGapW + nGapW2, nH - bmpText.Height + nGapH + nGapH2, bmpText);
// 음..브라우저에서 상하단 문구 제거 23_1017 13:26:47 kku
end else begin
// var sDocInfo: String := 'c:\ProgramData\HE\Task\$TEST.txt';
// begin
// if FileExists(sDocInfo) then
// begin
// var StrList: TStringList;
// Guard(StrList, TStringList.Create);
// StrList.LoadFromFile(sDocInfo, TEncoding.UTF8);
// DeleteFile(sDocInfo);
// if StrList.Text <> '' then
// begin
// sText := StrList.Text;
// MemCanvas.TextOut(nGapW - MemCanvas.TextWidth(sText), nGapH, Format('%s', [sText]));
// end;
// end;
// end;
var bmpText: TBitmap;
var rcText: TRect;
// 우측 상단
if _sLabelName <> '' then
begin
sText := _sLabelName;
if nDPI > 300 then
sText := sText + ' '; // 쿄세라 프린터에서 오른쪽 짤리는 현상이 있어서 공백 하나 넣어줌 24_0621 11:11:28 kku
Guard(bmpText, CreateTextBmp(sText));
ZeroMemory(@rcText, SizeOf(rcText));
rcText.Left := nW - bmpText.Width;
rcText.Right := rcText.Left + bmpText.Width + 1;
rcText.Top := 0;
rcText.Bottom := bmpText.Height + 1;
// MemCanvas.Draw(nW - bmpText.Width, 0, bmpText);
MemCanvas.StretchDraw(rcText, bmpText); // 이렇게 해야 프린터에서 인식함.. 24_0108 14:25:59 kku
// MemCanvas.TextOut(nW - MemCanvas.TextWidth(_sLabelName) + nGapW, nGapH, _sLabelName);
end;
// 우측 하단
begin
sText := 'Security Starts with Small Habits';
if nDPI > 300 then
sText := sText + ' '; // 쿄세라 프린터에서 오른쪽 짤리는 현상이 있어서 공백 하나 넣어줌 24_0621 11:11:28 kku
Guard(bmpText, CreateTextBmp(sText));
ZeroMemory(@rcText, SizeOf(rcText));
rcText.Left := nW - bmpText.Width + nGapW;
rcText.Right := rcText.Left + bmpText.Width + 1;
rcText.Top := nH - bmpText.Height;
rcText.Bottom := rcText.Top + bmpText.Height + 1;
// 왜인지는 모르겠지만.. 아래 텍스트와는 다르게 세로 갭을 넣을 필요가 없다... (winword.exe) 23_1211 16:10:21 kku
// MemCanvas.Draw(nW - bmpText.Width + nGapW, nH - bmpText.Height, bmpText);
MemCanvas.StretchDraw(rcText, bmpText);
// sText := Format('px=%d, 작은 습관으로 시작되는 보안', [MemCanvas.Font.PixelsPerInch]);
// sText := '작은 습관으로 시작되는 보안';
// MemCanvas.TextOut(nW - MemCanvas.TextWidth(sText) + nGapW,
// nH - MemCanvas.TextHeight(sText) + nGapH, sText);
end;
//
if nDPI < 600 then
MemCanvas.Font.Size := _nFontSize div 5
else
MemCanvas.Font.Size := _nFontSize div 4;
// 좌측 하단
// begin
// sText := '본 문서는 현대엔지니어링의 정보자산이며 본 문서에 대한 무단복제 및 무단도용은 당사 사규와 관련 법규에 의해 제재를 받을 수 있습니다.';
// Guard(bmpText, CreateTextBmp(sText));
//
// ZeroMemory(@rcText, SizeOf(rcText));
// rcText.Left := nGapW;
// rcText.Right := rcText.Left + bmpText.Width + 1;
// rcText.Top := nH - (bmpText.Height * 2);
// rcText.Bottom := rcText.Top + bmpText.Height + 1;
//
//// MemCanvas.Draw(nGapW, nH - (bmpText.Height * 2), bmpText);
// MemCanvas.StretchDraw(rcText, bmpText);
// end;
begin
sText := 'This document or drawing is the property of Hyundai Engineering. Any reproduction or distribution of the materials without permission of Hyundai engineering is strictly prohibited.';
if nDPI > 300 then
sText := ' ' + sText; // 쿄세라 프린터에서 왼쪽 짤리는 현상이 있어서 공백 넣어줌 24_0621 11:11:28 kku
Guard(bmpText, CreateTextBmp(sText));
ZeroMemory(@rcText, SizeOf(rcText));
rcText.Left := nGapW;
rcText.Right := rcText.Left + bmpText.Width + 1;
rcText.Top := nH - bmpText.Height - 5;
rcText.Bottom := rcText.Top + bmpText.Height + 1;
// MemCanvas.Draw(nGapW, nH - bmpText.Height - 5, bmpText);
MemCanvas.StretchDraw(rcText, bmpText);
end;
sText := '';
if gAppHook.Helper.CtrlOpt.sDeptName <> '' then
SumString(sText, gAppHook.Helper.CtrlOpt.sDeptName, '/');
if gAppHook.Helper.CtrlOpt.sUName <> '' then
SumString(sText, gAppHook.Helper.CtrlOpt.sUName, '/');
SumString(sText, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now), '/');
// 좌측 상단
// begin
// Guard(bmpText, CreateTextBmp(sText));
//
// ZeroMemory(@rcText, SizeOf(rcText));
// rcText.Left := 0;
// rcText.Right := rcText.Left + bmpText.Width + 1;
// rcText.Top := 0;
// rcText.Bottom := rcText.Top + bmpText.Height + 1;
//
//// MemCanvas.Draw(0, 0, bmpText);
// MemCanvas.StretchDraw(rcText, bmpText);
// end;
// if nGapH = 85 then
// begin
// sText := '본 문서는 현대엔지니어링의 정보자산이며 본 문서에 대한 무단복제 및 무단도용은 당사 사규와 관련 법규에 의해 제재를 받을 수 있습니다.';
// MemCanvas.TextOut(nGapW, nH - (MemCanvas.TextHeight(sText) * 2) + nGapH - 65, sText);
// sText := 'This document or drawing is the property of Hyundai Engineering. Any reproduction or distribution of the materials without permission of Hyundai engineering is strictly prohibited.';
// MemCanvas.TextOut(nGapW, nH - (MemCanvas.TextHeight(sText)) + nGapH - 65, sText);
// end else begin
// sText := '본 문서는 현대엔지니어링의 정보자산이며 본 문서에 대한 무단복제 및 무단도용은 당사 사규와 관련 법규에 의해 제재를 받을 수 있습니다.';
// MemCanvas.TextOut(nGapW, nH - (MemCanvas.TextHeight(sText) * 2) + nGapH, sText);
// sText := 'This document or drawing is the property of Hyundai Engineering. Any reproduction or distribution of the materials without permission of Hyundai engineering is strictly prohibited.';
// MemCanvas.TextOut(nGapW, nH - (MemCanvas.TextHeight(sText)) + nGapH, sText);
// end;
end;
// 워터마크 이미지 처리 23_1011 10:41:31 kku
sImgPath := ExtractFilePath(gAppHook.Helper.DllPath) + 'HWMJ.dat';
if FileExists(sImgPath) then
begin
if _bmpWaterP = nil then
begin
var jpg: TJPEGImage;
// Guard(jpg, TJPEGImage.Create);
jpg := TJPEGImage.Create;
jpg.LoadFromFile(sImgPath);
var bmpImg: TBitmap;
// Guard(bmpImg, TBitmap.Create);
bmpImg := TBitmap.Create;
bmpImg.Assign(jpg);
jpg.Free; // Free
// bmpImg.Canvas.Font.Name := 'Tahoma';
// bmpImg.Canvas.Font.Name := '돋음';
bmpImg.Canvas.Font.Assign(MemCanvas.Font);
bmpImg.Canvas.Font.Color := clSilver;
// bmpImg.Canvas.Font.Size := 40;
bmpImg.Canvas.Font.Size := _nFontSize - (_nFontSize div 2);
bmpImg.Canvas.Font.Style := bmpImg.Canvas.Font.Style + [fsBold];
//---
// sOut := '정보보호부문/2323308/10.177.15.123/2023-12-31';
// HEC 새로운 요구사항 반영 23_1121 10:22:09 kku
// bmpImg.Canvas.Font.Size := bmpImg.Canvas.Font.Size + 14;
// ScalePercentBmp(bmpImg, 120);
//---
if nDPI < 600 then
bmpImg.Canvas.Font.Size := bmpImg.Canvas.Font.Size + 20;
nWW := bmpImg.Canvas.TextWidth(sOut);
if bmpImg.Width > nWW then
nWW := bmpImg.Width;
nHH := bmpImg.Height + bmpImg.Canvas.TextHeight(sOut);
_bmpWaterP := TBitmap.Create;
_bmpWaterP.Canvas.Font.Assign(bmpImg.Canvas.Font);
_bmpWaterP.PixelFormat := pf4bit; // pf32bit;
_bmpWaterP.SetSize(nWW, nHH);
_bmpWaterP.Canvas.Brush.Color := clWhite;
_bmpWaterP.Canvas.Brush.Style := bsSolid;
_bmpWaterP.Canvas.FillRect(Rect(0, 0, _bmpWaterP.Width, _bmpWaterP.Height));
// _bmpWaterP.Canvas.Brush.Style := bsClear; // x
_bmpWaterP.Canvas.Draw((nWW div 2) - (bmpImg.Width div 2), 0, bmpImg);
_bmpWaterP.Canvas.TextOut(0, bmpImg.Height, sOut);
// _bmpWaterP.Canvas.TextOut(0, (_bmpWaterP.Height div 2) - (_bmpWaterP.Canvas.TextHeight(sOut) div 2), sOut);
bmpImg.Free; // Free
// RotateBitmap_STF(_bmpWaterP, -0.7, true, clWhite, 200);
RotateBitmap_PlgBlt(_bmpWaterP, -0.7, true, clWhite);
var ii: Integer;
var jj: Integer;
if gAppHook.Helper.IsExcel then
begin
// 도트 투명도 설정
for ii := 0 to _bmpWaterP.Width - 1 do
for jj := 0 to _bmpWaterP.Height - 1 do
if _bmpWaterP.Canvas.Pixels[ii, jj] <> clWhite then
if ((ii + jj) mod 4) = 0 then
_bmpWaterP.Canvas.Pixels[ii, jj] := clWhite
else
_bmpWaterP.Canvas.Pixels[ii, jj] := clSilver;
end else
begin
for ii := 0 to _bmpWaterP.Width - 1 do
for jj := 0 to _bmpWaterP.Height - 1 do
if _bmpWaterP.Canvas.Pixels[ii, jj] <> clWhite then
_bmpWaterP.Canvas.Pixels[ii, jj] := clGray;
end;
// if nDPI < 600 then
// ScalePercentBmp(_bmpWaterP, 65)
// else
ScalePercentBmp(_bmpWaterP, 60);
_bmpWaterP.TransparentColor := clWhite;
_bmpWaterP.Transparent := true;
end;
if (_bmpWater = nil) and (_bmpWaterP <> nil) then
begin
// HEC 보안프린터에서 컬러 출력시 아래 부분이 검은색으로 찍히는 문제가 있다...
// 이렇게 크기를 반으로 줄이고 덮어쓸때 늘리면 해결됨... 23_1103 13:42:54 kku
var nIW: Integer := nW - (nW div 2);
var nIH: Integer := nH - (nH div 2);
if nDPI < 600 then
begin
nIW := nIW * 2;
nIH := nIH * 2;
end;
_bmpWater := TBitmap.Create;
_bmpWater.PixelFormat := pf4bit;
// _bmpWater.SetSize(nW-1, nH-1); // 크기를 똑같이 하면 StretchDraw() 이게 무시되서 1씩 줄임
_bmpWater.SetSize(nIW, nIH); // 크기를 똑같이 하면 StretchDraw() 이게 무시되서 1씩 줄임
_bmpWater.Canvas.Brush.Color := clWhite;// clRed;
_bmpWater.Canvas.Brush.Style := bsSolid;
_bmpWater.Canvas.FillRect(Rect(0, 0, _bmpWater.Width, _bmpWater.Height));
// _bmpWater.Canvas.Brush.Style := bsClear;
// bmpWater.SaveToFile('C:\Users\kkuzil\Desktop\출력테스트\1.bmp');
nX := (nIW div 2) - (_bmpWaterP.Width div 2);
nY := (nIH div 2) - (nIH div 3);
_bmpWater.Canvas.Draw(nX, nY, _bmpWaterP);
// c.Draw(nX, nY, bmpWater);
// BitBlt(DC, nX, nY, nWW, nHH, bmpWater.Canvas.Handle, 0, 0, SRCCOPY);
nY := (nIH div 2) + (nIH div 10);
_bmpWater.Canvas.Draw(nX, nY, _bmpWaterP);
// c.Draw(nX, nY, bmpWater);
// BitBlt(DC, nX, nY, nWW, nHH, bmpWater.Canvas.Handle, 0, 0, SRCCOPY);
_bmpWater.TransparentColor := clWhite;
_bmpWater.Transparent := true;
end;
if bStartPage then
begin
// 왜인지는 모르겠지만... 워터마크 크기에 +1을 안해주면
// FinePrint, HEC 보안프린터에서 이미지 출력이 되지 않는다...23_1017 10:56:48 kku
nWW := _bmpWaterP.Width + 1;
nHH := _bmpWaterP.Height + 1;
// nWW := Round((nScalePercent / 100) * bmpWater.Width);
// nHH := Round((nScalePercent / 100) * bmpWater.Height);
nX := (nW div 2) - (nWW div 2);
nY := (nH div 2) - (nH div 3);
MemCanvas.StretchDraw(Rect(nX, nY, nX + nWW, nY + nHH), _bmpWaterP);
nY := (nH div 2) + (nH div 10);
MemCanvas.StretchDraw(Rect(nX, nY, nX + nWW, nY + nHH), _bmpWaterP);
end else
if _bmpWater <> nil then
begin
if gAppHook.Helper.IsExcel then
MemCanvas.StretchDraw(Rect(0, 0, nW, nH), _bmpWater)
else
DrawBitmapWater(MemCanvas.Handle, 0, 0, _bmpWater);
end;
end;
if bStartPage then
BitBlt(DC, 0, 0, nW, nH, MemCanvas.Handle, 0, 0, SRCCOPY);
finally
SetTextColor(MemCanvas.Handle, oldColor);
SelectObject(MemCanvas.Handle, hOldBmp);
DeleteObject(hbmp);
if bStartPage then // 필요없음
DeleteDC(MemCanvas.Handle);
MemCanvas.Handle := 0;
SelectObject(DC, hOldFont);
end;
gAppHook.Log(Format('ProcessWartermark_GEC() - Completed, LastError=%d', [GetLastError]));
except
// 실패하면 출력 안되게 해준다 22_0907 14:28:52 kku
Result := false;
DeleteDC(DC);
end;
finally
gAppHook.Helper.bIsWaterMaking_ := false;
RestoreDC(DC, -1);
end;
end;
end.