2023/01/02

KeyPreviewはあるがMousePreviewが無い

 元日はだらだらと生産的な作業はせずのんびりと過ごしました。が、今日からは気合入れて挑んでます。マウスの[進む][戻る]ボタン対応をアプリに実装する処理を考えてました。フォームのMouseDownイベントハンドラ追加しても、フォーム上のコントロールが置かれている場所では先にコントールのイベントに行くらしくフォールのイベントハンドラには飛んでこない。グーグル先生に聞くともう10年以上前から多くの方が悩んでるのが分かる。しかも、具体的な解決策はねぇ~orz

フォーム上に配置した全てのコントロールにイベントハンドラ追加すれば問題は解決するんだと思うが当然多くの方はスマートな方法ではないと判断して苦労している模様。まあ、そんな事はMSは関知せずかな。まあ、実装においてそれで実現しておけばしのげるのは確かかと。

private void RedirectMouseDown(object sender, MouseEventArgs e)
{
    Control control = (Control)sender;
    Point screenPoint = control.PointToScreen(new Point(e.X, e.Y));
    Point formPoint = PointToClient(screenPoint);
    MouseEventArgs args = new MouseEventArgs(e.Button, e.Clicks,formPoint.X, formPoint.Y, e.Delta);
    OnMouseDown(args);
}
これを定義しておいてフォームのLoadイベント内で
foreach (Control control in Controls)
{
    control.MouseDown += RedirectMouseDown;
}
ってすれば、まあ、取敢えず機能するっぽい。

追記 2023.1.3 10:39
新年早々甘かったorz 上記のControlsコレクションにはコンテナタイプのコントロールだと内部の物には適応されないです。なので再帰的に全てのコントロールを取得するメソッドを用意してイベントハンドラを追加する必要がありました。

private Control[] GetAllControls(Control tc)
{
    ArrayList al = new ArrayList();
    foreach (Control c in tc.Controls)
    {
        al.Add(c);
        al.AddRange(GetAllControls(c));
    }
    return (Control[])al.ToArray(typeof(Control));
}
としてフォームのLoadでは
Control[] allControls = GetAllControls(this);
foreach (Control control in allControls)
と修正する。

0 件のコメント:

コメントを投稿