Jump to content
JohnLM

StringGrid: how to get the column number via right-click

Recommended Posts

Using a string grid, (but I may also use a dbgrid later) how do I get the *column* number when I right-click on a column ?

I've searched around but could not find the answers. 

 

Below, shows column 2 was right-click-selected. 

 

The purpose of this is to allow me to right-click on a column and a pop-up menu with options for (copy_column, create_table) will show. 

1. I want to copy the text of the column to the clipboard.  

2. or, create a table out of the selected column's text. (I know how to do these parts.) 

 

TIA

 

108492797_im-stringgridcolumnnumberselectionindicator.png.4a37e51d28c45f4a0b6332c4a743b744.png

Share this post


Link to post

Hi,

Quote

how do I get the *column* number when I right-click on a column

Use the Grid's OnMouseUp event:

procedure TForm4.gridMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  ACol, ARow: Integer;
begin
  if Button = TMouseButton.mbRight then
  begin
    grid.MouseToCell(X, Y, ACol, ARow);
    ShowMessage('Col: ' + ACol.ToString);
  end;
end;

HTH

Edited by Achim Kalwa
  • Thanks 1

Share this post


Link to post

@Achim - your technique works for the stringgrid as well, thanks. 

 

However, before I found your code above, I also found this method to obtain the col/row values with this code: 

 

var i: integer; 
...
procedure TForm1.sg1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  i:=acol;
  edit1.Text:=inttostr(i);
end;

 

But my problem is trying to simulate the same as visually depicted in my original photo posted earlier.. if I right-click column 2, it would show like in the photo) and then I would call the popup menu, also shown in the photo. 

Share this post


Link to post

Actually, to be more precise, I want the whole column to show as highlighted and then show the pop-up menu. 

Share this post


Link to post

I believe I have to do the highlight steps in an .MouseDown event of the stringgrid. If down, then highlight, and then during the .MouseUp, do/show the pop-up menu. 

Share this post


Link to post
1 hour ago, JohnLM said:

before I found your code above, I also found this method to obtain the col/row values with this code: 

That is the wrong approach.  Do not perform business logic (like updating UI controls) inside a drawing event.

Quote

But my problem is trying to simulate the same as visually depicted in my original photo posted earlier.. if I right-click column 2, it would show like in the photo) and then I would call the popup menu, also shown in the photo. 

In the OnMouse... event(s), take note of which column is being clicked on, and save that value somewhere, then invalidate the Grid to trigger a repaint before displaying the popup menu.  When the popup menu is closed, clear the saved value and invalidate the grid again to trigger a new repaint.  Then, inside the grid's OnDraw... event(s), check if the value is set, and if so then draw any cells belonging to that saved column as highlighted.

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

I'm using the following code in my custom DBGrid-descendant to have a separate popup menu for the content and the header, which works well. I suppose with little to no modification it can be applied to a TStringGrid too:

 

Procedure TDBGrid.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
Var
  gc: TGridCoord;
Begin
  If Button = mbRight Then
  Begin
    gc := Self.MouseCoord(X, Y);
    If gc.Y > 0 Then
      _gridpopup.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y)
    Else If gc.Y = 0 Then
    Begin
      _colindex := gc.X;

      If dgIndicator In Self.Options Then
        Dec(_colindex);

      _headerpopup.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
    End;
  End
  Else
    inherited;
End;


_gridpopup is the content popup menu, _headerpopup is the popup menu for the header, _colindex is an integer which can be used later on to determine which column the popup menu was popped up from.

Edited by aehimself

Share this post


Link to post

Right now, I am focusing on getting the highlighting to work properly.   

 

I am able to do the following: 

 

1. obtain the column number.

2. highlight the column in question (all cells including the header) (but that only works if I click the stringgrid cells, not the header--I want the header to be the initiator)

 

But the above {2} is buggy.  At program startup, the stringgrid highlights for column 0 (the fixed header section). 

 

The other issue-1 I am having is that I can only get the highlighting to work if I use the left mouse button.  The stringgrid seems to ignore the Right-button click.  No action is taken. 

And, issue-2 is that I cannot initiate the highlight when I click on the top fixed row header area.  I need to be able to click that part only, not the cells. 

 

  if button = TMouseButton.mbLeft then // success, but:  if button = TMouseButton.mbRight then  // fails 

I guess will have to first use .mbLeft, and then do .mbRight for the popup part.  I will have to work that out if that is the route I will take. 

 

Here is the complete code that I managed to get working, though a bit buggy.  I have to work out the pre-highlight it does on the fixed row header part at startup.  There should be no highlighting at startup, not unless I click on the top fixed row header column. 

implementation 

var
  r,c: integer;
  MRect: TRect;

... 

procedure TForm1.sg1SelectCell(Sender: TObject; ACol, ARow: Integer;   // sg1=stringgrid
  var CanSelect: Boolean);
begin
  r:=arow;
  c:=acol;
end;

procedure TForm1.sg1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  Button: TMouseButton;
begin
  if button = TMouseButton.mbLeft then  // but .mbRight fails
  if (acol=c) then begin
    sg1.Canvas.Brush.Color:=clblue;
    sg1.Canvas.FillRect(rect);
  end;
end;

procedure TForm1.sg1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin 
  if button = tmousebutton.mbLeft then begin
    sg1.Invalidate;
    mrect := sg1.CellRect(c,r);
    sg1drawcell(self,c,r,mrect,[]);   // TGridDrawState = set of (gdSelected, gdFocused, gdFixed, gdRowSelected, gdHotTrack, gdPressed);
    sg1.Canvas.Brush.Color:=clblue;
    sg1.Canvas.FillRect(mrect);
  end;
  sg1.Invalidate;
end;

 

 

Share this post


Link to post
26 minutes ago, JohnLM said:

Here is the complete code that I managed to get working, though a bit buggy.  I have to work out the pre-highlight it does on the fixed row header part at startup.  There should

be no highlighting at startup, not unless I click on the top fixed row header column.

Your 'c' variable is initialized to 0, which is likely why your column 0 gets highlighted at startup.  Initialize the variable to -1 instead, and then update it on mouse clicks as needed.

 

Also, you don't need to use the OnSelectCell event at all, just let the OnMouseDown code determine the column using the provided X/Y coordinates.
 

Also, DO NOT call your OnDrawCell event handler direct!y.  Let the system call it for you when the Grid actually needs to be painted naturally.

 

Try something more like this instead:

 

implementation 

var
  HighlightedColumn: Integer;

... 

procedure TForm1.FormCreate(Sender: TObject);
begin
  HighlightedColumn := -1;
end;

procedure TForm1.sg1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  if (ACol = HighlightedColumn) then begin
    sg1.Canvas.Brush.Color := clBlue;
    sg1.Canvas.FillRect(Rect);
  end;
end;

procedure TForm1.sg1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  c, r: Longint;
begin 
  sgl.MouseToCell(X, Y, c, r);
  if (r < sgl.FixedRows) then begin
    HighlightedColumn := c;
    sg1.Invalidate;
  end;
end;

 

Edited by Remy Lebeau
  • Thanks 1

Share this post


Link to post

@Remey - your improved code snippet version is working much better than mine, thank you.  It even captures my right mouse click. 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×