Problemas al detectar movimientos del mouse en un TcxGrid al arrastrar archivos desde el Explorador de Windows

StackOverflow https://stackoverflow.com/questions/1620890

Pregunta

Recientemente agregué una característica a una aplicación grande escrita en Delphi (versión 2009) que permite al usuario arrastrar archivos desde el explorador de Windows y soltarlos en un control TcxGrid. Logré esto a través del método común de adjuntar mi propio proceso de ventana a la cuadrícula e interceptar el mensaje 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

Ahora estoy tratando de mejorar esta función para detectar cuándo el usuario coloca un archivo en una fila existente en la cuadrícula, lo que comenzará el proceso de sobrescribir un archivo existente con una nueva versión.

Mi primer pensamiento fue ver si el evento de mouseover del control de cuadrícula funcionaría. Lo hace, pero no durante la operación de arrastre.

Luego usé un programa llamado Winspector para ver qué mensajes se estaban enviando al control de cuadrícula cuando el mouse se mueve sobre la cuadrícula, y ahora puedo detectar en qué fila está el mouse y resaltarlo. Estoy usando la misma técnica que la anterior, pero en este caso, estoy anulando el procedimiento de ventana para GridSite y no la cuadrícula en sí, porque ahí es donde parecen ir los mensajes según Winspector:

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

Aquí está el cuerpo de 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;

Como puede ver, estoy atrapando el mensaje WM_NCHITTEST para lograr esto. De acuerdo con Winspector, este mensaje también se envía a la ventana del sitio de la cuadrícula durante la operación de arrastre, pero si elimino el comentario de esa declaración Log () que emitirá el valor del mensaje a una lista de cadenas (que luego vuelco manualmente a un campo memo), He determinado que, por alguna razón, solo recibo uno o dos de estos mensajes al arrastrar un archivo sobre la cuadrícula.

Ahora, aquí está la parte interesante: si tengo Winspector corriendo y monitoreando los mensajes que van a esa ventana, de repente empiezo a recibir todos los mensajes WM_NCHITTEST durante la operación de arrastre del archivo. Este es también el caso si envío el valor entero de todos los mensajes que vienen directamente al proc de la ventana a una ventana de registro separada en lugar de a un búfer de lista de cadenas primero. Espero que alguien pueda ofrecer alguna pista de por qué está sucediendo esto o cómo hacer que esto funcione.

¿Fue útil?

Solución

En lugar de usar el mensaje WM_DROPFILES, debes usar OLE Drag'n'Drop. Mira la API RegisterDropTarget. Puede obtener información más detallada sobre dónde se está arrastrando o soltando. También puede aceptar más tipos de objetos de arrastre.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top