ContextMenuStrip對於不像上下文菜單行爲的自定義彈出窗口的目標太吸引人了。這是可取的,因爲當用戶在菜單外單擊時它會自動彈出。儘管它有侷限性,但它不是一個很好的控制主機。點擊問題是經典問題,CMS捕獲鼠標以檢測用戶何時在窗口外點擊。
這真的應該是一種形式。爲了賦予它與CMS相同的行爲,需要一些工作。您必須檢測窗口外的鼠標點擊,以便讓窗口消失。像CMS一樣捕獲鼠標不起作用。一個竅門是使用IMessageFilter,它可以讓你在輸入消息被傳送到焦點窗口之前查看輸入消息。下面是一個實現此功能的示例窗體:
public partial class MyContextMenu : Form, IMessageFilter {
public MyContextMenu() {
InitializeComponent();
Application.AddMessageFilter(this);
}
protected override void OnFormClosed(FormClosedEventArgs e) {
Application.RemoveMessageFilter(this);
base.OnFormClosed(e);
}
public void Show(Control ctl, Point pos) {
this.StartPosition = FormStartPosition.Manual;
this.Location = ctl.PointToScreen(pos);
while (!(ctl is Form)) ctl = ctl.Parent;
this.Show((Form)ctl);
}
public bool PreFilterMessage(ref Message m) {
// Detect mouse clicks outside of the form
if (m.Msg == 0x201 || m.Msg == 0x204 || m.Msg == 0x207 ||
m.Msg == 0xA1 || m.Msg == 0xA4 || m.Msg == 0xA7) {
Point pos = new Point(m.LParam.ToInt32());
Control ctl = Control.FromHandle(m.HWnd);
if (ctl != null) pos = ctl.PointToScreen(pos);
pos = this.PointToClient(pos);
if (pos.X < 0 || pos.Y < 0 || pos.X >= this.Width || pos.Y >= this.Height) {
this.Close();
}
}
return false;
}
}
使用設計器作爲正常設計窗體。你至少想給它一個不同的FormBorderStyle。使用提供的Show()方法重載與使用CMS的方式相同。請注意,只有當您單擊應用程序所擁有的窗口時纔會彈出窗體,與CMS不同。功能,而不是一個錯誤。
嗯是的,這可能會作爲一個開始。儘管我認爲在表單中模仿CMS的外觀和感覺會有很多工作。最後,CMS上的大多數項目仍然是普通的舊文本項目,可能還有圖像。 – PJanssen 2011-03-06 10:42:55
它不會讓我編輯,因爲它沒有足夠的改變,但鼠標座標位於消息的'LParam'屬性而不是'WParam'。請參閱:http://msdn.microsoft.com/en-us/library/windows/desktop/ms645607%28v=vs.85%29.aspx – Anthony 2013-03-28 19:00:42