Enter键代替Tab键或模拟Tab键(100分)

  • 主题发起人 主题发起人 jjazz
  • 开始时间 开始时间
J

jjazz

Unregistered / Unconfirmed
GUEST, unregistred user!
请教各位大虾,如何在Delphi4中用Enter键代替Tab键或模拟Tab键(用来在窗口中代替Tab键改编辑框的Focus的),我不想在每一编辑框的OnKeyDown事件下写程序。
 
把下列代码放到onkeypress中,注意,如果是form, keyPreview:=true

var
MYForm: TCustomForm;
begin
if Key = #13 then
begin
MYForm := GetParentForm( Self );
if not (MYForm = nil ) then
SendMessage(MYForm.Handle, WM_NEXTDLGCTL, 0, 0);
Key := #0;

end;
if Key <> #0 then inherited KeyPress(Key);
end;
 
yifeng说的可以,比较简单,不过我没有试过,
还一种笨法就是,在每一个焦点控件的onkeydown
中加入下面语句也行:
例:有两个控件edit1,edit2如果在edit1中按enter键进入edit2
的话,只需在edit1.onkeydown中加入
if key=13 then
begin
key=0;
edit2.setfocus;
end;

OK!

 
把 form 的 keyPreview:=true,
FORM 的 FormKeyPress 的代码如下:
……

if (Sender is Tform) then
if key=#13 then
begin
SendMessage(Self.Handle, WM_NEXTDLGCTL, 0, 0);
Key := #0;
end;

这样不用在每一编辑框的OnKeyDown事件写代码,
在FORM的 FormKeyPress写一次即可。
如希望好象ComboBox等控件在下拉列表激活时 Enter 键照样有
作用,则要加一些判断,如下:

if (Sender is Tform) then
if not((ActiveControl is TDBlookupComBOBOX)and
(TDBlookupComBOBOX(activecontrol).ListVisible))then
if key=#13 then
begin
SendMessage(Self.Handle, WM_NEXTDLGCTL, 0, 0);
Key := #0;
end;

我的程序就是这样用的。

 
我的答案和yifen、aaa差不多,sendmessage()中的参数也可这样
sendmessage(self.handle,WM_KEYDOWN,VK_TAB,0);
 
procedure TForm.FormKeyPress(Sender: TObject; var Key: Char);
var
Sft: Byte;
begin
if (Key <> #13) or
(GetKeyState(VK_CONTROL) < 0) then exit;
{ Shift Key Pressed or not }
if GetKeyState(VK_Shift) < 0 then
Sft := 1
else
Sft := 0;

Key := #0;
if not (ActiveControl is TDBGrid) then
begin
Perform(WM_NEXTDLGCTL, Sft, 0);
Exit;
end;

with ActiveControl as TDBGrid do
begin
if Sft = 0 then
begin
if SelectedIndex < (Fieldcount -1) then
SelectedIndex := SelectedIndex + 1
else
begin
Datasource.Dataset.Next;
if Datasource.Dataset.EOF then
Self.Perform(WM_NEXTDLGCTL, Sft, 0);
end;
end
else
begin
if SelectedIndex > 0 then
SelectedIndex := SelectedIndex - 1
else
begin
Datasource.Dataset.Prior;
if Datasource.Dataset.BOF then
Self.Perform(WM_NEXTDLGCTL, Sft, 0);
end;
end;
end;
end;
 
yifeng说的对于Button等控制不起作用,此时必须处理WM_GETDLGCODE消息
接管其它需处理的键盘信息,具体请看WIN32的Help
 
hekai ,我记得有贴子说希望在button上按下enter键不要触发click事件,可以参考
那个贴子

一般情况下,都不会利用enter键在button间跳来跳去吧,windows的习惯是按下enter
键相当于click button哦,总不要违背这个习惯把

一个很简单的问题,大家讨论的太多了的说,都快偏题了
 
老问题了。而且的标准方法,keypress中加入如下指令:
Perform(CM_DIALOGKEY,VK_TAB,0);
再教你一招,若你将form的keypreview设为true,则只需将上述语句放入form的
keypress就行了。





 
试一试Delphi自带的函数SelectNext。
和前面各位说的差不多,form的KeyPreview设为true。在form的keypress中
if (key = #13) and (或者其他判断) then
begin
SelectNext(ActiveControl, true, true);
....
end;
 
procedure TF_LSell.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key=VK_RETURN then Perform(CM_DIALOGKEY,VK_TAB,0);
end;

设置form的keypreview为true
 
首先在主窗体的OnKeyPress事件中执行下列语句,
并将此窗体上TEdit或其他TControl控件的OnKeyPress
事件指向此事件,窗体上的输入框就可实现Tab的功能了。

procedure TfrmLogin.KeyEnter(Sender: TObject; var Key: Char);
begin
//实现回车转到下一个输入焦点
if key=#13 then
begin
Perform(CM_DialogKey,Vk_TAB,0);
key:=#0;
end;
end;
 
blade的方法是最方便的。可惜没有抢在前面灌进去
 
需要用回车键代替TAB键下移一个控件时,把KeyPreview设为True,
加入下列代码拦截击键:
Procedure TForm1.FormKeyPress(Sender:Tobject;Var Key:Char);
Begin
 if key=#13 then { 判断是按执行键}
 if not (ActiveControl is TDbgrid) Then
 Begin { 不是在TDbgrid控件内}
  key:=#0;
  perform(WM_NEXTDLGCTL,0,0);{移动到下一个控件}
 end else
 if (ActiveControl is TDbgrid) Then{是在 TDbgrid 控件内}
 begin
  With TDbgrid(ActiveControl) Do
  if Selectedindex<(FieldCount-1) then
  Selectedindex:=Selectedindex+1{ 移动到下一字段}
  else Selectedindex:=0;
 end;
End;
(在Delphi4下调试成功)
 
此地人傻,钱多,速来! :)
 
1.set form's property 'KeyPreView'=true;
2.write Onkeypress event
if key=#13 then
begin
selectnext(activecontrol as twincontrol,true,true);
key:=#0;
end;
3.ok!
 
使用这个构件吧,是我们论坛上的某位大虾写的(我忘了):
包你所有的问题都解决!


unit quickkey;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids, ExtCtrls, typinfo, math;

type
TMoveOptions = set of (moEditDeliver, moListDeliver,
moComboDeliver,moGridDeliver, moButtonDeliver,moRadioDeliver);

TQuickKey = class(TComponent)
private
// FComponents: TList;
FActive: boolean;
FOwnerKeyEvents : TMessageEvent;
FOptions : TMoveOptions;

FEdit : Boolean;
FList : Boolean;
FGrid : boolean;
FCombo : boolean;
FButton : boolean;
FRadio: boolean;
function MoveUpSide(Sender: TWinControl;Key: word):boolean;
function MoveDownSide(Sender: TWinControl;Key: word):boolean;
function MoveLeftSide(Sender: TWinControl;Key: word):boolean;
function MoveRightSide(Sender: TWinControl;Key: word):boolean;
function MoveNextSide(Sender: TWinControl;Key: word):boolean;
procedure GetControl(Sender: TWinControl;Direct: integer);
function CanEnterKey(Sender: TWincontrol): boolean;
function HasProperty(Sender: TObject; AProperty: string):boolean;
function TestProperty(Sender: TObject; AProperty: string;
Value: integer): boolean;
function GetPropertyValue(Sender: TObject; AProperty: string): integer;
protected
{ Protected declarations }
public
procedure NewKeyDown(var Msg: TMsg; var Handled: boolean);
{ Public declarations }
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property Active: boolean read FActive write FActive;
property Options : TMoveOptions read FOptions write FOptions
default [moEditDeliver, moListDeliver,
moGridDeliver, moButtonDeliver];
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('freeware', [TQuickKey]);
end;

constructor TQuickKey.Create(AOwner: TComponent);
var
Loop: integer;
begin
for Loop:=0 to AOwner.ComponentCount-1 do
if AOwner.Components[Loop] is TQuickKey then raise
EInvalidOperation.Create(
'TQuickKey can have only one instance per form');

// Create component and set default properties
inherited Create(AOwner);
FActive:=false;

FOptions:=[moEditDeliver, moListDeliver,
moComboDeliver,moGridDeliver, moButtonDeliver, moRadioDeliver];

FOwnerKeyEvents:=Application.OnMessage;
Application.OnMessage:=NewKeyDown;
end;

destructor TQuickKey.Destroy;
begin
Application.OnMessage:=FOwnerKeyEvents;
inherited;
end;

procedure TQuickKey.NewKeyDown(var Msg: TMsg; var handled: boolean);
var
v: TWinControl;
f: TForm;
begin
if FActive then
begin
f:=self.owner as TForm;
if f.Active and (Msg.message=WM_KEYDOWN) then
if
(Msg.wParam = VK_RETURN) or
(Msg.wParam = VK_LEFT) or
(Msg.wParam = VK_RIGHT) or
(Msg.wParam = VK_UP) or
(Msg.wParam = VK_DOWN) then begin
v:=f.ActiveControl;
FEdit := v is TCustomEdit;
FList := v is TCustomListBox;
FGrid := v is TDrawGrid;
FCombo := v is TCustomComboBox;
FButton := v is TButtonControl;
FRadio := v is TRadioGroup;

{ FEdit:=HasProperty(v,'Text');
FList:=HasProperty(v,'Items');
FGrid:=HasProperty(v,'ColCount') or HasProperty(v,'RowCount');
FButton:=v is TButtonControl;
}
case Msg.wParam of
VK_UP: Handled:=MoveUpSide(v, Msg.wParam);
VK_DOWN: Handled:=MoveDownSide(v, Msg.wParam);
VK_LEFT: Handled:=MoveLeftSide(v, Msg.wParam);
VK_RIGHT: Handled:=MoveRightSide(v, Msg.wParam);
VK_RETURN: Handled:=MoveNextSide(v, Msg.wParam);
end;
end;
end;
if assigned(FOwnerKeyEvents) then FOwnerKeyEvents(Msg,handled);

end;

function TQuickKey.MoveUpSide(Sender: TWinControl; Key: word):boolean;
var
v: boolean;
begin
v:=false;
if FList then
if moListDeliver in FOptions then
if (Sender as TCustomListBox).ItemIndex=0 then
v:=true
else
else
else if FCombo then
if moComboDeliver in FOptions then
if (Sender as TCustomComboBox).ItemIndex=0 then
v:=true
else
else
else if FButton then
if moButtonDeliver in FOptions then
v:=true
else
else if FRadio then
if moRadioDeliver in FOptions then
if (Sender as TRadioGroup).ItemIndex = 0 then
v:=true
else
else
else if FEdit then
if moEditDeliver in FOptions then
if CanEnterKey(Sender) then
if HasProperty(Sender, 'Lines') then
if (Sender as TCustomEdit).SelStart
+(Sender as TCustomEdit).SelLength=0 then
v:=true
else
else
v:=true
else
v:=true
else
else if FGrid then
if moGridDeliver in FOptions then
if (not CanEnterKey(Sender))
and ((Sender as TDrawGrid).row<=
GetPropertyValue(Sender,'FixedRows')
)
then
v:=true;
if v then
begin
GetControl(Sender,1);
end;
result:=v;
end;

function TQuickKey.MoveDownSide(Sender: TWinControl;
Key: word):boolean;
var
v: Boolean;
begin
v:=false;
if FList then
if moListDeliver in FOptions then
if (Sender as TCustomListBox).ItemIndex=
(Sender as TCustomListBox).Items.Count-1
then
v:=true
else
else
else if FCombo then
if moComboDeliver in FOptions then
if (Sender as TCustomComboBox).ItemIndex=
(Sender as TCustomComboBox).Items.Count-1
then
v:=true
else
else
else if FButton then
if moButtonDeliver in FOptions then
v:=true
else
else if FRadio then
if moRadioDeliver in FOptions then
if (Sender as TRadioGroup).ItemIndex =
(Sender as TRadioGroup).Items.Count-1
then
v:=true
else
else
else if FEdit then
if moEditDeliver in FOptions then
if CanEnterKey(Sender) then
if HasProperty(Sender, 'Lines') then
if (Sender as TCustomEdit).SelStart
+(Sender as TCustomEdit).SelLength>=
length((Sender as TCustomEdit).text)-1
then
v:=true
else
else
v:=true
else
v:=true
else
else if FGrid then
if moGridDeliver in FOptions then
if (not CanEnterKey(Sender))
and ((Sender as TDrawGrid).Row>=
GetPropertyValue(Sender, 'RowCount')-1)
then
v:=true;

if v then
begin
GetControl(Sender,3);
end;
result:=v;
end;

function TQuickKey.MoveLeftSide(Sender: TWinControl;
key: word):boolean;
var
v: boolean;
begin
v:=false;
if FList then
if moListDeliver in FOptions then
if (Sender as TCustomListBox).ItemIndex= 0
// (Sender as TCustomListBox).Items.Count-1
then
v:=true
else
else
else if FCombo then
if moComboDeliver in FOptions then
if CanEnterKey(Sender) then
if (Sender as TCustomCombobox).selstart
+(Sender as TCustomComboBox).SelLength = 0 then
v:=true
else
else
v:=true
else
else if FButton then
if moButtonDeliver in FOptions then
v:=true
else
else if FRadio then
if moRadioDeliver in FOptions then
if (Sender as TRadioGroup).ItemIndex = 0
// (Sender as TRadioGroup).Items.Count-1
then
v:=true
else
else
else if FEdit then
if moEditDeliver in FOptions then
if CanEnterKey(Sender) then
if (Sender as TCustomEdit).SelStart
+(Sender as TCustomEdit).SelLength=0
// length((Sender as TCustomEdit).text)-1
then
v:=true
else
else
v:=true
else
else if FGrid then
if moGridDeliver in FOptions then
if (not CanEnterKey(Sender))
and ((Sender as TDrawGrid).Col<=
GetPropertyValue(Sender,'FixedCols'))
then
v:=true;
if v then
begin
GetControl(Sender,0);
end;
result:=v;
end;

function TQuickKey.MoveRightSide(Sender: TWinControl;
Key: word):boolean;
var
v: boolean;
begin
v:=false;
if FList then
if moListDeliver in FOptions then
if (Sender as TCustomListBox).ItemIndex=
(Sender as TCustomListBox).Items.Count-1
then
v:=true
else
else
else if FCombo then
if moComboDeliver in FOptions then
if CanEnterKey(Sender) then
if (Sender as TCustomComboBox).SelStart
+(Sender as TCustomComboBox).SelLength>=
length((Sender as TComboBox).text)
then
v:=true
else
else
v:=true
else
else if FButton then
if moButtonDeliver in FOptions then
v:=true
else
else if FRadio then
if moRadioDeliver in FOptions then
if (Sender as TRadioGroup).ItemIndex =
(Sender as TRadioGroup).Items.Count-1
then
v:=true
else
else
else if FEdit then
if moEditDeliver in FOptions then
if CanEnterKey(Sender) then
if (Sender as TCustomEdit).SelStart
+(Sender as TCustomEdit).SelLength>=
length((Sender as TCustomEdit).text)
then
v:=true
else
else
v:=true
else
else if FGrid then
if moGridDeliver in FOptions then
if (not CanEnterKey(Sender))
and ((Sender as TDrawGrid).col>=
GetPropertyValue(Sender,'ColCount')-1)
then
v:=true;
if v then
begin
GetControl(Sender,2);
end;
result:=v;
end;

function TQuickKey.MoveNextSide(Sender: TwinControl;
Key: word):boolean;
var
v: boolean;
begin
v:=false;
if FList then
if moListDeliver in FOptions then
if (Sender as TCustomListBox).ItemIndex=
(Sender as TCustomListBox).Items.Count-1
then
v:=true
else
else
else if FCombo then
if moComboDeliver in FOptions then
if CanEnterKey(Sender) then
if (Sender as TCustomComboBox).SelStart
+(Sender as TCustomComboBox).SelLength>=
length((Sender as TComboBox).text)
then
v:=true
else
else
v:=true
else
else if FRadio then
if moRadioDeliver in FOptions then
if (Sender as TRadioGroup).ItemIndex =
(Sender as TRadioGroup).Items.Count-1
then
v:=true
else
else
else if FEdit then
if CanEnterKey(Sender) then
if HasProperty(Sender, 'Lines') then
if (Sender as TCustomEdit).SelStart
+(Sender as TCustomEdit).SelLength>=
length((Sender as TCustomEdit).text)
then
v:=true
else
else
v:=true
else
v:=true;
if v then
begin
// GetControl(Sender,4);
(Sender.Owner as TForm).Perform(WM_NEXTDLGCTL,0,0);
end;
result:=v;
end;

function TQuickKey.CanEnterKey(Sender: TWinControl): boolean;
begin
if hidecaret(0) then
begin
showcaret(0);
result:=true;
if HasProperty(Sender,'ReadOnly')
and (not TestProperty(Sender,'ReadOnly',0))
then
result:=false;
end
else
result:=false;
end;

function TQuickKey.HasProperty(Sender:TObject; AProperty: string):boolean;
begin
result:=(GetPropInfo(Sender.ClassInfo, AProperty)<>nil);
end;

function TQuickKey.TestProperty(Sender:TObject; AProperty: string;
Value: integer): boolean;
var
T:PPropInfo;
begin
T:=GetPropInfo(Sender.ClassInfo, AProperty);
result:=(GetOrdProp(Sender,T) = Value);
end;

procedure TQuickKey.GetControl(Sender:TWinControl;Direct:integer);
var
i: integer;
scs: TRect;
sc1,sc2: TRect;
wc: TWinControl ;
f:TForm;
begin
wc:=nil;
f:= Sender.Owner as TForm;
{ scs := Sender.BoundsRect;
scs.TopLeft :=
(Sender.Parent as TWinControl).ClientToScreen(sc1.TopLeft);
scs.BottomRight :=
(Sender.Parent as TWinControl).ClientToScreen(sc1.BottomRight);
}

scs := Sender.ClientRect;
scs.TopLeft :=
(Sender as TWinControl).ClientToScreen(scs.TopLeft);
scs.BottomRight :=
(Sender as TWinControl).ClientToScreen(scs.BottomRight);
{ }
case Direct of
0:
begin
scs.Right:=scs.Left-1;
scs.Left:=-3000;
end;
1:
begin
scs.Bottom:=scs.Top-1;
scs.Top:=-3000;
end;
2:
begin
scs.Left:=scs.Right+1;
scs.Right:=3000;
end;
3:
begin
scs.Top:=scs.bottom+1;
scs.Bottom:=3000;
end;
end;
for i:= 0 to f.ComponentCount-1 do
begin
if (f.Components <> Sender)
{ and (
(f.Components is TWinControl) and
(HasProperty(f.Components,'Text') or
HasProperty(f.Components,'Items') or
HasProperty(f.Components,'ColCount')
) )}
and (f.Components is TWinControl)
and (
(not HasProperty(f.Components,'ControlCount'))
or (
HasProperty(f.components,'ControlCount')
and TestProperty(f.Components,'ControlCount',0)
)
)
and (f.Components as TWinControl).CanFocus
then
begin
{
sc1:=(f.components as TWinControl).BoundsRect;
sc1.TopLeft:=
((f.Components as TWinControl).Parent as TWinControl).ClientToScreen(sc1.TopLeft);
sc1.BottomRight:=
((f.Components as TWinControl).Parent as TWinControl).ClientToScreen(sc1.BottomRight);
}
sc1:=(f.components as TWinControl).ClientRect;
sc1.TopLeft:=
(f.Components as TWinControl).ClientToScreen(sc1.TopLeft);
sc1.BottomRight:=
(f.Components as TWinControl).ClientToScreen(sc1.BottomRight);
{}
if IntersectRect(sc2,scs,sc1) then
begin
wc:=f.Components as TWinControl;
case Direct of
0: scs.Left:=sc2.Right+1;
1: scs.Top:=sc2.Bottom+1;
2: scs.Right:=sc2.Left-1;
3: scs.Bottom:=sc2.Top-1;
end;
if (scs.Top>scs.Bottom) or (scs.Left>scs.Right) then
break;
end;
end;
end;
if wc<>nil then
postmessage(f.Handle,WM_NEXTDLGCTL,wc.Handle,1)
else if Direct<=1 then
postmessage(f.handle,WM_NEXTDLGCTL,1,0)
else
postmessage(f.handle,WM_NEXTDLGCTL,0,0);

end;

function TQuickKey.GetPropertyValue(Sender:TObject; AProperty:string):integer;
var
T:PPropInfo;
begin
T:=GetPropInfo(Sender.ClassInfo,AProperty);
if T<>nil then
result:=GetOrdProp(Sender,T)
else
result:=-1;
end;

end.
 
请继续讨论或结束问题
如连不上:
http://202.120.85.61/DELPHIBBS/
 
你们有空呀,恶贴东西,唉,yifeng的方法好,menxin的是“标准”方法
 
后退
顶部