简体   繁体   中英

How to fake a keyboard shift press. Qt, Windows 10

I develop some software for a touch based tablet PC. The unit has no keyboard and has only a touch screen (the touch screen emulates a mouse). The OS is Windows 10 and we are using Qt as the graphical user interface framework.

We rely on a class library Point Cloud Library that has a component that requires the SHIFT key to be pressed to make something happen when we do a left mouse click.

I need to make the underlying software component believe that the SHIFT key has been pressed.

I have tried to send keypress events to the Qt widget via "Qt means" but the fake SHIFT keypress doesn't seem to reach the underlying sw. component. Probably since it is in a unrelated class library to Qt and that this software class library probably checks key events differently (for example via OS calls, c++ std ways or similar).

This didn't seem to work when trying the "Qt way":

QKeyEvent key_press(QEvent::KeyPress, Qt::Key_Shift, Qt::ShiftModifier);
QApplication::sendEvent(ui->qvtkWidget, &key_press);

Therefore I probably need to use an operating system method to fake a SHIFT key press.

Question: How can I can do an OS system call or similar from Qt to make the underlying software component think that a SHIFT key has been pressed and held ( at the same time the user presses the left mouse button).

What you want is not to fake a shift key input but disable the shift checking at interaction level. Definitely an XY problem.

The vtk InteractorStyle classes are responsible for handling user input events. You can see that in line 506 of pcl_visualizer.cpp

boost::signals2::connection
pcl::visualization::PCLVisualizer::registerPointPickingCallback (boost::function<void (const pcl::visualization::PointPickingEvent&)> callback)
{
  return (style_->registerPointPickingCallback (callback));
}

the callback gets registered in a PCLVisualizerInteractorStyle class.

You can pass your own custom interactor style at construction of PCLVisualizer so this one you can override safely. The constructor to use is this one

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

The PointPickingCallback class is being added automatically as a mouse callback upon initializing the default interactor style. So in order to override this behavior, you're required to derive your own class from PCLVisualizerInteractorStyle and override the Initialize() method and pass this new interactor style to a PCLVisualizer upon construction.

The Execute method inside the PointPickingCallback is where the check for the shift key happens.

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]

In summary you're gonna need to:

  1. Derive from PointPickingCallback a new class which overrides the check for the shift key inside the Execute method.
  2. Derive from PCLVisualizerInteractorStyle and override the Initialize method to register your new custom PointPickingCallback class which doesn't check for the shift key, as a mouse callback.
  3. Pass the new interactor style to the PCLVisualizer .

Worth noting. The visualizer supports two selection modes: rubber band for area selection and single point picking, which can be interchanged by pressing the key 'x'. I think the default one to be selected is the rubber band and that's why it might be checking for that shift key being pressed in the first place.

Not sure if the other solution is correct but I found an easier one.

Use the visualizers setupInteractor() function and give it the interactor of the QVTKWidget via: QVTKWidget::interactor()->GetInteractorStyle()->GetInteractor()

This should work when you press shift .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM