2010-08-25 83 views
26

我繼續在我簡單的圖形程序(使用C#)中編程某種鍵盤導航。我又一次遇到了麻煩。面板沒有得到重點

alt text

我的問題是,我要處理的鍵盤輸入來移動一個層。用鼠標移動圖層已經工作得很好,但控件沒有獲得焦點(KeyUp/KeyDown/KeyPress,也沒有爲此控件觸發GotFocus/LostFocus)。 由於我的類派生自Panel(並覆蓋了幾個事件),我也覆蓋了上面提到的事件,但我無法成功地觸發這些事件。

我想我可以設法使用類似於Keyboard.GetState()或ProcessCmdWnd之類的東西來實現鍵盤響應。但是:我仍然必須能夠分辨控制權何時得到關注。

有沒有或多或少的優雅的方式來添加此功能的用戶控制(這是基於面板)?

我在這裏檢查了很多線程,我可能使用this approach作爲鍵盤輸入。然而焦點問題仍然存在。

非常感謝您提前提供的信息!

伊戈爾。

p.s .:我用C#.NET v3.5編程,使用VS2008。這是一個Windows.Forms應用程序,而不是WPF

回答

57

Panel類被設計爲容器,它避免了焦點,所以一個子控件總是會得到它。你需要一些手術來解決這個問題。我在代碼扔得到在KeyDown事件光標鍵擊,以及:

using System; 
using System.Drawing; 
using System.Windows.Forms; 

class SelectablePanel : Panel { 
    public SelectablePanel() { 
     this.SetStyle(ControlStyles.Selectable, true); 
     this.TabStop = true; 
    } 
    protected override void OnMouseDown(MouseEventArgs e) { 
     this.Focus(); 
     base.OnMouseDown(e); 
    } 
    protected override bool IsInputKey(Keys keyData) { 
     if (keyData == Keys.Up || keyData == Keys.Down) return true; 
     if (keyData == Keys.Left || keyData == Keys.Right) return true; 
     return base.IsInputKey(keyData); 
    } 
    protected override void OnEnter(EventArgs e) { 
     this.Invalidate(); 
     base.OnEnter(e); 
    } 
    protected override void OnLeave(EventArgs e) { 
     this.Invalidate(); 
     base.OnLeave(e); 
    } 
    protected override void OnPaint(PaintEventArgs pe) { 
     base.OnPaint(pe); 
     if (this.Focused) { 
      var rc = this.ClientRectangle; 
      rc.Inflate(-2, -2); 
      ControlPaint.DrawFocusRectangle(pe.Graphics, rc); 
     } 
    } 
} 
+2

驚人!它真的起作用,並且它很容易實現。我不知道ControlStyles類,因此不知道我可以改變它。 非常感謝:)。 – Igor 2010-08-25 02:43:21

+0

@HansPassant在哪些情況下應該使用'Focus()'而不是'Select()'? – Medinoc 2014-04-03 10:57:54

+0

一個正確的答案是很長的一個,請使用Ask Question按鈕。 – 2014-04-03 11:03:27

6

同漢斯帕桑特代碼在VB.NET

Imports System 
Imports System.Drawing 
Imports System.Windows.Forms 

Public Class SelectablePanel 
    Inherits Panel 

    Public Sub SelectablePanel() 
     Me.SetStyle(ControlStyles.Selectable, True) 
     Me.TabStop = True 
    End Sub 

    Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs) 
     Me.Focus() 
     MyBase.OnMouseDown(e) 
    End Sub 

    Protected Overrides Function IsInputKey(ByVal keydata As Keys) As Boolean 
     If (keydata = Keys.Up OrElse keydata = Keys.Down) Then Return True 
     If (keydata = Keys.Left OrElse keydata = Keys.Right) Then Return True 
     Return MyBase.IsInputKey(keydata) 
    End Function 

    Protected Overrides Sub OnEnter(ByVal e As EventArgs) 
     Me.Invalidate() 
     MyBase.OnEnter(e) 
    End Sub 

    Protected Overrides Sub OnLeave(ByVal e As EventArgs) 
     Me.Invalidate() 
     MyBase.OnLeave(e) 
    End Sub 

    Protected Overrides Sub OnPaint(ByVal pe As PaintEventArgs) 
     MyBase.OnPaint(pe) 
     If (Me.Focused) Then 
      Dim rc As Rectangle = Me.ClientRectangle 
      rc.Inflate(-2, -2) 
      ControlPaint.DrawFocusRectangle(pe.Graphics, rc) 
     End If 
    End Sub 

End Class 
+5

'SelectablePanel()'是C#中的構造器,它在這裏應該是'Public Sub New'。 – KekuSemau 2013-05-12 18:51:31

0

通話焦點click事件

private void Panel_Click(object sender, EventArgs e) 
    { 
     Panel.Focus(); 
    } 
-1

面板沒有得到關注,如果要跟蹤請假並輸入事件,則必須選擇面板

致電panel1.Select()MouseClick事件

0

要獲得焦點,請在屬性窗口中檢查MouseEnter事件。

寫下面的代碼:

private void mainPanel_MouseEnter(object sender, EventArgs e) 
{ 
    mainPanel.Focus(); 
} 
0

我用的時候以任何理由我不能使用父窗體KeyPreview屬性,使表單處理關鍵事件,是把一個文本框上

最簡單的竅門

面板:

Panel.Controls.Add(_focusTextBox = new TextBox() { Visible = true , Left = -300, TabIndex = 0}); 

並用它來捕捉KeyDown事件:

_focusTextBox.KeyDown += panel_KeyDown; 

的最後一步是將焦點設置到該文本框時,面板上的其他控制點:

_focusTextBox.Focus();