如何使用主题api绘制任务栏按钮,如图标

Posted

技术标签:

【中文标题】如何使用主题api绘制任务栏按钮,如图标【英文标题】:how to draw a taskbar button like icon using theme api 【发布时间】:2014-04-01 14:01:48 【问题描述】:

目前我正在使用 c++ 开发桌带。现在我可以在任务栏窗口中画东西,我想画一个任务栏按钮,比如图标。我相信它不会太复杂,因为默认的触摸键盘和 TouchMousePointer 已经做到了。

我首先创建一个空白窗口,并使用主题 api 来绘制背景。但我真的不知道如何制作任务栏按钮。目前只有静态图标或半透明按钮(只有上面的文字是透明的)有效。

在这篇文章中 How do you draw a Taskbar button using visual styles? 他们通过使用 .net 提到了一些东西,但我真的不想这样做。只是想保持一切简单。(没有 mfc 或 .net)

这篇文章中还有一些信息 How to draw Windows 7 taskbar like Shaded Buttons 但不是很有用。

我还检查了 TipBand.dll(默认触摸键盘)的导入功能

   UxTheme.dll
         18000D088 Import Address Table
         18000D668 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                       9 CloseThemeData
                      11 DrawThemeParentBackground
                       D DrawThemeBackground
                      50 SetWindowTheme
                      4D OpenThemeData

COMCTL32.dll
         18000D0B8 Import Address Table
         18000D698 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                      7C InitCommonControlsEx

GDI32.dll
         18000D358 Import Address Table
         18000D938 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                     2D4 SelectObject
                      4C CreatePen
                      56 CreateSolidBrush
                     10E DeleteObject
                     261 LineTo
                     26F MoveToEx

他还在 user32.dll 中使用了 DrawIconEx,我试过了,但只是一个静态图标。

我也尝试了主题 api drawicon,但什么也没发生,只是空白。 请指导我............

【问题讨论】:

【参考方案1】:

1) 您的桌带必须实现 IOleCommandTarget。当 shell 使用 DBID_SETWINDOWTHEME 调用 IOleCommandTarget.Exec 时,您必须将主题名称存储在变量 WindowThemeSubClass 中。

2) 打开主题(来自我的 Shell Ace 库的代码):

FToolBarTheme := IntOpenThemeData(Handle, 'TOOLBAR', WindowThemeSubClass)

...

class function TdecShellExplorerForm.IntOpenThemeData(AWnd: HWND; const AClass, ASubClass: UnicodeString): HTHEME;
var
  Temp: TForm;
begin
  if ASubClass = '' then
    Result := OpenThemeData(AWnd, PWideChar(AClass))
  else
    if IsWindowsVistaOrLater then
      begin
        Result := OpenThemeData(AWnd, PWideChar(ASubClass + '::' + AClass));
        if Result = 0 then
          Result := OpenThemeData(AWnd, PWideChar(AClass));
      end
    else
      begin
        Temp := TForm.Create(Application);
        try
          SetWindowTheme(Temp.Handle, PWideChar(ASubClass), nil);
          Result := OpenThemeData(Temp.Handle, PWideChar(AClass));
          if Result = 0 then
            Result := OpenThemeData(AWnd, PWideChar(AClass));
        finally
          Temp.Free;
        end;
      end;
end;

XP 不支持带有 'SubClass::Class' 等参数的 OpenTheme!

3) 仅当鼠标悬停在您的按钮上或用户按下您的按钮时才绘制按钮:

DrawThemeBackground(FToolBarTheme, Canvas.Handle, TP_BUTTON, State, Rec.Rect, nil);

当用户将鼠标悬停在您的按钮上时状态为 TS_HOT,或者当用户按下您的按钮时状态为 TS_PRESSED。

结果:

鼠标悬停在 MS Tablet PC 输入面板上:

鼠标悬停在我的扩展上:

【讨论】:

对了,图片是怎么设置的?您在创建按钮或使用 gdi 时设置它?

以上是关于如何使用主题api绘制任务栏按钮,如图标的主要内容,如果未能解决你的问题,请参考以下文章

如何更改ANDROID API 22中的默认向上按钮图标

如何在跳转开始列表和任务栏中为不同的主题显示不同的应用程序图标?

如何删除通知栏无效图标(重置任务栏通知区域)

如何让 JFrame 没有任务栏按钮?

windows任务栏和桌面图标不见啦!!!解决重赏

python tkinter 如何修改任务栏的窗口图标?