Перевод WM_MOUSEWHEEL Delphi-кода в C ++ Builder

У меня есть эти ссылки с кодом:

WMMouseWheel не работает в Delphi

Как отключить MouseWheel, если мышь не находится над VirtualTreeView (TVirtualStringTree)

Перевели его на C ++ Builder, но он не работает:

ОБНОВИТЬ: После сужения проблемы выясняется, что сообщения WM_MOUSEWHEEL не работают не сфокусировано TVirtualStringTree только контроль, они работают над другими элементами управления. Когда фокус находится, например, на TMemo контроль, другое TMemo свитки управления на колесе, но не TVirtualStringTree контроль. Когда фокус на TVirtualStringTree это прокручивает TVirtualStringTree но не другие элементы управления. Так что проблема в настоящее время специфична для 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
}
}
}
}

Другая версия аналогичного кода, также не работает:

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;
}
}

Это должно работать, но это не так. Пробовал и другой код. Никакого эффекта — колесо мыши не работает при несфокусированном управлении. Как видите, я проверил все 3 варианта сообщений колеса, он получает правильный контроль под мышью, он показывает имя элемента управления, но элемент управления не получает сообщения колеса.

Есть идеи, какую часть головоломки мне не хватает, чтобы заставить ее работать?

1

Решение

Поскольку никто не предложил правильного решения, я публикую свое собственное. Решение не идеальное, но, по крайней мере, оно делает то, что ему нужно — колесико мыши прокручивает все элементы управления под ним, включая VirtualTreeView управления. Код в решении написан на C ++, но версия Delphi очень похожа (ее нужно только перевести).

Мое текущее решение состоит в том, чтобы захватить WM_MOUSEWHEEL события и перевести их в WM_VSCROLL или же WM_HSCROLL которому VirtualTreeView реагирует и прокручивает содержимое. Кроме того, необходимо учитывать колеса мыши высокой точности, которые могут иметь меньшее значение, чем WHEEL_DELTA (для которого установлено значение 120). Наконец, необходимо учитывать пользовательскую настройку количества прокручиваемых строк (устанавливается в панели управления в Windows). Итак, здесь идет:

Положить 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;
}
}
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]