tags:

views:

348

answers:

3

I've been assigned to make a custom grid control in C# with windows forms. One thing I'm unsure of is how to handle showing a blinking cursor (caret) to indicate where cell editing is taking place and the next character will be shown.

Does anyone know how this is done with the standard textbox? Is there a standard framework construct that will do this for me?

Obviously I can setup a timer and draw the cursor myself, but I was wondering if there was a better option. Note that this is a completely user drawn control, not a UserControl derivative and that subclassing an existing class is not an option for various reason.

A: 

The MSDN reference about Carets is here. The last time I looked (which was in 2.0 of the framework) carets weren't available as a managed API: and so you need to use the unmanaged API, or paint your own caret.

One thing to remember, when you implement a caret, is that you should not show it whenever your control doesn't have the focus (only one control at a time on the user's desktop, i.e. the control which has the input focus, should ever be showing the input caret).

ChrisW
A: 

Why re-invent the wheel? Just display a textbox when the grid needs editing.

Ok, I see you you use custom drawing, but what prevents you from placing a textbox on over it?

If you wanna go the hard way, Microsoft does have some old libraries that can provide a virtual textarea (or something like that, been a very long).

leppie
+5  A: 

Here you go:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public class MyWidget : Control {
  public MyWidget() {
    this.BackColor = Color.Yellow;
  }
  protected override void OnGotFocus(EventArgs e) {
    CreateCaret(this.Handle, IntPtr.Zero, 2, this.Height - 2);
    SetCaretPos(2, 1);
    ShowCaret(this.Handle);
    base.OnGotFocus(e);
  }
  protected override void OnLostFocus(EventArgs e) {
    DestroyCaret();
    base.OnLostFocus(e);
  }
  [DllImport("user32.dll", SetLastError = true)]
  private static extern bool CreateCaret(IntPtr hWnd, IntPtr hBmp, int w, int h);
  [DllImport("user32.dll", SetLastError = true)]
  private static extern bool SetCaretPos(int x, int y);
  [DllImport("user32.dll", SetLastError = true)]
  private static extern bool ShowCaret(IntPtr hWnd);
  [DllImport("user32.dll", SetLastError = true)]
  private static extern bool DestroyCaret();
}

I'll gladly pass the buck on figuring out where to put it.

Hans Passant
Perfect, thanks!
Bearddo