Page 1 of 1

ApplyStyleConv..(rv_BackColor) - error only in rveTable

Posted: Fri May 18, 2012 12:58 pm
by j&b
I want to mark a text with backcolor clYellow

All is ok if text is in memo, but only if text is in a rveTable I get an error-hint. After closing error-window progam runs without error.



procedure TForm1.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
{
var r,c,rs,cs: Integer;
Cell: TRVTableCellData;
Table: TRVTableItemInfo;
}
begin
//…
if (ssCtrl in Shift) then begin //Strg+key
if (key=vk_F4) or (key=vk_F10) then begin
try //Hintergrundfarbe
if (key=vk_F4) then cd.color:= clWhite
else if (key=vk_F10) then cd.color:= clYellow; //gelb

//error only appears in rveTable
Memo.ApplyStyleConversion(rv_BackCOLOR);
(I get the same error with Memo.ApplyStyleConversion(rv_COLOR);.

memo.deselect;
finally
if query1.state in [dsEdit, dsInsert] then query1.Post;
end;
memo.setfocus;
exit;
end;
end;



Program stops in unit RichView:

function TCustomRichView.GetTabNavigation:TRVTabNavigationType;
begin
Result := RVData.TabNavigation;
end;

    Posted: Fri May 18, 2012 1:38 pm
    by Sergey Tkachenko
    If you remove the code
    memo.deselect;
    finally
    if query1.state in [dsEdit, dsInsert] then query1.Post;
    end;
    memo.setfocus;
    exit;
    end;
    end;

    Does the error still exist?

    Posted: Fri May 18, 2012 2:28 pm
    by j&b
    Thank you. All runs.

    I only have to remove "memo.deselect"

    I deselect memo about key:= vk_right --> Caret jumps to next cell

    Now I am looking for a key which deselect memo but remains at the position.

    memo.deselect

    Posted: Fri May 18, 2012 3:28 pm
    by j&b
    Memo.ApplyStyleConversion(rv_BackCOLOR);
    if memo.GetCurrentItemEx(TRVTableItemInfo, rve, TCustomRVItemInfo(rveTable)) then key:= vk_right
    else memo.deselect;

    to deselect memo about key:= vk_right (or another key) is not the right way.

    Do you know another way ?

    Posted: Sat May 19, 2012 7:59 pm
    by Sergey Tkachenko
    It is not allowed to destroy cell inplace editor inside OnKeyDown event.
    Deselect destroys it,
    The best solution: instead of using OnKeyDown, create an action or a menu item with Ctrl+F4 and Ctrl+F10 shortcuts.

    create a menu item with Ctrl+F4 and Ctrl+F10 shortcuts

    Posted: Sun May 20, 2012 9:01 am
    by j&b
    Thank you, Sergey.


    >>create a menu item with Ctrl+F4 and Ctrl+F10 shortcuts. //do you mean AND and not OR ?

    All trials don’t memo.deselect. Can you tell me what I have to write?



    procedure TForm1.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);

    begin

    Memo.ApplyStyleConversion(rv_BackCOLOR);
    if memo.GetCurrentItemEx(TRVTableItemInfo, rve, TCustomRVItemInfo(rveTable)) then sendkeys(‘^{F4}, true) else memo.deselect;
    exit;

    end;


    procedure TForm1.testen1Click(Sender: TObject); //called up by Strg+F4
    begin
    ???? //memo.deselect  produces the same error
    end;

    Posted: Sun May 20, 2012 2:48 pm
    by Sergey Tkachenko
    Using SendKeys is not a solution. It calls SendMessage inside, so the key message is processed INSIDE SendKeys. I.e., it is the same as before, you call testen1Click (and hence memo.Deselect) from inside memoKeyDown.

    There are only two solutions

    1) Do not use OnKeyDown, use only buttons/actions with shortcuts.
    2) If you use OnKeyDown, but moves the code from it to another procedure, initiated using PostMessage.

    I.e.
    - define some constant greater than WM_USER

    Code: Select all

    const 
      WM_MYCOMMAND = WM_USER + 10; 
    - add in the form declaration:

    Code: Select all

    type 
    ...
      TForm1 = class(TForm) 
        ... 
        procedure WMMyCommand(var Msg: TMessage); message 
    WM_MYCOMMAND;
    - implementation:

    Code: Select all

    procedure TForm1.WMMyCommand(var Msg: TMessage); 
    begin 
      call memo.Deselect and other commands here
    end;
    - in OnKeyPress:

    Code: Select all

    procedure TForm1.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); 
    ...
    begin 
    ...
      PostMessage(Handle, WM_MYCOMMAND, 0, 0);
    ...
    end; 

    Posted: Sun May 20, 2012 4:25 pm
    by j&b
    That works, BUT

    cursor is beneath table and not at the end of text which was marked before.

    Therefore I add in procedure TForm1.WMMyCommand rveTable.xxx

    procedure TForm1.WMMyCommand(var Msg: TMessage);
    begin
    rveTable.GetEditedCell(rveTzeile1,rveTspalte1);
    memo.Deselect;
    rveTable.EditCell(rveTzeile1,rveTspalte1);
    // ??? go to the end of text which was marked before
    end;

    Now cursor stands at the first position of the cell and not at the end of text which was marked before.

    What's to do ?

    Posted: Sun May 20, 2012 5:11 pm
    by Sergey Tkachenko
    Sorry, what do you want to do by this code?
    Deselect and then select again?

    If you just want to make the selection empty without moving the caret, the code is:

    Code: Select all

    var ItemNo1, Offs1, ItemNo2, Offs2: Integer;
    
    memo.TopLevelEditor.GetSelectionBounds(ItemNo1, Offs1, ItemNo2, Offs2, False);
    if (ItemNo1>=0) then
      memo.TopLevelEditor.SetSelectionBounds(ItemNo2, Offs2, ItemNo2, Offs2);
    This code does not destroy the cell inplace editor, so it can be called in OnKeyDown.

    Posted: Tue May 22, 2012 4:19 pm
    by j&b
    procedure TForm1.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    ...
    begin
    ...
    if (ssCtrl in Shift) and (ssShift in Shift) then begin //Strg+Shift+key
    ...
    end else if (ssShift in Shift) then begin //Shift+key
    ...
    end else if (ssCtrl in Shift) and (ssShift in Shift) then begin //Strg+key
    if (key=vk_F10) then
    cd.color:= clYellow;
    Memo.ApplyStyleConversion(rv_backCOLOR);
    if memo.GetCurrentItemEx(TRVTableItemInfo, rve, TCustomRVItemInfo(rveTable)) then PostMessage(Handle, WM_MYCOMMAND,0,0)
    else memo.deselect;
    sysUtils.abort; //damit Cursor wieder 'blinkt'
    exit;
    end else if (key=vk_return) then begin ....


    procedure TForm1.WMMyCommand(var Msg: TMessage);
    var ItemNo1, Offs1, ItemNo2, Offs2: Integer;
    begin
    rveTable.GetEditedCell(rveTzeile1,rveTspalte1);
    memo.TopLevelEditor.GetSelectionBounds(ItemNo1, Offs1, ItemNo2, Offs2, False);
    memo.Deselect;
    rveTable.EditCell(rveTzeile1,rveTspalte1); //rveTable.GetEditedCell+rveTable.EditCell: Cursor steht im Memo
    if (ItemNo1>=0) then memo.TopLevelEditor.SetSelectionBounds(ItemNo2, Offs2, ItemNo2, Offs2); //damit Cursor hinter dem ehemals Markierten steht
    end;