2013-10-25 55 views
0

我把3 TextBoxesDataGridView.我可以集中它们并键入一个文本。但是当我尝试使用箭头在TexBox内移动光标时,DataGridView会窃取箭头键,并在网格中移动单元格选择。如何预防它?儿童控制和键盘箭头,退格键等

+0

您需要按[F2]进入细胞并键入 – Alireza

+1

好了,这是'DataGridView'一个非常流行的问题,**拦截**'DataGridView'命令键是非常棘手的事情。该解决方案可能需要使用某种“低级别键盘钩子”,因此这并不容易,需要进行大量测试。 –

回答

1

经过一番艰难的尝试,以覆盖默认的关键行为DataGridView,我结束了这个解决方法,棘手和hacky解决方案。它无缝地像你控制TextBox一样。在DataGridView上抑制Key message很容易,但不管怎样,子控件都不能受这些关键信息的影响,尽管它可以接收这些信息。真奇怪。我真的很想知道这个问题最为美观和直接的解决方案,如果有人知道,请添加您的答案或留下一些参考链接作为您的评论。这将不胜感激。这里是我的代码,正如我所说,这是棘手的,哈克,但它精美的作品:

//This helper class to use some Win32 functions, must add using System.Runtime.InteropServices; 
public class Win32 { 
    [DllImport("user32")] 
    public static extern bool GetCaretPos(out POINT pos); 
    [DllImport("user32")] 
    public static extern bool SetCaretPos(int x, int y); 
    [DllImport("user32")] 
    public static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); 
    public struct POINT { 
     public int x, y; 
    } 
} 
//This is the extension class for TextBox, it's just for convenience 
public static class TextBoxExtension { 
    public static void BeginUpdate(this TextBox text) { 
     Win32.SendMessage(text.Handle, 0xb, IntPtr.Zero, IntPtr.Zero); 
    } 
    public static void EndUpdate(this TextBox text) { 
     Win32.SendMessage(text.Handle, 0xb, new IntPtr(1), IntPtr.Zero); 
    } 
    public static int GetCaretCharIndex(this TextBox text){ 
     Win32.POINT p; 
     Win32.GetCaretPos(out p); 
     return text.GetCharIndexFromPosition(new Point(p.x, p.y)); 
    } 
    public static void SetCaretCharIndex(this TextBox text, int charIndex) { 
     Point p = text.GetPositionFromCharIndex(charIndex); 
     Win32.SetCaretPos(p.X, p.Y); 
    } 
    public static void ProcessRight(this TextBox text, bool shiftPressed) { 
     if (shiftPressed) { 
      int lastEndIndex = text.SelectionStart + text.SelectionLength; 
      int caretCharIndex = text.GetCaretCharIndex(); 
      if (caretCharIndex == lastEndIndex || (caretCharIndex == text.TextLength-1 && text.SelectionLength > 1)){ 
       text.SelectionLength++;      
      } else { 
       text.BeginUpdate(); 
       text.SelectionStart++;      
       if (lastEndIndex < text.TextLength) text.SelectionLength--; 
       text.EndUpdate(); 
       text.Refresh(); 
       if (text.SelectionStart < text.TextLength) text.SetCaretCharIndex(text.SelectionStart); 
      } 
     } else { 
      if (text.SelectionLength > 0) { 
       int s = text.SelectionLength; 
       text.SelectionLength = 0; 
       text.SelectionStart += s; 
      } 
      else if (text.SelectionStart < text.TextLength) text.SelectionStart++; 
     } 
    } 
    public static void ProcessLeft(this TextBox text, bool shiftPressed) { 
     if (shiftPressed) { 
      if (text.GetCaretCharIndex() == text.SelectionStart || text.SelectionStart == text.TextLength) { 
       if (text.SelectionStart > 0) { 
        text.BeginUpdate(); 
        text.SelectionStart--; 
        text.SelectionLength++;                   
        text.EndUpdate(); 
        text.Refresh(); 
        text.SetCaretCharIndex(text.SelectionStart); 
       } 
      } else { 
       text.SelectionLength--; 
      } 
     } else { 
      if (text.SelectionStart > 0 && text.SelectionLength == 0) text.SelectionStart--; 
      text.SelectionLength = 0; 
     } 
    } 
    public static void ProcessHome(this TextBox text, bool shiftPressed) { 
     if (shiftPressed) { 
      int i = text.SelectionStart; 
      text.SelectionStart = 0; 
      text.SelectionLength = i; 
      text.SetCaretCharIndex(0); 
     } else { 
      text.SelectionLength = 0; 
      text.SelectionStart = 0; 
     } 
    } 
    public static void ProcessEnd(this TextBox text, bool shiftPressed) { 
     if (shiftPressed) { 
      text.SelectionLength = text.TextLength - text.SelectionStart; 
     } else { 
      text.SelectionLength = 0; 
      text.SelectionStart = text.TextLength; 
     } 
    } 
    public static void ProcessDelete(this TextBox text) { 
     if (text.SelectionLength == 0) text.SelectionLength = 1; 
     text.SelectedText = ""; 
    } 
} 

//your custom DataGridView 
public class CustomDGV : DataGridView { 
    public event EventHandler InnerTextBoxEnterKeyPress;   
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { 
     TextBox childControl = Controls.OfType<TextBox>().FirstOrDefault(c=>c.Focused); 
     if (childControl != null) {     
      bool suppress = true; 
      switch (keyData) { 
       case Keys.Right: 
        childControl.ProcessRight(false); 
        break; 
       case Keys.Shift | Keys.Right: 
        childControl.ProcessRight(true); 
        break; 
       case Keys.Left: 
        childControl.ProcessLeft(false); 
        break; 
       case Keys.Shift | Keys.Left: 
        childControl.ProcessLeft(true); 
        break; 
       case Keys.End: 
        childControl.ProcessEnd(false); 
        break; 
       case Keys.Home: 
        childControl.ProcessHome(false); 
        break; 
       case Keys.Delete: 
        childControl.ProcessDelete(); 
        break; 
       case Keys.Shift | Keys.End: 
        childControl.ProcessEnd(true); 
        break; 
       case Keys.Shift | Keys.Home: 
        childControl.ProcessHome(true); 
        break; 
       case Keys.Control | Keys.C: 
        childControl.Copy(); 
        break; 
       case Keys.Control | Keys.X: 
        childControl.Cut(); 
        break; 
       case Keys.Control | Keys.V: 
        childControl.Paste(); 
        break; 
       case Keys.Enter: 
        EventHandler handler = InnerTextBoxEnterKeyPress; 
        if (handler != null) InnerTextBoxEnterKeyPress(childControl, EventArgs.Empty); 
        Focus(); 
        break; 
       default: 
        suppress = false; 
        break; 
      }     
      if (suppress) return true;     
     } 
     return base.ProcessCmdKey(ref msg, keyData); 
    }   
} 

注意:我还添加了名为InnerTextBoxEnterKeyPress一个事件,您可以在此事件以执行自己的行为时,注册用户按下Enter键在网格内TextBox,这样的事情:

customDGV1.InnerTextBoxEnterKeyPress += (s,e) => { 
    TextBox text = s as TextBox; 
    //your code goes here ... try showing some message to see it in action 
    MessageBox.Show(text.Text); 
};