1Option Explicit
23' WindowsAPI宣言
4' 各APIの詳細は (http://wisdom.sakura.ne.jp/system/winapi/win32/win90.html) を参照のこと
5Private Declare Function OpenClipboard Lib "user32.dll" (ByVal hWnd As Long) As Long
6Private Declare Function EmptyClipboard Lib "user32.dll" () As Long
7Private Declare Function CloseClipboard Lib "user32.dll" () As Long
8Private Declare Function IsClipboardFormatAvailable Lib "user32.dll" (ByVal wFormat As Long) As Long
9Private Declare Function GetClipboardData Lib "user32.dll" (ByVal wFormat As Long) As Long
10Private Declare Function SetClipboardData Lib "user32.dll" (ByVal wFormat As Long, ByVal hMem As Long) As Long
11Private Declare Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
12Private Declare Function GlobalLock Lib "kernel32.dll" (ByVal hMem As Long) As Long
13Private Declare Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As Long) As Long
14Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
15Private Declare Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyW" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long
1617' WindowsAPI゛て使用する定数宣言
18Private Const GMEM_MOVEABLE As Long = &H2
19Private Const GMEM_ZEROINIT As Long = &H40
20Private Const CF_UNICODETEXT As Long = &HD
212223Public Sub Test()
2425 ' クリップボードにテキストを設定
26 Call SetClipboard("テストテキスト")
2728 ' クリップボードのテキストを取得してイミディエイトウインドウに出力
29 Debug.Print GetClipboard
3031End Sub
3233' 文字列をクリップボードにコピーします
34' 本処理は DataObject を使用することで意図しない文字列がクリップボードに貼りつくことがあるため
35' DataObject を使用せずに WindowsAPI を使用した処理で実装する
36' また、処理中はメモリのロックを実施するため、本処理中で強制終了しないようにすること
37Public Sub SetClipboard(ByRef sUniText As String)
3839 ' 変数宣言
40 Dim iStrPtr As Long
41 Dim iLen As Long
42 Dim iLock As Long
4344 ' クリップボードを開く (開けなかった場合はエラーをスロー)
45 If OpenClipboard(0&) = 0 Then
46 ' 実は開けていた場合に備えて閉じる処理を呼び出す
47 On Error Resume Next
48 Call CloseClipboard
49 On Error GoTo 0
50 Err.Raise 1000, , "クリップボードを開けませんでした"
51 End If
5253 ' クリップボードを空にする (失敗した場合はクリップボードを閉じてエラーをスロー)
54 If EmptyClipboard = 0 Then
55 On Error Resume Next
56 Call CloseClipboard
57 On Error GoTo 0
58 Err.Raise 1000, , "クリップボードを空にできませんでした"
59 End If
6061 ' 確保するメモリ領域を取得 (終端文字ワイド文字列 分も確保するために2バイト多く確保)
62 iLen = LenB(sUniText) + 2&
6364 ' ヒープから指定されたバイト数のメモリを確保 (失敗した場合はクリップボードを閉じてエラーをスロー)
65 iStrPtr = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, iLen)
66 If iStrPtr = Null Then
67 On Error Resume Next
68 Call CloseClipboard
69 On Error GoTo 0
70 Err.Raise 1000, , "メモリの確保に失敗しました"
71 End If
7273 ' グローバルメモリオブジェクトをロックし、メモリブロックの先頭へのポインタを取得
74 iLock = GlobalLock(iStrPtr)
75 If iLock = Null Then
76 On Error Resume Next
77 Call CloseClipboard
78 On Error GoTo 0
79 Err.Raise 1000, , "メモリのロックに失敗しました"
80 End If
8182 ' 指定された文字列を、メモリにコピー
83 If lstrcpy(iLock, StrPtr(sUniText)) = Null Then
84 On Error Resume Next
85 Call CloseClipboard
86 On Error GoTo 0
87 Err.Raise 1000, , "メモリのコピーに失敗しました"
88 End If
8990 ' グローバルメモリオブジェクトのロックカウントを減らします
91 ' 0以外が返却された場合はロックが解放されなかったとしてエラーをスローします
92 If GlobalUnlock(iStrPtr) <> 0 Then
93 On Error Resume Next
94 Call CloseClipboard
95 On Error GoTo 0
96 Err.Raise 1000, , "メモリのアンロックに失敗しました"
97 End If
9899 ' クリップボードに、指定されたデータ形式でデータを格納
100 If SetClipboardData(CF_UNICODETEXT, iStrPtr) = Null Then
101 On Error Resume Next
102 Call CloseClipboard
103 On Error GoTo 0
104 Err.Raise 1000, , "クリップボードにデータを格納できませんでした"
105 End If
106107 ' クリップボードを閉じる
108 If CloseClipboard = 0 Then
109 Err.Raise 1000, , "クリップボードをクローズできませんでした"
110 End If
111112End Sub
113114' クリップボードからテキストを取得します
115' テキストを取得する処理においては DataObject を使用しても問題が発生しないことから
116' WindowsAPI を使用しない実装とします
117Public Function GetClipboard() As String
118119 With New DataObject
120 .GetFromClipboard
121 GetClipboard = .GetText
122 End With
123124End Function
125