123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- // Copyright 2013 The Walk Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // +build windows
- package walk
- import (
- "syscall"
- "unsafe"
- )
- import (
- "github.com/lxn/win"
- )
- const clipboardWindowClass = `\o/ Walk_Clipboard_Class \o/`
- func init() {
- MustRegisterWindowClass(clipboardWindowClass)
- hwnd := win.CreateWindowEx(
- 0,
- syscall.StringToUTF16Ptr(clipboardWindowClass),
- nil,
- 0,
- 0,
- 0,
- 0,
- 0,
- win.HWND_MESSAGE,
- 0,
- 0,
- nil)
- if hwnd == 0 {
- panic("failed to create clipboard window")
- }
- if !win.AddClipboardFormatListener(hwnd) {
- lastError("AddClipboardFormatListener")
- }
- clipboard.hwnd = hwnd
- }
- func clipboardWndProc(hwnd win.HWND, msg uint32, wp, lp uintptr) uintptr {
- switch msg {
- case win.WM_CLIPBOARDUPDATE:
- clipboard.contentsChangedPublisher.Publish()
- return 0
- }
- return win.DefWindowProc(hwnd, msg, wp, lp)
- }
- var clipboard ClipboardService
- // Clipboard returns an object that provides access to the system clipboard.
- func Clipboard() *ClipboardService {
- return &clipboard
- }
- // ClipboardService provides access to the system clipboard.
- type ClipboardService struct {
- hwnd win.HWND
- contentsChangedPublisher EventPublisher
- }
- // ContentsChanged returns an Event that you can attach to for handling
- // clipboard content changes.
- func (c *ClipboardService) ContentsChanged() *Event {
- return c.contentsChangedPublisher.Event()
- }
- // Clear clears the contents of the clipboard.
- func (c *ClipboardService) Clear() error {
- return c.withOpenClipboard(func() error {
- if !win.EmptyClipboard() {
- return lastError("EmptyClipboard")
- }
- return nil
- })
- }
- // ContainsText returns whether the clipboard currently contains text data.
- func (c *ClipboardService) ContainsText() (available bool, err error) {
- err = c.withOpenClipboard(func() error {
- available = win.IsClipboardFormatAvailable(win.CF_UNICODETEXT)
- return nil
- })
- return
- }
- // Text returns the current text data of the clipboard.
- func (c *ClipboardService) Text() (text string, err error) {
- err = c.withOpenClipboard(func() error {
- hMem := win.HGLOBAL(win.GetClipboardData(win.CF_UNICODETEXT))
- if hMem == 0 {
- return lastError("GetClipboardData")
- }
- p := win.GlobalLock(hMem)
- if p == nil {
- return lastError("GlobalLock()")
- }
- defer win.GlobalUnlock(hMem)
- text = win.UTF16PtrToString((*uint16)(p))
- return nil
- })
- return
- }
- // SetText sets the current text data of the clipboard.
- func (c *ClipboardService) SetText(s string) error {
- return c.withOpenClipboard(func() error {
- utf16, err := syscall.UTF16FromString(s)
- if err != nil {
- return err
- }
- hMem := win.GlobalAlloc(win.GMEM_MOVEABLE, uintptr(len(utf16)*2))
- if hMem == 0 {
- return lastError("GlobalAlloc")
- }
- p := win.GlobalLock(hMem)
- if p == nil {
- return lastError("GlobalLock()")
- }
- win.MoveMemory(p, unsafe.Pointer(&utf16[0]), uintptr(len(utf16)*2))
- win.GlobalUnlock(hMem)
- if 0 == win.SetClipboardData(win.CF_UNICODETEXT, win.HANDLE(hMem)) {
- // We need to free hMem.
- defer win.GlobalFree(hMem)
- return lastError("SetClipboardData")
- }
- // The system now owns the memory referred to by hMem.
- return nil
- })
- }
- func (c *ClipboardService) withOpenClipboard(f func() error) error {
- if !win.OpenClipboard(c.hwnd) {
- return lastError("OpenClipboard")
- }
- defer win.CloseClipboard()
- return f()
- }
|