tags:

views:

135

answers:

2

I want to make a button that acts with the keyboard as with the mouse. I'm implementing it this way:

class FunctionButton : System.Windows.Forms.Button
{
    public FunctionButton() : base() { }

    protected override void OnGotFocus(EventArgs e)
    {
        OnMouseEnter(null);
        base.OnGotFocus(e);
    }

    protected override void OnLostFocus(EventArgs e)
    {
        OnMouseLeave(null);
        base.OnLostFocus(e);
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        if (!Focused)
        {
            base.OnMouseLeave(e);
        }
    }

    public void FunctionKeyPressed()
    {
        OnMouseDown(new MouseEventArgs(MouseButtons.Left,1,0,0,0));
        PerformClick();
    }

    public void FunctionKeyReleased()
    {
        if (Focused)
        {
            OnMouseEnter(null);
        }
        else
        {
            base.OnMouseLeave(null);
        }
    }
}

I don't know how to get a valid click position for this button to generate de event

OnMouseDown(new MouseEventArgs(MouseButtons.Left,1,X,Y,0));

How can I do this? Is the better way to implement this kind of button?

A: 

If I understand you question correctly, you are creating a control that will show a button that the user can click, and that will also be bound to a function key that should invoke the same command.

I would believe that the simplest (although perhaps a slightly "hacky") way to do this, is to create a UserControl, add a MenuStrip control to your user control, add a ToolStripMenuItem to the MenuStrip control and set up a Click event handler, and set the Visible property of the MenuStrip to false. Also add a button to the user control, and set up a Click event handler for that one. Have both event handlers call some method to perform the action, and finally create a ShortcutKeys property reflecting the ShortcutKeys property of the menu item:

public partial class FunctionButton : UserControl
{
    public FunctionButton()
    {
        InitializeComponent();
    }

    private void MenuItem_Click(object sender, EventArgs e)
    {
        PerformCommand();            
    }

    private void Button_Click(object sender, EventArgs e)
    {
        PerformCommand();
    }

    private void PerformCommand()
    {
        OnClick(EventArgs.Empty);
    }

    public Keys ShortcutKeys
    {
        get
        {
            return _menuItem.ShortcutKeys;
        }
        set
        {
            _menuItem.ShortcutKeys = value;
        }
    }
}

In my sample the click event handlers will simply raise the Click event of the user control, so that the consumer can attach an event handler to that event and act on it.

Fredrik Mörk
A: 

Finally I implemented the button changing the background:

class FunctionButton : Button
{
    private Color m_colorOver;
    private bool m_isPressed;

    public FunctionButton() : base()
    {
        m_isPressed = false;
    }

    protected override void OnGotFocus(EventArgs e)
    {
        OnMouseEnter(null);
        base.OnGotFocus(e);
    }

    protected override void OnLostFocus(EventArgs e)
    {
        if (!m_isPressed)
        {
            OnMouseLeave(null);
        }

        base.OnLostFocus(e);
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        if (!Focused && !m_isPressed)
        {
            base.OnMouseLeave(e);
        }
    }

    public void FunctionKeyPressed()
    {
        // Handle just the first event
        if (!m_isPressed)
        {
            m_isPressed = true;
            m_colorOver = FlatAppearance.MouseOverBackColor;
            FlatAppearance.MouseOverBackColor = FlatAppearance.MouseDownBackColor;

            OnMouseEnter(null);
            PerformClick();    
        }
    }

    public void FunctionKeyReleased()
    {
        m_isPressed = false;
        FlatAppearance.MouseOverBackColor = m_colorOver;

        if (Focused)
        {
            OnMouseEnter(null);
        }
        else
        {
            base.OnMouseLeave(null);
        }
    }
}

It is not the most clean way but it works fine. I would like more examples doing this with a cleaner and more elegant style.

yeyeyerman