LoginSignup
7
8

More than 5 years have passed since last update.

Goでクリップボード監視をする(Windows Vista以降)

Posted at

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がないとRegisterClassExCreateWindowExで失敗します。

なお、classNameは適当な文字列で大丈夫です。

WM_CLIPBOARDUPDATE メッセージを受信する

受信用のコールバック関数wndProcでメッセージを受信しています。
クリップボードの変更があるたびにgetClipText()で取得した内容を表示しています。

クリップボードからテキストを取得する

CF_UNICODETEXTを指定して取得したハンドルを使ってデータ取得しています。
CF_TEXTを指定した場合は文字化けしまくりでした。

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8