【问题标题】:text menu as created window behaviour of highlighting文本菜单作为创建的高亮窗口行为
【发布时间】:2021-08-03 16:18:49
【问题描述】:

我创建了一个 Windows 应用程序。我创建的元素使用子类化,因为我想处理鼠标悬停事件。

DWORD dwStyleOfIcons = SS_BITMAP | SS_NOTIFY | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER;
img1 = CreateWindow(L"STATIC", NULL, dwStyleOfIcons,
            posX, posY, imgWt, imgHt,
            hWnd, (HMENU)ICON1_CLICKED, hInst, NULL);
SetWindowSubclass(img1, StaticSubClassWndProc, ICON1_CLICKED, 0);

在我的StaticSubClassWndProc() 中,我处理WM_MOUSEMOVEWM_MOUSELEAVEWM_MOUSEHOVER

LRESULT CALLBACK StaticSubClassWndProc (HWND  hwndsubclass, UINT msg, WPARAM wp, LPARAM lp, UINT_PTR uidsubclass , DWORD_PTR dwrefdata)
{
    ...
    switch(Msg)
    {
        case WM_MOUSEHOVER: {
            if(uidsubclass  == ICON1_CLICKED){
              texture = "texture2.bmp";
               modifyImage(texture);
            }
            break;
        }
        
        case WM_MOUSELEAVE: {
           if(uidsubclass  == ICON1_CLICKED){
               texture = "texture.bmp";
               modifyImage(texture);
            }
            break;
        }
 

我的应用程序中有许多 STATIC 项目,我想要的只是弹出上下文菜单的行为,例如当我将鼠标悬停在图像上时,它会变为选定的图像,而当光标不在视图中时图像恢复正常。我能够做到这一点。

我可以对充当图标的图像执行此操作,但如何为静态文本控件执行此操作?本质上,在弹出菜单中,选定的文本都被突出显示:

没有更简单的方法可以让我在这个窗口中的元素表现得像一个弹出菜单吗?我想要的只是弹出菜单行为的这种自定义结构。

【问题讨论】:

  • 您是否在问如何为STATIC 控件指定颜色?让 parent 窗口的 WndProc 处理 WM_CTLCOLORSTATIC 消息。
  • 我打算在鼠标悬停时更改窗口的颜色,并在文本静态控件中留下事件。我该怎么做?
  • 如前所述,您需要让父窗口处理WM_CTLCOLORSTATIC 消息。声明一个颜色变量,并在收到WM_CTLCOLORSTATIC 时应用它。在鼠标事件中,更新变量和InvalidateRect()STATIC控件以触发重绘,这将发送一条新消息。

标签: c++ visual-studio winapi


【解决方案1】:

我认为您没有正确处理TrackMouseEvent 函数,导致您的子窗口无法处理WM_MOUSEHOVERWM_MOUSELEAVE 消息。

我测试了以下代码,它对我有用:

HBITMAP hBmp1 = (HBITMAP)LoadImage(NULL, L"test1.bmp", IMAGE_BITMAP, 200, 300, LR_LOADFROMFILE);
HBITMAP hBmp2 = (HBITMAP)LoadImage(NULL, L"test2.bmp", IMAGE_BITMAP, 200, 300, LR_LOADFROMFILE);
HWND img1;

LRESULT CALLBACK StaticSubClassWndProc(HWND  hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uidsubclass, DWORD_PTR dwrefdata)
{
    switch (msg)
    {
    case WM_MOUSEMOVE:
    {
        TRACKMOUSEEVENT lpEventTrack;
        lpEventTrack.cbSize = sizeof(TRACKMOUSEEVENT);
        lpEventTrack.dwFlags = TME_HOVER | TME_LEAVE;
        lpEventTrack.hwndTrack = img1;
        lpEventTrack.dwHoverTime = 100;
        TrackMouseEvent(&lpEventTrack);
        break;
    }
    case WM_MOUSEHOVER:
    {
        if (uidsubclass == ICON1_CLICKED) {
            SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBmp1);
        }
        break;
    }
    case WM_MOUSELEAVE:
    {
        if (uidsubclass == ICON1_CLICKED) {
            SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBmp2);
        }
        break;
    }
    default:
        return DefSubclassProc(hwnd, msg, wParam, lParam);
    }
}

但是你需要注意WM_MOUSEHOVERWM_MOUSELEAVE会频繁触发,所以我认为你不应该在鼠标悬停或离开时使用这种方法加载图片,这样会频繁触发加载图片。

【讨论】:

  • 我确实处理了 WM_MOUSEMOVE(错误地离开了它)。我打算在鼠标悬停中更改窗口的颜色并在文本静态控件中留下事件。我该怎么做?
  • 关于性能,如果我想复制弹出行为,即当鼠标悬停在项目上时,该项目会以视觉方式发生变化
  • 我认为您不能以这种方式动态更改静态控件的颜色。您只能通过processing the WM_CTLCOLORSTATIC message 修改其背景颜色。至于效率问题,选择使用这种方式时,只能尽量避免频繁来回触发WM_MOUSELEAVEWM_MOUSEHOVER消息。
猜你喜欢
  • 2020-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-02
  • 2021-02-21
  • 1970-01-01
相关资源
最近更新 更多