Moving cursor into and out of inserted components
Moving cursor into and out of inserted components
Hi all
How can i move the caret (focus) with the arrow keys into an inserted edit field?
And how can i "leave" the field pressing the rigth/left arrow key at the end/beginning of the text?
Thanks
How can i move the caret (focus) with the arrow keys into an inserted edit field?
And how can i "leave" the field pressing the rigth/left arrow key at the end/beginning of the text?
Thanks
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Use Control.SetFocus to focus Control.
As for moving focus out of the control when pressing Left and Right keys:
1) This function returns the control position in TRichView
2) This is an event code for inserted TEdit:
3) When creating TEdit, assign this event to OnKeyDown:
4) Events of controls are not stored in RVF files. You need to reassign them on loading, using OnControlAction event:
As for moving focus out of the control when pressing Left and Right keys:
1) This function returns the control position in TRichView
Code: Select all
function FindControlLocation(RVData: TCustomRVData; ctrl: TControl;
var CtrlRVData: TCustomRVData;
var CtrlItemNo: Integer): Boolean;
var i,r,c: Integer;
table: TRVTableItemInfo;
begin
Result := False;
for i := 0 to RVData.Items.Count-1 do
case RVData.GetItemStyle(i) of
rvsComponent:
begin
Result := TRVControlItemInfo(RVData.GetItem(i)).Control=ctrl;
if Result then begin
CtrlRVData := RVData.GetSourceRVData;
CtrlItemNo := i;
exit;
end;
end;
rvsTable:
begin
table := TRVTableItemInfo(RVData.GetItem(i));
for r := 0 to table.Rows.Count-1 do
for c := 0 to table.Rows[r].Count-1 do
if table.Cells[r,c]<>nil then begin
Result := FindControlLocation(table.Cells[r,c].GetRVData, ctrl, CtrlRVData, CtrlItemNo);
if Result then
exit;
end;
end;
end;
end;
Code: Select all
procedure TForm1.DoEditKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var RVData: TCustomRVData;
ItemNo, Offs: Integer;
Edit: TEdit;
begin
Edit := Sender as TEdit;
case Key of
VK_LEFT:
begin
if Edit.SelStart<>0 then
exit;
Offs := 0;
end;
VK_RIGHT:
begin
if Edit.SelStart+Edit.SelLength<>Length(Edit.Text) then
exit;
Offs := 1;
end;
else
exit;
end;
if not FindControlLocation(RichViewEdit1.RVData, Sender as TControl,
RVData, ItemNo) then exit;
RVData := RVData.Edit;
TCustomRVFormattedData(RVData).SetSelectionBounds(ItemNo, Offs, ItemNo, Offs);
TCustomRVFormattedData(RVData).Invalidate;
TCustomRVFormattedData(RVData).GetParentControl.SetFocus;
end;
Code: Select all
edt.OnKeyDown := DoEditKeyDown;
Code: Select all
procedure TForm1.RichViewEdit1ControlAction(Sender: TCustomRichView;
ControlAction: TRVControlAction; ItemNo: Integer; var ctrl: TControl);
begin
if ControlAction=rvcaAfterRVFLoad then begin
if ctrl is TEdit then
TEdit(ctrl).OnKeyDown := DoEditKeyDown;
end;
end;
Hi Sergey
Thanks for your answer.
The second part (returns the control position in TRichView) works fine.
But
Thanks again
Thanks for your answer.
The second part (returns the control position in TRichView) works fine.
But
at the moment i have no idea when or what event i have to use to set the focus to the control. How do i know the cursor is before or behind a control?Sergey Tkachenko wrote:Use Control.SetFocus to focus Control.
Thanks again
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
RichViewEdit1.OnKeyDown:
Code: Select all
procedure TForm1.RichViewEdit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var rve: TCustomRichViewEdit;
ItemNo, Offs: Integer;
Name: String;
VAlign: TRVVAlign;
Tag: Integer;
Control: TControl;
begin
rve := RichViewEdit1.TopLevelEditor;
ItemNo := rve.CurItemNo;
Offs := rve.OffsetInCurItem;
case Key of
VK_RIGHT:
begin
if (Offs<=rve.GetOffsBeforeItem(ItemNo)) and
(rve.GetItemStyle(ItemNo)=rvsComponent) then
ItemNo := ItemNo
else if (Offs>=rve.GetOffsAfterItem(ItemNo)) and
(ItemNo+1<rve.ItemCount) and
(rve.GetItemStyle(ItemNo+1)=rvsComponent) then
inc(ItemNo)
else
exit;
rve.GetControlInfo(ItemNo, Name, Control, VAlign, Tag);
if not (Control is TEdit) then
exit;
TEdit(Control).SetFocus;
TEdit(Control).SelLength := 0;
TEdit(Control).SelStart := 0;
Key := 0;
end;
VK_LEFT:
begin
if (Offs>=rve.GetOffsAfterItem(ItemNo)) and
(rve.GetItemStyle(ItemNo)=rvsComponent) then
ItemNo := ItemNo
else if (Offs<=rve.GetOffsBeforeItem(ItemNo)) and
(ItemNo-1>=0) and
(rve.GetItemStyle(ItemNo-1)=rvsComponent) then
dec(ItemNo)
else
exit;
rve.GetControlInfo(ItemNo, Name, Control, VAlign, Tag);
if not (Control is TEdit) then
exit;
TEdit(Control).SetFocus;
TEdit(Control).SelLength := 0;
TEdit(Control).SelStart := Length(TEdit(Control).Text);
Key := 0;
end;
end;
end;
Hi Sergey
Once again thanks for your excelent answer.
With an edit field, your code works but i have also TCheckBoxes and TRadioGroups in the RichView.
When i call TheCheckbox.SetFocus, RichView draws the "RichView selection border" arround the embedded TCheckBox and the focus rectangle. Then, if i press the arrow keys, the cursor jumps to the prev/next embedded component instead to the prec/following text. I also never get the OnKeyDown message. Either the RichViev.KeyDown nor the TCheckBox.OnKeyDown.
The focussing of the TRadioGroup draws also the border. But there is no focus-rectangle arround the ItemIndex-item and it is not possible to select another RadioButton by keyboard. The impossibility to select the text arround the TRadioGroup is the same as the TCheckBox.
Any idea?
Once again thanks for your excelent answer.
With an edit field, your code works but i have also TCheckBoxes and TRadioGroups in the RichView.
When i call TheCheckbox.SetFocus, RichView draws the "RichView selection border" arround the embedded TCheckBox and the focus rectangle. Then, if i press the arrow keys, the cursor jumps to the prev/next embedded component instead to the prec/following text. I also never get the OnKeyDown message. Either the RichViev.KeyDown nor the TCheckBox.OnKeyDown.
The focussing of the TRadioGroup draws also the border. But there is no focus-rectangle arround the ItemIndex-item and it is not possible to select another RadioButton by keyboard. The impossibility to select the text arround the TRadioGroup is the same as the TCheckBox.
Any idea?
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Please tell me how can I reproduce the problems with visualisation of controls.
TRichViewEdit never draws a focusing rectangle.
TRichView can draw it around hypelinks (text or images), but never draws it around controls.
Drawing of controls themselves should not be modifed. I just created a demo with TRadioGroup: http://www.trichview.com/forums/viewtopic.php?t=1131
As you can see, the selection rectangle is shown properly.
TRichViewEdit never draws a focusing rectangle.
TRichView can draw it around hypelinks (text or images), but never draws it around controls.
Drawing of controls themselves should not be modifed. I just created a demo with TRadioGroup: http://www.trichview.com/forums/viewtopic.php?t=1131
As you can see, the selection rectangle is shown properly.
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
As for the checkboxes.
There is one problem: TCheckBox does not have OnKeyDown event. So you cannot use it. But you can create your own component inherited from TCheckBox:
Do not forget to register this class: RegisterClass(TMyCheckBox).
Unlike TEdit, checkbox does not have caret position, so its OnKeyDown is more simple:
TRichViewEdit's OnKeyDown should be modified to work with all types of controls:
There is one problem: TCheckBox does not have OnKeyDown event. So you cannot use it. But you can create your own component inherited from TCheckBox:
Code: Select all
type
TMyCheckBox = class (TCheckBox)
private
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
published
property OnKeyDown;
end;
procedure TMyCheckBox.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
Message.Result := DLGC_WANTARROWS;
end;
Unlike TEdit, checkbox does not have caret position, so its OnKeyDown is more simple:
Code: Select all
procedure TForm1.DoControlKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var RVData: TCustomRVData;
ItemNo, Offs: Integer;
begin
case Key of
VK_LEFT:
Offs := 0;
VK_RIGHT:
Offs := 1;
else
exit;
end;
if not FindControlLocation(RichViewEdit1.RVData, Sender as TControl,
RVData, ItemNo) then exit;
RVData := RVData.Edit;
TCustomRVFormattedData(RVData).SetSelectionBounds(ItemNo, Offs, ItemNo, Offs);
TCustomRVFormattedData(RVData).Invalidate;
TCustomRVFormattedData(RVData).GetParentControl.SetFocus;
end;
Code: Select all
procedure TForm1.RichViewEdit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var rve: TCustomRichViewEdit;
ItemNo, Offs: Integer;
Name: String;
VAlign: TRVVAlign;
Tag: Integer;
Control: TControl;
begin
rve := RichViewEdit1.TopLevelEditor;
ItemNo := rve.CurItemNo;
Offs := rve.OffsetInCurItem;
case Key of
VK_RIGHT:
begin
if (Offs<=rve.GetOffsBeforeItem(ItemNo)) and
(rve.GetItemStyle(ItemNo)=rvsComponent) then
ItemNo := ItemNo
else if (Offs>=rve.GetOffsAfterItem(ItemNo)) and
(ItemNo+1<rve.ItemCount) and
(rve.GetItemStyle(ItemNo+1)=rvsComponent) then
inc(ItemNo)
else
exit;
rve.GetControlInfo(ItemNo, Name, Control, VAlign, Tag);
if Control is TWinControl then
TWinControl(Control).SetFocus;
if Control is TEdit then begin
TEdit(Control).SelLength := 0;
TEdit(Control).SelStart := 0;
end;
Key := 0;
end;
VK_LEFT:
begin
if (Offs>=rve.GetOffsAfterItem(ItemNo)) and
(rve.GetItemStyle(ItemNo)=rvsComponent) then
ItemNo := ItemNo
else if (Offs<=rve.GetOffsBeforeItem(ItemNo)) and
(ItemNo-1>=0) and
(rve.GetItemStyle(ItemNo-1)=rvsComponent) then
dec(ItemNo)
else
exit;
rve.GetControlInfo(ItemNo, Name, Control, VAlign, Tag);
if Control is TWinControl then
TWinControl(Control).SetFocus;
if Control is TEdit then begin
TEdit(Control).SelLength := 0;
TEdit(Control).SelStart := Length(TEdit(Control).Text);
end;
Key := 0;
end;
end;
end;
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Hi SergeySergey Tkachenko wrote:As for TRadioGroup, I did not test it, but probably you should do it like with TCheckBox.
Your code works great for TCheckBox.
To navigate into and out of a TRadioGroup is with DLGC_WANTARROWS partially possible. Partially, because the whole TRadioGroup receives/looses the focus instead of one of the Items (ItemIndex). So it's not possible to change the ItemIndex by keypress.
Does anybody knows, how to set the focus INTO the RadioGroup?
Thanks
Patrik