Skip to content

Instantly share code, notes, and snippets.

@kurogelee
Created October 9, 2016 18:25
Show Gist options
  • Save kurogelee/8e034bece098006b359d61f0a75a3928 to your computer and use it in GitHub Desktop.
Save kurogelee/8e034bece098006b359d61f0a75a3928 to your computer and use it in GitHub Desktop.
Goでクリップボードにテキスト/ファイルリストの読み書きをする(Windows) ref: http://qiita.com/kurogelee/items/862c4e653103808f901d
package main
import (
"fmt"
"syscall"
"unsafe"
"github.com/AllenDang/w32"
)
// #include <string.h>
import "C"
type clipboardFormat uint
const (
textFormat clipboardFormat = w32.CF_UNICODETEXT
fileListFormat clipboardFormat = w32.CF_HDROP
)
func isAvailable(format clipboardFormat) bool {
return w32.IsClipboardFormatAvailable(uint(format))
}
func getText() (string, error) {
if w32.OpenClipboard(0) {
defer w32.CloseClipboard()
hclip := w32.HGLOBAL(w32.GetClipboardData(w32.CF_UNICODETEXT))
if hclip == 0 {
return "", fmt.Errorf("GetClipboardData")
}
u16pstr := w32.GlobalLock(hclip)
defer w32.GlobalUnlock(hclip)
return w32.UTF16PtrToString((*uint16)(u16pstr)), nil
}
return "", fmt.Errorf("OpenClipboard")
}
func getFileList() ([]string, error) {
if w32.OpenClipboard(0) {
defer w32.CloseClipboard()
hclip := w32.HDROP(w32.GetClipboardData(w32.CF_HDROP))
if hclip == 0 {
return nil, fmt.Errorf("GetClipboardData")
}
_, count := w32.DragQueryFile(hclip, 0xffffffff)
files := make([]string, count)
for i := uint(0); i < count; i++ {
files[i], _ = w32.DragQueryFile(hclip, i)
}
return files, nil
}
return nil, fmt.Errorf("OpenClipboard")
}
func setText(text string) error {
if w32.OpenClipboard(0) {
defer w32.CloseClipboard()
u16str, err := syscall.UTF16FromString(text)
if err != nil {
return fmt.Errorf("UTF16FromString")
}
hmem := w32.GlobalAlloc(w32.GHND, uint32(2*len(u16str)))
outPstr := w32.GlobalLock(hmem)
defer w32.GlobalUnlock(hmem)
w32.Lstrcpy((*[1]uint16)(outPstr)[:], &u16str[0])
w32.EmptyClipboard()
w32.SetClipboardData(w32.CF_UNICODETEXT, w32.HANDLE(hmem))
}
return fmt.Errorf("OpenClipboard")
}
func buildU16files(files []string) ([]uint16, error) {
var u16files []uint16
for _, s := range files {
u16str, err := syscall.UTF16FromString(s)
if err != nil {
return nil, fmt.Errorf("UTF16FromString")
}
u16files = append(u16files, u16str...)
}
u16files = append(u16files, 0)
return u16files, nil
}
func setFileList(files []string) error {
if w32.OpenClipboard(0) {
defer w32.CloseClipboard()
u16files, err := buildU16files(files)
if err != nil {
return err
}
type POINT struct {
x int32
y int32
}
type DROPFILES struct {
pFiles w32.DWORD
pt POINT
fNC w32.BOOL
fWide w32.BOOL
}
dfiles := DROPFILES{fWide: w32.BoolToBOOL(true)}
dfiles.pFiles = w32.DWORD(unsafe.Sizeof(dfiles))
hmem := w32.GlobalAlloc(w32.GHND, uint32(dfiles.pFiles)+uint32(2*len(u16files)))
outFiles := w32.GlobalLock(hmem)
defer w32.GlobalUnlock(hmem)
C.memcpy(outFiles, unsafe.Pointer(&dfiles), C.size_t(dfiles.pFiles))
C.memcpy(unsafe.Pointer(uintptr(outFiles)+uintptr(dfiles.pFiles)),
unsafe.Pointer(&u16files[0]), C.size_t(2*len(u16files)))
w32.EmptyClipboard()
w32.SetClipboardData(w32.CF_HDROP, w32.HANDLE(hmem))
}
return fmt.Errorf("OpenClipboard")
}
func main() {
if isAvailable(textFormat) {
text, err := getText()
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("clipdata[text]:", text)
setText("text:" + text)
} else if isAvailable(fileListFormat) {
files, err := getFileList()
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("clipdata[fileList]:", files)
if len(files) > 0 {
setFileList(files[1:])
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment