none
フォームのタイトルバーの文字列をクリックしたときのイベント RRS feed

  • 質問

  • VisualStdio2008 VB.netを使っております。

    フォームのタイトルバーの文字をクリックした際の動作を追加したいのですが、可能でしょうか?

    できるのであればどうすれば可能かご教授いただけますか?

    よろしくお願いします。

    2015年7月9日 7:16

回答

  • 文字列上となると、ちょっと厳しいと思います・・・
    発想を変えて、タイトルバー自体を無くしてしまい、タイトルバーのようなものを自分で付けるというのは・・・

    (参考)
    Windowsフォーム関連 > フォーム関連 > タイトルバーなし
    http://www.mitchy-world.jp/dotnet/WindowsForm/Form_Form04.htm


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答の候補に設定 星 睦美 2015年7月22日 5:18
    • 回答としてマーク 星 睦美 2015年7月27日 4:37
    2015年7月9日 8:47
    モデレータ
  • タイトル文字を消した状態と表示した状態とでマウス近辺をキャプチャして、差があれば文字の近くにあると判定してみる

    Public Class Form1
        Protected Overrides Sub WndProc(ByRef m As Message)
            Const WM_NCLBUTTONDOWN As Integer = &HA1
            Const HTCAPTION As Integer = 2
            If (m.Msg = WM_NCLBUTTONDOWN) Then
                If (m.WParam = HTCAPTION) Then
    
                    Dim title As String = Me.Text
                    Me.Text = ""
                    Dim bytes1 As Byte() = GetCapture()
                    Me.Text = title
                    Dim bytes2 As Byte() = GetCapture()
    
                    If (Not bytes1.SequenceEqual(bytes2)) Then
                        MessageBox.Show("Hit")
                    End If
                End If
            End If
            MyBase.WndProc(m)
        End Sub
    
        Private Function GetCapture() As Byte()
            Dim bmp1 As New Bitmap(20, 20, Imaging.PixelFormat.Format32bppArgb)
            Using g = System.Drawing.Graphics.FromImage(bmp1)
                Dim pos = MousePosition
                pos.X -= bmp1.Width / 2
                pos.Y -= bmp1.Height / 2
                g.CopyFromScreen(pos, Point.Empty, bmp1.Size)
            End Using
            Dim lock1 As System.Drawing.Imaging.BitmapData = bmp1.LockBits(New Rectangle(0, 0, 20, 20), Imaging.ImageLockMode.ReadOnly, bmp1.PixelFormat)
            Dim bs1 As Byte() = New Byte(lock1.Stride * lock1.Height - 1) {}
            System.Runtime.InteropServices.Marshal.Copy(lock1.Scan0, bs1, 0, bs1.Length)
            bmp1.UnlockBits(lock1)
            Return bs1
        End Function
    End Class
    チラついてしまうので、事前にタイトルバー全域の表示と非表示の差分を取っておいて位置を探っておいた方がいいですね

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2015年7月9日 10:21
    • 回答の候補に設定 星 睦美 2015年7月22日 5:18
    • 回答としてマーク 星 睦美 2015年7月27日 4:37
    2015年7月9日 10:18

すべての返信

  • 具体例として、同様の動作をするアプリケーションやもしくはヒントとなった類似動作をするアプリケーションを挙げてみませんか? それとも誰も思いつかなかった革新的な動作を追加しようとお考えなのでしょうか?
    2015年7月9日 7:19
  • 失礼いたしました。

    具体例ですと、フォーム1のタイトルバーにある文字列を起動するとMessageboxが現れるという感じです。

    2015年7月9日 7:26
  • 「文字列を起動」って全くイメージが湧きませんが……。

    その操作の対象は、ご自分で作成中のアプリケーションが表示しているフォームということでいいですか? Windows上で実行中の任意のウィンドウと言うことになると、正直なところ諦めてくださいとしか言えません。

    あと、そのUIだと「タイトルバーのドラッグでウィンドウを動かせる」というWindowsのウィンドウアプリケーションとしての基本操作が損なわれるかと思いますが大丈夫ですかね……。

    さて、とりあえず、目的のフォームのWndProcをオーバーライドするなりして、WM_NCLBUTTONDOWNを処理することで、タイトルバーやアイコン、上下左右のボーダー、右上の各種ボタン上でマウス左ボタン押下したときに反応することはできます。(タッチ操作の時にどうなるかは未検証)

    このとき、WParamの値を確認すれば、それがタイトルバー(フォーム最上部の内、アイコン、ボーダー、各種ボタンの領域を除いた部分)であるかどうかを判定することはできます。

    ただ、それが表示している文字列の上かどうかまで必要だとすると、なかなか難しいかもしれません。

    2015年7月9日 7:44
  • 感謝とともに自分の説明下手さを謝します。

    サイズ・位置ともに変更できないフォーラムを作成しました。

    そこで、そのフォーラムのタイトルバーにある文字列をクリックした際にメッセージボックスが現れる、といった感じにしたいのです。

    ご説明の通り、タイトルバーであるかをWParamで判断しまして実行するというところまではできたのですが

    文字列の上かどうかという判断がどうも思いつかなくて困っている、といったところです。

    ですが、厳しそうですね…もうすこし考えてみます。

    2015年7月9日 7:51
  • 文字列上となると、ちょっと厳しいと思います・・・
    発想を変えて、タイトルバー自体を無くしてしまい、タイトルバーのようなものを自分で付けるというのは・・・

    (参考)
    Windowsフォーム関連 > フォーム関連 > タイトルバーなし
    http://www.mitchy-world.jp/dotnet/WindowsForm/Form_Form04.htm


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答の候補に設定 星 睦美 2015年7月22日 5:18
    • 回答としてマーク 星 睦美 2015年7月27日 4:37
    2015年7月9日 8:47
    モデレータ
  • タイトル文字を消した状態と表示した状態とでマウス近辺をキャプチャして、差があれば文字の近くにあると判定してみる

    Public Class Form1
        Protected Overrides Sub WndProc(ByRef m As Message)
            Const WM_NCLBUTTONDOWN As Integer = &HA1
            Const HTCAPTION As Integer = 2
            If (m.Msg = WM_NCLBUTTONDOWN) Then
                If (m.WParam = HTCAPTION) Then
    
                    Dim title As String = Me.Text
                    Me.Text = ""
                    Dim bytes1 As Byte() = GetCapture()
                    Me.Text = title
                    Dim bytes2 As Byte() = GetCapture()
    
                    If (Not bytes1.SequenceEqual(bytes2)) Then
                        MessageBox.Show("Hit")
                    End If
                End If
            End If
            MyBase.WndProc(m)
        End Sub
    
        Private Function GetCapture() As Byte()
            Dim bmp1 As New Bitmap(20, 20, Imaging.PixelFormat.Format32bppArgb)
            Using g = System.Drawing.Graphics.FromImage(bmp1)
                Dim pos = MousePosition
                pos.X -= bmp1.Width / 2
                pos.Y -= bmp1.Height / 2
                g.CopyFromScreen(pos, Point.Empty, bmp1.Size)
            End Using
            Dim lock1 As System.Drawing.Imaging.BitmapData = bmp1.LockBits(New Rectangle(0, 0, 20, 20), Imaging.ImageLockMode.ReadOnly, bmp1.PixelFormat)
            Dim bs1 As Byte() = New Byte(lock1.Stride * lock1.Height - 1) {}
            System.Runtime.InteropServices.Marshal.Copy(lock1.Scan0, bs1, 0, bs1.Length)
            bmp1.UnlockBits(lock1)
            Return bs1
        End Function
    End Class
    チラついてしまうので、事前にタイトルバー全域の表示と非表示の差分を取っておいて位置を探っておいた方がいいですね

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2015年7月9日 10:21
    • 回答の候補に設定 星 睦美 2015年7月22日 5:18
    • 回答としてマーク 星 睦美 2015年7月27日 4:37
    2015年7月9日 10:18