2008年9月30日火曜日

[.NET]普通のボタンにショートカットキーを割り当てる(その2)

先日ダミーのメニューを使ったボタンのショートカット機能ですが、別の方法として、ErrorProviderっぽい実装ができないか考えてみました。実装してみるとそれらしく動作しました。

コンポーネントなので、デザイナーのFormにドロップすればよいのですが、TargetForm(ComponetからFormを取得す方法がわからない)とKeyPreviewプロパティをそれらしく設定する必要があります。
FormのKeyPreviewの代わりに、このコンポーネントのKeyPreviewをTrueにすると、初期化時にTargetFormのTargetFormをそれらしく設定します。

/// <summary>
/// ショートカットキー機能を付加するExtenderProvide
/// </summary>
[ProvideProperty("ShortcutKeys"typeof(Control))]
public partial class ShortcutKeyProvider : ComponentIExtenderProviderISupportInitialize
{
    /// <summary>
    /// 情報格納エリア
    /// </summary>
    private Dictionary<KeysControlextInfo = new Dictionary<KeysControl>();
    
    private Form targetForm = null;
    /// <summary>
    /// 対象のForm
    /// </summary>
    [Description("ショートカットを有効にする対象のform")]
    public Form TargetForm
    {
        get { return targetForm; }
        set { targetForm = value; }
    }

    private bool keyPreview = true;
    /// <summary>
    /// キーイベントの設定
    /// </summary>
    /// <remarks>FormのKeyPreviewがFalseの場合、この値をFormのKeyPreviewに設定します</remarks>
    [Description("キーボードイベントがフォームとともに登録されるかを決定します")]
    public bool KeyPreview
    {
        get { return keyPreview; }
        set { keyPreview = value; }
    }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public ShortcutKeyProvider()
    {
        InitializeComponent();
    }

    /// <summary>
    /// コンテナ指定付コンストラクタ
    /// </summary>
    /// <param name="container">コンテナ</param>
    public ShortcutKeyProvider(IContainer container)
    {
        container.Add(this);

        InitializeComponent();
    }

    #region ISupportInitialize メンバ

    /// <summary>
    /// 初期化の開始
    /// </summary>
    public void BeginInit()
    {
    }

    /// <summary>
    /// 初期化の終了
    /// </summary>
    public void EndInit()
    {
        //キー押下イベントを設定
        if (TargetForm != null)
        {
            TargetForm.KeyDown += new KeyEventHandler(TargetForm_KeyDown);
            if (TargetForm.KeyPreview == false)
            {
                System.Diagnostics.Debug.WriteLine("****FORMのKeyPreviewを変更します!! ==> " + KeyPreview);
                TargetForm.KeyPreview = KeyPreview;
            }
        }
    }

    #endregion



    #region IExtenderProvider メンバ

    bool IExtenderProvider.CanExtend(object extendee)
    {
        //ボタンのみ対応する.対応するコントロールを増やすならここに追加
        return extendee is Button;
    }

    #endregion

    /// <summary>
    /// ショートカットキーの取得
    /// </summary>
    /// <param name="ctrl">該当のコントロール</param>
    /// <returns>キー</returns>
    [Description("このコントロールに割り当てたいショートカットキーを設定・取得します")]
    [DefaultValue(typeof(Keys), "None")]
    public Keys GetShortcutKeys(Control control)
    {
        return GetKeysByControl(control);
    }

    /// <summary>
    /// ショートカットキーの設定
    /// </summary>
    /// <param name="ctrl">該当のコントロール</param>
    /// <param name="value">割り当てられたキー</param>
    [Description("このコントロールに割り当てたいショートカットキーを設定・取得します")]
    public void SetShortcutKeys(Control controlKeys shortcutKey)
    {
        //キーがほかに割り当て済みの場合、例外とする
        Control checkCtrl;
        if (extInfo.TryGetValue(shortcutKeyout checkCtrl))
        {
            if (checkCtrl != control)
            {
                throw new ArgumentException("ショートカットキー重複 " + checkCtrl.ToString());
            }
        }
        
        //登録済みの場合削除
        Keys key = GetKeysByControl(control);
        if (key != Keys.None)
        {
            //MAPより削除する
            extInfo.Remove(key);
        }

        //指定されたキーがNone以外の場合、MAPに格納する
        if (shortcutKey != Keys.None)
        {
            extInfo.Add(shortcutKeycontrol);
        }

    }

    /// <summary>
    /// キーとコントロールの変換
    /// </summary>
    /// <param name="key">コントロール</param>
    /// <returns>対応付けられたショートカットキー</returns>
    private Keys GetKeysByControl(Control control)
    {
        Keys result = Keys.None;
        foreach (Keys key in extInfo.Keys)
        {
            //コントロールからショートカットキーを割り出す
            if (extInfo[key] == control)
            {
                result = key;
                break;
            }
        }

        return result;
    }

    /// <summary>
    /// キー押下イベント
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void TargetForm_KeyDown(object senderKeyEventArgs e)
    {
        Control control = null;
        if (extInfo.TryGetValue(e.KeyDataout control))
        {
            if (control != null && control.Enabled == true)
            {
                ((Button)control).PerformClick();
            }
        }
        
    }

}


partial class ShortcutKeyProvider
{
    /// <summary>
    /// 必要なデザイナ変数です。
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// 使用中のリソースをすべてクリーンアップします。
    /// </summary>
    /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region コンポーネント デザイナで生成されたコード

    /// <summary>
    /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
    /// コード エディタで変更しないでください。
    /// </summary>
    private void InitializeComponent()
    {
        components = new System.ComponentModel.Container();
    }

    #endregion
}

0 件のコメント: