📄 dialogs.pas
字号:
var
Device, Driver, Port: array[0..1023] of char;
DevNames: PDevNames;
Offset: PChar;
begin
Printer.GetPrinter(Device, Driver, Port, DeviceMode);
if DeviceMode <> 0 then
begin
DeviceNames := GlobalAlloc(GHND, SizeOf(TDevNames) +
StrLen(Device) + StrLen(Driver) + StrLen(Port) + 3);
DevNames := PDevNames(GlobalLock(DeviceNames));
try
Offset := PChar(DevNames) + SizeOf(TDevnames);
with DevNames^ do
begin
wDriverOffset := Longint(Offset) - Longint(DevNames);
Offset := StrECopy(Offset, Driver) + 1;
wDeviceOffset := Longint(Offset) - Longint(DevNames);
Offset := StrECopy(Offset, Device) + 1;
wOutputOffset := Longint(Offset) - Longint(DevNames);;
StrCopy(Offset, Port);
end;
finally
GlobalUnlock(DeviceNames);
end;
end;
end;
procedure SetPrinter(DeviceMode, DeviceNames: THandle);
var
DevNames: PDevNames;
begin
DevNames := PDevNames(GlobalLock(DeviceNames));
try
with DevNames^ do
Printer.SetPrinter(PChar(DevNames) + wDeviceOffset,
PChar(DevNames) + wDriverOffset,
PChar(DevNames) + wOutputOffset, DeviceMode);
finally
GlobalUnlock(DeviceNames);
GlobalFree(DeviceNames);
end;
end;
function CopyData(Handle: THandle): THandle;
var
Src, Dest: PChar;
Size: Integer;
begin
if Handle <> 0 then
begin
Size := GlobalSize(Handle);
Result := GlobalAlloc(GHND, Size);
if Result <> 0 then
try
Src := GlobalLock(Handle);
Dest := GlobalLock(Result);
if (Src <> nil) and (Dest <> nil) then Move(Src^, Dest^, Size);
finally
GlobalUnlock(Handle);
GlobalUnlock(Result);
end
end
else Result := 0;
end;
{ TPrinterSetupDialog }
function TPrinterSetupDialog.Execute: Boolean;
var
PrintDlgRec: TPrintDlg;
DevHandle: THandle;
begin
FillChar(PrintDlgRec, SizeOf(PrintDlgRec), 0);
with PrintDlgRec do
begin
lStructSize := SizeOf(PrintDlgRec);
hInstance := SysInit.HInstance;
GetPrinter(DevHandle, hDevNames);
hDevMode := CopyData(DevHandle);
Flags := PD_ENABLESETUPHOOK or PD_PRINTSETUP;
lpfnSetupHook := DialogHook;
hWndOwner := Application.Handle;
Result := TaskModalDialog(@PrintDlg, PrintDlgRec);
if Result then
SetPrinter(hDevMode, hDevNames)
else begin
if hDevMode <> 0 then GlobalFree(hDevMode);
if hDevNames <> 0 then GlobalFree(hDevNames);
end;
end;
end;
{ TPrintDialog }
procedure TPrintDialog.SetNumCopies(Value: Integer);
begin
FCopies := Value;
Printer.Copies := Value;
end;
function TPrintDialog.Execute: Boolean;
const
PrintRanges: array[TPrintRange] of Integer =
(PD_ALLPAGES, PD_SELECTION, PD_PAGENUMS);
var
PrintDlgRec: TPrintDlg;
DevHandle: THandle;
begin
FillChar(PrintDlgRec, SizeOf(PrintDlgRec), 0);
with PrintDlgRec do
begin
lStructSize := SizeOf(PrintDlgRec);
hInstance := SysInit.HInstance;
GetPrinter(DevHandle, hDevNames);
hDevMode := CopyData(DevHandle);
Flags := PrintRanges[FPrintRange] or (PD_ENABLEPRINTHOOK or
PD_ENABLESETUPHOOK);
if FCollate then Inc(Flags, PD_COLLATE);
if not (poPrintToFile in FOptions) then Inc(Flags, PD_HIDEPRINTTOFILE);
if not (poPageNums in FOptions) then Inc(Flags, PD_NOPAGENUMS);
if not (poSelection in FOptions) then Inc(Flags, PD_NOSELECTION);
if poDisablePrintToFile in FOptions then Inc(Flags, PD_DISABLEPRINTTOFILE);
if FPrintToFile then Inc(Flags, PD_PRINTTOFILE);
if poHelp in FOptions then Inc(Flags, PD_SHOWHELP);
if not (poWarning in FOptions) then Inc(Flags, PD_NOWARNING);
if Template <> nil then
begin
Flags := Flags or PD_ENABLEPRINTTEMPLATE;
lpPrintTemplateName := Template;
end;
nFromPage := FFromPage;
nToPage := FToPage;
nMinPage := FMinPage;
nMaxPage := FMaxPage;
lpfnPrintHook := DialogHook;
lpfnSetupHook := DialogHook;
hWndOwner := Application.Handle;
Result := TaskModalDialog(@PrintDlg, PrintDlgRec);
if Result then
begin
SetPrinter(hDevMode, hDevNames);
FCollate := Flags and PD_COLLATE <> 0;
FPrintToFile := Flags and PD_PRINTTOFILE <> 0;
if Flags and PD_SELECTION <> 0 then FPrintRange := prSelection else
if Flags and PD_PAGENUMS <> 0 then FPrintRange := prPageNums else
FPrintRange := prAllPages;
FFromPage := nFromPage;
FToPage := nToPage;
if nCopies = 1 then
Copies := Printer.Copies else
Copies := nCopies;
end
else begin
if hDevMode <> 0 then GlobalFree(hDevMode);
if hDevNames <> 0 then GlobalFree(hDevNames);
end;
end;
end;
{ TPageSetupDialog }
var
PgSetupDlg: TPageSetupDialog; // Used for page paint callback
function PagePaint(Wnd: HWND; Message: UINT; wParam: WPARAM; lParam: LPARAM): UINT; stdcall;
var
DoneDrawing: Boolean;
procedure CallPaintEvent(Event: TPaintPageEvent);
var
Canvas: TCanvas;
begin
Canvas := TCanvas.Create;
try
Canvas.Handle := HDC(wParam);
if Assigned(Event) then
Event(PgSetupDlg, Canvas, PRect(lParam)^, DoneDrawing);
finally
Canvas.Free;
end;
end;
const
PageType: array[Boolean] of TPageType = (ptEnvelope, ptPaper);
Orientation: array[Boolean] of TPrinterOrientation = (poPortrait, poLandscape);
begin
Result := UINT(False);
if not Assigned(PgSetupDlg) then exit;
DoneDrawing := False;
if Message = WM_PSD_PAGESETUPDLG then
begin
if Assigned(PgSetupDlg.FBeforePaint) then
// Constants used below are from WinAPI help on WM_PSD_PAGESETUPDLG
PgSetupDlg.BeforePaint(PgSetupDlg, (wParam and $FFFF),
Orientation[(wParam shr 16) in [$0001,$0003, $000B, $0019]],
PageType[(wParam shr 16) > $000B], DoneDrawing);
end
else
with PgSetupDlg do
case Message of
WM_PSD_FULLPAGERECT : CallPaintEvent(FOnDrawFullPage);
WM_PSD_MINMARGINRECT : CallPaintEvent(FOnDrawMinMargin);
WM_PSD_MARGINRECT : CallPaintEvent(FOnDrawMargin);
WM_PSD_GREEKTEXTRECT : CallPaintEvent(FOnDrawGreekText);
WM_PSD_ENVSTAMPRECT : CallPaintEvent(FOnDrawEnvStamp);
WM_PSD_YAFULLPAGERECT: CallPaintEvent(FOnDrawRetAddress);
end;
Result := UINT(DoneDrawing);
end;
constructor TPageSetupDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Options := [psoDefaultMinMargins];
GetDefaults;
end;
function TPageSetupDialog.Execute: Boolean;
var
DevHandle: THandle;
begin
FillChar(FPageSetupDlgRec, SizeOf(PageSetupDlgRec), 0);
with PageSetupDlgRec do
begin
lStructSize := SizeOf(PageSetupDlgRec);
hwndOwner := Application.Handle;
hInstance := SysInit.HInstance;
GetPrinter(DevHandle, hDevNames);
hDevMode := CopyData(DevHandle);
Flags := PSD_RETURNDEFAULT;
PageSetupDlg(FPageSetupDlgRec);
Flags := PSD_ENABLEPAGEPAINTHOOK or PSD_ENABLEPAGESETUPHOOK or PSD_MARGINS;
case FUnits of
// pmDefault : Read from locale settings by the dialog
pmInches : Inc(Flags, PSD_INTHOUSANDTHSOFINCHES);
pmMillimeters: Inc(Flags, PSD_INHUNDREDTHSOFMILLIMETERS);
end;
if psoDefaultMinMargins in FOptions then Inc(Flags, PSD_DEFAULTMINMARGINS);
if psoDisableMargins in FOptions then Inc(Flags, PSD_DisableMargins);
if psoDisableOrientation in FOptions then Inc(Flags, PSD_DISABLEORIENTATION);
if psoDisablePagePainting in FOptions then
Inc(Flags, PSD_DISABLEPAGEPAINTING)
else
begin
PgSetupDlg := Self;
lpfnPagePaintHook := PagePaint;
end;
if psoDisablePaper in FOptions then Inc(Flags, PSD_DISABLEPAPER);
if psoDisablePrinter in FOptions then Inc(Flags, PSD_DISABLEPRINTER);
if psoMargins in FOptions then Inc(Flags, PSD_MARGINS);
if psoMinMargins in FOptions then Inc(Flags, PSD_MINMARGINS);
if psoShowHelp in FOptions then Inc(Flags, PSD_SHOWHELP);
if not (psoWarning in FOptions) then Inc(Flags, PSD_NOWARNING);
if psoNoNetworkButton in FOptions then Inc(Flags, PSD_NONETWORKBUTTON);
ptPaperSize := Point(FPageWidth, FPageHeight);
rtMinMargin := Rect(FMinMarginLeft, FMinMarginTop, FMinMarginRight, FMinMarginBottom);
rtMargin := Rect(FMarginLeft, FMarginTop, FMarginRight, FMarginBottom);
lpfnPageSetupHook := DialogHook;
Result := TaskModalDialog(@PageSetupDlg, FPageSetupDlgRec);
if Result then
begin
PageWidth := ptPaperSize.x;
PageHeight := ptPaperSize.y;
MarginLeft := rtMargin.Left;
MarginTop := rtMargin.Top;
MarginRight := rtMargin.Right;
MarginBottom := rtMargin.Bottom;
SetPrinter(hDevMode, hDevNames)
end
else begin
if hDevMode <> 0 then GlobalFree(hDevMode);
if hDevNames <> 0 then GlobalFree(hDevNames);
end;
end;
end;
function TPageSetupDialog.GetDefaults: Boolean;
var
PageSetupDlgRec: TPageSetupDlg;
begin
Result := False;
try
Printer.PrinterIndex; // raises an exception if there is no default printer
except
exit;
end;
FillChar(PageSetupDlgRec, SizeOf(PageSetupDlgRec), 0);
with PageSetupDlgRec do
begin
lStructSize := SizeOf(PageSetupDlgRec);
hwndOwner := Application.Handle;
hInstance := SysInit.HInstance;
case FUnits of
// pmDefault : Read from locale settings by the dialog
pmInches : Inc(Flags, PSD_INTHOUSANDTHSOFINCHES);
pmMillimeters: Inc(Flags, PSD_INHUNDREDTHSOFMILLIMETERS);
end;
if psoDefaultMinMargins in FOptions then Inc(Flags, PSD_DEFAULTMINMARGINS);
if psoDisableMargins in FOptions then Inc(Flags, PSD_DISABLEMARGINS);
if psoDisableOrientation in FOptions then Inc(Flags, PSD_DISABLEORIENTATION);
if psoDisablePagePainting in FOptions then
Inc(Flags, PSD_DISABLEPAGEPAINTING);
if psoDisablePaper in FOptions then Inc(Flags, PSD_DISABLEPAPER);
if psoDisablePrinter in FOptions then Inc(Flags, PSD_DISABLEPRINTER);
ptPaperSize := Point(FPageWidth, FPageHeight);
rtMinMargin := Rect(FMinMarginLeft, FMinMarginTop, FMinMarginRight, FMinMarginBottom);
rtMargin := Rect(FMarginLeft, FMarginTop, FMarginRight, FMarginBottom);
lpfnPageSetupHook := DialogHook;
Flags := Flags or PSD_RETURNDEFAULT;
Result := PageSetupDlg(PageSetupDlgRec);
if Result then
begin
FPageWidth := ptPaperSize.x;
FPageHeight := ptPaperSize.y;
FMarginLeft := rtMargin.Left;
FMarginTop := rtMargin.Top;
FMarginRight := rtMargin.Right;
FMarginBottom := rtMargin.Bottom;
if hDevMode <> 0 then GlobalFree(hDevMode);
if hDevNames <> 0 then GlobalFree(hDevNames);
end;
end;
end;
{ TRedirectorWindow }
{ A redirector window is used to put the find/replace dialog into the
ownership chain of a form, but intercept messages that CommDlg.dll sends
exclusively to the find/replace dialog's owner. TRedirectorWindow
creates its hidden window handle as owned by the target form, and the
find/replace dialog handle is created as owned by the redirector. The
redirector wndproc forwards all messages to the find/replace component.
}
type
TRedirectorWindow = class(TWinControl)
private
FFindReplaceDialog: TFindDialog;
FFormHandle: THandle;
procedure CMRelease(var Message); message CM_Release;
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure WndProc(var Message: TMessage); override;
end;
procedure TRedirectorWindow.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
Style := WS_VISIBLE or WS_POPUP;
WndParent := FFormHandle;
end;
end;
procedure TRedirectorWindow.WndProc(var Message: TMessage);
begin
inherited WndProc(Message);
if (Message.Result = 0) and (Message.Msg <> CM_RELEASE) and
Assigned(FFindReplaceDialog) then
Message.Result := Integer(FFindReplaceDialog.MessageHook(Message));
end;
procedure TRedirectorWindow.CMRelease(var Message);
begin
Free;
end;
{ Find and Replace dialog routines }
function FindReplaceWndProc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint; stdcall;
function CallDefWndProc: Longint;
begin
Result := CallWindowProc(Pointer(GetProp(Wnd,
MakeIntAtom(WndProcPtrAtom))), Wnd, Msg, WParam, LParam);
end;
begin
case Msg of
WM_DESTROY:
if Application.DialogHandle = Wnd then Application.DialogHandle := 0;
WM_NCACTIVATE:
if WParam <> 0 then
begin
if Application.DialogHandle = 0 then Application.DialogHandle := Wnd;
end else
begin
if Application.DialogHandle = Wnd then Application.DialogHandle := 0;
end;
WM_NCDESTROY:
begin
Result := CallDefWndProc;
RemoveProp(Wnd, MakeIntAtom(WndProcPtrAtom));
Exit;
end;
end;
Result := CallDefWndProc;
end;
function FindReplaceDialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
begin
Result := DialogHook(Wnd, Msg, wParam, lParam);
if Msg = WM_INITDIALOG then
begin
with TFindDialog(PFindReplace(LParam)^.lCustData) do
if (Left <> -1) or (Top <> -1) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -