65.9K
CodeProject is changing. Read more.
Home

KeyState Struct Objectifies KeyState Property

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.30/5 (9 votes)

Feb 15, 2003

1 min read

viewsIcon

60611

downloadIcon

445

A KeyState struct to objectify the KeyState property of DragEventArgs.

Introduction

In order to make programs more readable and therefore more maintainable, I am always on the lookout for ways to hide messy implementation details. While adding drag and drop functionality to a TreeView, I found such an opportunity. The DragEventArgs (or QueryContinueDragEventArgs) parameter to the OnDrag... event methods, exposes the state of the control keys and mouse buttons as bits packed into a hard-working int. While this is a clever way to pack a lot of info into one property, cleverness seldom wins maintainability awards. Unless one programs these events often or has a prodigious memory, they will not be able to remember which bit is the Shift bit or middle mouse button bit. This led me to write a small struct to encapsulate this naked bit-bashing and add what probably should have been included in the framework.

Background

I won't bore the reader with which bit is which (say that three times fast: which bit's which) a quick search of the help file for KeyState will yield that. This KeyState struct does what would normally be done in event code:

protected override void OnDragOver(DragEventArgs e)
    // If the Shift key is pressed...
    if (e.KeyState & 4)
    {
        ...
    }

And removes those details to the struct innards, to be replaced with code which is more self-documenting:

protected override void OnDragOver(DragEventArgs e)
    KeyState keyState = new KeyState (e.KeyState)
    if (keyState.Shift)
    {
       ...
    }

Or, the static methods (overloaded for both DragEventArgs and QueryContinueDragEventArgs may be employed:

protected override void OnDragOver(DragEventArgs e)
    if (KeyState.IsShiftPressed (e))
    {
        ...
    }

Using the code

The struct is a snap to use. It receives an integer in its constructor which is a KeyState property from a DragEventArgs object. Then all the key states packed into the value are exposed as properties.

protected override void OnDragOver(DragEventArgs e)
{
    KeyState keyState = new KeyState (e.KeyState);

    if (keyState.Shift)
        e.AllowedEffect = DragDropEffects.Move;
    else if (keyState.Ctrl)
        e.AllowedEffect = DragDropEffects.Copy;
    else
        e.AllowedEffect = DragDropEffects.Scroll;
}

Alternatively, using the static methods:

protected override void OnDragOver(DragEventArgs e)
{
    if (KeyState.IsShiftPressed (e))
        e.AllowedEffect = DragDropEffects.Move;
    else if (KeyState.IsCtrlPressed (e))
        e.AllowedEffect = DragDropEffects.Copy;
    else
        e.AllowedEffect = DragDropEffects.Scroll;
}

History

  • May 15, 2003: Thanks to the excellent suggestion of allancto, I added support for static methods.
  • February 16, 2003: After submission, I felt the article inadequate and needed elaboration.
  • February 15, 2003: Submitted.