Windows xp 如何像Windows XP在桌面图标上那样用阴影绘制文本?

Windows xp 如何像Windows XP在桌面图标上那样用阴影绘制文本?,windows-xp,gdi,shadow,drawtext,Windows Xp,Gdi,Shadow,Drawtext,Windows XP使用漂亮的阴影绘制图标文本,这有助于在各种背景下阅读文本。字体颜色为白色,阴影为黑色(如果桌面背景为白色),或者根本没有阴影(如果桌面背景为黑色) 因此,有两个子任务: 阴影是怎么画出来的?它不是一个简单的文本x、y偏移量;阴影在我看来更像是模糊的 如何使阴影在白色背景上更可见,而在黑暗背景下更不可见 我需要一个GDI解决方案(不是GDI+)。请阅读。灵感来自 如果您需要快速且不太脏的解决方案,您可能还需要执行以下操作: 在黑色位图上绘制文本,然后alpha将其混合到主hdc

Windows XP使用漂亮的阴影绘制图标文本,这有助于在各种背景下阅读文本。字体颜色为白色,阴影为黑色(如果桌面背景为白色),或者根本没有阴影(如果桌面背景为黑色)

因此,有两个子任务:

  • 阴影是怎么画出来的?它不是一个简单的文本x、y偏移量;阴影在我看来更像是模糊的

  • 如何使阴影在白色背景上更可见,而在黑暗背景下更不可见

  • 我需要一个GDI解决方案(不是GDI+)。

    请阅读。

    灵感来自

    如果您需要快速且不太脏的解决方案,您可能还需要执行以下操作:

    在黑色位图上绘制文本,然后alpha将其混合到主hdc,但:将目标矩形移动到-1。。2乘x和-1。。3乘以y(即,一个回路中的多个混合物)。要实现阴影淡入效果,请针对外部混合(| x |>1或| y |>1)相应修改SourceConstantAlpha

    这是一个粗略的方法,请随意尝试细节


    我不确定这种解决方案的性能和视觉质量方面,但在某些情况下它可能足够了。

    也可以在此处查看DrawShadowText函数:

    函数原型是这样的:过程DrawShadowText(aCanvas:TCanvas;CONST Text:string;CONST X,Y,Opacity:Integer;TextColor,ShadowColor:TColor)

    它已经可以使用了。

    另一个DrawShadowText函数,这次是基于MS Win API的。需要Windows Vista和更高版本

    资料来源:

    以下是英文版本:

    {-------------------------------------------------------------------------------------------------------------
      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.
    
    {-------------------------------------------------------------------------------------------------------------
    Matthias G.aka turboPASCAL的单位阴影文本
    1.0版(VCL)
    使用阴影绘制文本(此单元提供ComCtl32.dll中的函数DrawShadowText)
    最低要求:
    Windows Vista
    Comctl32.dll v6
    如果在XP或没有Windows XP清单的情况下运行,将使用替代函数显示阴影。
    从用户手册:要使用DrawShadowText,请在清单中指定Comctl32.dll版本6。有关清单的详细信息,请参阅启用视觉样式。
    Src:https://www.delphipraxis.net/66678-drawshadowtext-delphi-commctrl-h-comctl32-dll-3.html
    API文档:https://docs.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-drawshadowtext
    测试人员:c:\Myprojects\Project Testers\gr cGraphUtil.pas\
    -------------------------------------------------------------------------------------------------------------}
    单位阴影文本;
    接口
    使用
    Windows、SysUtils、System.Class、图形;
    变量
    //确定如果ComCtl32.dll中的函数不可用,是否应使用替代阴影
    UseLQShadow:Boolean=True;
    //通过指定X和Y坐标输出带阴影的文本
    函数DrawShadowText(ACanvas:TCanvas;x,y:Integer;AText:string;TextColor,ShadowColor:TColor;ShadowSpaceX,ShadowSpaceY:Integer):整数;
    //带阴影的文本输出到树状结构上,并指定文本格式(文本标志见Delphi帮助“DrawText”)
    函数DrawShadowTextR(ACanvas:TCanvas;TextRect:TRect;x,y:Integer;AText:string;TextColor,ShadowColor:TColor;ShadowSpaceX,ShadowSpaceY:Integer;TextFlags:DWord):Integer;
    实施
    类型
    TDrawShadowTextI=函数(hdc:hdc;
    pszText:LPCWSTR;
    cch:UINT;
    常数预测:预测;
    德沃德;
    crText:COLORREF;
    crShadow:COLORREF;
    ixOffset:整数;
    iyOffset:整数):整数;stdcall;
    变量
    hComCtl32DLL:THandle=0;
    DrawShadowTextI:TDrawShadowTextI;
    OldCanvasColor:TColor;
    OldBkModeColor:整数;
    //ComCtl32.dll中声明的DrawShadowText(需要WindowsXP清单!)
    //函数DrawShadowText(hdc:hdc;pszText:LPCWSTR;cch:UINT;const pRect:pRect;dwFlags:DWORD;crText:COLORREF;crShadow:COLORREF;ixOffset:Integer;iyOffset:Integer):整数;stdcall;外部“ComCtl32.dll”名称“DrawShadowText”;
    //确定上WinXP的Windows版本是否可用。
    函数IsWindowsXPAndUp:布尔值;
    开始
    结果:=((Win32MajorVersion=5)和(Win32MinorVersion>=1))或(Win32MajorVersion>5);
    结束;
    //DrawShadowTextL(L-低质量)
    函数DrawShadowTextL(ACanvas:TCanvas;TextRect:TRect;AText:string;
    TextColor,ShadowColor:t颜色;ShadowSpaceX,
    ShadowSpaceY:Integer;TextFlags:DWORD):Integer;
    开始
    OldBkModeColor:=SetBKMode(ACanvas.Handle,透明);
    OldCanvasColor:=ACanvas.Font.Color;
    如果使用Qshadow
    然后
    开始
    inc(TextRect.Left,ShadowSpaceX);
    inc(TextRect.Top,ShadowSpaceY);
    inc(TextRect.Right,ShadowSpaceX);
    inc(TextRect.Bottom,ShadowSpaceY);
    ACanvas.Font.Color:=阴影颜色;
    结果:=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);
    结束
    其他的
    结果:=1;
    ACanvas.Font.Color:=TextColor;
    结果:=结果和DrawText(ACanvas.Handle、PChar(AText)、长度(AText)、TextRect、TextFlags);
    ACanvas.Font.Color:=旧画布颜色;
    SetBKMode(ACanvas.Handle,OldBkModeColor);
    结束;
    //DrawShadowText:für einfache Ausgabe
    函数DrawShadowText(ACanvas:TCanvas;x,y:Integer;AText:string;TextColor,ShadowColor:TColor;ShadowSpaceX,ShadowSpaceY:Integer):整数;
    VAR TextRect:TRect;
    开始
    TextRect:=RECT(x,y,x+ACanvas.TextWidth(AText),y+ACanvas.TextHeight(AText));
    如果@DrawShadowTextI为零
    然后结果:=DrawShadowTextI(ACanvas.Handle,PWideChar(宽字符串(AText)),长度(AText),@TextRect,0,COLORREF(TextColor),COLORREF(ShadowColor),ShadowSpaceX,ShadowSpaceY)
    else结果:=DrawShadowTextL(ACanvas、TextRect、AText、TextColor、ShadowColor、ShadowSpaceX、ShadowSpaceY,0);
    结束;
    /