Solved

Drag and Drop in a TStringGrid

Posted on 2007-04-06
12
1,241 Views
Last Modified: 2013-11-17
I've got a new application with a TStringGrid that contains simple text.  I'd like to be able to swap the contents of two cells with a simple drag and drop but this seems to be a control that doesn't behave as expected.

When I click on a cell, the cell highlights by a double line around the cell.  If I click on another control the cell background changes color and looks like a normal highlighted cell.

I cannot drop to a cell.  The OnClick() method is called and I can clearly see that I'm entering the cell, but the OnDragDrop() method is never called.

Any thoughts on how to use this control would be appreciated.

Thanks,
Kent

0
Comment
Question by:Kent Olsen
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 6
12 Comments
 
LVL 18

Expert Comment

by:Jose Parrot
ID: 18870755
Hi,

Let's use three TLabel (Label1, Label2 and Label3) all with DragMode set to dmAutomatic.
And one TStringGrid (StringGrid1).
Use the code below to drag the caption from each label to any cell at the grid.

//---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1DragOver(TObject *Sender,
      TObject *Source, int X, int Y, TDragState State, bool &Accept)
{
   Accept = Source->ClassNameIs("TLabel");    
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1DragDrop(TObject *Sender,
      TObject *Source, int X, int Y)
{
  if (Sender->ClassNameIs("TStringGrid") && Source->ClassNameIs("TLabel"))
  {
    TStringGrid *DestGrid = (TStringGrid *)Sender;
    int localCol=X/StringGrid1->DefaultColWidth;
    int localRow=Y/StringGrid1->DefaultRowHeight;
    DestGrid->Cells[localCol][localRow]=((TLabel *)Source)->Caption;
  }
}

Jose
0
 
LVL 18

Expert Comment

by:Jose Parrot
ID: 18870774
Sorry... Misunderstand the question.
Hummm... interesting problem, both source and destin are the same component...
Let's think a bit more...
Jose
0
 
LVL 45

Author Comment

by:Kent Olsen
ID: 18870825

Yeah.  :)  This is an interesting poser that has a real use.

The simplest thing may be to just use a different type of control, but at this point I'd rather see if a reasonable solution exists.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 18

Accepted Solution

by:
Jose Parrot earned 500 total points
ID: 18870842
Well, that is:
Let DragMode in default dmManual.
The code below permits cell editing (of course with goEditing = true) and change contents between cells when we make drag & drop.

void __fastcall TForm1::StringGrid1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
    globalCol=X/StringGrid1->DefaultColWidth;
    globalRow=Y/StringGrid1->DefaultRowHeight;
    globalAS = StringGrid1->Cells[globalCol][globalRow];
}
//---------------------------------------------------------------------------

void __fastcall TForm1::StringGrid1MouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
    int localCol=X/StringGrid1->DefaultColWidth;
    int localRow=Y/StringGrid1->DefaultRowHeight;
    if (globalAS != "")
    {
        AnsiString localAS = StringGrid1->Cells[localCol][localRow];
        StringGrid1->Cells[localCol][localRow] = globalAS;
        StringGrid1->Cells[globalCol][globalRow] = localAS;
    }
}
//---------------------------------------------------------------------------

Ugly to use globals, but this is the simpler (BTW not wrong) way to make the temporary storage of col, row and string, as tag can have just one int.

Jose
0
 
LVL 45

Author Comment

by:Kent Olsen
ID: 18870861


Ahhh...   Just use the MouseDown and MouseUp events.....

Sometimes the simple solutions evade us.  I'll try it.  :)


0
 
LVL 45

Author Comment

by:Kent Olsen
ID: 18876218
Hi Jose,

That worked better than I could have possibly hoped.  :)  kudos.

I'm going to post the basic code and leave the question open for a few more days.  This new EE protocol seems to bury the new questions as soon as they are closed.

Kent

// Set DragMode to dmManual
// Set goEditing to true

// In MainForm

  bool Swapping;        // Set to false in the instantiator
  int    SwapFromX;
  int    SwapFromY;

// Methods

void __fastcall TMainForm::GridMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  Grid->MouseToCell (X, Y, SwapFromX, SwapFromY);
  if (SwapFromX < Grid->ColCount && SwapFromY < Grid->RowCount)
  {
    StatusBar->SimpleText = Format ("Swap: (%s) [Drag the mouse to the name you wish to swap]",
      ARRAYOFCONST ((DrawingGrid->Cells[SwapFromX][SwapFromY])));
    Swapping =true;
  }
  else
    StatusBar->SimpleText = "";
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::GridMouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
  int CurrentX;
  int CurrentY;

  Grid->MouseToCell (X, Y, CurrentX, CurrentY);
  if (Swapping && CurrentX > 0 && CurrentY > 0 &&
      CurrentX < Grid->ColCount && CurrentY < Grid->RowCount &&
     (CurrentX != SwapFromX || CurrentY != SwapFromY))
    StatusBar->SimpleText = Format ("Swap: (%s) with (%s)",
      ARRAYOFCONST ((Grid->Cells[SwapFromX][SwapFromY], Grid->Cells[CurrentX][CurrentY])));
  else
    StatusBar->SimpleText = "";

}
//---------------------------------------------------------------------------

void __fastcall TMainForm::GridMouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  String S;
  int CurrentX;
  int CurrentY;

  Grid->MouseToCell (X, Y, CurrentX, CurrentY);
  if (Swapping && CurrentX > 0 && CurrentY > 0 &&
      CurrentX < Grid->ColCount && CurrentY < Grid->RowCount &&
     (CurrentX != SwapFromX || CurrentY != SwapFromY))
  {
    S = Grid->Cells[CurrentX][CurrentY];
    Grid->Cells[CurrentX][CurrentY] = Grid->Cells[SwapFromX][SwapFromY];
    Grid->Cells[SwapFromX][SwapFromY] = S;
  }
  Swapping = false;
}



0
 
LVL 18

Expert Comment

by:Jose Parrot
ID: 18876851
Hummm.. with improvements and a touch of coding elegance!
Jose
0
 
LVL 45

Author Comment

by:Kent Olsen
ID: 18877023

Oops.    :)

It needs another improvement.  It doesn't differentiate between the left and right mouse buttons.


Do you really think this programming stuff is ever going to catch on?  ;)

0
 
LVL 18

Expert Comment

by:Jose Parrot
ID: 18887431
Yes, I think so. Conceptually, seems to be correct. Of course, turn this piece of code part of a commercial product will spend some extra effort, for exemple, in the differentiation of left/right button, as you have noticed (by accepting just mbLeft, for example) or adding columns/rows swapping (by accepting row and col zero).
When running your code I've changed DrawingGrid to Grid in the status bar text creation, as DrawingGrid didn't run in my environment (Builder 6).
0
 
LVL 45

Author Comment

by:Kent Olsen
ID: 18888707

Hi Jose,

DrawingGrid was the name of the object in my application.  That seemed confusing for this kind of post so I changed the name to "Grid".  Guess that I missed one.  :/

Other small improvements include checking the value of Swapping before calling MouseToCell(), etc.


Thanks again for a great suggestion!
Kent
0
 
LVL 18

Expert Comment

by:Jose Parrot
ID: 18970759
Anything else?
0
 
LVL 45

Author Comment

by:Kent Olsen
ID: 19001362

I've been out for the past week so I never got back to close this question.

Consider it closed and thanks again,
Kent
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand columnThat will then direct you to their download page.From that page s…
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question