CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Delphi >  VCL组件开发及应用

高手不要错过哦

楼主fengjn(颗粒)2003-09-03 10:57:02 在 Delphi / VCL组件开发及应用 提问

请问  
  1、TCustomForm   中WantChildKey函数是做什么用的。  
  2、它在TCustomActiveForm类中有什么特殊的含义。  
  3、为什么在TCustomActiveForm类的对象中,如果包含编辑控件,并且编辑控件按下方向键,在WantChildKey中的child参数始终是TCustomActiveForm的派生类对象,而并不是相应的编辑控件呢?(只有方向键是这样)  
  4、如何使其中的编辑控件获得方向键信息?(最关心这条) 问题点数:50、回复次数:32Top

1 楼guanghui(不归路)回复于 2003-09-03 11:16:03 得分 0

我还是错过好了,帮你UP一下   :)Top

2 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 11:21:02 得分 45

1、当窗体的子控件接受到键盘事件时(如敲击一个键),会调用窗体的WantChildKey,意思是该事件是否由窗体处理(由WantChildKey的返回值决定)。因此可以覆盖WantChildKey从而接管子控件的一些键盘事件。  
  2、ActiveForm需要处理子控件的一些键盘事件,所以对WantChildKey作了覆盖。  
  3、child参数始终是TCustomActiveForm的派生类对象?应该不可能。在TControl.WndProc中是这样调用的:Form.WantChildKey(Self,   Message)  
  4、源代码为:  
  function   TCustomActiveForm.WantChildKey(Child:   TControl;   var   Message:   TMessage):   Boolean;  
  begin  
      Result   :=   ((Message.Msg   =   WM_CHAR)   and   (Message.WParam   =   VK_TAB))   or  
          (Child.Perform(CN_BASE   +   Message.Msg,   Message.WParam,  
              Message.LParam)   <>   0);  
  end;  
  你可以覆盖处理它,当是方向键时返回False.  
   
  ————————————————————————————————————  
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。  
  ————————————————————————————————————Top

3 楼fengjn(颗粒)回复于 2003-09-03 11:38:11 得分 0

前两条可能你说的对。但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函数被调用之前,方向键已经被屏蔽掉了。所以想要在该方法中做文章的可能性不大了。Top

4 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 13:29:50 得分 0

TExeTemplet是什么?你是将一个ActiveXForm放在它上面么?  
   
  ————————————————————————————————————  
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。  
  ————————————————————————————————————  
  Top

5 楼fengjn(颗粒)回复于 2003-09-03 13:32:41 得分 0

TExeTemplet   =   class(TActiveForm,   IExeTemplet)Top

6 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 13:43:57 得分 0

你可以调试AxCtrls单元的function   TActiveXControl.TranslateAccelerator(var   msg:   TMsg):   HResult;中的代码。我这里无法运行ActivexForm  
   
  ————————————————————————————————————  
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。  
  ————————————————————————————————————Top

7 楼fengjn(颗粒)回复于 2003-09-03 13:44:28 得分 0

各位大侠,请最好在解决小弟的问题之前先做一个简单的例子。如下  
  new   ---   active   form  
  添加memo在窗体上,memo1.align:=   alClient;  
  注册该activex  
   
  Component---添加刚才注册的activex控件  
   
  new   ---   application  
  在窗体上放一个刚添加的activex控件。运行。  
  使memo获得输入焦点,按下方向键,看memo是否有响应Top

8 楼fengjn(颗粒)回复于 2003-09-03 13:48:30 得分 0

我也想调试那个方法,因为我看到其中调用了oleinpalce……的那个方法,但是我不知道返回S_OK是什么含义。还有就是如何直接调试(不使用载体)Top

9 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 14:06:47 得分 0

我知道问题的原因了。  
  将TExeTemplet.WantChildKey中的  
  Result   :=   false;  
  放到最后。  
   
  ————————————————————————————————————  
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。  
  ————————————————————————————————————Top

10 楼fengjn(颗粒)回复于 2003-09-03 14:13:32 得分 0

没有用的  
  在function   TActiveXControl.TranslateAccelerator(var   msg:   TMsg):   HResult;中  
  对于方向键调用(包括home和end)  
  Control.Perform(CM_WANTSPECIALKEY,   wParam,   0)   <>   0;  
  对于home和end调用的结果是0,而left..down调用的结果是非0Top

11 楼lw549(那个孩子他爹)回复于 2003-09-03 14:14:11 得分 0

MarkTop

12 楼viaboy(平凡)回复于 2003-09-03 14:16:14 得分 0

studyTop

13 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 14:17:02 得分 0

对,上面那个“放到最后”写错了,是没用的。  
  不过我现在已经感觉很奇怪了。我这里作出来的结果和你相反,就是无论按下什么键,都能正确显示Control.ClassName。  
  但是开始是不行的,有一次将Result     :=     false;     改为了Result     :=     True;     就可以了。最后再改回去还是可以,即使新建一个ActivexForm也正确!?  
   
  ————————————————————————————————————  
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。  
  ————————————————————————————————————Top

