【问题标题】:Getting mouse presses on a console window for python在 python 的控制台窗口上获取鼠标按下
【发布时间】:2012-01-30 10:45:06
【问题描述】:

是否有某种方法可以在 python 中的控制台窗口上获得鼠标按下?我知道你可以这样做,因为如果你正在运行 Windows,你可以打开 cmd 并输入“edit”。例如,您将如何在 python 中执行此操作?谢谢。

【问题讨论】:

  • 请参阅this SO 问题和答案。您可能必须用 C 语言创建一个模块,因为我怀疑标准 Python 是否为此提供了本机模块。

标签: python console window cmd


【解决方案1】:

前面的两个答案都是正确的:您可以在 Windows 上使用 pywin32 或在 Linux 上使用 curses 来处理您的鼠标输入。但是,两者都不能在其他平台上运行。

如果您想要同时处理这两者或只是一个更简单的 API,您可以使用我最近编写的一个包 - asciimatics。 Screen 类handles mouse input 通过包装上述两种解决方案,以跨平台方式用于控制台。

【讨论】:

    【解决方案2】:

    我个人不喜欢最后一个答案中的 PyWin32,因为它仅在第一次导入时才有效,之后无法导入它的主要 pyd 模块。
    然后是它不是跨平台的。

    curses 是一个更好的选择,虽然它对 python27 并不完全友好,但我已经设法让它在 Wine 中工作:

    import _curses # _curses.pyd supplied locally for python27 win32
    import curses 
    
    screen = curses.initscr() 
    #curses.noecho() 
    curses.curs_set(0) 
    screen.keypad(1) 
    curses.mousemask(curses.ALL_MOUSE_EVENTS)
    
    screen.addstr("This is a Sample Curses Script\n\n") 
    
    key=0
    while key!=27: # Esc to close
        key = screen.getch() 
        #screen.erase()
        if key == curses.KEY_MOUSE:
            _, mx, my, _, _ = curses.getmouse()
            y, x = screen.getyx()
            screen.addstr('mx, my = %i,%i                \r'%(mx,my))
        screen.refresh()
    
    curses.endwin()
    

    在此示例中,您需要单击、拖动和释放才能注册事件,但我认为有一种解决方法。

    我自己只是在玩这个(我不想让 PyQt 或 PyGLFW 变得复杂)

    编辑:
    设法让它按预期工作并更新了代码。 您无需再拖动即可注册活动。

    【讨论】:

      【解决方案3】:

      是的,但这是相当多的工作。

      http://sourceforge.net/projects/pywin32/files/

      它的工作方式就像从 C 代码中与 Win32API 对话一样。

      如果您在 MSDN 上搜索函数名称,Microsoft 文档会非常好。

      pywin32 包含一个名为 win32console_demo.py 的文件

      添加以下行以启用鼠标输入。就在 conin 创建之后。

      conin.SetConsoleMode(ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT)
      

      编辑win32console_demo.py 以启用鼠标输入。

      import win32con
      import win32file
      from win32console import *
      import traceback, time
      
      
      virtual_keys={}
      for k,v in win32con.__dict__.items():
          if k.startswith('VK_'):
              virtual_keys[v]=k 
      
      free_console=True
      try:
          AllocConsole()
      except error, exc:
          if exc.winerror!=5:
              raise
          ## only free console if one was created successfully
          free_console=False
      
      stdout=GetStdHandle(STD_OUTPUT_HANDLE)
      
      conin=PyConsoleScreenBufferType( win32file.CreateFile( "CONIN$", win32con.GENERIC_READ|win32con.GENERIC_WRITE, win32con.FILE_SHARE_READ, None, win32con.OPEN_EXISTING, 0, 0))
      
      conin.SetConsoleMode(ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT)
      
      newbuffer=CreateConsoleScreenBuffer()
      newbuffer.SetConsoleActiveScreenBuffer()
      newbuffer.SetConsoleTextAttribute(FOREGROUND_RED|FOREGROUND_INTENSITY
              |BACKGROUND_GREEN|BACKGROUND_INTENSITY)
      newbuffer.WriteConsole('This is a new screen buffer\n')
      
      newbuffer.SetConsoleTextAttribute(FOREGROUND_RED|FOREGROUND_INTENSITY
              |BACKGROUND_GREEN|BACKGROUND_INTENSITY)
      newbuffer.WriteConsole('Press some keys, click some characters with the mouse\n')
      
      newbuffer.SetConsoleTextAttribute(FOREGROUND_BLUE|FOREGROUND_INTENSITY
              |BACKGROUND_RED|BACKGROUND_INTENSITY)
      newbuffer.WriteConsole('Hit "Esc" key to quit\n')
      
      
      breakout=False
      while not breakout:
          input_records=conin.ReadConsoleInput(10)
          for input_record in input_records:
              if input_record.EventType==KEY_EVENT:
                  if input_record.KeyDown:
                      if input_record.Char=='\0':
                          newbuffer.WriteConsole(virtual_keys.get(input_record.VirtualKeyCode, 'VirtualKeyCode: %s' %input_record.VirtualKeyCode))
                      else:
                          newbuffer.WriteConsole(input_record.Char)
                      if input_record.VirtualKeyCode==win32con.VK_ESCAPE:
                          breakout=True
                          break
              elif input_record.EventType==MOUSE_EVENT:
                  if input_record.EventFlags==0:  ## 0 indicates a button event
                      if input_record.ButtonState!=0:   ## exclude button releases
                          pos=input_record.MousePosition
                          # switch the foreground and background colors of the character that was clicked
                          attr=newbuffer.ReadConsoleOutputAttribute(Length=1, ReadCoord=pos)[0]
                          new_attr=attr
                          if attr&FOREGROUND_BLUE:
                              new_attr=(new_attr&~FOREGROUND_BLUE)|BACKGROUND_BLUE
                          if attr&FOREGROUND_RED:
                              new_attr=(new_attr&~FOREGROUND_RED)|BACKGROUND_RED
                          if attr&FOREGROUND_GREEN:
                              new_attr=(new_attr&~FOREGROUND_GREEN)|BACKGROUND_GREEN
      
                          if attr&BACKGROUND_BLUE:
                              new_attr=(new_attr&~BACKGROUND_BLUE)|FOREGROUND_BLUE
                          if attr&BACKGROUND_RED:
                              new_attr=(new_attr&~BACKGROUND_RED)|FOREGROUND_RED
                          if attr&BACKGROUND_GREEN:
                              new_attr=(new_attr&~BACKGROUND_GREEN)|FOREGROUND_GREEN
                          newbuffer.WriteConsoleOutputAttribute((new_attr,),pos)
              else:
                  newbuffer.WriteConsole(str(input_record))
          time.sleep(0.1)
      
      newbuffer.Close()
      
      if free_console:
           FreeConsole()
      

      【讨论】:

        猜你喜欢
        • 2023-01-31
        • 2015-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 2017-04-22
        • 1970-01-01
        相关资源
        最近更新 更多