В надстройке 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