📄 mydialogs.pas
字号:
destructor TFontDialog.Destroy;
begin
FFont.Free;
inherited Destroy;
end;
procedure TFontDialog.WndProc(var Message: TMessage);
begin
{ Make sure we only take values from the color combobox and script combobox
if they have been changed. }
if (Message.Msg = WM_COMMAND) and (Message.WParamHi = CBN_SELENDOK) then
if (Message.WParamLo = cmb4) then FFontColorModified := True
else if (Message.WParamLo = cmb5) then FFontCharsetModified := True;
inherited WndProc(Message);
end;
procedure TFontDialog.Apply(Wnd: HWND);
begin
if Assigned(FOnApply) then FOnApply(Self, Wnd);
end;
procedure TFontDialog.DoApply(Wnd: HWND);
const
IDCOLORCMB = $473;
var
I: Integer;
LogFont: TLogFont;
begin
SendMessage(Wnd, WM_CHOOSEFONT_GETLOGFONT, 0, LongInt(@LogFont));
UpdateFromLogFont(LogFont);
I := SendDlgItemMessage(Wnd, IDCOLORCMB, CB_GETCURSEL, 0, 0);
if I <> CB_ERR then
Font.Color := SendDlgItemMessage(Wnd, IDCOLORCMB, CB_GETITEMDATA, I, 0);
try
Apply(Wnd);
except
Application.HandleException(Self);
end;
end;
function TFontDialog.Execute: Boolean;
const
FontOptions: array[TFontDialogOption] of DWORD = (
CF_ANSIONLY, CF_TTONLY, CF_EFFECTS, CF_FIXEDPITCHONLY, CF_FORCEFONTEXIST,
CF_NOFACESEL, CF_NOOEMFONTS, CF_NOSIMULATIONS, CF_NOSIZESEL,
CF_NOSTYLESEL, CF_NOVECTORFONTS, CF_SHOWHELP,
CF_WYSIWYG or CF_BOTH or CF_SCALABLEONLY, CF_LIMITSIZE,
CF_SCALABLEONLY, CF_APPLY);
Devices: array[TFontDialogDevice] of DWORD = (
CF_SCREENFONTS, CF_PRINTERFONTS, CF_BOTH);
var
ChooseFontRec: TChooseFont;
LogFont: TLogFont;
Option: TFontDialogOption;
SaveFontDialog: TFontDialog;
OriginalFaceName: string;
begin
with ChooseFontRec do
begin
lStructSize := SizeOf(ChooseFontRec);
hDC := 0;
if FDevice <> fdScreen then hDC := Printer.Handle;
lpLogFont := @LogFont;
GetObject(Font.Handle, SizeOf(LogFont), @LogFont);
OriginalFaceName := LogFont.lfFaceName;
Flags := Devices[FDevice] or (CF_INITTOLOGFONTSTRUCT or CF_ENABLEHOOK);
for Option := Low(Option) to High(Option) do
if Option in FOptions then
Flags := Flags or FontOptions[Option];
if Assigned(FOnApply) then Flags := Flags or CF_APPLY;
if Template <> nil then
begin
Flags := Flags or CF_ENABLETEMPLATE;
lpTemplateName := Template;
end;
rgbColors := Font.Color;
lCustData := 0;
lpfnHook := FontDialogHook;
nSizeMin := FMinFontSize;
nSizeMax := FMaxFontSize;
if nSizeMin > nSizeMax then Flags := Flags and (not CF_LIMITSIZE);
hWndOwner := Application.Handle;
SaveFontDialog := FontDialog;
FontDialog := Self;
FFontColorModified := False;
FFontCharsetModified := False;
Result := TaskModalDialog(@ChooseFont, ChooseFontRec);
FontDialog := SaveFontDialog;
if Result then
begin
if AnsiCompareText(OriginalFaceName, LogFont.lfFaceName) <> 0 then
FFontCharsetModified := True;
UpdateFromLogFont(LogFont);
if FFontColorModified then Font.Color := rgbColors;
end;
end;
end;
procedure TFontDialog.SetFont(Value: TFont);
begin
FFont.Assign(Value);
end;
procedure TFontDialog.UpdateFromLogFont(const LogFont: TLogFont);
var
Style: TFontStyles;
begin
with LogFont do
begin
Font.Name := LogFont.lfFaceName;
Font.Height := LogFont.lfHeight;
if FFontCharsetModified then
Font.Charset := TFontCharset(LogFont.lfCharSet);
Style := [];
with LogFont do
begin
if lfWeight > FW_REGULAR then Include(Style, fsBold);
if lfItalic <> 0 then Include(Style, fsItalic);
if lfUnderline <> 0 then Include(Style, fsUnderline);
if lfStrikeOut <> 0 then Include(Style, fsStrikeOut);
end;
Font.Style := Style;
end;
end;
{ Printer dialog routines }
procedure GetPrinter(var DeviceMode, DeviceNames: THandle);
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);
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;
{ 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
SetWindowPos(Wnd, 0, Left, Top, 0, 0, SWP_NOACTIVATE or
SWP_NOSIZE or SWP_NOZORDER);
SetProp(Wnd, MakeIntAtom(WndProcPtrAtom), GetWindowLong(Wnd, GWL_WNDPROC));
SetWindowLong(Wnd, GWL_WNDPROC, Longint(@FindReplaceWndProc));
Result := 1;
end;
end;
const
FindOptions: array[TFindOption] of DWORD = (
FR_DOWN, FR_FINDNEXT, FR_HIDEMATCHCASE, FR_HIDEWHOLEWORD,
FR_HIDEUPDOWN, FR_MATCHCASE, FR_NOMATCHCASE, FR_NOUPDOWN, FR_NOWHOLEWORD,
FR_REPLACE, FR_REPLACEALL, FR_WHOLEWORD, FR_SHOWHELP);
{ TFindDialog }
constructor TFindDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FOptions := [frDown];
FPosition.X := -1;
FPosition.Y := -1;
with FFindReplace do
begin
lStructSize := SizeOf(TFindReplace);
hWndOwner := Application.Handle;
hInstance := SysInit.HInstance;
lpstrFindWhat := FFindText;
wFindWhatLen := SizeOf(FFindText);
lpstrReplaceWith := FReplaceText;
wReplaceWithLen := SizeOf(FReplaceText);
lCustData := Longint(Self);
lpfnHook := FindReplaceDialogHook;
end;
FFindReplaceFunc := @CommDlg.FindText;
end;
destructor TFindDialog.Destroy;
begin
if FFindHandle <> 0 then SendMessage(FFindHandle, WM_CLOSE, 0, 0);
if Assigned(FRedirector) then
TRedirectorWindow(FRedirector).FFindReplaceDialog := nil;
FreeAndNil(FRedirector);
inherited Destroy;
end;
procedure TFindDialog.CloseDialog;
begin
if FFindHandle <> 0 then PostMessage(FFindHandle, WM_CLOSE, 0, 0);
end;
function GetTopWindow(Wnd: THandle; var ReturnVar: THandle):Bool; stdcall;
var
Test: TWinControl;
begin
Test := FindControl(Wnd);
Result := True;
if Assigned(Test) and (Test is TForm) then
begin
ReturnVar := Wnd;
Result := False;
end;
end;
function TFindDialog.Execute: Boolean;
var
Option: TFindOption;
begin
if FFindHandle <> 0 then
begin
BringWindowToTop(FFindHandle);
Result := True;
end else
begin
FFindReplace.Flags := FR_ENABLEHOOK;
FFindReplace.lpfnHook := FindReplaceDialogHook;
FRedirector := TRedirectorWindow.Create(nil);
with TRedirectorWindow(FRedirector) do
begin
FFindReplaceDialog := Self;
EnumThreadWindows(GetCurrentThreadID, @GetTopWindow, LPARAM(@FFormHandle));
end;
FFindReplace.hWndOwner := FRedirector.Handle;
for Option := Low(Option) to High(Option) do
if Option in FOptions then
FFindReplace.Flags := FFindReplace.Flags or FindOptions[Option];
if Template <> nil then
begin
FFindReplace.Flags := FFindReplace.Flags or FR_ENABLETEMPLATE;
FFindReplace.lpTemplateName := Template;
end;
CreationControl := Self;
FFindHandle := FFindReplaceFunc(FFindReplace);
Result := FFindHandle <> 0;
end;
end;
procedure TFindDialog.Find;
begin
if Assigned(FOnFind) then FOnFind(Self);
end;
function TFindDialog.GetFindText: string;
begin
Result := FFindText;
end;
function TFindDialog.GetLeft: Integer;
begin
Result := Position.X;
end;
function TFindDialog.GetPosition: TPoint;
var
Rect: TRect;
begin
Result := FPosition;
if FFindHandle <> 0 then
begin
GetWindowRect(FFindHandle, Rect);
Result := Rect.TopLeft;
end;
end;
function TFindDialog.GetReplaceText: string;
begin
Result := FReplaceText;
end;
function TFindDialog.GetTop: Integer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -