【问题标题】:Transparent Tooltip Background [closed]透明工具提示背景
【发布时间】:2012-12-14 13:33:30
【问题描述】:

我在一个窗口中有 2 个区域,每个区域都有自己的工具提示。
这些工具提示是通过处理 WM_PAINT 消息自定义绘制的(以防止闪烁)。

这是工具提示的创建:

tooltips[MAIN_GRAPH_TT].tthWnd =  CreateWindowEx(WS_EX_TOPMOST,TOOLTIPS_CLASS,0,WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP | TTS_NOFADE,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,0,0,g_hInst,0);  
tooltips[SECONDARY_GRAPH_TT].tthWnd =   CreateWindowEx(WS_EX_TOPMOST,TOOLTIPS_CLASS,0,WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP | TTS_NOFADE,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,0,0,g_hInst,0);  

这是工具提示的初始化:

if (tooltips[MAIN_GRAPH_TT].tthWnd)
{

    lpfnOldTTProc = (WNDPROC)SetWindowLong(tooltips[MAIN_GRAPH_TT].tthWnd,
        GWL_WNDPROC, (DWORD) TooltipProc);
    SetWindowLong(tooltips[MAIN_GRAPH_TT].tthWnd, GWL_EXSTYLE, WS_EX_LAYERED|WS_EX_TOOLWINDOW);
    SetLayeredWindowAttributes(tooltips[MAIN_GRAPH_TT].tthWnd,RGB(255,0,0),0,ULW_COLORKEY);
    SendMessage(tooltips[MAIN_GRAPH_TT].tthWnd,CWM_SETWNDPROC,0,(LPARAM)new WNDPROC(lpfnOldTTProc));
}

if (tooltips[SECONDARY_GRAPH_TT].tthWnd)
{

    lpfnOldTTProc = (WNDPROC)SetWindowLong(tooltips[SECONDARY_GRAPH_TT].tthWnd, GWL_WNDPROC, (DWORD) TooltipProc);
    SetWindowLong(tooltips[SECONDARY_GRAPH_TT].tthWnd, GWL_EXSTYLE, WS_EX_LAYERED|WS_EX_TOOLWINDOW);
    SetLayeredWindowAttributes(tooltips[SECONDARY_GRAPH_TT].tthWnd,RGB(255,0,0),0,ULW_COLORKEY);
    SendMessage(tooltips[SECONDARY_GRAPH_TT].tthWnd,CWM_SETWNDPROC,0,(LPARAM)new WNDPROC(lpfnOldTTProc));
}  

这是自定义工具提示 WNDPROC 的 WM_PAINT:

 case WM_PAINT:
     {

        const int FRAME_WIDTH = 1;
        const int CORNER_DIAMETER = 10;
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd,&ps);
        HDC hMemDC;
        RECT cr;
        GetClientRect(hWnd,&cr);
        hMemDC = CreateCompatibleDC(hdc);
        HBITMAP memBM = CreateCompatibleBitmap(hdc, cr.right-cr.left, cr.bottom-cr.top);
        HBITMAP hOldBM = (HBITMAP) SelectObject(hMemDC,memBM);
        //drawing start [draw to hMemDC]
        {
            FillSolidRect(hMemDC,0,0,cr.right-cr.left,cr.bottom-cr.top,RGB(255,0,0));               
            HPEN hFramePen = CreatePen(PS_SOLID,FRAME_WIDTH,BLACK);
            HBRUSH hBGBrush = GetSysColorBrush(COLOR_INFOBK);
            SetTextColor(hMemDC,GetSysColor(COLOR_INFOTEXT));
            SetBkColor(hMemDC,WHITENESS);
            SetBkMode(hMemDC,TRANSPARENT);
            HBRUSH hOldBrush = (HBRUSH) SelectObject(hMemDC,hBGBrush);
            HPEN hOldPen = (HPEN) SelectObject(hMemDC,hFramePen);
            HFONT hOldFont = SelectFont(hMemDC,g_hFonts[FONT_TOOLTIP]);
            RoundRect(hMemDC,cr.left,cr.top,cr.right,cr.bottom,CORNER_DIAMETER,CORNER_DIAMETER);
            RECT textRec = cr;
            textRec.left += FRAME_WIDTH*2;
            textRec.right -= FRAME_WIDTH*2;
            textRec.top += FRAME_WIDTH*2;
            textRec.bottom -= FRAME_WIDTH*2;
            if(hWnd == tooltips[MAIN_GRAPH_TT].tthWnd)
                DrawText(hMemDC,tttBuffer[MAIN_GRAPH_TT],sizeof(tttBuffer),&textRec,DT_LEFT|DT_TOP);
            else if(hWnd == tooltips[SECONDARY_GRAPH_TT].tthWnd)
                DrawText(hMemDC,tttBuffer[SECONDARY_GRAPH_TT],sizeof(tttBuffer),&textRec,DT_LEFT|DT_TOP);
            SelectObject(hMemDC,hOldBrush);
            SelectObject(hMemDC,hOldPen);
            SelectObject(hMemDC,hOldFont);
            DeleteObject(hFramePen);
            DeleteObject(hBGBrush);

        }
        //drawing end
        BitBlt(hdc,
                cr.left,
                cr.top,
                cr.right-cr.left, cr.bottom-cr.top,
                hMemDC,
                0,
                0,
                SRCCOPY);
        SelectObject(hdc,hOldBM);
        DeleteObject(memBM);
        DeleteDC(hMemDC);
        EndPaint(hWnd,&ps);
     }
    break;

这些工具提示的问题是,角落(在圆形矩形之外)应该是透明的,但我似乎无法让它们消失。
我曾尝试(天真地)使用 HOLLOW_BRUSH 绘制背景矩形,但没有奏效,正如您从示例中看到的那样,我尝试使用分层窗口方法,再次无济于事。

谁能帮我获得工具提示背景的透明度?


这是一张不透明的工具提示图片
[为了能见度,角落已重新涂成白色——这些是需要透明的部分]
(文本空白)

【问题讨论】:

  • 呃。透明工具提示的概念是一个非常奇怪的概念。它应该在任何重叠的地方都清晰可见,因此提示易于阅读。我怀疑你需要 SetWindowRgn()。
  • 工具提示是图片中的颜色,它只是需要透明的角落(它们是圆角的)——虽然图片不是很清晰,但你应该能够确定它们是红色的。它们是需要透明度的部分。
  • 角落现在是白色的,以便更好地看到
  • 对于 SetWindowRgn(),这似乎是个好主意,我得试一试,看看我是否不能用它从头开始创建工具提示。我更喜欢通过工具提示控件来实现,但它绝对值得一试。

标签: c winapi tooltip transparency


【解决方案1】:

在处理控件和透明度时,我发现 WS_EX_TRANSPARENT exStyle 可以为您节省一些时间。此外,您可能想要检查工具提示是否向主窗口发送 WM_CTLCOLORSTATIC 消息,如果是,您可能想要发回一个空心(空)画笔句柄作为响应。您可能还需要在那个时间点将背景模式设置为透明,方法是在 WM_CTLCOLORSTATIC 消息提供的 hDC 上调用 SetBkMode。

很抱歉没有对此进行任何测试,但它适用于静态和组控件。到目前为止,我证明对这种方法没有响应的唯一控件是复选框按钮,我无法为其设置背景透明度。

问候。

【讨论】:

  • 感谢您的回复...我没有考虑过处理颜色信息...我真的应该这样做。是的,我已经尝试过使用其他样式的 ws_ex_transparant,虽然我没有提及它......不过会看看通过一个空心刷是否可以帮助我
  • @Daboyzuk 不客气。不要忘记设置背景模式
  • 抱歉延迟响应,似乎(除非我做错了什么,或者阻止它们)工具提示实际上没有收到任何 WM_CTLCOLOR 消息,我发现有点奇怪。
  • @Daboyzuk 没关系。 IDK,这并不奇怪。 Winapi 中的常见控件非常奇怪,这是一个众所周知且令人遗憾的事实。就像我上面提到的复选框示例一样。一个愚蠢的问题,你确定你在正确的父窗口中等待它们吗?
  • 是的,我很确定。我不是万无一失的,但我只是仔细检查了一下,我仍然没有收到任何关于工具提示的 CTLCOLOR(+ 朋友)消息。
【解决方案2】:

您可以使用SetWindowRgn 使窗口的某些部分透明(使用CreateRoundRectRgn 创建一个区域)。

或者,您可以使用SetLayeredWindowAttributes 使用真正的 Alpha 混合来使窗口的某些部分透明。

【讨论】:

  • 我不确定真正的 alpha 混合是否是我想要的,但我想如果我正在控制 wm_paint,我想我只是忽略了窗口应该是透明和绘画的事实。 . 有空我会试一试
  • SetWindowRgn 和 CreateRoundRectRgn 已经完成了这项工作,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-31
  • 2020-10-29
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多