如何模拟键盘的Shift按键。Qt,Windows 10

3
我为一款基于触摸屏的平板电脑开发了一些软件。该设备没有键盘,只有一个触摸屏幕(触摸屏模拟鼠标)。操作系统是Windows 10,并且我们使用Qt作为图形用户界面框架。
我们依赖于一个类库Point Cloud Library,其中有一个组件需要按住SHIFT键才能在进行左键单击时发生某些事情。
我需要让底层软件组件相信SHIFT键已被按下。
我尝试通过“Qt方式”向Qt小部件发送按键事件,但伪造的SHIFT键按下似乎没有到达底层软件组件。这可能是因为它与Qt无关的类库并且这个软件类库可能会以不同的方式检查键事件(例如通过OS调用、C++标准方式或类似方式)。
当尝试使用“Qt方式”时,这似乎没有起作用:
QKeyEvent key_press(QEvent::KeyPress, Qt::Key_Shift, Qt::ShiftModifier);
QApplication::sendEvent(ui->qvtkWidget, &key_press);

因此,我可能需要使用操作系统方法来模拟按下SHIFT键。
问题: 我该如何在Qt中进行操作系统调用或类似操作,以使底层软件组件认为已经按下并保持了SHIFT键(与用户同时按下左鼠标键)。

1
也许这可以帮助您:https://batchloaf.wordpress.com/2012/04/17/simulating-a-keystroke-in-win32-c-or-c-using-sendinput/ - HEvTH
1
有强烈的迹象表明,这是一个XY问题。请解释一下,当您进行Shift-Click操作时,点云库(PCL)确切地执行了什么操作(以及在哪里)。如果所有其他方法都失败了,您是否尝试过发送QMouseEvent?它允许您将键盘修饰符与单击一起发送。取决于库如何确定是否按住了[Shift]键,您可能会运气不佳。特别是在使用Qt时,它具有令人昏昏欲睡的消息处理实现。 - IInspectable
既然我怀疑你的实际目标不是一个沮丧的Shift键,而只是达到目的的手段,那么更优雅的方法是直接告诉底层软件组件将其行为更改为(按下Shift键时的任何行为)。当然,这可能需要对底层软件组件进行修改,如果不可能,则您可能只能使用黑客技巧(如模拟按下Shift键)作为唯一选择,但这并不是最好的方法。 - Jeremy Friesner
2个回答

0

不确定其他解决方案是否正确,但我找到了一个更简单的方法。

使用可视化工具setupInteractor()函数,并通过以下方式将QVTKWidget的交互器传递给它:QVTKWidget::interactor()->GetInteractorStyle()->GetInteractor()

当您按下shift键时,应该可以正常工作。


0
你想要的不是模拟Shift键输入,而是在交互级别上禁用Shift检查。这绝对是一个XY问题。
vtk InteractorStyle类负责处理用户输入事件。您可以在pcl_visualizer.cpp的第506行中看到。
boost::signals2::connection
pcl::visualization::PCLVisualizer::registerPointPickingCallback (boost::function<void (const pcl::visualization::PointPickingEvent&)> callback)
{
  return (style_->registerPointPickingCallback (callback));
}

回调函数在PCLVisualizerInteractorStyle类中注册。

您可以在构建PCLVisualizer时传递自己的自定义交互器样式,因此您可以安全地覆盖它。要使用的构造函数是one

PCLVisualizer (int &argc, char **argv, const std::string &name="", PCLVisualizerInteractorStyle *style=PCLVisualizerInteractorStyle::New(), const bool create_interactor=true) 

PointPickingCallback 类在初始化默认交互器样式时会自动添加为鼠标回调函数。因此,如果要覆盖此行为,则需要从 PCLVisualizerInteractorStyle 派生您自己的类,并重写 Initialize() 方法,然后将此新交互器样式传递给 PCLVisualizer

PointPickingCallback 中的 Execute 方法是检查 Shift 键的地方。

void
pcl::visualization::PointPickingCallback::Execute (vtkObject *caller, unsigned long eventid, void*)
{
  PCLVisualizerInteractorStyle *style = reinterpret_cast<PCLVisualizerInteractorStyle*>(caller);
  vtkRenderWindowInteractor* iren = reinterpret_cast<pcl::visualization::PCLVisualizerInteractorStyle*>(caller)->GetInteractor ();
  if (style->CurrentMode == 0)
  {
    if ((eventid == vtkCommand::LeftButtonPressEvent) && (iren->GetShiftKey () > 0))
    {
      float x = 0, y = 0, z = 0;
      int idx = performSinglePick (iren, x, y, z);
      // Create a PointPickingEvent if a point was selected   
      [... and so on]

总结一下,你需要:

  1. PointPickingCallback派生一个新类,覆盖Execute方法中的shift键检查。
  2. PCLVisualizerInteractorStyle派生并覆盖Initialize方法,将你的新自定义PointPickingCallback类注册为鼠标回调函数,该函数不检查shift键。
  3. 将新的交互样式传递给PCLVisualizer

值得注意的是,可视化器支持两种选择模式:橡皮筋区域选择和单点选择,可以通过按下“x”键进行切换。我认为默认选择的是橡皮筋模式,这也是为什么它可能会首先检查shift键是否被按下。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接