Drag & Drop TDragObject

Hi, just a little background! I have 3 types of controls

Tjob: an ancestor of Tstatictext
Tresource: an ancestor of Tpanel
TAdvStringGrid: an ancestor of tstringgrid (From RX suite)

Multiple instances of Tjobs can sit on multiple instances of TPanel.  TAdvStringGrid can also hold Tjobs in its objects array, and displays corresponding info on each row for each associated Tjob it has.  Basically I want to be able to drag Tjobs between the Tresource panels and the TAdvStringGrid.  Dragging a job to the grid isn't a problem, but I can't work out how I can drag the Tjob item corresponding to the row selection from the grid on to a TResource panel.  

TheTjob item I want to drag is given by:
AdvStringGrid.objects[0,AdvStringGrid.Row] as TJob;

The Tresource drag & drop handlers require a Tjob object, ie:

procedure TResource.ResourceDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
begin
If Source is TJob then
   Accept:=IsCanAcceptJob(Source as TJob)
   else
   Accept:=false;
end;

(& similar for DragDrop)

So this is fine when dragging a Tjob on a Tresource, but when dragging from the grid, the Source becomes TadvStringGrid. Basically need to change it so that
Source is a specific TJob within the grid.

So do I need to create a TDragObject to do this and if so how should/can I pass the selected Tjob information within the TDragObject?  Hope u can help, and sorry this is a little long winded, although I'm sure you're used to my protracted explanations by now!!! Many thanks, P.
LVL 1
PandoraAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
kretzschmarConnect With a Mentor Commented:
hi,

i didn't have this grid,
but i guess there may a mousetocell-method,
then you could use soemthing like this
(sample with a tstringgrid, maybe applyable to the tadvstringgrid)

procedure TForm1.StringGrid1StartDrag(Sender: TObject;
  var DragObject: TDragObject);
var P : TPoint;
    ACol, ARow : Integer;
begin
  GetCursorPos(P);  //where is the mouse
  P := StringGrid1.ScreenToClient(P);  //transform to relative coords
  StringGrid1.MouseToCell(P.x,P.y,ACol,ARow); //transform to gridccoords
  StringGrid1.Col := ACol;    //select the cell
  StringGrid1.Row := ARow;
  SHowMessage('Starting Drag');  //not needed
  //assign your dragjob now
end;


meikl ;-)
0
 
PandoraAuthor Commented:
p.s. I don't want to reference the TAdvStringGrid in the Tresource class unit, ie I want the resource to stay ignorant of the state of the TAdvStringGrid altogether, if that makes sense!
0
 
kretzschmarCommented:
?maybe

why not supply an additional attribute, maybe DragJob : TJob,
on the onstartdrag-event of the tjob and
like

-- in the type-declartion of your form
...
  private
     DragJob : TJob  public
   public
...

- in the Start of the TJOB

procedure TForm1.Job1StartDrag(Sender: TObject;
  var DragObject: TDragObject);
begin
  DragJob := Self;
end;

- in the grid

procedure TForm1.AdvStringGrid1StartDrag(Sender: TObject;
  var DragObject: TDragObject);
begin
  DragJob := HoweverYouKnowWhichTJobThisCurrentIs;
end;

- in your dragOver

procedure TResource.ResourceDragOver(Sender, Source: TObject; X,
        Y: Integer; State: TDragState; var Accept: Boolean);
begin
    Accept:= Assigned(DragJob) and (IsCanAcceptJob(DragJob))
end;

- in your dragdrop
...
  //your stuff you will do with TJob=DragJob
  DragJob := Nil;
...

- you may also set it to nil, if the dragopoeration is canceled

meikl ;-)
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
PandoraAuthor Commented:
Thanks Meikl very cunning! - sometimes I wonder why I don't just address my questions to you personally!!  

Just for PAQ refs, Because the TResource is a seperate unit (not referencing the main form in the uses clause) I have put a global var that equates to the DragDrop var used above in the Tjob unit instead - this was already referenced by the Tresource unit and the main form (holding the TAdvStringGrid) and so the change doesn't require extra units to be added to the TResource unit uses clause.

Meikl, could I ask you a related quicky (I've increased points to 300 to compensate!).  I'm having problems with drag-drop generally (particularly on the TAdvStringGrid) because the OnStartDrag event fires before other events such as the OnSelectCell & OnRowChanging events.  As such when I try to reference the AdvStringGrid.row property in the OnStartDrag proc, the row being dragged is not the same as the 'selected' row.  How can I ensure that these are the same?  I think I effectively need to call the OnSelectCell event in/before the OnstartDrag.  Should I be cunningly alternating the drag mode between dmmanual to dmautomatic to stop the OnstartDrag happening when the row is just being selected? but then I still want to be able to drag & drop as well as select. Agggh! Hope you can help this poor bewildered soul, many thanks again, P.
0
 
kretzschmarCommented:
o yeah,

you wrote it in your q
(AdvStringGrid.objects[0,AdvStringGrid.Row] as TJob;)

procedure TForm1.StringGrid1StartDrag(Sender: TObject;
var DragObject: TDragObject);
var P : TPoint;
     ACol, ARow : Integer;
begin
  GetCursorPos(P);  //where is the mouse
  P := StringGrid1.ScreenToClient(P);  //transform to relative coords
  StringGrid1.MouseToCell(P.x,P.y,ACol,ARow); //transform to gridccoords
  StringGrid1.Col := ACol;    //select the cell
  StringGrid1.Row := ARow;
  {
  //now you assign here
  DragJob := AdvStringGrid.objects[0,ARow] as TJob;
  }
end;

meikl ;-)
0
 
PandoraAuthor Commented:
Aha! Thanks Meikl, thats done the trick! Best wishes, P :)
0
All Courses

From novice to tech pro — start learning today.