2010-06-01 33 views
4

我的問題很簡單:發送鍵盤事件,以另一種形式

我們的C#應用​​程序有一個MainForm中有一個菜單,並在菜單項相關的幾個快捷鍵。

現在我們還需要從某些子窗體中觸發菜單條目。但是由於當其中一個子窗體處於活動狀態時,MainForm處於非活動狀態,因此快捷方式不起作用。

是否有一種簡單的方法將所有鍵盤事件從子窗體傳播到「所有者」窗體?或者只是針對另一種形式?

啊,我們不能使用一些低級別的窗口,因爲我們需要在Mono/Linux上運行應用程序。

編輯: 我的確切問題是觸發與另一種形式相同的快捷菜單項。當然,如果添加新項目的菜單更改,則不更新表單中的代碼。

+0

我拼命地想這個問題的答案,以及我的編輯程序。 – Tesserex 2010-06-01 14:44:51

+0

IMessageFilter在Mono中可用,您可以將它用於主窗體。 – 2010-06-01 17:16:36

+0

hm ...不知道我們是否想處理這個消息對象..或者有沒有簡單的方法將這樣的消息轉換爲事件? – thalm 2010-06-04 18:39:22

回答

1

這是固定的,對我來說:

public class MainForm : Form 
{ 
    public bool ProcessCmdKeyFromChildForm(ref Message msg, Keys keyData) 
    { 
     Message messageCopy = msg; 
     messageCopy.HWnd = this.Handle; // We need to assign our own Handle, otherwise the message is rejected! 

     return ProcessCmdKey(ref messageCopy, keyData); 
    } 
} 

public class MyChildForm : Form 
{ 
    private MainForm mMainForm; 

    public MyChildForm(MainForm mainForm) 
    { 
     mMainForm = mainForm; 
    } 

    // This is meant to forward accelerator keys (eg. Ctrl-Z) to the MainForm 
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     if (mMainForm.ProcessCmdKeyFromChildForm(ref msg, keyData)) 
     { 
      return true; 
     } 

     return base.ProcessCmdKey(ref msg, keyData); 
    } 
} 
0

我想你想設置KeyPreview父窗體爲true

當此屬性設置爲true,窗體將接收所有按鍵響應,KeyDown和KEYUP事件。在表單的事件處理程序完成鍵擊處理之後,將鍵擊分配給具有焦點的控件。例如,如果KeyPreview屬性設置爲true,並且當前選定的控件是一個TextBox,則在由該窗體的事件處理程序處理擊鍵後,TextBox控件將接收按下的鍵。要僅處理表單級別的鍵盤事件並且不允許控件接收鍵盤事件,請將表單的KeyPress事件處理函數中的KeyPressEventArgs.Handled屬性設置爲true。

編輯:

this question答案可能會有所幫助:

+0

這隻會導致窗體處理收到其控件的關鍵事件。 – SLaks 2010-06-01 14:37:05

+0

好主意,但它沒有幫助,因爲MainForm只是子表單的'所有者',而不是'。Parent'的.Net意義上的(我在帖子中的命名並不清楚,對不起)。當我嘗試設置'Parent'屬性時,我得到一個異常,因爲表單是一個頂層控制..任何進一步的想法? – thalm 2010-06-01 14:51:12

+0

編輯我的答案,因爲我第一次提供不會做你想做的。 – 2010-06-01 14:59:47

0

ToolStrip.AllowMerge屬性 「中獲取或設置[...]無論多MenuStripToolStripDropDownMenuToolStripMenuItem,和其他類型的可以結合起來。」 (MSDN)。

這意味着您可以:

「使用AllowMerge屬性啓用多文檔接口(MDI)的孩子各自的菜單在MDI父結合起來。」 (AllowMerge屬性,此言一出,MSDN)

參見:

  1. MergeAction
  2. MergeIndex

此,我希望,可以幫助你得到你想要的東西。現在,我不知道這是適用於Windows窗體,還是一旦構建就可以在Linux上運行。

+0

看到其他帖子,我們沒有任何其他菜單加入或合併..或者你是怎麼意思這可以解決問題? – thalm 2010-06-04 18:37:26

+0

您必須在MDI容器和子窗體上都有一個MenuStrip。然後,您允許它們合併,甚至替換某些相同的對等菜單。 – 2010-06-07 02:28:50

1

你試過類似的東西嗎?

ParentForm : Form 
{ 
    public NotifyKeyPress(KeyPressEventArgs e) 
    { 
     OnKeyPress(e); 
    } 
} 

ChildForm : Form 
{ 
    ParentForm _parent; 
    public ChildForm(ParentForm parent) 
    { 
     _parent = parent; 
     KeyPress += KeyPressHandler; 
    } 

    public KeyPressHandler(object sender, KeyPressEventArgs e) 
    { 
     if (_parent != null) 
     { 
      _parent.NotifyKeyPress(e); 
     } 
    } 
} 
+0

是的,我想這可以工作,我會試試看,並報告.. thnx! – thalm 2010-06-04 18:39:56

+0

你好再次,它不工作就像..我可以將鍵盤事件發送到MainForm,並調用OnKeyXXX事件,但這不會觸發MenuItems中的事件..這真是一個奇怪的問題..我認爲這會更容易... – thalm 2010-06-04 21:40:45

+0

也許嘗試使用RaiseKeyEvent。 – 2010-06-04 22:18:47

0

我認爲你是不活躍的,你的意思是說它沒有焦點?

執行此操作最簡單的方法是讓每個表單暴露與正在操作的菜單相關的事件。當您創建表單時,將它們訂閱給彼此(或從孩子到MainForm或以任何方式流向需要)。點擊菜單後,執行您的額外事件,另一個表單將收到此信息。

這有幫助嗎?我認爲這比手動強制消息更好,因爲它將是自我記錄代碼,表單需要彼此作出反應。

更「遠離問題」的方法,你需要兩種形式還是可以重構UI設計?

+0

你好,謝謝你的回覆! 我們只有一個菜單,即主窗體,但其他窗體都應該可以用鍵盤快捷鍵觸發菜單項。我們不需要另一種形式的另一個菜單,並且如果菜單項被點擊,我們不需要通知其他形式。所以它沒有真正的幫助.. – thalm 2010-06-04 18:35:21

+0

啊..是的..我可以重構UI設計。那麼你的想法是什麼? – thalm 2010-06-06 18:19:53

0

有很簡單的方法來做到這一點。菜單項應該觸發適當的方法調用。然後你可以在應用程序的任何地方調用這些方法。

+0

是的,我可以做到這一點,但我想用其他形式的鍵盤快捷鍵觸發它們。我想只定義一次當然的快捷方式... – thalm 2010-06-06 18:21:13

0

而不是將主鍵快捷鍵綁定到主窗體上的菜單項,您可以創建一個對鍵快捷鍵作出反應的自定義鍵處理方法。把這個方法放在主窗體中。然後從關鍵事件的所有子窗體中調用此方法。 @Adam Driscoll的代碼與這種方法非常相容。