14 楼fhuibo(永远深爱一个叫“莎”的好女孩儿)回复于 2003-09-03 14:19:18 得分 0

斑竹就是厉害Top

15 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 14:23:51 得分 0

对,上面那个“放到最后”写错了,是没用的。  
  不过我现在已经感觉很奇怪了。我这里作出来的结果和你相反,就是无论按下什么键,都能正确显示Control.ClassName。  
  但是开始是不行的,有一次将Result     :=     false;     改为了Result     :=     True;     就可以了。最后再改回去还是可以,即使新建一个ActivexForm也正确!?  
   
  ————————————————————————————————————  
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。  
  ————————————————————————————————————Top

16 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 14:31:17 得分 0

说明一点,我这里无论如何作不出“弹出的信息都是“TExeTemplet””的效果。如果你测试时,窗体上除了放置ActivexForm,且还有别的窗口控件如TEdit、TButton的话,那么在ActivexForm中的控件上按下方向键时,焦点应该跳转到主窗体的别的控件上(这个是TControl.WndProc处理的,不需要说),因此最后显示最后跳转到的控件的类名,但是应该不可能显示ActivexForm的类名吧(难道焦点跳转到它上面?当然是不可能的,它本身不能获得焦点)。  
   
  ————————————————————————————————————  
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。  
  ————————————————————————————————————Top

17 楼fengjn(颗粒)回复于 2003-09-03 14:36:59 得分 0

我是delphi6和win2000。按下方向键后无法显示出出类名  
  可不可以把你ocx发给我?  
  ffjn@163.comTop

18 楼myling(不理你)回复于 2003-09-03 14:43:09 得分 5

使memo获得输入焦点,按下方向键,看memo是否有响应  
   
   
  =================================================没有响应!!  
   
   
   
  我觉得应该在注册前先提前把事件写好了,到时候调用就行了  
   
   
  一旦注册以后,……  
   
  正在研究中  
   
   
  Top

19 楼fengjn(颗粒)回复于 2003-09-03 14:49:26 得分 0

我认为关键在于  
  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;  
  Top

20 楼fengjn(颗粒)回复于 2003-09-03 14:50:47 得分 0

对于方向键,显示的信息是0,对于home和end显示的信息是1。这是为什么?Top

21 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 14:56:35 得分 0

不用发ocx了,本质上就是方向键被TActiveXControl转化为类似TAB键的功能,实现焦点转移,可以看作一个屏蔽。因此需要在这里作文章,其他的如让ActiveXForm.KeyPress=True等都不要考虑。其实方法是有的,待会看能不能给你一段代码。  
   
  ————————————————————————————————————  
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。  
  ————————————————————————————————————Top

22 楼myling(不理你)回复于 2003-09-03 14:58:11 得分 0

晕  
   
  刚刚试了下,在注册前加的事件  
   
  Procedure   TActiveFormX.Memo1KeyDown(Sender:   TObject;   Var   Key:   Word;  
        Shift:   TShiftState);  
  Begin  
        Case   key   Of  
            VK_UP:   showmessage('UP');  
            VK_DOWN:   showmessage('DOWN');  
        End;  
  End;  
   
  在编辑的时候响应???   在运行以后反而不响应了???  
   
  Top

23 楼fengjn(颗粒)回复于 2003-09-03 15:04:37 得分 0

2     lxpbuaa(桂枝香在故国晚秋)    
  对,我也同意你上面的说法,不过还不知道在什么地方解决Top

24 楼fengjn(颗粒)回复于 2003-09-03 15:15:11 得分 0

to   ad  
  在编辑的时候消息是靠Form.Designer.IsDesignMsg(Self,   Message)传递的,好象正好被delphi给搞反了。Top

25 楼fengjn(颗粒)回复于 2003-09-03 15:21:42 得分 0

哈哈,好象有眉目了。等我整理一下大家在研究研究Top

26 楼lw549(那个孩子他爹)回复于 2003-09-03 15:30:27 得分 0

upTop

27 楼fengjn(颗粒)回复于 2003-09-03 16:27:54 得分 0

刚才已经说过,问题关键似乎在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;  
  大家有兴趣不妨试试第一种方法。Top

28 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 17:14:27 得分 0

