Is there some sort of way to get mouse presses on console windows in python? I know you can do this, because if you're running windows you can open up the cmd and type "edit". How would you do this for example in python? Thanks.
-
See [this](http://stackoverflow.com/questions/6285270/how-can-i-get-the-mouse-position-in-a-console-program) SO question and answers. You might have to make a module in C, as I doubt standard Python comes with a native module for this. – Some programmer dude Dec 30 '11 at 08:55
3 Answers
I personally don't like PyWin32 from the last answer for the fact that it only works the first time it's imported, afterwards it can't import it's main pyd module.
and then there's the fact it's not cross-platform.
curses is a better alternative, though it's not exactly friendly with python27, but I've managed to get it working in 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()
in this example you need to click, drag, and release for the event to register, but I think there's a way around that.
I'm only just playing with this myself (I don't want to get all complex with PyQt or PyGLFW)
EDIT:
managed to get it working as expected and updated the code.
you don't need to drag anymore for the event to register.

- 7,140
- 1
- 20
- 23
Both the previous answers are correct: you can use pywin32 on Windows or curses on Linux to handle your mouse input. Neither works on the other platform, though.
If you want something that handles both or is just a simpler API, you could use a package I recently wrote - asciimatics. The Screen class handles mouse input for a console in a cross-platform way by wrapping both the above solutions.

- 13,489
- 3
- 41
- 57
Yes, but it's a fair amount of work.
http://sourceforge.net/projects/pywin32/files/
It works just like talking to the Win32API from C code.
The Microsoft documentation is pretty good if you Google the function names on MSDN.
pywin32 includes a file called win32console_demo.py
Add the following line to enable mouse input. Just after conin is created.
conin.SetConsoleMode(ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT)
win32console_demo.py edited to enable mouse input.
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()

- 2,485
- 3
- 20
- 33