from tkinter import *
import subprocess, psutil, threading
import os, win32gui, win32process, time
import win32con, pywintypes, win32api
import win32ui, easygui, sys
# Sample settings for VN's using LEProc.exe
# Just change these values
prog = "T:\Path\To\Locale Emulator\LEProc.exe"
args = '"T:\Path\To\Actual\Game\With\The\Executable\LPK-12010.exe"'
exeName = "LPK-12010.exe"
progFull = f'{prog} {args}'
screen_win_width = 800
screen_win_height = 600
frame_win_width = 800
frame_win_height = 600
def get_pid_by_exe(exe=''):
for proc in psutil.process_iter(['pid','exe']):
try:
if os.path.basename(proc.exe()).lower() == exe.lower():
return proc.pid
except psutil.AccessDenied:
pass
return None
# https://stackoverflow.com/q/51418928
def get_hwnds_for_pid (pid):
def callback (hwnd, hwnds):
# EDITED TO IMMEDIATELY GET THE PROGRAM
#if win32gui.IsWindowVisible (hwnd) and win32gui.IsWindowEnabled (hwnd):
_, found_pid = win32process.GetWindowThreadProcessId (hwnd)
if found_pid == pid:
hwnds.append (hwnd)
return True
hwnds = []
win32gui.EnumWindows (callback, hwnds)
return hwnds
def pid_thread(pid):
while psutil.pid_exists(pid):
time.sleep(0.5)
pass
os._exit(1)
# Create frame window
window = Tk()
window.title("Frame App")
window.iconbitmap(default='.\main.ico')
window.configure(width=frame_win_width, height=frame_win_height)
window.configure(bg='lightgray')
frame_window_handle = window.winfo_id()
print("opening process")
subprocess.Popen(progFull)
print("waiting process to load")
while get_pid_by_exe(exeName) is None:
pass
print("process loaded")
gamePID = get_pid_by_exe(exeName)
p = psutil.Process(gamePID)
# Game close thread
closeThread = threading.Thread(target=pid_thread, args=(gamePID,),daemon=True)
closeThread.start()
# Get Game ICON KINDA NOT WORKING
#ico_x = win32api.GetSystemMetrics(win32con.SM_CXICON)
#ico_y = win32api.GetSystemMetrics(win32con.SM_CYICON)
#large, small = win32gui.ExtractIconEx(psutil.Process(gamePID).exe(),0)
#win32gui.DestroyIcon(small[0])
#hdc = win32ui.CreateDCFromHandle( win32gui.GetDC(0) )
#hbmp = win32ui.CreateBitmap()
#hbmp.CreateCompatibleBitmap( hdc, ico_x, ico_x )
#hdc = hdc.CreateCompatibleDC()
#hdc.SelectObject( hbmp )
#hdc.DrawIcon( (0,0), large[0] )
#hbmp.SaveBitmapFile( hdc, 'icon.ico')
# wait until handles are loaded
handles = get_hwnds_for_pid(gamePID)
oldlen = len(handles)
sec = 0
startTime = time.time()
while True:
handles = get_hwnds_for_pid(gamePID)
if len(handles) != oldlen:
oldlen = len(handles)
break
lapseTime = time.time()
sec = lapseTime - startTime
if sec >= 5: break
game_window_handle = get_hwnds_for_pid(gamePID)[0]
# Pass close to the child window
window.protocol("WM_DELETE_WINDOW", lambda: {win32gui.PostMessage(game_window_handle,win32con.WM_CLOSE,0,0)})
# Change title to window title and ICON
window.title(win32gui.GetWindowText(game_window_handle))
#window.iconbitmap(default='.\icon.ico')
# RESIZE WINDOW
devmode = pywintypes.DEVMODEType()
devmode.PelsWidth = screen_win_width
devmode.PelsHeight = screen_win_height
devmode.Fields = win32con.DM_PELSWIDTH | win32con.DM_PELSHEIGHT
win32api.ChangeDisplaySettings(devmode, 0)
def hide_icon():
for item in get_hwnds_for_pid(gamePID):
#Hide game taskbar icon
try:
if win32gui.IsWindowVisible(item):
#win32gui.ShowWindow(item, SW_HIDE)
win32gui.SetWindowLong(item, win32con.GWL_EXSTYLE, win32gui.GetWindowLong(item, win32con.GWL_EXSTYLE)| win32con.WS_EX_TOOLWINDOW)
win32gui.ShowWindow(item, win32con.SW_SHOW)
except win32gui.error:
print("error hiding icon")
# Center Window
window.eval('tk::PlaceWindow . center')
# Connect the window
window.after(100,hide_icon)
window.after(200,lambda: {win32gui.SetParent(game_window_handle,frame_window_handle)})
# Reset the screen and frame geometry
window.after(300,lambda: {win32api.ChangeDisplaySettings(None, 0)})
window.after(1000,lambda: {window.geometry(f'{frame_win_width}x{frame_win_height}')})
# Start the main frame window
window.mainloop()