在Linux/Ubuntu中捕获窗口事件(屏幕捕获和鼠标/键盘事件) 我想在C++中开发一个应用程序,它需要通过标准的IO(鼠标+键盘)与其他程序交互。它应该能够将鼠标/键盘输入发送到窗口,并捕获特定窗口的“屏幕截图”
(1) 现在我做了一些研究,我知道Linux使用“X窗口”系统。建议从这一层开始编程,还是应该使用更高级别的框架(例如wxWidgets) (2) 即使窗口未聚焦,也可以将输入事件发送到/捕获窗口的屏幕吗 (3) 我不是在问你代码,但我很乐意阅读一些关于这个主题的文献。遗憾的是,我找不到关于这个话题的好消息来源 如果有人能在这件事上帮我,那就太好了 提前谢谢你在Linux/Ubuntu中捕获窗口事件(屏幕捕获和鼠标/键盘事件) 我想在C++中开发一个应用程序,它需要通过标准的IO(鼠标+键盘)与其他程序交互。它应该能够将鼠标/键盘输入发送到窗口,并捕获特定窗口的“屏幕截图”,c++,linux,keyboard,mouse,capture,C++,Linux,Keyboard,Mouse,Capture,(1) 现在我做了一些研究,我知道Linux使用“X窗口”系统。建议从这一层开始编程,还是应该使用更高级别的框架(例如wxWidgets) (2) 即使窗口未聚焦,也可以将输入事件发送到/捕获窗口的屏幕吗 (3) 我不是在问你代码,但我很乐意阅读一些关于这个主题的文献。遗憾的是,我找不到关于这个话题的好消息来源 如果有人能在这件事上帮我,那就太好了 提前谢谢你 (注:此程序应作为后端运行,稍后执行java应用程序的命令。该计划是为Windows/Linux提供后端C++应用程序) < P>强>解
(注:此程序应作为后端运行,稍后执行java应用程序的命令。该计划是为Windows/Linux提供后端C++应用程序)
< P>强>解决方案1 <强>,我可以推荐一段代码来发送我自己用来模拟按键的键盘事件。它基于XSendEvent#include <X11/Xlib.h>
#include <X11/keysym.h>
/** Modifier states */
#define MOD_ALT 0x8
#define MOD_CONTROL 0x4
#define MOD_CONTROL_ALT 0xc
#define MOD_SHIFT_CONTROL 0x5
#define MOD_SHIFT_ALT 0x9
XKeyEvent createKeyEvent(Display *display, Window &win,
Window &winRoot, bool press,
int keycode, int modifiers)
{
XKeyEvent event;
event.display = display;
event.window = win;
event.root = winRoot;
event.subwindow = None;
event.time = CurrentTime;
event.x = 1;
event.y = 1;
event.x_root = 1;
event.y_root = 1;
event.same_screen = True;
event.keycode = XKeysymToKeycode(display, keycode);
event.state = modifiers;
if(press)
event.type = KeyPress;
else
event.type = KeyRelease;
return event;
}
void pressKey(Display* display, Window &win_focus, Window &win_root,
KeySym key, int modifiers)
{
// Send a fake key press event to the window.
XKeyEvent event = createKeyEvent(display, win_focus, win_root, true, key, modifiers);
XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
// Send a fake key release event to the window.
event = createKeyEvent(display, win_focus, win_root, false, key, modifiers);
XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
}
解决方案2使用XTest库可以实现类似的行为。不过,它在“更高级别”上运行,例如,窗口管理器也将接收这些按键。XTest的按键功能可能如下所示(代码不是很干净):
解决方案3另一个解决方案是使用以下工具编写解决方案。基本上,您描述的大部分内容都可以通过bash脚本实现。这也是一个很好的信息来源,告诉你如何实现你想要的一切。嘿,安德烈,谢谢你快速而简洁的回答!所以你建议我使用XWindow。然后我有一些更详细的问题。(1) 如何获取没有键盘焦点的特定窗口的“句柄”?(2) 如果我可以做所有与该窗口相关的事情(例如,鼠标坐标不是相对于屏幕,而是相对于窗口),那将是最好的。你知道这可能吗?(3) XWindow是否支持拍摄我必须拥有的窗口截图。你有什么建议吗?(如果你知道一个好的消息来源,我很乐意看一看!)首先,我假设你希望这是一个C++应用程序。在这种情况下,x lib确实是一条出路。有XSendEvent方法,但也有XTest方法,对您来说可能更简单。不过,也可以通过外部工具实现很多功能,只需编写脚本即可。我也会用这个解决方案来扩展我的答案。@Marvin,如果这个解决方案对你有帮助,你能接受这个答案吗?
// Obtain the X11 display.
Display *display = XOpenDisplay(0);
if (display == NULL)
{
printf("Null display!\n");
return 1;
}
// Get the root window for the current display
Window win_root = XDefaultRootWindow(display);
// Find the window which has the current keyboard focus
Window win_focus;
int revert;
XGetInputFocus(display, &win_focus, &revert);
pressKey(display, win_focus, win_root, XK_w, MOD_ALT);
if (display)
XCloseDisplay(display);
void pressKey(Display* display, KeySym modifier1, KeySym modifier2, KeySym key)
{
// Release every other modifier
KeyCode keycodec = XKeysymToKeycode(display, XK_Control_L);
KeyCode keycodea = XKeysymToKeycode(display, XK_Alt_L);
KeyCode keycodes = XKeysymToKeycode(display, XK_Shift_L);
XTestFakeKeyEvent(display, keycodec, False, 0); // key release event
XTestFakeKeyEvent(display, keycodea, False, 0); // key release event
XTestFakeKeyEvent(display, keycodes, False, 0); // key release event
XFlush(display);
// Press the actual keys
KeyCode keycode1 = XKeysymToKeycode(display, modifier1);
KeyCode keycode2 = XKeysymToKeycode(display, modifier2);
KeyCode keycode3 = XKeysymToKeycode(display, key);
if (keycode1)
XTestFakeKeyEvent(display, keycode1, True, 0); // key press event
if (keycode2)
XTestFakeKeyEvent(display, keycode2, True, 0); // key press event
if (keycode3)
{
XTestFakeKeyEvent(display, keycode3, True, 0); // key press event
XTestFakeKeyEvent(display, keycode3, False, 0); // key release event
}
if (keycode2)
XTestFakeKeyEvent(display, keycode2, False, 0); // key release event
if (keycode1)
XTestFakeKeyEvent(display, keycode1, False, 0); // key release event
XFlush(display);
}