📄 vclutils.pas
字号:
function DialogUnitsToPixelsX(DlgUnits: Word): Word;
begin
Result := (DlgUnits * LoWord(GetDialogBaseUnits)) div 4;
end;
function DialogUnitsToPixelsY(DlgUnits: Word): Word;
begin
Result := (DlgUnits * HiWord(GetDialogBaseUnits)) div 8;
end;
function PixelsToDialogUnitsX(PixUnits: Word): Word;
begin
Result := PixUnits * 4 div LoWord(GetDialogBaseUnits);
end;
function PixelsToDialogUnitsY(PixUnits: Word): Word;
begin
Result := PixUnits * 8 div HiWord(GetDialogBaseUnits);
end;
{ Service routines }
type
THack = class(TCustomControl);
function LoadDLL(const LibName: string): THandle;
var
ErrMode: Cardinal;
{$IFNDEF WIN32}
P: array[0..255] of Char;
{$ENDIF}
begin
ErrMode := SetErrorMode(SEM_NOOPENFILEERRORBOX);
{$IFDEF WIN32}
Result := LoadLibrary(PChar(LibName));
{$ELSE}
Result := LoadLibrary(StrPCopy(P, LibName));
{$ENDIF}
SetErrorMode(ErrMode);
if Result < HINSTANCE_ERROR then
{$IFDEF WIN32}
Win32Check(False);
{$ELSE}
raise EOutOfResources.CreateResFmt(SLoadLibError, [LibName]);
{$ENDIF}
end;
function RegisterServer(const ModuleName: string): Boolean;
{ RegisterServer procedure written by Vladimir Gaitanoff, 2:50/430.2 }
type
TProc = procedure;
var
Handle: THandle;
DllRegServ: Pointer;
begin
Result := False;
Handle := LoadDLL(ModuleName);
try
DllRegServ := GetProcAddress(Handle, 'DllRegisterServer');
if Assigned(DllRegServ) then begin
TProc(DllRegServ);
Result := True;
end;
finally
FreeLibrary(Handle);
end;
end;
procedure Beep;
begin
MessageBeep(0);
end;
procedure FreeUnusedOle;
begin
{$IFDEF WIN32}
FreeLibrary(GetModuleHandle('OleAut32'));
{$ENDIF}
end;
procedure NotImplemented;
begin
Screen.Cursor := crDefault;
MessageDlg(LoadStr(SNotImplemented), mtInformation, [mbOk], 0);
Abort;
end;
{$IFNDEF WIN32}
procedure MoveWindowOrg(DC: HDC; DX, DY: Integer);
var
P: TPoint;
begin
GetWindowOrgEx(DC, @P);
SetWindowOrgEx(DC, P.X - DX, P.Y - DY, nil);
end;
function IsLibrary: Boolean;
begin
Result := (PrefixSeg = 0);
end;
{$ENDIF WIN32}
procedure PaintInverseRect(const RectOrg, RectEnd: TPoint);
var
DC: HDC;
R: TRect;
begin
DC := GetDC(0);
try
R := Rect(RectOrg.X, RectOrg.Y, RectEnd.X, RectEnd.Y);
InvertRect(DC, R);
finally
ReleaseDC(0, DC);
end;
end;
procedure DrawInvertFrame(ScreenRect: TRect; Width: Integer);
var
DC: HDC;
I: Integer;
begin
DC := GetDC(0);
try
for I := 1 to Width do begin
DrawFocusRect(DC, ScreenRect);
InflateRect(ScreenRect, -1, -1);
end;
finally
ReleaseDC(0, DC);
end;
end;
function WidthOf(R: TRect): Integer;
begin
Result := R.Right - R.Left;
end;
function HeightOf(R: TRect): Integer;
begin
Result := R.Bottom - R.Top;
end;
function PointInRect(const P: TPoint; const R: TRect): Boolean;
begin
with R do
Result := (Left <= P.X) and (Top <= P.Y) and
(Right >= P.X) and (Bottom >= P.Y);
end;
function PointInPolyRgn(const P: TPoint; const Points: array of TPoint): Boolean;
type
PPoints = ^TPoints;
TPoints = array[0..0] of TPoint;
var
Rgn: HRgn;
begin
Rgn := CreatePolygonRgn(PPoints(@Points)^, High(Points) + 1, WINDING);
try
Result := PtInRegion(Rgn, P.X, P.Y);
finally
DeleteObject(Rgn);
end;
end;
function PaletteColor(Color: TColor): Longint;
begin
Result := ColorToRGB(Color) or PaletteMask;
end;
procedure KillMessage(Wnd: HWnd; Msg: Cardinal);
{ Delete the requested message from the queue, but throw back }
{ any WM_QUIT msgs that PeekMessage may also return. }
{ Copied from DbGrid.pas }
var
M: TMsg;
begin
M.Message := 0;
if PeekMessage(M, Wnd, Msg, Msg, PM_REMOVE) and (M.Message = WM_QUIT) then
PostQuitMessage(M.WParam);
end;
function CreateRotatedFont(Font: TFont; Angle: Integer): HFont;
var
LogFont: TLogFont;
begin
FillChar(LogFont, SizeOf(LogFont), 0);
with LogFont do begin
lfHeight := Font.Height;
lfWidth := 0;
lfEscapement := Angle * 10;
lfOrientation := 0;
if fsBold in Font.Style then lfWeight := FW_BOLD
else lfWeight := FW_NORMAL;
lfItalic := Ord(fsItalic in Font.Style);
lfUnderline := Ord(fsUnderline in Font.Style);
lfStrikeOut := Byte(fsStrikeOut in Font.Style);
{$IFDEF RX_D3}
lfCharSet := Byte(Font.Charset);
if AnsiCompareText(Font.Name, 'Default') = 0 then
StrPCopy(lfFaceName, DefFontData.Name)
else
StrPCopy(lfFaceName, Font.Name);
{$ELSE}
{$IFDEF VER93}
lfCharSet := Byte(Font.Charset);
{$ELSE}
lfCharSet := DEFAULT_CHARSET;
{$ENDIF}
StrPCopy(lfFaceName, Font.Name);
{$ENDIF}
lfQuality := DEFAULT_QUALITY;
lfOutPrecision := OUT_DEFAULT_PRECIS;
lfClipPrecision := CLIP_DEFAULT_PRECIS;
case Font.Pitch of
fpVariable: lfPitchAndFamily := VARIABLE_PITCH;
fpFixed: lfPitchAndFamily := FIXED_PITCH;
else lfPitchAndFamily := DEFAULT_PITCH;
end;
end;
Result := CreateFontIndirect(LogFont);
end;
procedure Delay(MSecs: Longint);
var
FirstTickCount, Now: Longint;
begin
FirstTickCount := GetTickCount;
repeat
Application.ProcessMessages;
{ allowing access to other controls, etc. }
Now := GetTickCount;
until (Now - FirstTickCount >= MSecs) or (Now < FirstTickCount);
end;
function PaletteEntries(Palette: HPALETTE): Integer;
begin
GetObject(Palette, SizeOf(Integer), @Result);
end;
procedure CenterControl(Control: TControl);
var
X, Y: Integer;
begin
X := Control.Left;
Y := Control.Top;
if Control is TForm then begin
with Control do begin
if (TForm(Control).FormStyle = fsMDIChild) and
(Application.MainForm <> nil) then
begin
X := (Application.MainForm.ClientWidth - Width) div 2;
Y := (Application.MainForm.ClientHeight - Height) div 2;
end
else begin
X := (Screen.Width - Width) div 2;
Y := (Screen.Height - Height) div 2;
end;
end;
end
else if Control.Parent <> nil then begin
with Control do begin
Parent.HandleNeeded;
X := (Parent.ClientWidth - Width) div 2;
Y := (Parent.ClientHeight - Height) div 2;
end;
end;
if X < 0 then X := 0;
if Y < 0 then Y := 0;
with Control do SetBounds(X, Y, Width, Height);
end;
procedure FitRectToScreen(var Rect: TRect);
var
X, Y, Delta: Integer;
begin
X := GetSystemMetrics(SM_CXSCREEN);
Y := GetSystemMetrics(SM_CYSCREEN);
with Rect do begin
if Right > X then begin
Delta := Right - Left;
Right := X;
Left := Right - Delta;
end;
if Left < 0 then begin
Delta := Right - Left;
Left := 0;
Right := Left + Delta;
end;
if Bottom > Y then begin
Delta := Bottom - Top;
Bottom := Y;
Top := Bottom - Delta;
end;
if Top < 0 then begin
Delta := Bottom - Top;
Top := 0;
Bottom := Top + Delta;
end;
end;
end;
procedure CenterWindow(Wnd: HWnd);
var
R: TRect;
begin
GetWindowRect(Wnd, R);
R := Rect((GetSystemMetrics(SM_CXSCREEN) - R.Right + R.Left) div 2,
(GetSystemMetrics(SM_CYSCREEN) - R.Bottom + R.Top) div 2,
R.Right - R.Left, R.Bottom - R.Top);
FitRectToScreen(R);
SetWindowPos(Wnd, 0, R.Left, R.Top, 0, 0, SWP_NOACTIVATE or
SWP_NOSIZE or SWP_NOZORDER);
end;
procedure MergeForm(AControl: TWinControl; AForm: TForm; Align: TAlign;
Show: Boolean);
var
R: TRect;
AutoScroll: Boolean;
begin
AutoScroll := AForm.AutoScroll;
AForm.Hide;
THack(AForm).DestroyHandle;
with AForm do begin
BorderStyle := bsNone;
BorderIcons := [];
Parent := AControl;
end;
AControl.DisableAlign;
try
if Align <> alNone then AForm.Align := Align
else begin
R := AControl.ClientRect;
AForm.SetBounds(R.Left + AForm.Left, R.Top + AForm.Top, AForm.Width,
AForm.Height);
end;
AForm.AutoScroll := AutoScroll;
AForm.Visible := Show;
finally
AControl.EnableAlign;
end;
end;
{$IFDEF WIN32}
{ ShowMDIClientEdge function has been copied from Inprise's FORMS.PAS unit,
Delphi 4 version }
procedure ShowMDIClientEdge(ClientHandle: THandle; ShowEdge: Boolean);
var
Style: Longint;
begin
if ClientHandle <> 0 then
begin
Style := GetWindowLong(ClientHandle, GWL_EXSTYLE);
if ShowEdge then
if Style and WS_EX_CLIENTEDGE = 0 then
Style := Style or WS_EX_CLIENTEDGE
else
Exit
else if Style and WS_EX_CLIENTEDGE <> 0 then
Style := Style and not WS_EX_CLIENTEDGE
else
Exit;
SetWindowLong(ClientHandle, GWL_EXSTYLE, Style);
SetWindowPos(ClientHandle, 0, 0,0,0,0, SWP_FRAMECHANGED or SWP_NOACTIVATE or
SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER);
end;
end;
function MakeVariant(const Values: array of Variant): Variant;
begin
if High(Values) - Low(Values) > 1 then
Result := VarArrayOf(Values)
else if High(Values) - Low(Values) = 1 then
Result := Values[Low(Values)]
else Result := Null;
end;
{$ENDIF WIN32}
{ Shade rectangle }
procedure ShadeRect(DC: HDC; const Rect: TRect);
const
HatchBits: array[0..7] of Word = ($11, $22, $44, $88, $11, $22, $44, $88);
var
Bitmap: HBitmap;
SaveBrush: HBrush;
SaveTextColor, SaveBkColor: TColorRef;
begin
Bitmap := CreateBitmap(8, 8, 1, 1, @HatchBits);
SaveBrush := SelectObject(DC, CreatePatternBrush(Bitmap));
try
SaveTextColor := SetTextColor(DC, clWhite);
SaveBkColor := SetBkColor(DC, clBlack);
with Rect do PatBlt(DC, Left, Top, Right - Left, Bottom - Top, $00A000C9);
SetBkColor(DC, SaveBkColor);
SetTextColor(DC, SaveTextColor);
finally
DeleteObject(SelectObject(DC, SaveBrush));
DeleteObject(Bitmap);
end;
end;
function ScreenWorkArea: TRect;
{$IFNDEF WIN32}
const
SPI_GETWORKAREA = 48;
{$ENDIF}
begin
if not SystemParametersInfo(SPI_GETWORKAREA, 0, @Result, 0) then
with Screen do Result := Bounds(0, 0, Width, Height);
end;
function WindowClassName(Wnd: HWnd): string;
var
Buffer: array[0..255] of Char;
begin
SetString(Result, Buffer, GetClassName(Wnd, Buffer, SizeOf(Buffer) - 1));
end;
{$IFDEF WIN32}
function GetAnimation: Boolean;
var
Info: TAnimationInfo;
begin
Info.cbSize := SizeOf(TAnimationInfo);
if SystemParametersInfo(SPI_GETANIMATION, SizeOf(Info), @Info, 0) then
{$IFDEF RX_D3}
Result := Info.iMinAnimate <> 0
{$ELSE}
Result := Info.iMinAnimate
{$ENDIF}
else Result := False;
end;
procedure SetAnimation(Value: Boolean);
var
Info: TAnimationInfo;
begin
Info.cbSize := SizeOf(TAnimationInfo);
BOOL(Info.iMinAnimate) := Value;
SystemParametersInfo(SPI_SETANIMATION, SizeOf(Info), @Info, 0);
end;
procedure ShowWinNoAnimate(Handle: HWnd; CmdShow: Integer);
var
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -