JohnLM 14 Posted November 2, 2023 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 Share this post Link to post
Achim Kalwa 61 Posted November 2, 2023 (edited) 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 November 2, 2023 by Achim Kalwa 1 Share this post Link to post
JohnLM 14 Posted November 3, 2023 @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
JohnLM 14 Posted November 3, 2023 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
JohnLM 14 Posted November 3, 2023 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
Remy Lebeau 1394 Posted November 3, 2023 (edited) 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 November 3, 2023 by Remy Lebeau 1 Share this post Link to post
aehimself 396 Posted November 3, 2023 (edited) 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 November 3, 2023 by aehimself Share this post Link to post
JohnLM 14 Posted November 3, 2023 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
Remy Lebeau 1394 Posted November 3, 2023 (edited) 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 November 3, 2023 by Remy Lebeau 1 Share this post Link to post
JohnLM 14 Posted November 4, 2023 @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