Проблема с обнаружением движений мыши в TcxGrid при перетаскивании файлов из проводника Windows

Недавно я добавил функцию в большое приложение, написанное на Delphi (версия 2009), которое позволяет пользователю перетаскивать файлы из проводника Windows и помещать их в элемент управления TcxGrid. Я добился этого с помощью обычного метода прикрепления моего собственного окна к сетке и перехвата сообщения WM_DROPFILES:

 originalGridWindowProc := cxGrid.WindowProc; // remember the old one
 cxGrid.WindowProc := GridWindowProc;  // assign the new one
 DragAcceptFiles(cxGrid.Handle, LongBool(True)); // setup to accept dropped files

Теперь я пытаюсь улучшить эту функцию, чтобы обнаруживать, когда пользователь помещает файл в существующую строку в сетке, что запускает процесс перезаписи существующего файла новой версией.

Моей первой мыслью было посмотреть, будет ли работать событие mouseover элемента управления сеткой. Это происходит, но не во время операции перетаскивания.

Затем я использовал программу под названием Winspector, чтобы увидеть, какие сообщения отправлялись в элемент управления сеткой, когда мышь перемещается по сетке, и теперь я могу определить, над какой строкой находится мышь, и выделить ее. Я использую ту же технику, что и выше, но в этом случае я переопределяю процесс окна для GridSite, а не саму сетку, потому что именно там сообщения, по-видимому, поступают в соответствии с Winspector:

  originalGridSiteWindowProc := cxGrid.ActiveView.Site.WindowProc;
  cxGrid.ActiveView.Site.WindowProc := GridSiteWindowProc;

Вот тело GridSiteWindowProc:

procedure Tfrm.GridSiteWindowProc(var message: TMessage);
var
  hitTest: TcxCustomGridHitTest;
  gridRecord: TcxCustomGridRecord;
begin
  //Log(IntToStr(message.Msg));
  case message.Msg of
    WM_NCHITTEST: begin
      hitTest := cxGrid.ActiveView.GetHitTest(cxGrid.ScreenToClient(Mouse.CursorPos));
      if hitTest is TcxGridRecordCellHitTest then begin
        gridRecord := TcxGridRecordCellHitTest(HitTest).GridRecord;
        if Not gridRecord.Focused then
          gridRecord.Focused := True;
      end;
      originalGridSiteWindowProc(message);
    end
    else
      originalGridSiteWindowProc(message);
  end;
end;

Как видите, для этого я перехватываю сообщение WM_NCHITTEST. Согласно Winspector, это сообщение также отправляется в окно сайта сетки во время операции перетаскивания, но если я раскомментирую этот оператор Log (), который будет выводить значение сообщения в список строк (который я впоследствии вручную выгружаю в мемо-поле), Я определил, что по какой-то причине я получаю только одно или два из этих сообщений при перетаскивании файла по сетке.

А теперь самое интересное: если у меня запущен Winspector и я отслеживаю сообщения, идущие в это окно, я внезапно начинаю получать все сообщения WM_NCHITTEST во время операции перетаскивания файла. Это также имеет место, если я сначала выведу целочисленное значение всех сообщений, поступающих в процесс окна, в отдельное окно журнала, а не в буфер списка строк. Я надеюсь, что кто-то сможет предложить ключ к разгадке причин, почему это происходит, или как заставить это работать.


person PBenz    schedule 25.10.2009    source источник


Ответы (1)


Вместо сообщения WM_DROPFILES следует использовать OLE Drag'n'Drop. Посмотрите на API RegisterDropTarget. Вы можете получить более подробную информацию о месте перетаскивания. Вы также можете принять больше видов перетаскиваемых объектов.

person Allen Bauer    schedule 25.10.2009
comment
Спасибо. Поскольку я уже использовал OLE D&D для поддержки удаления писем из Outlook, мне удалось улучшить код для поддержки удаления из проводника, и похоже, что это будет работать отлично. Здесь есть отличная информация: msdn.microsoft. com / en-us / library / bb776904 (VS.85) .aspx Я бы выбрал метод OLE на первом месте, но метод WM_DROPFILES оказался значительно проще в реализации. - person PBenz; 26.10.2009