Windows XP 绘制带有漂亮阴影的图标文本,这有助于阅读各种背景上的文本。字体颜色为白色,阴影为黑色(如果桌面背景为白色)或根本没有阴影(如果桌面背景为黑色)。
所以有两个子任务:
阴影是如何绘制的?它不是文本的简单 x,y 偏移;阴影对我来说更像是一种模糊。
如何使阴影的行为方式在白色背景上变得更明显而在黑暗中变得不那么明显?
我需要 GDI(不是 GDI+)的解决方案。
Windows XP 绘制带有漂亮阴影的图标文本,这有助于阅读各种背景上的文本。字体颜色为白色,阴影为黑色(如果桌面背景为白色)或根本没有阴影(如果桌面背景为黑色)。
所以有两个子任务:
阴影是如何绘制的?它不是文本的简单 x,y 偏移;阴影对我来说更像是一种模糊。
如何使阴影的行为方式在白色背景上变得更明显而在黑暗中变得不那么明显?
我需要 GDI(不是 GDI+)的解决方案。
如果您需要快速且不那么脏的解决方案,您可能还需要执行以下操作:
在黑色位图上绘制文本,然后将其 alpha 混合到主 hdc,但是:将目标矩形 -1 .. 2 移动 x 并将 -1 .. 3 移动 y (即循环中的多个混合)。为了实现阴影淡化效果,相应地修改 SourceConstantAlpha 以用于外部混合(|x| > 1 或 |y| > 1)。
这是一个粗略的方法,请随意尝试细节。
我不确定这种解决方案的性能和视觉质量方面,但在某些情况下可能就足够了。
另请参阅此处的 DrawShadowText 函数:在图像上写入透明文本
函数原型是这样的:procedure DrawShadowText(aCanvas: TCanvas; CONST Text: string; CONST X, Y, Opacity: Integer; TextColor, ShadowColor: TColor);
它可以使用了。
另一个 DrawShadowText 函数,这次基于 MS Win API。需要 Windows Vista 及更高版本。
来源:https ://www.delphipraxis.net/66678-drawshadowtext-delphi-commctrl-h-comctl32-dll-3.html
这是英文版:
{-------------------------------------------------------------------------------------------------------------
Unit ShadowText by Matthias G. aka turboPASCAL
Version 1.0 (VCL)
Draws text with shadow (This unit provides the function DrawShadowText from the ComCtl32.dll)
Minimum req:
Windows Vista
Comctl32.dll v6
If running under XP or without Windows XP Manifest, a substitute function is used to display the shadow.
From the user manual: To use DrawShadowText, specify Comctl32.dll version 6 in the manifest. For more information on manifests, see Enabling Visual Styles.
Src: https://www.delphipraxis.net/66678-drawshadowtext-delphi-commctrl-h-comctl32-dll-3.html
API docs: https://docs.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-drawshadowtext
Tester: c:\Myprojects\Project Testers\gr cGraphUtil.pas\
-------------------------------------------------------------------------------------------------------------}
UNIT ShadowText;
INTERFACE
USES
Windows, SysUtils, System.Classes, Graphics;
VAR
// determines whether the alternative shadow should be used if the function from ComCtl32.dll is not available
UseLQShadow : Boolean = True;
// Output of a text with shadow by specifying X and Y coordinates
function DrawShadowText(ACanvas: TCanvas; x, y: Integer; AText: string; TextColor, ShadowColor: TColor; ShadowSpaceX, ShadowSpaceY: Integer): Integer;
// Output of a text with shadow over a TRect structure with specification of the text formatting (text flags see Delphi help "DrawText")
function DrawShadowTextR(ACanvas: TCanvas; TextRect: TRect; x, y: Integer; AText: string; TextColor, ShadowColor: TColor; ShadowSpaceX, ShadowSpaceY: Integer; TextFlags: DWord): Integer;
IMPLEMENTATION
TYPE
TDrawShadowTextI = function(hdc: HDC;
pszText: LPCWSTR;
cch: UINT;
const pRect: PRect;
dwFlags: DWORD;
crText: COLORREF;
crShadow: COLORREF;
ixOffset: Integer;
iyOffset: Integer): Integer; stdcall;
VAR
hComCtl32DLL: THandle = 0;
DrawShadowTextI: TDrawShadowTextI;
OldCanvasColor: TColor;
OldBkModeColor: Integer;
// DrawShadowText as declared in ComCtl32.dll ( requires WindowsXP-Manifest! )
// function DrawShadowText_(hdc: HDC; pszText: LPCWSTR; cch: UINT; const pRect: PRect; dwFlags: DWORD; crText: COLORREF; crShadow: COLORREF; ixOffset: Integer; iyOffset: Integer): Integer; stdcall; external 'ComCtl32.dll' name 'DrawShadowText';
// Determines whether a Windows version from WinXP on is available.
function IsWindowsXPAndUp: Boolean;
begin
Result := ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1)) or (Win32MajorVersion > 5);
end;
// DrawShadowTextL (L - Low Quality)
function DrawShadowTextL(ACanvas: TCanvas; TextRect: TRect; AText: string;
TextColor, ShadowColor: TColor; ShadowSpaceX,
ShadowSpaceY: Integer; TextFlags: DWORD): Integer;
begin
OldBkModeColor := SetBKMode(ACanvas.Handle, TRANSPARENT);
OldCanvasColor := ACanvas.Font.Color;
if UseLQShadow
then
begin
inc(TextRect.Left, ShadowSpaceX);
inc(TextRect.Top, ShadowSpaceY);
inc(TextRect.Right, ShadowSpaceX);
inc(TextRect.Bottom, ShadowSpaceY);
ACanvas.Font.Color := ShadowColor;
Result := DrawText(ACanvas.Handle, PChar(AText), length(AText), TextRect, TextFlags);
dec(TextRect.Left, ShadowSpaceX);
dec(TextRect.Top, ShadowSpaceY);
dec(TextRect.Right, ShadowSpaceX);
dec(TextRect.Bottom, ShadowSpaceY);
end
else
Result := 1;
ACanvas.Font.Color := TextColor;
Result := Result AND DrawText(ACanvas.Handle, PChar(AText), length(AText), TextRect, TextFlags);
ACanvas.Font.Color := OldCanvasColor;
SetBKMode(ACanvas.Handle, OldBkModeColor);
end;
// DrawShadowText: für einfache Ausgabe
function DrawShadowText(ACanvas: TCanvas; x, y: Integer; AText: string; TextColor, ShadowColor: TColor; ShadowSpaceX, ShadowSpaceY: Integer): Integer;
VAR TextRect: TRect;
begin
TextRect := RECT(x, y, x + ACanvas.TextWidth(AText), y + ACanvas.TextHeight(AText));
if @DrawShadowTextI <> nil
then Result := DrawShadowTextI(ACanvas.Handle, PWideChar(WideString(AText)), length(AText), @TextRect, 0, COLORREF(TextColor), COLORREF(ShadowColor), ShadowSpaceX, ShadowSpaceY)
else Result := DrawShadowTextL(ACanvas, TextRect, AText, TextColor, ShadowColor, ShadowSpaceX, ShadowSpaceY, 0);
end;
// DrawShadowTextR: for formatted output (R - Text[R]ect)
function DrawShadowTextR(ACanvas: TCanvas; TextRect: TRect; x, y: Integer; AText: string; TextColor, ShadowColor: TColor; ShadowSpaceX, ShadowSpaceY: Integer; TextFlags: DWord): Integer;
begin
if @DrawShadowTextI <> NIL
then Result := DrawShadowTextI(ACanvas.Handle, PWideChar(WideString(AText)), length(AText), @TextRect, TextFlags, COLORREF(TextColor), COLORREF(ShadowColor), ShadowSpaceX, ShadowSpaceY)
else Result := DrawShadowTextL(ACanvas, TextRect, AText, TextColor, ShadowColor, ShadowSpaceX, ShadowSpaceY, TextFlags);
end;
initialization
if IsWindowsXPAndUp then
begin
hComCtl32DLL := LoadLibrary('ComCtl32.dll');
@DrawShadowTextI := GetProcAddress(hComCtl32DLL, 'DrawShadowText');
end;
finalization
if hComCtl32DLL <> 0
then FreeLibrary(hComCtl32DLL);
end.