请教KeyPreview的原理!【KeyPreview】问题了,问题解答后把把分加满~~~~~
KeyPreview本是TCustomForm公开的属性:property KeyPreview: Boolean read FKeyPreview write FKeyPreview stored IsForm default False;
且只是设置FKeyPreview而已。而TForm只是公开了这个属性而已,且在Forms单元,没找到与KeyPreview相关的代码!那么VCl如何实现的Form的KeyPreview的?

解决方案 »

  1.   

    根据Call Stack中的记录
    TForm1.FormKeyPress($CD17BC,'d')---1
    TWinControl.KeyPress('d')---2
    TWinControl.DoKeyPress((258, 100, 0, 2097153, 0))---3
    TWinControl.DoKeyPress((258, 100, 0, 2097153, 0))---4
    TWinControl.WMChar((258, 100, 0, 2097153, 0))---5
    TControl.WndProc((258, 100, 2097153, 0, 100, 0, 1, 32, 0, 0))---6
    TWinControl.WndProc((258, 100, 2097153, 0, 100, 0, 1, 32, 0, 0))---7
    TWinControl.MainWndProc((258, 100, 2097153, 0, 100, 0, 1, 32, 0, 0))---8
    StdWndProc(722470,258,100,2097153)---9
    TApplication.HandleMessage---10
    TApplication.Run---11
    Project1---12
    判断,是在第6行的TControl.WndProc中,由Dispatch(Message)语句触发了第7行的TWinControl.WMChar
      

  2.   

    但其中也没对KeyPreview做任何判断的啊~~~
      

  3.   

    顺带问一句,是不是CSDN对帐号管理做了特殊处理了啊~~~~~
    我用我的小马甲问的问题,居然编程这个号问的了~
      

  4.   

    根据帮助来看,如果KeyPreview属性为true的话,是Form响应按键在先,具体如何响应的正在寻找中If KeyPreview is true, keyboard events occur on the form before they occur on the active control. (The active control is specified by the ActiveControl property.) If KeyPreview is false, keyboard events occur only on the active control.Navigation keys (Tab, BackTab, the arrow keys, and so on) are unaffected by KeyPreview because they do not generate keyboard events. Similarly, when a button has focus or when its Default property is true, the Enter key is unaffected by KeyPreview because it does not generate a keyboard events.KeyPreview is false by default.
      

  5.   

    function TWinControl.DoKeyDown(var Message: TWMKey): Boolean;
    var
      ShiftState: TShiftState;
      Form: TCustomForm;
    begin
      Result := True;
      Form := GetParentForm(Self);
      if (Form <> nil) and (Form <> Self) and Form.KeyPreview and
        TWinControl(Form).DoKeyDown(Message) then Exit;
      with Message do
      begin
        ShiftState := KeyDataToShiftState(KeyData);
        if not (csNoStdEvents in ControlStyle) then
        begin
          KeyDown(CharCode, ShiftState);
          if CharCode = 0 then Exit;
        end;
      end;
      Result := False;
    end;
      

  6.   

    .net和delphi的实现方法基本一致[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true), SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
    protected internal virtual bool ProcessKeyMessage(ref Message m)
    {
          if ((this.parent != null) && this.parent.ProcessKeyPreview(ref m))
          {
                return true;
          }
          return this.ProcessKeyEventArgs(ref m);
    }
      

  7.   

    顺带问一句,是不是CSDN对帐号管理做了特殊处理了啊~~~~~
    我用我的小马甲问的问题,居然编程这个号问的了~>呵呵,可能要关掉浏览器重新登陆,我用散分马甲的时候也中过一次招了。