前两条可能你说的对。但3、4肯定你没有实际试验过,根本和你说的不一样。对于3有下面的代码
function TExeTemplet.WantChildKey(Child: TControl;
var Message: TMessage): Boolean;
var i: integer;
begin
Result := false;
if message.WParam in [VK_LEFT..VK_DOWN] then
begin
showmessage(Child.ClassName);
end;
end;
当运行的时候,不论在什么编辑控件按下方向键,弹出的信息都是“TExeTemplet”,并不是TEdit或TMemo什么的。所以说在WantChildKey函数被调用之前,方向键已经被屏蔽掉了。所以想要在该方法中做文章的可能性不大了。
刚才已经说过,问题关键似乎在TActiveXControl.TranslateAccelerator函数的处理上。
通过上面的比较发现,对于方向键Control.Perform(CM_WANTSPECIALKEY, wParam, 0)的返回值为非0,而home和end返回值是0。这个差异导致了该函数无法调用FOleControlSite.TranslateAccelerator,致使方向键被屏蔽。因此,解决的方案就有两种方法。
1、使Control.Perform调用后返回0。
2、在判断是方向键后,调用完DispatchMessage(msg)并不退出,保证程序可以顺利的执行到FOleControlSite.TranslateAccelerator;
由于时间的关系,我采用了第2种方法。但是建议还是使用方法1比较妥当。(第2种简单啊,哈哈)
代码如下:
function TActiveXControl.TranslateAccelerator(var msg: TMsg): HResult;
var
Control: TWinControl;
Form: TCustomForm;
HWindow: THandle;
Mask: Integer;
begin
with Msg do
if (Message >= WM_KEYFIRST) and (Message <= WM_KEYLAST) then
begin
Control := FindControl(HWnd);
if Control = nil then
begin
HWindow := HWnd;
repeat
HWindow := GetParent(HWindow);
if HWindow <> 0 then Control := FindControl(HWindow);
until (HWindow = 0) or (Control <> nil);
end;
if Control <> nil then
begin
Result := S_OK;
if (Message = WM_KEYDOWN) and (Control.Perform(CM_CHILDKEY, wParam, Integer(Control)) <> 0) then Exit;
Mask := 0;
case wParam of
VK_TAB:
Mask := DLGC_WANTTAB;
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT, VK_HOME, VK_END:
begin
Mask := DLGC_WANTARROWS;
end;
VK_RETURN, VK_EXECUTE, VK_ESCAPE, VK_CANCEL:
Mask := DLGC_WANTALLKEYS;
end;
if (Mask <> 0) and
((Control.Perform(CM_WANTSPECIALKEY, wParam, 0) <> 0) or
((Control.Perform(WM_GETDLGCODE, 0, 0) and Mask <> 0))) then
begin
TranslateMessage(msg);
DispatchMessage(msg);
if not wParam in [VK_LEFT..VK_DOWN] then
Exit;
end;
if (Message = WM_KEYDOWN) and (Control.Parent <> nil) then
Form := GetParentForm(Control)
else
Form := nil;
if (Form <> nil) and (Form.Perform(CM_DIALOGKEY, wParam, lParam) = 1) then
Exit;
end;
end;
if FOleControlSite <> nil then
begin
Result := FOleControlSite.TranslateAccelerator(@msg, GetKeyModifiers);
end
else
Result := S_FALSE;
end;
大家有兴趣不妨试试第一种方法。
Procedure TActiveFormX.Memo1KeyDown(Sender: TObject; Var Key: Word;
Shift: TShiftState);
Begin
Case key Of
VK_UP: showmessage('UP');
VK_DOWN: showmessage('DOWN');
End;
End;
我认为关键在于
function TActiveXControl.TranslateAccelerator(var msg: TMsg): HResult;函数
function TActiveXControl.TranslateAccelerator(var msg: TMsg): HResult;
begin
//……前面被省略了
if Control <> nil then
begin
Result := S_OK;
if (Message = WM_KEYDOWN) and (Control.Perform(CM_CHILDKEY, wParam, Integer(Control)) <> 0) then Exit;
Mask := 0;
case wParam of
VK_TAB:
Mask := DLGC_WANTTAB;
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT, VK_HOME, VK_END:
begin
Mask := DLGC_WANTARROWS;
showmessage(inttostr(wParam));
end;
VK_RETURN, VK_EXECUTE, VK_ESCAPE, VK_CANCEL:
Mask := DLGC_WANTALLKEYS;
end;
if (Mask <> 0) then //为了便于观察,在这里改变了原来的结构
begin
if (Control.Perform(CM_WANTSPECIALKEY, wParam, 0) <> 0) then
begin
TranslateMessage(msg);
DispatchMessage(msg);
showmessage('0');
Exit;
end else
begin
showmessage('1');
if (Control.Perform(WM_GETDLGCODE, 0, 0) and Mask <> 0) then
begin
TranslateMessage(msg);
DispatchMessage(msg);
showmessage('2');
Exit;
end;
end;
//……后面被省略了
end;