fengjn(小枫)     :      
  归纳起来,目前就两种方法:      
  1、覆盖TControl.Perform或者WndProc等,对方法方向键作处理。其缺点是要对很多个类作处理,比如你在ActiveXForm上要使用Edit、Button、Memo,那么必须对这三个类作处理。      
  2、那就是直接改VCL源代码,然后重新编译。不作覆盖了。这种最省事,但是后患最多。      
     
  开始我就考虑这两种方法了,但是缺点很明显,所以希望找到另外的解决办法。我曾考虑在ActiveXForm中对它所有子控件的WndProc作一个替换处理,这样无须处理多个类,    
   
      回复人:lxpbuaa(桂枝香在故国晚秋)   ()   信誉:168     2003-9-3   17:07:02     删除      
     
      fengjn(小枫)     :      
  归纳起来,目前就两种方法:      
  1、覆盖TControl.Perform或者WndProc等,对方法方向键作处理。其缺点是要对很多个类作处理,比如你在ActiveXForm上要使用Edit、Button、Memo,那么必须对这三个类作处理。      
  2、那就是直接改VCL源代码,然后重新编译。不作覆盖了。这种最省事,但是后患最多。      
     
  开始我就考虑这两种方法了,但是缺点很明显,所以希望找到另外的解决办法。我曾考虑在ActiveXForm中对它所有子控件的WndProc作一个替换处理,这样无须处理多个类。      
     
  ————————————————————————————————————      
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。      
  ————————————————————————————————————      
     
        ╭     ╭──╮     ╮        
        ╰═@ @ ═╯        
                ╭oo      │───╮       
                ╰╮     ─╯       ╞╮        
                            │ ┌─╮         │╰=        
                        └└┘└└─┘Top

29 楼fengjn(颗粒)回复于 2003-09-03 17:14:56 得分 0

re   lxpbuaa(桂枝香在故国晚秋)    
   
  通过观察发现,在TActiveXControl.TranslateAccelerator中的control实际就是一个tactiveform对象。  
  “ActiveXForm中根本就没有子控件的概念”着是什么意思?  
  ActiveControl返回的不是当前焦点控件吗?  
  Top

30 楼lxpbuaa(桂枝香在故国晚秋)回复于 2003-09-03 17:15:26 得分 0

fengjn(小枫)     :      
  归纳起来,目前就两种方法:      
  1、覆盖TControl.Perform或者WndProc等,对方法方向键作处理。其缺点是要对很多个类作处理,比如你在ActiveXForm上要使用Edit、Button、Memo,那么必须对这三个类作处理。      
  2、那就是直接改VCL源代码,然后重新编译。不作覆盖了。这种最省事,但是后患最多。      
     
  开始我就考虑这两种方法了,但是缺点很明显,所以希望找到另外的解决办法。我曾考虑在ActiveXForm中对它所有子控件的WndProc作一个替换处理,这样无须处理多个类,    
   
      回复人:lxpbuaa(桂枝香在故国晚秋)   ()   信誉:168     2003-9-3   17:07:02     删除      
     
      fengjn(小枫)     :      
  归纳起来,目前就两种方法:      
  1、覆盖TControl.Perform或者WndProc等,对方法方向键作处理。其缺点是要对很多个类作处理,比如你在ActiveXForm上要使用Edit、Button、Memo,那么必须对这三个类作处理。      
  2、那就是直接改VCL源代码,然后重新编译。不作覆盖了。这种最省事,但是后患最多。      
     
  开始我就考虑这两种方法了,但是缺点很明显,所以希望找到另外的解决办法。我曾考虑在ActiveXForm中对它所有子控件的WndProc作一个替换处理,这样无须处理多个类。      
     
  ————————————————————————————————————      
  宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。      
  ————————————————————————————————————      
     
        ╭     ╭──╮     ╮        
        ╰═@ @ ═╯        
                ╭oo      │───╮       
                ╰╮     ─╯       ╞╮        
                            │ ┌─╮         │╰=        
                        └└┘└└─┘Top

31 楼fengjn(颗粒)回复于 2003-09-03 17:20:02 得分 0

你在干什么呢,刚才明明我上面还有一个回复,怎么没了?  
   
  牛歪了     :)Top

32 楼fengjn(颗粒)回复于 2003-09-04 09:10:19 得分 0

大家还有什么好的方法吗?Top

33 楼geyobing(大地精灵)回复于 2003-09-04 09:14:19 得分 0

现在没时间,做个记号,中午好好看Top

相关问题

  • 抢分不要错过:::sizeof()...........
  • 高分,不要错过~
  • 经典C不要错过
  • 到手的分,不要错过呦
  • 走过路过不要错过!!!
  • 路过不要错过,捡分啊。
  • 走过路过,不要错过了!
  • 路过,走过,千万不要错过!!!
  • 走过路过不要错过阿
  • 走过,路过,不要错过!!!

关键词

  • 控件
  • activexform
  • vk
  • wantchildkey
  • tactivexcontrol
  • 方向键
  • 调用
  • 处理
  • translateaccelerator
  • dlgc

得分解答快速导航

  • 帖主:fengjn
  • lxpbuaa
  • myling

相关链接

  • Delphi类图书
  • Delphi类源码下载
  • Delphi控件下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo