views:

307

answers:

2

I recently added a feature to a large application written in Delphi (version 2009) that allows the user to drag files from Windows explorer and drop them on a TcxGrid control. I achieved this via the common method of attaching my own window proc to the grid and intercepting the WM_DROPFILES message:

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

I now am trying to enhance this feature to detect when the user drops a file onto an existing row in the grid, which will begin the process of overwriting an existing file with a new version.

My first thought was to see if the grid control's mouseover event would work. It does, but not during the drag operation.

I then used a program called Winspector to see what messages were being sent to the grid control as the mouse is moved over the grid, and I can now detect what row the mouse is over and highlight it. I'm using the same technique as above, but in this case I am overriding the window proc for the GridSite and not the grid itself, because that is where the messages appear to be going according to Winspector:

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

Here is the body of 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;

As you can see, I'm trapping the WM_NCHITTEST message to achieve this. According to Winspector, this message also gets sent to the grid site window during the drag operation, but if I uncomment that Log() statement which will output the message value to a string list (which I manually dump to a memo field afterwards), I have determined that for some reason, I only get one or two of these messages when dragging a file over the grid.

Now - here's the interesting part: if I have Winspector running and monitoring messages going to that window, I suddenly start getting all the WM_NCHITTEST messages during the file drag operation. This is also the case if I output the integer value of all the messages coming to the window proc directly to a separate log window instead of to a string list buffer first. I am hoping that someone will be able to offer some clue as to why this is happening or how to get this to work.

+3  A: 

Rather than using the WM_DROPFILES message, you should use OLE Drag'n'Drop. Look at the RegisterDropTarget API. You can get more detailed information about where a drag or drop is taking place. You can also accept more kinds of drag objects.

Allen Bauer
PBenz
A: 

PBenz,

Did you get the drag & drop to work with cxGrid? I'm looking for this for some time now, but I just can't seem to get it working. Could please post your code? This would be a tremendous help. Thanks a lot!

koderJan
Yes I did manage to get it to work. I started with the code on this page that accepts items dropped from Outlook:http://www.delphi3000.com/articles/article_3533.aspand modified it heavily to accept files dropped from Explorer. It was a lot of code and I don't seem to have enough room to paste it into this comment.
PBenz