this can help somebody
from tkinter import colorchooser,Tk,messagebox
from colored import fg,bg,attr
import win32console
import threading
import win32gui
import win32api
import colorama
import atexit
import mouse
import time
import sys
import os
class console:
def __init__(self):
self._is_enabled = False
self._last_pos = (0,0)
self.hwnd = win32console.GetConsoleWindow()
atexit.register(lambda:self.set_input(True))
def _mouse_thread(self):
while True:
if self.get_mouse_position()[1] > 30:
if self.is_input():
self._set_input(False)
else:
if not self.is_input():
self._set_input(True)
def _focus_thread(self):
while True:
if win32gui.GetForegroundWindow() != self.hwnd:
win32gui.SetForegroundWindow(self.hwnd)
def run_focus_thread(self):
threading.Thread(target=self._focus_thread,daemon=1).start()
def run_moveable_thread(self):
threading.Thread(target=self._mouse_thread,daemon=1).start()
def get_position(self):
return win32gui.GetWindowRect(self.hwnd)[:2]
def get_mouse_position(self):
try:
pos = win32gui.GetCursorPos()
self._last_pos = pos
except:
pos = self._last_pos
return (pos[0]-self.get_position()[0]-7,
pos[1]-self.get_position()[1]-30)
def _set_input(self,value):
win32gui.EnableWindow(self.hwnd,value)
def set_input(self,value):
self._is_enabled = value
win32gui.EnableWindow(self.hwnd,value)
def is_input(self):
return win32gui.IsWindowEnabled(self.hwnd)
def set_focus(self):
win32gui.SetForegroundWindow(self.hwnd)
win32gui.SetFocus(self.hwnd)
def is_focus(self):
return win32gui.GetForegroundWindow() == self.hwnd and \
self.get_mouse_position()[1] >= 30 and \
self.get_mouse_position()[0] > 0 and \
self.get_mouse_position()[0] <= self.get_size()[0]-7 and \
self.get_mouse_position()[1] <= self.get_size()[1]
def get_size(self):
return (win32gui.GetWindowRect(self.hwnd)[2]-7,
win32gui.GetWindowRect(self.hwnd)[3]-30)
def set_size(self,w,h):
win32gui.MoveWindow(self.hwnd,*self.get_position(),int(w),int(h),True)
def set_position(self,x,y):
win32gui.MoveWindow(self.hwnd,int(x),int(y),*self.get_size(),True)
def set_rect(self,x,y,w,h):
win32gui.MoveWindow(self.hwnd,int(x),int(y),int(w),int(h),True)
def set_center(self):
self.set_position(get_screen_size()[0]/2-self.get_size()[0]/2,
get_screen_size()[1]/2-self.get_size()[1]/2)
def set_title(self,title):
win32gui.SetWindowText(self.hwnd,title)
console = console()
def get_screen_size():
return (win32api.GetSystemMetrics(0),
win32api.GetSystemMetrics(1))
font_size = [8.2,15.5]
class canvas:
def __init__(self,width,height):
self.sp = (width*font_size[0],height*font_size[1])
self.width, self.height = width, height
self.changed = True
self.pixels = [[" " for i in range(self.width)] for i in range(self.height)]
console.set_size(self.sp[0]+30,self.sp[1]+10)
def clear(self):
# os.system("cls")
print("\033[H\033[J",end="")
def fill(self,symbol=" ",update=True):
self.pixels = [[symbol for i in range(self.width)] for i in range(self.height)]
self.changed = True
if update: self.update()
def update(self):
self.changed = False
out = ""
for y in self.pixels:
for x in y:
out += x
out += "\n"
self.clear()
print(out,end="")
def set(self,x,y,symbol,update=True):
if x < self.width and y < self.height:
self.pixels[y][x] = symbol
self.changed = True
if update: self.update()
def write(self,x,y,text,update=True):
self.changed = True
for n,s in enumerate(text):
self.set(x+n,y,s,False)
if update: self.update()
def get(self,x,y):
return self.pixels[y][x]
def all(self):
return self.pixels
def get_mouse_position(self):
return (console.get_mouse_position()[0]/self.sp[0]*self.width,
(console.get_mouse_position()[1]/(self.sp[1]-font_size[1]*4)*self.height))
def color_symbol(color):
return fg(color)+bg(color)+"#"+attr('reset')
# ------- create canvas -------
console.set_title("hello world button") # set console title
console.run_moveable_thread() # run thread that prohibits clicking on the console
win = canvas(64,34) # creating canvas
# ------- create buttons -------
btns = []
def btn(text,x,y,cb):
btns.append([text,x,y,cb,False])
def btncallback():
Tk().withdraw()
messagebox.showinfo("hello world","Hello World!")
btn("click me!",25,15,btncallback)
# ------- create main view -------
for i in btns:
win.set(i[1],i[2],i[0][0],False)
win.write(i[1]+1,i[2],i[0][1:][:-1],False)
win.set(i[1]+len(i[0])-1,i[2],i[0][-1],False)
win.update()
# ------- main loop -------
run = True
while run:
if win.changed:
win.update()
if console.is_focus():
pos = win.get_mouse_position()
pos = (round(pos[0]),round(pos[1]))
if mouse.is_pressed("left"):
for i in btns:
if pos[0] >= i[1] and pos[0] <= i[1]+len(i[0]) \
and pos[1] == i[2]+1 and not i[4]:
win.set(i[1],i[2],fg("black")+bg("white")+i[0][0],False)
win.write(i[1]+1,i[2],i[0][1:][:-1],False)
win.set(i[1]+len(i[0])-1,i[2],i[0][-1]+attr("reset"),False)
i[4] = True
else:
for i in btns:
if i[4]:
win.set(i[1],i[2],i[0][0],False)
win.write(i[1]+1,i[2],i[0][1:][:-1],False)
win.set(i[1]+len(i[0])-1,i[2],i[0][-1],False)
i[4] = False
i[3]()