你好,我正在编写一个c++程序,需要将剪贴板中的内容获取到一个字符串变量中。我找到了很多解决方案,但它们都是为Windows编写的。有没有不使用QT库的方法?我找到了一些与X11相关的东西,但也不是非常明确。
非常感谢!
你好,我正在编写一个c++程序,需要将剪贴板中的内容获取到一个字符串变量中。我找到了很多解决方案,但它们都是为Windows编写的。有没有不使用QT库的方法?我找到了一些与X11相关的东西,但也不是非常明确。
非常感谢!
gtk_clipboard_get()
,Qt的QApplication::clipboard()
,Tk的clipboard_get)。但是,如果您没有使用工具包,或者必须通过剪贴板缓冲区传递大量数据而不将其全部保存在内存中,则可以使用X11 API手动完成此操作。CLIPBOARD
是通常的显式缓冲区:您可以使用编辑/复制菜单将内容复制到其中,并使用编辑/粘贴菜单将其粘贴出来。
- PRIMARY
选择是一种隐式鼠标选择功能:当使用鼠标光标进行选择时,文本会进入其中,并在文本输入字段上进行中键单击时从其中粘贴。UTF8_STRING
格式,并退回到STRING
。SelectionNotify
事件通知您。CLIPBOARD
, PRIMARY
),格式
(UTF8_STRING
, STRING
)和一个窗口属性来存储结果XConvertSelection()
请求缓冲区SelectionNotify
事件// gcc -o xclipget xclipget.c -lX11
#include <stdio.h>
#include <limits.h>
#include <X11/Xlib.h>
Bool PrintSelection(Display *display, Window window, const char *bufname, const char *fmtname)
{
char *result;
unsigned long ressize, restail;
int resbits;
Atom bufid = XInternAtom(display, bufname, False),
fmtid = XInternAtom(display, fmtname, False),
propid = XInternAtom(display, "XSEL_DATA", False),
incrid = XInternAtom(display, "INCR", False);
XEvent event;
XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime);
do {
XNextEvent(display, &event);
} while (event.type != SelectionNotify || event.xselection.selection != bufid);
if (event.xselection.property)
{
XGetWindowProperty(display, window, propid, 0, LONG_MAX/4, False, AnyPropertyType,
&fmtid, &resbits, &ressize, &restail, (unsigned char**)&result);
if (fmtid == incrid)
printf("Buffer is too large and INCR reading is not implemented yet.\n");
else
printf("%.*s", (int)ressize, result);
XFree(result);
return True;
}
else // request failed, e.g. owner can't convert to the target format
return False;
}
int main()
{
Display *display = XOpenDisplay(NULL);
unsigned long color = BlackPixel(display, DefaultScreen(display));
Window window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0,0, 1,1, 0, color, color);
Bool result = PrintSelection(display, window, "CLIPBOARD", "UTF8_STRING") ||
PrintSelection(display, window, "CLIPBOARD", "STRING");
XDestroyWindow(display, window);
XCloseDisplay(display);
return !result;
}
INCR
的属性,而不是将其存储到窗口属性中。如果您删除它,所有者会认为您已经阅读了它,并在同一属性中放置下一个块。这将继续进行,直到读取并删除了最后一个块。最后,所有者设置大小为0的属性以标记数据的结尾。INCR
属性并等待属性再次出现(PropertyNotify
事件,状态== PropertyNewValue
),然后读取并删除它,等待它再次出现,依此类推,直到它以零大小出现。// gcc -o xclipget xclipget.c -lX11
#include <stdio.h>
#include <limits.h>
#include <X11/Xlib.h>
Bool PrintSelection(Display *display, Window window, const char *bufname, const char *fmtname)
{
char *result;
unsigned long ressize, restail;
int resbits;
Atom bufid = XInternAtom(display, bufname, False),
fmtid = XInternAtom(display, fmtname, False),
propid = XInternAtom(display, "XSEL_DATA", False),
incrid = XInternAtom(display, "INCR", False);
XEvent event;
XSelectInput (display, window, PropertyChangeMask);
XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime);
do {
XNextEvent(display, &event);
} while (event.type != SelectionNotify || event.xselection.selection != bufid);
if (event.xselection.property)
{
XGetWindowProperty(display, window, propid, 0, LONG_MAX/4, True, AnyPropertyType,
&fmtid, &resbits, &ressize, &restail, (unsigned char**)&result);
if (fmtid != incrid)
printf("%.*s", (int)ressize, result);
XFree(result);
if (fmtid == incrid)
do {
do {
XNextEvent(display, &event);
} while (event.type != PropertyNotify || event.xproperty.atom != propid || event.xproperty.state != PropertyNewValue);
XGetWindowProperty(display, window, propid, 0, LONG_MAX/4, True, AnyPropertyType,
&fmtid, &resbits, &ressize, &restail, (unsigned char**)&result);
printf("%.*s", (int)ressize, result);
XFree(result);
} while (ressize > 0);
return True;
}
else // request failed, e.g. owner can't convert to the target format
return False;
}
int main()
{
Display *display = XOpenDisplay(NULL);
unsigned long color = BlackPixel(display, DefaultScreen(display));
Window window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0,0, 1,1, 0, color, color);
Bool result = PrintSelection(display, window, "CLIPBOARD", "UTF8_STRING") ||
PrintSelection(display, window, "CLIPBOARD", "STRING");
XDestroyWindow(display, window);
XCloseDisplay(display);
return !result;
}
xsel
工具对于大于 4000 的缓冲区使用 INCR
传输。根据 ICCCM,选择合理的大小限制取决于应用程序。PRIMARY
选择。将 "CLIPBOARD" 替换为 "PRIMARY",以打印 PRIMARY
选择内容。
XCopy()
和XPaste()
实现xsel
和xclip
源码