简体   繁体   English

将WM_MOUSEWHEEL Delphi代码转换为C ++ Builder

[英]Translating WM_MOUSEWHEEL Delphi code to C++ Builder

I have these links with code: 我有这些代码链接:

WMMouseWheel not working in Delphi WMMouseWheel在Delphi中不起作用

How to disable MouseWheel if mouse is not over VirtualTreeView (TVirtualStringTree) 如果鼠标不在VirtualTreeView(TVirtualStringTree)上,如何禁用MouseWheel

Translated it to C++ Builder but it doesn't work: 将其翻译为C ++ Builder,但不起作用:

UPDATE: After narrowing the problem down it appears that WM_MOUSEWHEEL messages don't work over unfocused TVirtualStringTree control only, they work over other controls. 更新:缩小问题范围后,似乎WM_MOUSEWHEEL消息仅对未聚焦的TVirtualStringTree控件起作用,而对其他控件起作用。 When focus is on eg TMemo control, other TMemo control scrolls on wheel but not TVirtualStringTree control. 当焦点集中在TMemo控件上时,其他TMemo控件在滚轮上滚动而不是TVirtualStringTree控件。 When focus is on TVirtualStringTree it scrolls TVirtualStringTree but not other controls. 当焦点在TVirtualStringTree它将滚动TVirtualStringTree但不滚动其他控件。 So the problem is now specific to TVirtualStringTree only. 因此,该问题现在仅特定于TVirtualStringTree

void __fastcall TForm1::ApplicationEventsMessage(tagMSG &Msg, bool &Handled)
{
TPoint Pt;
HWND   Wnd;

if (Msg.message == WM_MOUSEWHEEL ||
    Msg.message == WM_VSCROLL    ||
    Msg.message == WM_HSCROLL)
    {
    if (GetCursorPos(&Pt))
        {
        Wnd = WindowFromPoint(Pt);
        // It must be a VCL control otherwise we could get access violations
        if (IsWindowEnabled(Wnd) && FindControl(Wnd) != NULL)
            {
            Msg.hwnd = Wnd; // change the message receiver to the control under the cursor
            }
        }
    }
}

Different version of the similar code, also doesn't work: 相似代码的不同版本,也不起作用:

TPoint       pnt;
TWinControl *ctrl;

if ((Msg.message == WM_MOUSEWHEEL ||
     Msg.message == WM_VSCROLL    ||
     Msg.message == WM_HSCROLL) &&
    GetCursorPos(&pnt))
    {
    ctrl = FindVCLWindow(pnt);
    if (ctrl != NULL)
        {
        SendMessage(ctrl->Handle, Msg.message, Msg.wParam, Msg.lParam); // No effect
//      SendMessage(ctrl->Handle, WM_VSCROLL, 1, 0); // This is the only thing that actually moves scrollbars but this is not exactly the same message like above

//      Msg.hwnd = ctrl->Handle; // No effect
        this->Caption=ctrl->Name; // This shows correct control name so the message IS GETTING THROUGH!
        Handled = true;
        }
    }

It should work but it doesn't. 它应该可以,但是不能。 Tried other code as well. 也尝试了其他代码。 No effect - mouse wheel does not operate on unfocused control. 无效果-鼠标滚轮无法在未聚焦的控件上运行。 As you can see, I checked for all 3 variants of wheel messages, it gets correct control under the mouse, it shows that control name but the control doesn't receive wheel messages. 如您所见,我检查了Wheel消息的所有3个变体,它在鼠标下获得了正确的控件,它显示了控件名称,但控件未接收到Wheel消息。

Any ideas what piece of the puzzle am I missing to get it to work? 有什么主意我想让它起作用的难题是哪一个?

As nobody offered any proper solution, I am posting my own. 由于没有人提供任何适当的解决方案,因此我发布了自己的解决方案。 The solution is not perfect but at least it does what it needs to do - mouse wheel scrolls all controls under it, including the VirtualTreeView controls. 该解决方案并不完美,但至少可以完成所需的工作-鼠标滚轮滚动其下的所有控件,包括VirtualTreeView控件。 The code in solution is in C++ but Delphi version is very similar (it only needs to be translated). 解决方案中的代码是C ++,但是Delphi版本非常相似(只需要翻译)。

My current solution is to grab WM_MOUSEWHEEL events and translate them into WM_VSCROLL or WM_HSCROLL to which VirtualTreeView reacts and scrolls the content. 我当前的解决方案是获取WM_MOUSEWHEEL事件并将其转换为VirtualTreeView对其进行VirtualTreeView并滚动内容的WM_VSCROLLWM_HSCROLL Additionally, it needs to take into account high-precision mouse wheels which can have smaller value than WHEEL_DELTA (which is set to 120). 此外,它需要考虑高精度鼠标滚轮,该滚轮的值可能小于WHEEL_DELTA(设置为120)。 Finally, it needs to take into account user setting for number of lines to scroll (set in Control Panel in Windows). 最后,它需要考虑用户设置的滚动行数(在Windows的“控制面板”中设置)。 So here goes: 因此,这里去:

Put a TApplicationEvents to a form and in the OnMessage event do this: TApplicationEvents放入表单,然后在OnMessage事件中执行以下操作:

void __fastcall TFormMain::ApplicationEventsMessage(tagMSG &Msg, bool &Handled)
{
// Check these 3 messages because some mouse drivers may use VSCROLL instead of MOUSESWHEEL message
if (Msg.message == WM_MOUSEWHEEL || Msg.message == WM_VSCROLL || Msg.message == WM_HSCROLL)
    {
    TPoint       pnt;
    TWinControl *ctrl;

    if (!GetCursorPos(&pnt)) return;

    ctrl = FindVCLWindow(pnt);

    if (ctrl != NULL)
        {
// ToDo: implement if user needs wheel-click - then we also need KEYSTATE but for this example it is not needed
//      int fwKeys = GET_KEYSTATE_WPARAM(Msg.wParam);
        int      zDelta  = GET_WHEEL_DELTA_WPARAM(Msg.wParam),
                 pvParam = 3;                                                   // Windows default value
        unsigned MyMsg   = WM_VSCROLL;


// ToDo: extract SystemParametersInfo somewhere else so it is not extracted for each WM_MOUSEWHEEL message which may not be needed
        switch (Msg.message)
            {
            // This will translate WM_MOUSEWHEEL into WM_VSCROLL
                    case WM_MOUSEWHEEL:
            case WM_VSCROLL:
    // Windows setting which determines how many lines to scroll - we'll send that many WM_VSCROLL or WM_HSCROLL messages
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pvParam, 0);
                                MyMsg = WM_VSCROLL;
                                break;
            case WM_HSCROLL:    
      // Same as above but for WM_HSCROLL (horizontal wheel)
      SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &pvParam, 0);
                                MyMsg = WM_HSCROLL;
                                break;
            }

        // This calculation takes into account high-precision wheels with delta smaller than 120
        // Possible TODO: Round up values smaller than 1 (e.g. 0.75 * pvParam) if pvParam is 1
        int ScrollBy = ((double)zDelta / (double)WHEEL_DELTA) * pvParam;

        // Send multiple messages based on how much the zDelta value was
        if (zDelta > 0)
            {
            do
                {
                SendMessage(ctrl->Handle, MyMsg, SB_LINEUP, 0);
                }
            while (--ScrollBy > 0);
            }
        else
            {
            do
                {
                SendMessage(ctrl->Handle, MyMsg, SB_LINEDOWN, 0);
                }
            while (++ScrollBy < 0);
            }

        Handled = true;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM