各位老大 今天做程序的时候遇到一个问题 客户要求在窗体上加一个快捷键 用ctrl控制一个按钮 以前在另外一个窗体上实现过这个功能 但是 这次客户要求的窗体是继承自另外一个基本窗体的 结果KEYDOWN事件就不响应了 请问各位有什么解决的办法么?谢谢

解决方案 »

  1.   

    KEYDOWN是在父窗体的事件吗,还做其它处理了吗
      

  2.   

    我只是想在子窗口中实现这个事件 父窗体中原来没有这个事件的 曾经在网上找过答案 结果在父窗体中的KEYDOWN事件中添加了代码 在子窗体中继承也还是不行的
      

  3.   

    对了 我的这个项目中的父窗体 定义了一个shortcut的过程
    procedure ShortCut(var Message: TMessage); message WM_SHORTCUT;
    代码是这样的:
    procedure TFrmBase.ShortCut(var Message: TMessage);
    begin
      Case Message.WParam of
        vk_F1  : if BtnNew.Enabled then  BtnNew.OnClick(BtnNew);
        vk_F2  : if BtnEdit.Enabled then  BtnEdit.OnClick(BtnEdit);
        vk_F3  : if BtnSave.Enabled then  BtnSave.OnClick(BtnSave);
        vk_F4  : if BtnUndo.Enabled then  BtnUndo.OnClick(BtnUndo);
        vk_F5  : if BtnDelete.Enabled then  BtnDelete.OnClick(BtnDelete);
        vk_F6  : if BtnCopy.Enabled then  BtnCopy.OnClick(BtnCopy);
        vk_F7  : if BtnImport.Enabled then  BtnImport.OnClick(BtnImport);
        vk_F8  : if BtnFilter.Enabled then  BtnFilter.OnClick(BtnFilter);
        vk_F9  : if BtnReFresh.Enabled then  BtnReFresh.OnClick(BtnReFresh);
        vk_F10 : if BtnPrint.Enabled then  BtnPrint.OnClick(BtnPrint);
        vk_F11 : if BtnCheck.Enabled then  BtnCheck.OnClick(BtnCheck);
        vk_F12 : if BtnExit.Enabled then  BtnExit.OnClick(BtnExit);
      end;
    end;
    会不会和这个有关系呢?
    也不对啊 之前我实现功能的那个窗体也有这个过程的 所不同的是那个是在自己的窗体中实现的 这个是在父窗体中实现的 会产生问题么?
      

  4.   

    对了 我的这个项目中的父窗体 定义了一个shortcut的过程
    procedure ShortCut(var Message: TMessage); message WM_SHORTCUT;
    代码是这样的:
    procedure TFrmBase.ShortCut(var Message: TMessage);
    begin
      Case Message.WParam of
        vk_F1  : if BtnNew.Enabled then  BtnNew.OnClick(BtnNew);
        vk_F2  : if BtnEdit.Enabled then  BtnEdit.OnClick(BtnEdit);
        vk_F3  : if BtnSave.Enabled then  BtnSave.OnClick(BtnSave);
        vk_F4  : if BtnUndo.Enabled then  BtnUndo.OnClick(BtnUndo);
        vk_F5  : if BtnDelete.Enabled then  BtnDelete.OnClick(BtnDelete);
        vk_F6  : if BtnCopy.Enabled then  BtnCopy.OnClick(BtnCopy);
        vk_F7  : if BtnImport.Enabled then  BtnImport.OnClick(BtnImport);
        vk_F8  : if BtnFilter.Enabled then  BtnFilter.OnClick(BtnFilter);
        vk_F9  : if BtnReFresh.Enabled then  BtnReFresh.OnClick(BtnReFresh);
        vk_F10 : if BtnPrint.Enabled then  BtnPrint.OnClick(BtnPrint);
        vk_F11 : if BtnCheck.Enabled then  BtnCheck.OnClick(BtnCheck);
        vk_F12 : if BtnExit.Enabled then  BtnExit.OnClick(BtnExit);
      end;
    end;
    会不会和这个有关系呢?
    也不对啊 之前我实现功能的那个窗体也有这个过程的 所不同的是那个是在自己的窗体中实现的 这个是在父窗体中实现的 会产生问题么?
      

  5.   

    跟踪一下看看有没有触发这个消息过程,或者在子窗体中也创建KewDown事件,然后写上inerited,看看能不能执行父类的KewDown
      

  6.   

    没有执行KeyDown 父窗体的也没有执行
      

  7.   

    WM_SHORTCUT  這個信息你是在什麼時候處理,然後將消息傳給這個消息的?? 應該是這裏處理完自定義消息後沒有繼承原有信息的發送。
      

  8.   

    WM_SHORTCUT貌似是只有按下F1-F9键的时候才进行处理的 这个FRMBASE界面就是这个项目中的基窗体要如何继承原有消息的发送呢?
      

  9.   

    如果是窗体的Keydown,设置KeyPreview:=True试试,只是猜测了
      

  10.   

    你原來將系統隊列中的消息,根據自己的辦法發送到  WM_ShortCut  這個地方你貼出來才好解決。
      

  11.   

    procedure ShortCut(var Message: TMessage); message WM_SHORTCUT;这个项目的框架因为是别人完成的 所以我只能进行猜测 会不会是这个过程对消息进行拦截
    然后根据按键消息进行判断呢
     Case Message.WParam of 
        vk_F1  : if BtnNew.Enabled then  BtnNew.OnClick(BtnNew); 
        vk_F2  : if BtnEdit.Enabled then  BtnEdit.OnClick(BtnEdit); 
        vk_F3  : if BtnSave.Enabled then  BtnSave.OnClick(BtnSave); 
        vk_F4  : if BtnUndo.Enabled then  BtnUndo.OnClick(BtnUndo); 
        vk_F5  : if BtnDelete.Enabled then  BtnDelete.OnClick(BtnDelete); 
        vk_F6  : if BtnCopy.Enabled then  BtnCopy.OnClick(BtnCopy); 
        vk_F7  : if BtnImport.Enabled then  BtnImport.OnClick(BtnImport); 
        vk_F8  : if BtnFilter.Enabled then  BtnFilter.OnClick(BtnFilter); 
        vk_F9  : if BtnReFresh.Enabled then  BtnReFresh.OnClick(BtnReFresh); 
        vk_F10 : if BtnPrint.Enabled then  BtnPrint.OnClick(BtnPrint); 
        vk_F11 : if BtnCheck.Enabled then  BtnCheck.OnClick(BtnCheck); 
        vk_F12 : if BtnExit.Enabled then  BtnExit.OnClick(BtnExit); 
      end; 
    在这个基窗体中也没有再找到其他的相关内容了 呵呵 小弟水平不高 只能这么猜测了~!
      

  12.   

    哦 我想起来了 好像还有个自写的控件 是在这里进行消息传递的吧unit KeyJump;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls;type
      TJumpOptions = set of (moEnter,moUpDn);  TKeyJump = class(TComponent)
      private
        FActive        : boolean;
        FOptions       : TJumpOptions;
        FEditNoBeep    : boolean;
        FOwnerKeyDown  : TKeyEvent;
        FOwnerKeyPress : TKeyPressEvent;
        FLastWasEdit   : boolean;
      protected
        procedure NewKeyDown(Sender : TObject;var Key : word;Shift : TShiftState);
        procedure NewKeyPress(Sender : Tobject;var Key : char);
      public
        constructor Create(AOwner : TComponent); override;
      published
        property Active : boolean read FActive write FActive 
          default true;
        property Options : TJumpOptions read FOptions write FOptions 
          default [moEnter,moUpDn];
        property EditNoBeep : boolean read FEditNoBeep write FEditNoBeep
          default true;  
      end;const
      WM_SHORTCUT =     WM_USER + $120;
      WM_HLPAPPEAR=     WM_USER + $140;
    implementation//-----------------------------------------------------------------------------
    constructor TKeyJump.Create(AOwner : TComponent);
    var
      Loop : integer;
      tmpForm: TForm;
    begin
      // 首先检查是否已经存在本类控件
      for Loop:=0 to AOwner.ComponentCount-1 do
        if AOwner.Components[Loop] is TKeyJump then raise
          EInvalidOperation.Create('TKeyJump can have only one instance per form');  // 创建控件实例,并设置参数的默认值
      inherited Create(AOwner);
      FActive:=true;
      FOptions:=[moEnter,moUpDn];
      FEditNoBeep:=true;  //截取拥有者的 OnKeyDown 和 OnKeyPress 事件.
      tmpForm := GetParentForm(AOwner as TForm) as TForm;
      tmpForm.KeyPreview:=true;
      FOwnerKeyDown:=tmpForm.OnKeyDown;
      tmpForm.OnKeyDown:=NewKeyDown;
      FOwnerKeyPress:=tmpForm.OnKeyPress;
      tmpForm.OnKeyPress:=NewKeyPress;
      
    end; // Create//-----------------------------------------------------------------------------
    procedure TKeyJump.NewKeyDown(Sender : TObject;var Key : word;
      Shift : TShiftState);
    var
      tmpForm: TForm;
    begin  if FActive then begin
        tmpForm := GetParentForm(Owner as TForm) as TForm;    //判断当前获得焦点的控件是否是从 TCustomEdit类继承下来的(必须是编辑类控件)
        FLastWasEdit:=(Owner as TForm).ActiveControl is TCustomEdit;
        
        if ((Key = VK_F1)  and (ssCtrl in SHIFT)) THEN
        //if ((key= VK_F1 + VK_CONTROL)) THEN
            tmpForm.Perform(WM_HLPAPPEAR, 0, 0)
        else
        if key in [vk_F1..vk_F12] then
            tmpForm.Perform(WM_SHORTCUT,key,0);    if (FOptions<>[]) then begin      // 特殊键的句柄
          if Key <> VK_CONTROL + VK_RETURN then
          if ((Key=VK_DOWN) and (moUpDn in FOptions)) or
             ((Key=VK_RETURN) and (moEnter in FOptions)) then
            tmpForm.Perform(WM_NEXTDLGCTL,0,0)
          else if (Key=VK_UP) and (moUpDn in FOptions) then
            tmpForm.Perform(WM_NEXTDLGCTL,1,0);      
        end; // if Options<>[] ...
      end; // if FActive ...  // 完成控件的跳转控制后,调用拥有者控件本身的 OnKeyDown 方法
      if assigned(FOwnerKeyDown) then FOwnerKeyDown(Sender,Key,Shift);
    end; // NewKeyDown//-----------------------------------------------------------------------------
    procedure TKeyJump.NewKeyPress(Sender : TObject;var Key : char);
    begin
      if FActive then begin
        // Handle 'Enter' key that makes Edits beep
        if FEditNoBeep and FLastWasEdit and (Key=#13) then Key:=#0;  end; // if FActive ...  // Call owner OnKeyPress if it's assigned
      if assigned(FOwnerKeyPress) then FOwnerKeyPress(Sender,Key);
    end; // NewKeyPressend.
      

  13.   

    // 完成控件的跳转控制后,调用拥有者控件本身的 OnKeyDown 方法 
      if assigned(FOwnerKeyDown) then FOwnerKeyDown(Sender,Key,Shift); 但是这个控件在执行完Keydown后 还是会调用窗体的Onkeydown事件 没道理会没有反应的呀!
      

  14.   

    const 
      WM_SHORTCUT =    WM_USER + $120; 這個終於看到了。但發送部分呢? 知道這個地方就知道問題在什麼地方了。 
      

  15.   


    在認為你以前的兄弟寫的代碼不錯的情況下,你貼出來你創建窗體的代碼create(self)  or Create(nil) or Create(父。。 )
      

  16.   

    TFrmInOutCustom = class(TFrmBase)FrmInoutCustom 就是我要改动的窗体 FrmBase就是父窗体了
      

  17.   

    在 FrmInoutCustom 类的 Create 中添加 KeyPreview:=True 再试试...
    觉得还是因为他而导致窗体没有接收到KeyDown事件。。
      

  18.   


      //截取拥有者的 OnKeyDown 和 OnKeyPress 事件. 
      tmpForm := GetParentForm(AOwner as TForm) as TForm; 
      tmpForm.KeyPreview:=true; 
      FOwnerKeyDown:=tmpForm.OnKeyDown; 
      tmpForm.OnKeyDown:=NewKeyDown; 
      FOwnerKeyPress:=tmpForm.OnKeyPress; 
      tmpForm.OnKeyPress:=NewKeyPress;发送的话是这里吧 截取拥有者的 OnKeyDown 和 OnKeyPress 事件. 从而产生消息 可以这样理解么?
      

  19.   

    我只是想在子窗口中实现这个事件 父窗体中原来没有这个事件的 曾经在网上找过答案 结果在父窗体中的KEYDOWN事件中添加了代码 在子窗体中继承也还是不行的
      

  20.   

    可以的,加上inerited,再跟蹤下代碼
      

  21.   


    procedure TRES_SOP_F.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    var
      Model_no,Routing_no:string;
      Station,Pag:Integer;
    begin
      inherited;
      if not(qry_main.State in [dsinsert,dsedit]) then
      begin
        if ((Key=37) or (Key=39)) then
        begin
          if (not IsLRDown) then
          begin
            sSQL:=qry_main.SQL.Text;
            RecorIndex:=qry_main.RecNo;
          end;
          Pag:=qry_main.fieldbyname('Page').AsInteger;
          Model_no:=qry_main.fieldbyname('Model_no').AsString;
          Routing_no:=qry_main.fieldbyname('Routing_no').AsString;
          Station:=qry_main.fieldbyname('Station').AsInteger;
        end;  
        case Key of
          68:begin if Shift=[ssCtrl] then btnSB_SearchClick(Sender); end;
          37:
          begin
            if Pag>1
            then
            begin
              qry_main.Close;
              qry_main.SQL.Text:='select * from SOP_Main where Model_no='''+Model_no+''' and Routing_no='''+Routing_no+''' and Station='''+inttostr(Station)+''' and Page='''+inttostr(pag-1)+'''';
              qry_main.Open;
              IsLRDown:=True;
            end;
          end;
          39:
          begin
            qry_op.Close;
            qry_op.SQL.Text:='select * from SOP_Main where Model_no='''+Model_no+''' and Routing_no='''+Routing_no+''' and Station='''+inttostr(Station)+''' and Page='''+inttostr(pag+1)+'''';
            qry_op.Open;
            if qry_op.RecordCount>0 then
            begin
              qry_main.Close;
              qry_main.SQL.Text:=qry_op.SQL.Text;
              qry_main.Open;
              IsLRDown:=True;
            end;  
          end;
          38:
          begin
            if IsLRDown then
            begin
              qry_main.Close;
              qry_main.SQL.Text:=sSQL;
              qry_main.Open;
              qry_main.RecNo:=RecorIndex;
              IsLRDown:=False;
            end;  
            btn4Click(Sender);
          end;
          40:
          begin
            if IsLRDown then
            begin
              qry_main.Close;
              qry_main.SQL.Text:=sSQL;
              qry_main.Open;
              qry_main.RecNo:=RecorIndex;
              IsLRDown:=False;
            end;
            btn2Click(Sender);
          end;
        end;
      end;
    end;
      

  22.   

    應該是對DELPHI 不太熟悉ONKEYDOWN,ONKEYUP可能的過程指針已經改變了,指向了其它地方,你要下對斷點才好調試
    procedure ShortCut(var Message: TMessage); message WM_SHORTCUT; 
    代码是这样的: 
    procedure TFrmBase.ShortCut(var Message: TMessage); 
    begin 
      showMessage('OK');//   加這麼一句看下,要先判斷到這個KEY是不是在這裏有響應,但沒有處理。再找 你的代碼裏什麼時候向 WM_ShortCut  發了消息。
      Case Message.WParam of 
        vk_F1  : if BtnNew.Enabled then  BtnNew.OnClick(BtnNew); 
        vk_F2  : if BtnEdit.Enabled then  BtnEdit.OnClick(BtnEdit); 
        vk_F3  : if BtnSave.Enabled then  BtnSave.OnClick(BtnSave); 
        vk_F4  : if BtnUndo.Enabled then  BtnUndo.OnClick(BtnUndo); 
        vk_F5  : if BtnDelete.Enabled then  BtnDelete.OnClick(BtnDelete); 
        vk_F6  : if BtnCopy.Enabled then  BtnCopy.OnClick(BtnCopy); 
        vk_F7  : if BtnImport.Enabled then  BtnImport.OnClick(BtnImport); 
        vk_F8  : if BtnFilter.Enabled then  BtnFilter.OnClick(BtnFilter); 
        vk_F9  : if BtnReFresh.Enabled then  BtnReFresh.OnClick(BtnReFresh); 
        vk_F10 : if BtnPrint.Enabled then  BtnPrint.OnClick(BtnPrint); 
        vk_F11 : if BtnCheck.Enabled then  BtnCheck.OnClick(BtnCheck); 
        vk_F12 : if BtnExit.Enabled then  BtnExit.OnClick(BtnExit); 
      end; 
    end; 
      

  23.   

    starluck老大:小弟实在是菜鸟啊 那个 发送消息的代码大概是什么样的语句呢 因为我对消息机制了解的实在不是很多还请指点 呵呵 小弟拜谢了!
      

  24.   


     一般是 SendMessage, PostMessage  之類。
      

  25.   

    哦 谢啦 starluck老大 我找找看看再说 结贴给分了!