如何为 `TBitBtn` 设置 `ElevationRequired`

How to set `ElevationRequired` for `TBitBtn`

我需要标记一个 TBitBtn(不是 TButton),按钮操作需要提升。我将 ElevationRequired 设置为 True,但我没有看到盾牌图标。

要复制,请在表格上放置 TButtonTBitBtn

procedure TForm1.FormCreate(Sender: TObject);
begin
    Button1.ElevationRequired := True;
    BitBtn1.ElevationRequired := True;
end;

Button1显示盾牌图标,BitBtn1不显示。

这是不可能的。

一个 VCL TBitBtn is an owner-drawn Win32 BUTTON 控件。你可以在这里看到:

procedure TBitBtn.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do Style := Style or BS_OWNERDRAW;
end;

因此,TBitBtn 不是 由 Windows 绘制,而是由 Vcl.Buttons.pas 中的 Pascal 代码手动绘制。具体来说,TBitBtn.DrawItem(const DrawItemStruct: TDrawItemStruct) 作画。

而这里你可以看到没有提到ElevationRequired

因此,TBitBtn不支持这个。

一般情况下,不要使用TBitBtn;使用 TButton 获取本机 Win32 按钮。

因为 ElevationRequired 没有为 TBitBtn 实现(参见 )。我最终通过此过程 (Vista+) 绘制了盾牌图标:

procedure MarkElevationRequired(ABitBtn: TBitBtn);
var
    Icon: TIcon;
begin
    Assert(Assigned(ABitBtn));
    //---
    try
        Icon := TIcon.Create;
        try
            Icon.Handle := GetSystemIcon(SIID_SHIELD, TSystemIconSize.Small); //see WinApi.ShellApi
            ABitBtn.Glyph.Assign(Icon);
        finally
            Icon.Free;
        end;
    except
        //CreateSystemIcon throws an exception for <WinVista
    end;
end;

/// Get system icon for SIID, see https://docs.microsoft.com/de-de/windows/win32/api/shellapi/ne-shellapi-shstockiconid
/// Works for Win Vista or better
/// see https://community.idera.com/developer-tools/b/blog/posts/using-windows-stock-icons-in-delphi
function GetSystemIcon(Id: integer; Size: TSystemIconSize = TSystemIconSize.Large;
  Overlay: Boolean = False; Selected: Boolean = False): HICON;
var
    Flags: Cardinal;
    SSII: TSHStockIconInfo;
    ResCode: HResult;
begin
    if not TOSVersion.Check(6, 0) then
      raise Exception.Create('SHGetStockIconInfo is only available in Win Vista or better.');

    case Size of
        TSystemIconSize.Large: Flags := SHGSI_ICON or SHGSI_LARGEICON;
        TSystemIconSize.Small: Flags := SHGSI_ICON or SHGSI_SMALLICON;
        TSystemIconSize.ShellSize: Flags := SHGSI_ICON or SHGSI_SHELLICONSIZE;
    end;

    if Selected then
      Flags := Flags OR SHGSI_SELECTED;
    if Overlay then
      Flags := Flags OR SHGSI_LINKOVERLAY;

    SSII.cbSize := SizeOf(SSII);
    ResCode := SHGetStockIconInfo(Id, Flags, SSII);

    if ResCode <> S_OK then
    begin
        if ResCode = E_INVALIDARG then
          raise Exception.Create(
            'The stock icon identifier [' + IntToStr(id) + '] is invalid')
        else
          raise Exception.Create(
            'Error calling GetSystemIcon: ' + IntToStr(ResCode));
    end
    else
      Result := SSII.hIcon;
end;