只要鼠標懸停在特定控件上,我們就會顯示某種形式。當鼠標離開控制器時,我們會在稍微超時後隱藏控制器。這是標準的懸停行爲。.NET控件上的C#鼠標輸入監聽器滾動條
然而,當控制(例如樹視圖)有一個滾動條,並且鼠標上或通過滾動條,該事件不火......
如果我們能找到的一個參考滾動條控件,這將解決我們的問題,因爲我們將相同的偵聽器事件添加到滾動條。然而,據我所知滾動條不可訪問...
我們該如何解決這個問題?
只要鼠標懸停在特定控件上,我們就會顯示某種形式。當鼠標離開控制器時,我們會在稍微超時後隱藏控制器。這是標準的懸停行爲。.NET控件上的C#鼠標輸入監聽器滾動條
然而,當控制(例如樹視圖)有一個滾動條,並且鼠標上或通過滾動條,該事件不火......
如果我們能找到的一個參考滾動條控件,這將解決我們的問題,因爲我們將相同的偵聽器事件添加到滾動條。然而,據我所知滾動條不可訪問...
我們該如何解決這個問題?
滾動條在樹視圖中的非客戶區。當鼠標移動到那裏時,它開始生成非客戶端消息,如WM_NCMOUSEMOVE和WM_NCMOUSELEAVE。您必須對TreeView進行子類別重寫並覆蓋WndProc()來檢測這些消息。
雖然這並不能真正解決您的問題,但在邊緣情況下您仍然很難。一個帶有計時器的低技術的方法總是工作:
private Form frmPopup;
private void treeView1_MouseEnter(object sender, EventArgs e) {
timer1.Enabled = true;
if (frmPopup == null) {
frmPopup = new Form2();
frmPopup.StartPosition = FormStartPosition.Manual;
frmPopup.Location = PointToScreen(new Point(treeView1.Right + 20, treeView1.Top));
frmPopup.FormClosed += (o, ea) => frmPopup = null;
frmPopup.Show();
}
}
private void timer1_Tick(object sender, EventArgs e) {
Rectangle rc = treeView1.RectangleToScreen(new Rectangle(0, 0, treeView1.Width, treeView1.Height));
if (!rc.Contains(Control.MousePosition)) {
timer1.Enabled = false;
if (frmPopup != null) frmPopup.Close();
}
}
我認爲有幾種不同的方法可以做到這一點,但關鍵是您希望暫停操作。我認爲兩種技術的組合可能有效:
將控件放在面板上,停靠填充並使用面板的MouseEnter打開您的行爲 - 這將包含控件的滾動條。您也可以使用面板的MouseLeave事件,但您必須檢查光標的位置以確保它未移入包含的控件。此方法大多可靠,但快速移動鼠標可能會使其混淆。
如果將此功能與計時器結合起來,該計時器會在顯示/隱藏控件顯示時啓動,並定期檢查光標位置。這會起作用,但是在隱藏控件之前你的超時不一定是一致的(因爲定時器在他們進入控件時開始)。您可以停止/啓動控制器中的mousemove計時器,以稍微緩解這一點。
我放在一起的不同的方法我試過這裏的項目:http://lovethedot.s3.amazonaws.com/100609StackoverflowScrollbarQuestion.zip
通過對接要在面板跟蹤控制,它本質上包裹它,你會在的最邊緣得到的MouseEnter跟蹤控件:
private void panel1_MouseEnter(object sender, EventArgs e)
{
this.Text = "in";
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
if (!new Rectangle(new Point(0, 0), panel1.Size).Contains(panel1.PointToClient(Control.MousePosition)))
this.Text = "out";
}
您正在跟蹤圍繞控件的面板的入口,如果光標不在跟蹤控件的內部,則退出該面板。
爲了更好地「離開」的經驗,它結合檢查,看看光標所在以及定時器:
private void listBox3_MouseEnter(object sender, EventArgs e)
{
button1.Visible = true;
visibleTimer.Stop();
visibleTimer.Start();
}
void visibleTimer_Tick(object sender, EventArgs e)
{
if (!new Rectangle(new Point(0, 0), listBox3.Size).Contains(listBox3.PointToClient(Control.MousePosition)))
{
visibleTimer.Stop();
button1.Visible = false;
}
}
面板容器是一個好主意,但是,這並不工作,因爲事件不AR鼓泡,父控件...這將是相同的加入mouseenter事件到整個表單。 超時和定時器不是問題,那些工作很好。雖然謝謝! – 2010-06-09 13:34:15