Windows Vista以降で使えるAddClipboardFormatListener
(Win32 API)を使うと簡単にクリップボード監視できるみたい。
watch_clipboard.go
package main
import (
"fmt"
"syscall"
"unsafe"
"github.com/AllenDang/w32"
)
func getClipText() (string, error) {
if w32.OpenClipboard(0) {
defer w32.CloseClipboard()
hclip := w32.HGLOBAL(w32.GetClipboardData(w32.CF_UNICODETEXT))
if hclip == 0 {
return "", fmt.Errorf("GetClipboardData")
}
lpstr := w32.GlobalLock(hclip)
defer w32.GlobalUnlock(hclip)
return w32.UTF16PtrToString((*uint16)(lpstr)), nil
}
return "", fmt.Errorf("OpenClipboard")
}
func wndProc(hwnd w32.HWND, msg uint32, wParam, lParam uintptr) uintptr {
if msg == w32.WM_CLIPBOARDUPDATE {
text, err := getClipText()
if err != nil {
fmt.Println("error:", err)
return 0
}
fmt.Println("clipdata:", text)
return 0
}
return w32.DefWindowProc(hwnd, msg, wParam, lParam)
}
func main() {
className := syscall.StringToUTF16Ptr("for clipboard")
wndClassEx := w32.WNDCLASSEX{
ClassName: className,
WndProc: syscall.NewCallback(wndProc),
}
wndClassEx.Size = uint32(unsafe.Sizeof(wndClassEx))
w32.RegisterClassEx(&wndClassEx)
// Message-Only Window
hwnd := w32.CreateWindowEx(0, className, className, 0, 0, 0, 0, 0, w32.HWND_MESSAGE, 0, 0, nil)
w32.AddClipboardFormatListener(hwnd)
defer w32.RemoveClipboardFormatListener(hwnd)
msg := w32.MSG{}
for w32.GetMessage(&msg, 0, 0, 0) > 0 {
w32.DispatchMessage(&msg)
}
}
メッセージ受信用のウィンドウを作る
AddClipboardFormatListener
を使うにはウィンドウハンドルが必要なので、main
の中でメッセージ受信用の非表示のウィンドウを作っています。
WNDCLASSEX
にはClassName
,WndProc
,Size
がないとRegisterClassEx
かCreateWindowEx
で失敗します。
なお、className
は適当な文字列で大丈夫です。
WM_CLIPBOARDUPDATE メッセージを受信する
受信用のコールバック関数wndProc
でメッセージを受信しています。
クリップボードの変更があるたびにgetClipText()で取得した内容を表示しています。
クリップボードからテキストを取得する
CF_UNICODETEXT
を指定して取得したハンドルを使ってデータ取得しています。
CF_TEXT
を指定した場合は文字化けしまくりでした。