Recent

Author Topic: (Custom) StringGrid Cut/copy paste undocumented(?) Procedures  (Read 656 times)

Derz

  • New Member
  • *
  • Posts: 12
(Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« on: January 24, 2023, 10:30:09 pm »
In creating a new app with a stringGrid, I was expecting to create clipboard procedures for the standard cut, copy, and paste to permit exchange with other apps including spreadsheets.

To my surprise, I discovered that the standard ^X, ^C, and ^V keyboard shortcuts work in delivered Lazarus StringGrids.

So, I wanted to place these commands in the "Edit" menu under Cut ^X, Copy ^C and Paste ^V, to make the app familiar.

I was able to find the tStringGrid.CopyToClipboard function and placed it in associated menu event, and that worked.

     procedure TMainForm.mmCopyClick(Sender: TObject);
     begin
       StringGrid1.CopyToClipboard(True);
     end;

But, there are no documented procedures for what the accelerator keys (^X and ^V) do.  And, I would want to have the menu actions function the same way as the accelerator keys.  I presume I can look into the StringGrid code, but others have probably run into this and perhaps can save me some time.

I suspect there are no "undocumented" procedures.  But why would the developers create this functionality and not expose it?

Blaazen

  • Hero Member
  • *****
  • Posts: 3062
  • POKE 54296,15
    • Eye-Candy Controls
Re: (Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« Reply #1 on: January 24, 2023, 10:50:56 pm »
When you are editing the cell, i.e. when carret is visible and you select piece of text with Shift+Arrow, here Ctrl+C, Ctrl+V etc. are provided by OS (by desktop environment).

When the cell is just selected, Ctrl+C, V, X is done in TCustomGrid.KeyDown. If you don't like it, you can implement OnKeyDown event and eventually write "Key:=0;" in the end to avoid any code in TCustomGrid.KeyDown.
Lazarus 2.3.0 (rev main-2_3-2634-g7fb388c217) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Derz

  • New Member
  • *
  • Posts: 12
Re: (Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« Reply #2 on: January 25, 2023, 12:09:10 am »
Thank you Blaazen,

I tested what you described about Windows handling "paste" events only when the cell was being edited, but not when selected only.  I found that selecting a cell (r2,c3), then pressing ^V, "pasted" cells from the clipboard into into r2,c3..5.

Perhaps there will be more on this behavior from others.  With further testing, I did note some paste issues, so perhaps I am better off overriding the OnKeyDown event as you suggest. 
« Last Edit: January 25, 2023, 04:21:51 pm by Derz »

Derz

  • New Member
  • *
  • Posts: 12
Re: (Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« Reply #3 on: January 25, 2023, 09:33:31 pm »
I found the following in Lazarus' Grids.pas verifying that tCustomStringGrid does handle accelerator keys for cut (^X), copy (^C) and paste (^V).  While there are internal procedures for all three, only CopyToClipboard is declared Public.  I wonder why?

============================================
procedure TCustomGrid.KeyDown(var Key: Word; Shift: TShiftState);
...

    VK_C:
      if not FEditorKey and (Shift = [ssModifier]) then
        doCopyToClipboard;
    VK_V:
      if not FEditorKey and (Shift = [ssModifier]) then
        doPasteFromClipboard;
    VK_X:
      if not FEditorKey and (Shift = [ssShift]) then
        doCutToClipboard;

======

procedure TCustomStringGrid.DoCopyToClipboard;
begin
  CopyCellRectToClipboard(Selection);
end;

procedure TCustomStringGrid.DoCutToClipboard;
begin
  if EditingAllowed(Col) then begin
    doCopyToClipboard;
    Clean(Selection, []);
  end;
end;

procedure TCustomStringGrid.DoPasteFromClipboard;
begin
  // Unpredictable results when a multiple selection is pasted back in.
  // Therefore we inhibit this here.
  if HasMultiSelection then
    exit;

  if EditingAllowed(Col) then
  begin
    if Clipboard.HasFormat(CF_TEXT) and not Clipboard.HasFormat(CF_HTML) then SelectionSetText(Clipboard.AsText);
    if Clipboard.HasFormat(CF_TEXT) and Clipboard.HasFormat(CF_HTML) then SelectionSetHTML(Clipboard.GetAsHtml(True), Clipboard.AsText);
  end;
end;

=======
{This is procedure is declared "Public"}
      
procedure TCustomStringGrid.CopyToClipboard(AUseSelection: boolean = false);
begin
  if AUseSelection then
    doCopyToClipboard
  else
    CopyCellRectToClipboard(Rect(0,0,ColCount-1,RowCount-1));
end;

Nicole

  • Hero Member
  • *****
  • Posts: 634
Re: (Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« Reply #4 on: January 25, 2023, 09:58:52 pm »
I would not recommend to do anything like this.

Those keys work in windows sometimes, sometimes not. Some (rare) situations block them.
I use them all day long and so I know, they work in about 99% of all cases. So if you figure, how many values in the StringGrid may chance, you can figure, how instable it may be.

And:
You write a implementation, which will use key, which mean in Windows copy and in Linux close app.


Thaddy

  • Hero Member
  • *****
  • Posts: 12630
Re: (Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« Reply #5 on: January 25, 2023, 10:01:18 pm »
Blaazen's answer is correct. I would not pay much attention to the other answers...
"Looks" OK, doesn't mean it is IS OK.

Derz

  • New Member
  • *
  • Posts: 12
(Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« Reply #6 on: January 26, 2023, 12:09:34 am »
Replacing these "delivered" routines with something I write myself makes no sense..

Having nothing better to offer, I will use, or at least start with, these "Lazarus developed" routines for cut/copy and paste in a CustomStringGrid.  I will be happy to contribute to this thread my findings.  And I encourage others to do so as well.  This is basic functionality in all platforms that could improve the delivered code at some point.

It would be great to understand the shortcomings, if nothing else, to abort the procedure with a reason in specific conditions.
« Last Edit: January 26, 2023, 12:16:57 am by Derz »

Derz

  • New Member
  • *
  • Posts: 12
(Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« Reply #7 on: February 05, 2023, 09:03:59 pm »
I wound up creating a descendant of tStringGrid (tMyStringGrid) to expose the internal DoPasteFromClipboard and DoCutToClipboard as public routines PasteFromClipboard and CutToClipboard.

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyStringGrid = class(TStringGrid)
  3.  
  4.   public
  5. //    Procedure DoPasteFromClipboard; override;
  6.     Procedure PasteFromClipboard;
  7.     Procedure CutToClipboard;
  8.   end;
  9.  
  10. implementation
  11.  
  12. {  I might want to override this somewhat complex routine in the future..
  13. Procedure TMyStringGrid.DoPasteFromClipboard;
  14. begin
  15.   inherited;
  16. end;
  17. }
  18.  
  19. Procedure TMyStringGrid.PasteFromClipboard;
  20. Begin
  21.   DoPasteFromClipboard;
  22. end;
  23.  
  24. Procedure TMyStringGrid.CutToClipboard;
  25. Begin
  26.   DoCutToClipboard;
  27. end;
  28.  

I then replaced the tStringGrid component on my form with tMyStringGrid.  This was more difficult than it had been with Delphi where I could just edit the source file to add the "My" in the objecttype. In Lazarus, this caused run time errors.  So I deleted the tStringGrid from the form and configured a new tMyStringGrid from scratch.

Finally, I added a StringGrid1KeyDown event to modify the "delivered" ^X,^C,^V functionality as below.  Some folks still use the insert and delete keys for this.

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.StringGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  2. var DoAction:char='0';
  3. begin
  4.   case key of
  5.     Ord('x'): if ssCtrl in Shift Then DoAction:='X';
  6.     Ord('c'): if ssCtrl in Shift Then DoAction:='C';
  7.     Ord('v'): if ssCtrl in Shift Then DoAction:='V';
  8.     VK_Delete: If ssShift in Shift Then DoAction:='X'
  9.                Else DoAction:='D';
  10.     VK_Insert: If ssCtrl in Shift Then DoAction:='C'
  11.                Else If ssShift in Shift Then DoAction:='V';
  12.   end;
  13.   Case DoAction of
  14.     'X': StringGrid1.CutToClipboard;
  15.     'C': StringGrid1.CopyToClipboard(True);
  16.     'V': StringGrid1.PasteFromClipboard;
  17.     'D': StringGrid1.Clean(Stringgrid1.Selection,[]);
  18.   end;
  19.   If DoAction<>'0' then Key:=0;  //If any Action taken in this routine, pass nokey
  20. end;
  21.  


Bart

  • Hero Member
  • *****
  • Posts: 4888
    • Bart en Mariska's Webstek
Re: (Custom) StringGrid Cut/copy paste undocumented(?) Procedures
« Reply #8 on: February 05, 2023, 10:28:42 pm »
Quote
This was more difficult than it had been with Delphi where I could just edit the source file to add the "My" in the objecttype. In Lazarus, this caused run time errors.
If you drop a TStringGtind on your form, and name your own derived TStringGrid also TStringGrind, and you put the your unit after "grids" in the uses clase, then when your application instantiaes the TStringGrid, in fact it will instantiate the TStringGrid from your own unit.

In your own unit you could de clare yout derived class like this:
Code: Pascal  [Select][+][-]
  1. type
  2.   TStringGrid = class(Grids.TStringGrid)
  3.   public
  4.     Procedure PasteFromClipboard;
  5.     Procedure CutToClipboard;  
  6.   end;

 

TinyPortal © 2005-2018