📄 rxvclutils.pas
字号:
function StringToPChar(var S: string): PChar;
begin
Result := PChar(S);
end;
function DropT(const S: string): string;
begin
if (UpCase(S[1]) = 'T') and (Length(S) > 1) then
Result := Copy(S, 2, MaxInt)
else Result := S;
end;
{ Cursor routines }
{$IFNDEF RX_D3}
const
RT_ANICURSOR = MakeIntResource(21);
{$ENDIF}
function LoadAniCursor(Instance: THandle; ResID: PChar): HCursor;
{ Unfortunately I don't know how we can load animated cursor from
executable resource directly. So I write this routine using temporary
file and LoadCursorFromFile function. }
var
S: TFileStream;
Path, FileName: array[0..MAX_PATH] of Char;
Rsrc: HRSRC;
Res: THandle;
Data: Pointer;
begin
Result := 0;
Rsrc := FindResource(Instance, ResID, RT_ANICURSOR);
if Rsrc <> 0 then begin
Win32Check(GetTempPath(MAX_PATH, Path) <> 0);
Win32Check(GetTempFileName(Path, 'ANI', 0, FileName) <> 0);
try
Res := LoadResource(Instance, Rsrc);
try
Data := LockResource(Res);
if Data <> nil then
try
S := TFileStream.Create(StrPas(FileName), fmCreate);
try
S.WriteBuffer(Data^, SizeOfResource(Instance, Rsrc));
finally
S.Free;
end;
Result := LoadCursorFromFile(FileName);
finally
UnlockResource(Res);
end;
finally
FreeResource(Res);
end;
finally
Windows.DeleteFile(FileName);
end;
end;
end;
function DefineCursor(Instance: THandle; ResID: PChar): TCursor;
var
Handle: HCursor;
begin
Handle := LoadCursor(Instance, ResID);
if Handle = 0 then
Handle := LoadAniCursor(Instance, ResID);
if Handle = 0 then ResourceNotFound(ResID);
for Result := 100 to High(TCursor) do { Look for an unassigned cursor index }
if (Screen.Cursors[Result] = Screen.Cursors[crDefault]) then begin
Screen.Cursors[Result] := Handle;
Exit;
end;
DestroyCursor(Handle);
raise EOutOfResources.Create(ResStr(SOutOfResources));
end;
const
WaitCount: Integer = 0;
SaveCursor: TCursor = crDefault;
procedure StartWait;
begin
if WaitCount = 0 then begin
SaveCursor := Screen.Cursor;
Screen.Cursor := WaitCursor;
end;
Inc(WaitCount);
end;
procedure StopWait;
begin
if WaitCount > 0 then begin
Dec(WaitCount);
if WaitCount = 0 then Screen.Cursor := SaveCursor;
end;
end;
{ Grid drawing }
const
DrawBitmap: TBitmap = nil;
procedure UsesBitmap;
begin
if DrawBitmap = nil then DrawBitmap := TBitmap.Create;
end;
procedure ReleaseBitmap; far;
begin
if DrawBitmap <> nil then DrawBitmap.Free;
DrawBitmap := nil;
end;
procedure WriteText(ACanvas: TCanvas; ARect: TRect; DX, DY: Integer;
const Text: string; Alignment: TAlignment; WordWrap: Boolean
{$IFDEF RX_D4}; ARightToLeft: Boolean = False {$ENDIF});
const
AlignFlags: array [TAlignment] of Integer =
(DT_LEFT or DT_EXPANDTABS or DT_NOPREFIX,
DT_RIGHT or DT_EXPANDTABS or DT_NOPREFIX,
DT_CENTER or DT_EXPANDTABS or DT_NOPREFIX);
WrapFlags: array[Boolean] of Integer = (0, DT_WORDBREAK);
{$IFDEF RX_D4}
RTL: array [Boolean] of Integer = (0, DT_RTLREADING);
{$ENDIF}
var
B, R: TRect;
I, Left: Integer;
begin
UsesBitmap;
I := ColorToRGB(ACanvas.Brush.Color);
if not WordWrap and (Integer(GetNearestColor(ACanvas.Handle, I)) = I) and
(Pos(#13, Text) = 0) then
begin { Use ExtTextOut for solid colors }
{$IFDEF RX_D4}
{ In BiDi, because we changed the window origin, the text that does not
change alignment, actually gets its alignment changed. }
if (ACanvas.CanvasOrientation = coRightToLeft) and (not ARightToLeft) then
ChangeBiDiModeAlignment(Alignment);
{$ENDIF}
case Alignment of
taLeftJustify: Left := ARect.Left + DX;
taRightJustify: Left := ARect.Right - ACanvas.TextWidth(Text) - 3;
else { taCenter }
Left := ARect.Left + (ARect.Right - ARect.Left) shr 1
- (ACanvas.TextWidth(Text) shr 1);
end;
{$IFDEF RX_D4}
ACanvas.TextRect(ARect, Left, ARect.Top + DY, Text);
{$ELSE}
ExtTextOut(ACanvas.Handle, Left, ARect.Top + DY, ETO_OPAQUE or
ETO_CLIPPED, @ARect, PChar(Text), Length(Text), nil);
{$ENDIF}
end
else begin { Use FillRect and DrawText for dithered colors }
{$IFDEF RX_D3}
DrawBitmap.Canvas.Lock;
try
{$ENDIF}
with DrawBitmap, ARect do { Use offscreen bitmap to eliminate flicker and }
begin { brush origin tics in painting / scrolling. }
Width := Max(Width, Right - Left);
Height := Max(Height, Bottom - Top);
R := Rect(DX, DY, Right - Left - 1,
Bottom - Top - 1);
B := Rect(0, 0, Right - Left, Bottom - Top);
end;
with DrawBitmap.Canvas do begin
Font := ACanvas.Font;
Font.Color := ACanvas.Font.Color;
Brush := ACanvas.Brush;
Brush.Style := bsSolid;
FillRect(B);
SetBkMode(Handle, TRANSPARENT);
{$IFDEF RX_D4}
if (ACanvas.CanvasOrientation = coRightToLeft) then
ChangeBiDiModeAlignment(Alignment);
DrawText(Handle, PChar(Text), Length(Text), R, AlignFlags[Alignment]
or RTL[ARightToLeft] or WrapFlags[WordWrap]);
{$ELSE}
DrawText(Handle, PChar(Text), Length(Text), R,
AlignFlags[Alignment] or WrapFlags[WordWrap]);
{$ENDIF}
end;
ACanvas.CopyRect(ARect, DrawBitmap.Canvas, B);
{$IFDEF RX_D3}
finally
DrawBitmap.Canvas.Unlock;
end;
{$ENDIF}
end;
end;
{$IFDEF RX_D4}
procedure DrawCellTextEx(Control: TCustomControl; ACol, ARow: Longint;
const S: string; const ARect: TRect; Align: TAlignment;
VertAlign: TVertAlignment; WordWrap: Boolean; ARightToLeft: Boolean);
const
MinOffs = 2;
var
H: Integer;
begin
case VertAlign of
vaTopJustify: H := MinOffs;
vaCenter:
with THack(Control) do
H := Max(1, (ARect.Bottom - ARect.Top -
Canvas.TextHeight('W')) div 2);
else {vaBottomJustify} begin
with THack(Control) do
H := Max(MinOffs, ARect.Bottom - ARect.Top -
Canvas.TextHeight('W'));
end;
end;
WriteText(THack(Control).Canvas, ARect, MinOffs, H, S, Align, WordWrap,
ARightToLeft);
end;
procedure DrawCellText(Control: TCustomControl; ACol, ARow: Longint;
const S: string; const ARect: TRect; Align: TAlignment;
VertAlign: TVertAlignment; ARightToLeft: Boolean);
begin
DrawCellTextEx(Control, ACol, ARow, S, ARect, Align, VertAlign,
Align = taCenter, ARightToLeft);
end;
{$ENDIF}
procedure DrawCellTextEx(Control: TCustomControl; ACol, ARow: Longint;
const S: string; const ARect: TRect; Align: TAlignment;
VertAlign: TVertAlignment; WordWrap: Boolean);
const
MinOffs = 2;
var
H: Integer;
begin
case VertAlign of
vaTopJustify: H := MinOffs;
vaCenter:
with THack(Control) do
H := Max(1, (ARect.Bottom - ARect.Top -
Canvas.TextHeight('W')) div 2);
else {vaBottomJustify} begin
with THack(Control) do
H := Max(MinOffs, ARect.Bottom - ARect.Top -
Canvas.TextHeight('W'));
end;
end;
WriteText(THack(Control).Canvas, ARect, MinOffs, H, S, Align, WordWrap);
end;
procedure DrawCellText(Control: TCustomControl; ACol, ARow: Longint;
const S: string; const ARect: TRect; Align: TAlignment;
VertAlign: TVertAlignment);
begin
DrawCellTextEx(Control, ACol, ARow, S, ARect, Align, VertAlign,
Align = taCenter);
end;
procedure DrawCellBitmap(Control: TCustomControl; ACol, ARow: Longint;
Bmp: TGraphic; Rect: TRect);
begin
Rect.Top := (Rect.Bottom + Rect.Top - Bmp.Height) div 2;
Rect.Left := (Rect.Right + Rect.Left - Bmp.Width) div 2;
THack(Control).Canvas.Draw(Rect.Left, Rect.Top, Bmp);
end;
{ TScreenCanvas }
destructor TScreenCanvas.Destroy;
begin
FreeHandle;
inherited Destroy;
end;
procedure TScreenCanvas.CreateHandle;
begin
if FDeviceContext = 0 then FDeviceContext := GetDC(0);
Handle := FDeviceContext;
end;
procedure TScreenCanvas.FreeHandle;
begin
if FDeviceContext <> 0 then begin
Handle := 0;
ReleaseDC(0, FDeviceContext);
FDeviceContext := 0;
end;
end;
procedure TScreenCanvas.SetOrigin(X, Y: Integer);
var
FOrigin: TPoint;
begin
SetWindowOrgEx(Handle, -X, -Y, @FOrigin);
end;
procedure RaiseWin32Error(ErrorCode: DWORD);
{$IFDEF RX_D3}
var
{$IFDEF RX_D6} // Polaris
Error: EOSError;
{$ELSE}
Error: EWin32Error;
{$ENDIF}
{$ENDIF}
begin
if ErrorCode <> ERROR_SUCCESS then begin
{$IFDEF RX_D3}
{$IFDEF RX_D6} // Polaris
Error := EOSError.CreateFmt(SOSError, [ErrorCode,
SysErrorMessage(ErrorCode)]);
{$ELSE}
Error := EWin32Error.CreateFmt(SWin32Error, [ErrorCode,
SysErrorMessage(ErrorCode)]);
{$ENDIF}
Error.ErrorCode := ErrorCode;
raise Error;
{$ELSE}
raise Exception.CreateFmt('%s (%d)', [SysErrorMessage(ErrorCode),
ErrorCode]);
{$ENDIF}
end;
end;
{ Win32Check is used to check the return value of a Win32 API function
which returns a BOOL to indicate success. }
{$IFNDEF RX_D3}
function Win32Check(RetVal: Bool): Bool;
var
LastError: DWORD;
begin
if not RetVal then begin
LastError := GetLastError;
raise Exception.CreateFmt('%s (%d)', [SysErrorMessage(LastError),
LastError]);
end;
Result := RetVal;
end;
{$ENDIF RX_D3}
function CheckWin32(OK: Boolean): Boolean;
begin
Result := Win32Check(Ok);
end;
{$IFNDEF RX_D3}
function ResStr(Ident: Cardinal): string;
begin
Result := LoadStr(Ident);
end;
{$ELSE}
function ResStr(const Ident: string): string;
begin
Result := Ident;
end;
{$ENDIF}
{ Check if this is the active Windows task }
{ Copied from implementation of FORMS.PAS }
type
PCheckTaskInfo = ^TCheckTaskInfo;
TCheckTaskInfo = record
FocusWnd: HWnd;
Found: Boolean;
end;
function CheckTaskWindow(Window: HWnd; Data: Longint): WordBool;
stdcall;
begin
Result := True;
if PCheckTaskInfo(Data)^.FocusWnd = Window then begin
Result := False;
PCheckTaskInfo(Data)^.Found := True;
end;
end;
function IsForegroundTask: Boolean;
var
Info: TCheckTaskInfo;
begin
Info.FocusWnd := GetActiveWindow;
Info.Found := False;
EnumThreadWindows(GetCurrentThreadID, @CheckTaskWindow, Longint(@Info));
Result := Info.Found;
end;
function GetWindowsVersion: string;
const
sWindowsVersion = 'Windows %s %d.%.2d.%.3d %s';
var
Ver: TOsVersionInfo;
Platform: string[4];
begin
Ver.dwOSVersionInfoSize := SizeOf(Ver);
GetVersionEx(Ver);
with Ver do begin
case dwPlatformId of
VER_PLATFORM_WIN32s: Platform := '32s';
VER_PLATFORM_WIN32_WINDOWS:
begin
dwBuildNumber := dwBuildNumber and $0000FFFF;
if (dwMajorVersion > 4) or ((dwMajorVersion = 4) and
(dwMinorVersion >= 10)) then Platform := '98'
else Platform := '95';
end;
VER_PLATFORM_WIN32_NT: Platform := 'NT';
end;
Result := Trim(Format(sWindowsVersion, [Platform, dwMajorVersion,
dwMinorVersion, dwBuildNumber, szCSDVersion]));
end;
end;
initialization
finalization
ReleaseBitmap;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -