0

I am trying to detect the keyboard presses just when I am in the cmd window running a ROS2 node.

I have already written this using pynput, but it detects all keys pressed even if I am in another window.

import sys

import os
import signal
import time
    
from pynput import keyboard

import rclpy
from rclpy.parameter import Parameter
import std_msgs.msg


class KeystrokeListen:
    def __init__(self, name=None):
        self.node = rclpy.create_node(name or type(self).__name__)
        self.pub_glyph = self.node.create_publisher(std_msgs.msg.String, 'glyphkey_pressed', 10)
        self.pub_code = self.node.create_publisher(std_msgs.msg.UInt32, 'key_pressed', 10)

    def spin(self):
            with keyboard.Listener(on_press=self.on_press, on_release=self.on_release) as listener:
                while rclpy.ok() and listener.running:
                    rclpy.spin_once(self.node, timeout_sec=0.1)

    @property
    def logger(self):
        return self.node.get_logger()


    def on_release(self, key):
        pass


    def on_press(self, key): 
        try:
            char = getattr(key, 'char', None)
            if isinstance(char, str):
                self.logger.info('pressed ' + char)
                self.pub_glyph.publish(self.pub_glyph.msg_type(data=char))
            else:
                try:
                    # known keys like spacebar, ctrl
                    name = key.name
                    vk = key.value.vk
                except AttributeError:
                    # unknown keys like headphones skip song button
                    name = 'UNKNOWN'
                    vk = key.vk
                self.logger.info('pressed {} ({})'.format(name, vk))
                # todo: These values are not cross-platform. When ROS2 supports Enums, use them instead
                self.pub_code.publish(self.pub_code.msg_type(data=vk))
        except Exception as e:
            self.logger.error(str(e))
            raise

        if key == keyboard.Key.esc:
            self.logger.info('stopping listener')
            raise keyboard.Listener.StopException            
            os.kill(os.getpid(), signal.SIGINT)


def main(args=None):
    rclpy.init(args=args)
    KeystrokeListen().spin()


if __name__ == '__main__':
    main()

I have found here How to detect key presses? something related with win32gui, as getting the name of the current window and then the name of the window we want the key presses to be detected:

from win32gui import GetWindowText, GetForegroundWindow
current_window = (GetWindowText(GetForegroundWindow()))
desired_window_name = "Stopwatch"

However, I just want for my program to work whenever I am in the cmd where I launched it.

Any idea??

Thank you in advance!

marpe
  • 185
  • 2
  • 9

1 Answers1

1

Indeed, this module might help you out. Here is an example of how I would do it:

from win32gui import GetForegroundWindow, GetWindowText

if all(win_name in GetWindowText(GetForegroundWindow()) for win_name in ["cmd.exe", __file__]):
    print("this program's cmd is focused!")
cfgn
  • 201
  • 2
  • 10
  • I managed to do it thanks to you! I realized that the names from the statement you gave me didn't match although pointing to the same window. The GetWindowText gives the command introduced, which is also the name of the window, while the other one gives the route to the file. However, I change the name of the cmd window from the file, to the one I want, and then I just simply checked that the names match with the GetWindowText function. Thank you!! – marpe May 08 '22 at 18:39
  • I'm glad I could be of help! I think you can accept the answer, so it marks the question as resolved. Good luck with your project ;) – cfgn May 09 '22 at 13:26