クリップボードの履歴が見れるアプリ

さっき書いた記事の内容を元に、クリップボードの履歴を監視するアプリを作ってます。こんなアプリを想定してます。

  • クリップボードの履歴をn件まで確認できる
  • 過去にクリップした内容を再びクリップできる
  • 文字をコピーしたら文字を表示
  • ファイルをコピーしたらファイルをアイコン付きで表示
  • イメージをコピーしたらイメージを表示

もうだいたい出来てるんだけど、デザインが気にくわなくてなかなか完成しません・・・。用途を考えるとウィンドウのサイズが大き過ぎない方がいいけど、クリップボードの履歴をテキストとか画像を付けて具体的に表示するんだったら結構スペース取っちゃうんですよね。うーん。

クリップボードの監視

個人的なメモ。WindowsAPIを利用してクリップボードが更新されると通知される仕組み。元の記事のほぼパクリ

元の記事との違いは拾ってこれるクリップボードの内容を単なるテキストから、IDataObjectに対応させた。これによって様々な形式のクリップボードを拾ってこれる

まずイベント引数のクラス

Public Class ClipboardEventArgs
    Inherits EventArgs
    Private _clipData As IDataObject

    Public ReadOnly Property ClipData() As IDataObject
        Get
            Return Me._clipData
        End Get
    End Property

    Public Sub New(ByVal clipData As IDataObject)
        Me._clipData = clipData
    End Sub
End Class

クリップボードを監視するためのクラス

Imports System.Runtime.InteropServices

Public Delegate Sub ClipboardEventHandler(ByVal sender As Object, _
     ByVal ev As ClipboardEventArgs)

<System.Security.Permissions.PermissionSet( _
    System.Security.Permissions.SecurityAction.Demand, _
    Name:="FullTrust")> _
Friend Class MyClipboardViewer
    Inherits NativeWindow

    <DllImport("user32")> _
    Public Shared Function SetClipboardViewer( _
        ByVal hWndNewViewer As IntPtr) As IntPtr
    End Function

    <DllImport("user32")> _
    Public Shared Function ChangeClipboardChain( _
        ByVal hWndRemove As IntPtr, _
        ByVal hWndNewNext As IntPtr) As Boolean
    End Function

    <DllImport("user32")> _
    Public Shared Function SendMessage( _
        ByVal hWnd As IntPtr, ByVal Msg As Integer, _
        ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    End Function

    Private Const WM_DRAWCLIPBOARD As Integer = &H308
    Private Const WM_CHANGECBCHAIN As Integer = &H30D
    Private nextHandle As IntPtr


    Public Event ClipboardHandler As ClipboardEventHandler

    Public Sub New(ByVal parent As Form)
        AddHandler parent.HandleCreated, AddressOf Me.OnHandleCreated
        AddHandler parent.HandleDestroyed, AddressOf Me.OnHandleDestroyed

    End Sub

    Friend Sub OnHandleCreated(ByVal sender As Object, ByVal e As EventArgs)
        AssignHandle(DirectCast(sender, Form).Handle)
        ' ビューアを登録
        nextHandle = SetClipboardViewer(Me.Handle)
    End Sub

    Friend Sub OnHandleDestroyed(ByVal sender As Object, ByVal e As EventArgs)
        ' ビューアを解除
        Dim sts As Boolean = ChangeClipboardChain(Me.Handle, nextHandle)
        ReleaseHandle()
    End Sub

    Protected Overloads Overrides Sub WndProc(ByRef msg As Message)
        Select Case msg.Msg

            Case WM_DRAWCLIPBOARD
                RaiseEvent ClipboardHandler(Me, New ClipboardEventArgs(Clipboard.GetDataObject()))

                If CInt(nextHandle) <> 0 Then
                    SendMessage(nextHandle, msg.Msg, msg.WParam, msg.LParam)
                End If
                Exit Select

                ' クリップボード・ビューア・チェーンが更新された
            Case WM_CHANGECBCHAIN
                If msg.WParam = nextHandle Then
                    nextHandle = msg.LParam
                ElseIf CInt(nextHandle) <> 0 Then
                    SendMessage(nextHandle, msg.Msg, msg.WParam, msg.LParam)
                End If
                Exit Select

        End Select
        MyBase.WndProc(msg)
    End Sub
End Class