【问题标题】:How Do I Create a 32-bit Tray Icon With Transparency (using GDI)?如何创建具有透明度的 32 位托盘图标(使用 GDI)?
【发布时间】:2011-08-21 01:19:43
【问题描述】:

我正在尝试创建一个在系统托盘中显示一段文本的图标。 (显然,它不会超过几个字符。)

到目前为止我已经尝试过:

#include <tchar.h>
#include <Windows.h>
#include <Windowsx.h>

static HICON CreateIcon(LPCTSTR txt) {
    HICON hIcon = NULL;
    HDC hDC = NULL; {
        HDC hDCScreen = GetDC(NULL);
        if (hDCScreen != NULL) {
            __try { hDC = CreateCompatibleDC(hDCScreen); }
            __finally { ReleaseDC(NULL, hDCScreen); }
        }
    }
    if (hDC != NULL) {
        __try {
            HFONT hFont = CreateFontIndirect(&ncm.lfMessageFont);
            if (hFont != NULL) {
                __try { SelectFont(hDC, hFont); }
                __finally { DeleteFont(hFont); }
            }
            int width = GetSystemMetrics(SM_CXSMICON),
                height = GetSystemMetrics(SM_CYSMICON);
            HBITMAP hBmp = CreateCompatibleBitmap(hDC, width, height);
            if (hBmp != NULL) {
                __try {
                    HBITMAP hMonoBmp =
                        CreateCompatibleBitmap(hDC, width, height);
                    if (hMonoBmp != NULL) {
                        __try {
                            RECT rect = { 0, 0, width, height };
                            HGDIOBJ prev = SelectObject(hDC, hBmp);
                            __try {
                                SetBkMode(hDC, TRANSPARENT);
                                SetTextColor(hDC, RGB(255, 255, 255));
                                ICONINFO ii = { TRUE, 0, 0, hMonoBmp, hBmp };
                                int textHeight =
                                    DrawText(hDC, txt, _tcslen(txt), &rect, 0);
                                if (textHeight != 0) {
                                    hIcon = CreateIconIndirect(&ii);
                                }
                            } __finally { SelectObject(hDC, prev); }
                        } __finally { DeleteObject(hMonoBmp); }
                    }
                } __finally { DeleteObject(hBmp); }
            }
        } __finally { DeleteDC(hDC); }
    }
    return hIcon;
}

使用此代码:

static void _tmain(int argc, TCHAR* argv[]) {
    HICON hIcon = CreateIcon(_T("Hi"));
    if (hIcon != NULL) {
        __try {
            NOTIFYICONDATA nid = { sizeof(nid) };
            nid.hWnd = GetConsoleWindow();
            BOOL success = Shell_NotifyIcon(NIM_ADD, &nid);
            if (success) {
                nid.uFlags = NIF_ICON;
                nid.hIcon = hIcon;
                success = Shell_NotifyIcon(NIM_MODIFY, &nid);
            }
        } __finally { DestroyIcon(hIcon); }
    }
}

但我得到的只是一个单色位图,上面写着Hi,在黑色背景上用白色文本显示。 (如果我稍微改变一下RGB(255, 255, 255),比如RGB(255, 255, 254),它就会变成黑色,所以它是单色的。)

有什么想法吗?

(*注意:我不是寻找 MFC、ATL 或任何其他库解决方案,只是 Win32/GDI 调用。)


编辑:

这是目前的样子:

【问题讨论】:

  • 请注意,它不叫“系统托盘”,也从未被称为“系统托盘”。这是任务栏通知区
  • @Cody:是的,why use two syllables 九点什么时候可以?
  • 不幸的是,在英语中,音节的数量和方便程度并不是决定短语正确性的主要因素。该区域称为通知区域。 Raymond Chen's blog article 是惯用的参考。你有没有想过为什么相关功能会提到“通知图标”?是的,您发现了一篇标题不准确的知识库文章。其中有很多。有一些信息完全不正确,尤其是关于 VB 的文章。
  • @Cody:博文倒数第三行准确地总结了我的感受。 ;)
  • 感谢您的意见,马德赫德。

标签: winapi gdi system-tray trayicon


【解决方案1】:

如果我没记错的话,一个部分透明的图标(我认为这是我想要的)有一个单色位图作为它的掩码。这个掩码恰好被忽略了,但您仍然必须提供它。您不是在创建单色位图,而是在创建 32bpp 位图。我也看不到您为主位图初始化 alpha 值的任何地方,以便您不写入的区域是透明的。

此处提供了一个带有代码的示例:How To Create an Alpha Blended Cursor or Icon in Windows XP

【讨论】:

  • @David:透明度是的,我指的是 alpha 透明度,而不是传统的粉色蒙版式透明度。我对如何实际编码感到困惑......所有这些与兼容的位图和DIB的混乱,它们通常是单色的,除非你使用内存DC(在这种情况下它应该是彩色的,除非它不是似乎)只是真的让我感到困惑......你碰巧知道我可以遵循的任何例子吗?另外,我没有在任何地方初始化 alpha 值,这是真的,但我不确定这有什么不同,因为我遇到了文本问题,而不仅仅是背景。
  • @Mehrdad 我现在很忙,所以也许其他人可以为您提供更详细的帮助,但我怀疑我已经强调了您当前代码的至少两个问题。
  • @David:好的,谢谢,我会尝试设置 alpha 位。 (如果位图是单色的,我不确定它是否会起作用——希望我不会超出一些缓冲区,哈哈——但我会试试的,谢谢。)
  • 只有主位图有 alpha 值。掩码被忽略,但您仍然必须提供它。重要的是它每个像素有 1 位颜色,即单色。它的内容无关紧要。
  • @David:哦,真的吗?!我不知道它被忽略了......哈哈谢谢,我会试试看。
猜你喜欢
  • 1970-01-01
  • 2010-10-17
  • 2020-04-12
  • 2017-07-02
  • 2011-01-23
  • 1970-01-01
  • 1970-01-01
  • 2011-11-26
  • 2011-12-31
相关资源
最近更新 更多