DragDetect не работает в обратном вызове MouseProc, зарегистрированном в SetWindowsHookEx - PullRequest
0 голосов
/ 11 января 2019

В надстройке Excel VSTO мне нужно перехватить собственный перетаскивание Excel по сетке (окна EXCEL7).

Я пытаюсь сделать это, зарегистрировав функцию обратного вызова MouseProc через SetWindowsHookEx пользователя user32.dll

Оформление крючка:

using (Process process = Process.GetCurrentProcess())
{
  using (ProcessModule module = process.MainModule)
  {
    _hMouseHook = WinApi.SetWindowsHookEx(WinApi.WH_MOUSE, _mouseHookProcedure,
      WinApi.GetModuleHandle(module.ModuleName), (int)WinApi.GetCurrentThreadId());
  }
}

В моем MouseHookProcedure () я использую DragDetect из user32.dll, чтобы узнать, запустил ли пользователь операцию перетаскивания. К сожалению, он всегда возвращает false, даже если пользователь в данный момент перетаскивает ячейку.

private int MouseHookProcedure(int nCode, Int32 wParam, IntPtr lParam)
{
  if (nCode == WinApi.HC_ACTION)
  {
    var mouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
    WinApi.WindowMessage message = (WinApi.WindowMessage)wParam;

    if (message == WinApi.WindowMessage.WM_LBUTTONDOWN)
    {
      // dragDetected will be always be false - even when user is dragging.
      var dragDetected = WinApi.DragDetect((IntPtr)mouseHookStruct.hwnd, mouseHookStruct.pt);
      Debug.WriteLine($"MouseHook:  X:{mouseHookStruct.pt.X}  Y:{mouseHookStruct.pt.Y} Handle:{(IntPtr)mouseHookStruct.hwnd}  DragDetected:{dragDetected}  Message:{message}");
    }
  }

  try
  {
    // event not handled, call next Hook to process / delegate event
    return WinApi.CallNextHookEx(_hMouseHook, nCode, wParam, lParam);
  }
  catch
  {
    return 0;
  }
}

Сценарий: Мне нужно обнаружение перетаскивания, чтобы заменить встроенную обработку перетаскивания на мою собственную, чтобы предлагать пользовательские зоны перетаскивания для перетаскиваемой ячейки через наложение на сетку.

Это уже было успешно достигнуто с помощью подклассов. При создании подкласса окна EXCEL7 и перехвате события WindowMessage.WM_LBUTTONDOWN DragDetect вернет true (для того же дескриптора и координат мыши).

MouseHook: X: 125 Y: 291 Обрабатывать: 1509280 DragDected: False
Подклассы: X: 125 Y: 291 Обработка: 1509280 DragDetected: True

К сожалению, мне нужно избавиться от решения для создания подклассов, так как оно часто вызывает проблемы взаимодействия между другими надстройками, которые также используют создание подклассов (происходит сбой Excel из-за разного порядка при «отмене создания подклассов»).

Я подготовил решение VS2017, содержащее реализацию перехвата и создания подклассов, которую вы можете использовать для воспроизведения (просмотр вывода на консоль) описанного поведения (требуется установленный VSTO Tools): OneDrive Link . При выполнении тестового проекта вы также сможете заметить, что обратный вызов MouseHookProcedure хука всегда запускается дважды (оба с nCode 0), что также кажется мне странным.

У кого-нибудь есть идеи, как заставить DragDetect работать с крючком? Или, может быть, у кого-то есть идея, как я могу обнаружить операцию перетаскивания в сетке Excel, которая не требует перехвата или создания подкласса окна?

Большое спасибо и наилучшие пожелания, Maggi

...