how to read window dialog fields values using python? - python

I try to read values from fields of a window dialog.
In the dialog configuration I have this:
#define IDC_SYMBOL 8011
#define IDC_SHARES 8012
dialog snapshot picture
this is my simple code tried:
import win32gui,win32con
wT="my_dialog"
dlg=win32gui.FindWindow(None,wT)
d1=win32gui.GetDlgItem(dlg, 8011)
d2=win32gui.GetDlgItem(dlg, 8012)
print('d1: ', d1)
print('d2: ', d2)
def dumpWindow(hwnd, wantedText=None, wantedClass=None):
windows = []
hwndChild = None
while True:
hwndChild = win32gui.FindWindowEx(hwnd, hwndChild, wantedClass, wantedText)
if hwndChild:
textName = win32gui.GetWindowText(hwndChild)
className = win32gui.GetClassName(hwndChild)
windows.append((hwndChild, textName, className))
else:
return windows
windows = dumpWindow(dlg, wantedText='Symbol')
print(windows)
And this is what I get when running it:
d1: 1051340
d2: 920324
[(9112016, 'Symbol', 'Static')]
How do I read the actual values in those window dialog fields?
I also tried to get the dialog item text:
dText=win32gui.GetDlgItemText(dlg, 8011)
print('dText: ', dText)
and result is empty while the expected result is 'AAPL' for example, or whatever is there.
dText:

Why you don't use GetDlgItemText.
Normally, this function will return the text of a dialog control

Solution:
from sys import exit
import win32gui,win32con
wT="my_dialog"
dlg=win32gui.FindWindow(None,wT)
d1=win32gui.GetDlgItem(dlg, 8011) #symbol
def getEditText(hwnd):
buffer = win32gui.PyMakeBuffer(255)
bufLen = win32gui.SendMessage(hwnd, win32con.WM_GETTEXTLENGTH, 255, buffer)
win32gui.SendMessage(hwnd, win32con.WM_GETTEXT, 255, buffer)
text = buffer[0:bufLen*2]
return text
print ('Symbol: ', str(getEditText(d1),'utf-16'))
this script prints the selected symbol:
Symbol: ZVZZT

Related

Python: How to retrieve pressed characters in wxPython ListBox respecting keyboard layout?

In Python 3.10.5 on Windows 11 employing the wxPython 4.2.0 package, I have created a wx.ListBox widget. Now I want to listen to key presses when the list box is focused. But I need the character codes returned by the key press handler to respect the current keyboard layout, that is, for instance, whenever I press with the Czech keyboard layout the keys in the second key row that produce numbers 1, 2, 3, etc. in the English keyboard layout, I need not to receive character codes which when converted to characters using the chr() Python function result in numbers 1, 2, 3, etc., but instead I need to receive unicode char codes which when converted with chr() result in the Czech accented characters ě, š, č, etc.
The code snippet I am using so far is the following:
listbox = wx.ListBox(panel, size=(1200, 500), choices=[], style=wx.LB_SINGLE)
listbox.Bind(wx.EVT_CHAR_HOOK, onListboxCharHook)
...
def onListboxCharHook(self, event):
unicodeKey = event.GetUnicodeKey()
print(chr(unicodeKey))
In other words, the code above prints 1, 2, 3, 4, etc. when keys in the number row are pressed, but instead I need +, ě, š, č, etc. if the Czech keyboard layout is active.
I've also tried using EVT_KEY_DOWN event type instead of EVT_CHAR_HOOK, but the result is the same. Note that the wx.TextCtrl has a EVT_CHAR event type. When this event type is used, the chr(event.GetUnicodeKey()) correctly returns the characterss respecting the current keyboard layout as I need. But the problem is that wx.ListBox does not support the EVT_CHAR event type, so I am not able to get those actually pressed characters using wx.ListBox.
Therefore, is there some way using the wx.ListBox widget to translate the EVT_CHAR_HOOK event key codes into the actually pressed characters respecting the current keyboard layout?
Thanks to the answer to a similar question - Detect keyboard input with support of other languages from English, I have put together a working code which on key press prints the pressed character respecting the current keyboard layout as intended by the question. The releveant parts of that code are the following.
import wx
listbox = wx.ListBox(panel, size=(1200, 500), choices=[], style=wx.LB_SINGLE)
listbox.Bind(wx.EVT_KEY_DOWN, self.onListboxKeyDown)
def onListboxKeyDown(self, event):
rawKey = event.GetRawKeyCode()
unicodeKey = event.GetUnicodeKey()
modifiers = event.GetModifiers()
onlyShiftDown = modifiers == (wx.MOD_SHIFT)
# Handle the press of any character key without any or only with the Shift modifier
if (unicodeKey != wx.WXK_NONE) and (not modifiers or onlyShiftDown):
char = getCurrentLayoutChar(rawKey, onlyShiftDown)
print(char)
return
event.Skip()
import os
import sys
### Translate the specified virtual-key code and keyboard state
# to the corresponding Unicode character or characters.
# learn.microsoft.com/en-gb/windows/win32/api/winuser/nf-winuser-tounicodeex
### Adapted from
# the solution to https://stackoverflow.com/questions/38224277/
# by https://stackoverflow.com/users/235698/mark-tolonen
###
from ctypes import (
WinDLL, POINTER, create_string_buffer, create_unicode_buffer,
c_int32, c_uint, c_uint, c_char, c_wchar, c_int, c_uint, c_void_p
)
_ToUnicodeEx = WinDLL('user32').ToUnicodeEx
_ToUnicodeEx.argtypes = [
c_uint, # wVirtKey virtual-key code to be translated
c_uint, # wScanCode hardware scan code of ˙wVirtKey˙
POINTER(c_char), # lpKeyState current keyboard state (256-byte array)
POINTER(c_wchar), # pwszBuff buffer that receives translated chars
c_int, # cchBuff size of the `pwszBuff` buffer (in chars)
c_uint, # wFlags behavior of the function
c_void_p # dwhkl input locale identifier
]
_ToUnicodeEx.restype = c_int
def ToUn(vk,sc,wfl,hkid, shiftDown=False):
kst = create_string_buffer(256)
if shiftDown:
kst[16] = 0x80
b = create_unicode_buffer(5)
if _ToUnicodeEx(vk,sc,kst,b,5,wfl,hkid):
return b.value
else:
return chr( 0xFFFD) # Replacement Character
### Retrieve the active input locale identifier
# (formerly called the keyboard layout)
# https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getkeyboardlayout
###
# Method based on my own research; non-optimized, debugged on Windows 10…
###
from ctypes import WinDLL
user32 = WinDLL('user32', use_last_error=True)
def get_servant_conhost(pid, proclist):
"""Find “attendant” host process (conhost.exe)"""
aux = [_ for _ in proclist if _[0] == pid]
if len( aux) > 0:
auxcon = [x for x in proclist if (
x[1] == aux[0][0] and x[2] == "conhost.exe")]
if len( auxcon) == 0:
auxconret = get_servant_conhost(aux[0][1], proclist)
return auxconret
else:
auxconret = auxcon[0]
auxconret.append( aux[0][2])
return auxconret
else:
return []
def get_conhost_threads():
if sys.executable.lower().endswith('\\pythonw.exe'):
return []
import wmi
c = wmi.WMI()
w_where = ' or '.join([
'Name like "p%.exe"', # py.exe|python.exe|pwsh.exe|powershell.exe
'Name = "conhost.exe"',
'Name = "cmd.exe"'
])
w_properties = 'ProcessId, ParentProcessId, Name'
w_wql = f'SELECT {w_properties} FROM Win32_Process where {w_where}'
w_wqlaux = c.query(w_wql)
proc_list = [[wqlitem.__getattr__('ProcessId'),
wqlitem.__getattr__('ParentProcessId'),
wqlitem.__getattr__('Name')] for wqlitem in w_wqlaux]
servant_conhost = get_servant_conhost(os.getpid(), proc_list)
if len( servant_conhost) == 0:
return []
else:
try:
w_where = f'ProcessHandle = {servant_conhost[0]}'
w_wql = f'SELECT Handle FROM Win32_Thread WHERE {w_where}'
w_wqlHandle = c.query(w_wql)
wqlthreads = [x.__getattr__('Handle') for x in w_wqlHandle]
except:
wqlthreads = []
return wqlthreads
# required if run from `cmd` or from the `Run` dialog box (`<WinKey>+R`)
conhost_threads = get_conhost_threads()
def get_current_keyboard_layout():
foregroundWindow = user32.GetForegroundWindow();
foregroundProcess = user32.GetWindowThreadProcessId(int(foregroundWindow), 0);
keyboardLayout = user32.GetKeyboardLayout(int(foregroundProcess));
keyboardLayout0 = user32.GetKeyboardLayout(int(0));
if keyboardLayout == 0 or len(conhost_threads):
if keyboardLayout == 0:
keyboardLayout = keyboardLayout0
for thread in conhost_threads:
aux = user32.GetKeyboardLayout( int(thread))
if aux != 0 and aux != keyboardLayout0:
keyboardLayout = aux
break
return keyboardLayout
def getCurrentLayoutChar(key, shiftDown):
c_hkl = get_current_keyboard_layout()
char = ToUn(key, 0, 0,c_hkl, shiftDown)
return char

How To Read File Input In pySimpleGUI Then Pass It On To A Number-Crunching Processor

I would like to take input from pySimpleGUI, feed it into a normal Python var, then feed it into a music processor as I love music.
I had already tried to use wxPython for this but was unable to even get a simple fileDialog without crashing.
from pydub import AudioSegment
from os import listdir
import numpy as np
import math
import PySimpleGUI as sg
class Dankify():
song_dir = "songs"
attenuate_db = 0
accentuate_db = 2
yeet = sg.Window('Dankify ALL THE THINGS!'). Layout([[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()] ]).Read()
event, values = yeet.Read()
yeet1 = event, values
def bass_line_freq(track):
sample_track = list(track)
# c-value
est_mean = np.mean(sample_track)
# a-value
est_std = 3 * np.std(sample_track) / (math.sqrt(2))
bass_factor = int(round((est_std - est_mean) * 0.005))
return bass_factor
songfile = yeet1
for filename in listdir(songfile):
sample = AudioSegment.from_mp3(songfile)
filtered = sample.low_pass_filter(bass_line_freq(sample.get_array_of_samples()))
combined = (sample - attenuate_db).overlay(filtered + accentuate_db)
combined.export("exports/" + filename.replace(".mp3", "") + "-export.mp3", format="mp3")
However, it just does nothing, not even processing it. A reminder that I am using some open-source code and that I'm a beginner which knows nothing about how all this works and am trying to build real stuff to gain experience. Thanks!
I guess you are missing the "event loop".
Try something like this, hope it helps.
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_') ],
[sg.Input(do_not_clear=True, key='_IN_')],
[sg.Button('Show'), sg.Button('Exit')]]
window = sg.Window('Window Title').Layout(layout)
while True: # Event Loop
event, values = window.Read()
print(event, values)
if event is None or event == 'Exit':
break
if event == 'Show':
# change the "output" element to be the value of "input" element
window.FindElement('_OUTPUT_').Update(values['_IN_'])
window.Close()
You're doing 2 Read calls.
Try changing to this:
yeet = sg.Window('Dankify ALL THE THINGS!').Layout(
[[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()]])
event, values = yeet.Read()
Without the Read on the end of the first statement.
You are instantiating this class, right?
d = Dankify()

Find the last window created in Maya?

I was wondering if there is any way to find the name of the last window created in Maya, knowing that I can't add any information to the window itself before that... I checked in both the cmds and API but couldn't find anything. Maybe in PyQt but I don't know much about it.
I'm looking for any solution. Thanks
you can work with something like a close callback, save the needed information and restore it again
def restoreLayout(self):
"""
Restore the layout of each widget
"""
settings=self.settings
try:
self.restoreGeometry(settings.value("geometry").toByteArray())
self.restoreState(settings.value("windowState").toByteArray())
size=settings.value('fontSize').toFloat()[0]
self.setFontSize(size)
except:
pass
def saveLayout(self):
"""
Save the layout of each widget
Save the main window id to your data base
"""
settings=self.settings
settings.setValue("geometry", self.saveGeometry())
settings.setValue("windowState", self.saveState())
settings.setValue("fontSize", app.font().pointSize())
def closeEvent(self, event):
QtGui.QMainWindow.closeEvent(self, event)
self.saveLayout()
a simple case/idea to save tha main win_id and a child button_id:
from functools import partial
import json
def close_ui(*args):
win_id = args[0]
if cmds.window(win_id, exists=True):
cmds.deleteUI(win_id, window=True)
with open('dataBase/ui/uidata.json', 'w') as outfile:
json.dump(args, outfile)
win = {}
win["main_win"] = cmds.window()
cmds.columnLayout()
cmds.text( label='closing it' )
win["btn"] = cmds.button( label='Close')
cmds.button(win["btn"],e=True, command=partial(close_ui, win["main_win"], win["btn"]))
cmds.showWindow(win["main_win"])
Here is what I came up with, it's surely not the "cleanest" solution but it works!
# List all the currently opened windows
uisBefore = cmds.lsUI (wnd = True)
# Execute the function which may or may not create a window
func(*args, **kwargs)
# List all the opened windows again
uisAfter = cmds.lsUI (wnd = True)
# Find all the windows that were opened after executing func()
newUIs = [ui for ui in uisAfter if ui not in uisBefore]
If you create a window with the window command, you'll get back the name of the window you just created:
import maya.cmds as cmds
w = cmds.window()
c= cmds.columnLayout()
def who_am_i(*_):
print "window is", w
b = cmds.button('push', c=who_am_i)
cmds.showWindow(w)
If for some reason you don't own the code that creates the window:
existing_windows = set(cmds.lsUI(type = 'window'))
// make your window here
new_windows = list(set(cmds.lsUI(type = 'window') - existing_windows))

Python - Get Path of Selected File in Current Windows Explorer

I am trying to do this in Python 2.7. I have found an answer for it in C# here, but I am having trouble recreating it in Python. The answer suggested here does explain the concept which I understand, but I have no idea how to get it going.
Basically I just want to mark a file, press Winkey+C and have its path copied. I know how to do the hotkey part (pyhk, win32 [RegisterHotKey]), but my trouble is working around with the filepath.
Thanks in advance!
it takes a lot of hacking around, but a rough solution is below:
#!python3
import win32gui, time
from win32con import PAGE_READWRITE, MEM_COMMIT, MEM_RESERVE, MEM_RELEASE, PROCESS_ALL_ACCESS, WM_GETTEXTLENGTH, WM_GETTEXT
from commctrl import LVM_GETITEMTEXT, LVM_GETITEMCOUNT, LVM_GETNEXTITEM, LVNI_SELECTED
import os
import struct
import ctypes
import win32api
GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId
VirtualAllocEx = ctypes.windll.kernel32.VirtualAllocEx
VirtualFreeEx = ctypes.windll.kernel32.VirtualFreeEx
OpenProcess = ctypes.windll.kernel32.OpenProcess
WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
memcpy = ctypes.cdll.msvcrt.memcpy
def readListViewItems(hwnd, column_index=0):
# Allocate virtual memory inside target process
pid = ctypes.create_string_buffer(4)
p_pid = ctypes.addressof(pid)
GetWindowThreadProcessId(hwnd, p_pid) # process owning the given hwnd
hProcHnd = OpenProcess(PROCESS_ALL_ACCESS, False, struct.unpack("i",pid)[0])
pLVI = VirtualAllocEx(hProcHnd, 0, 4096, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)
pBuffer = VirtualAllocEx(hProcHnd, 0, 4096, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)
# Prepare an LVITEM record and write it to target process memory
lvitem_str = struct.pack('iiiiiiiii', *[0,0,column_index,0,0,pBuffer,4096,0,0])
lvitem_buffer = ctypes.create_string_buffer(lvitem_str)
copied = ctypes.create_string_buffer(4)
p_copied = ctypes.addressof(copied)
WriteProcessMemory(hProcHnd, pLVI, ctypes.addressof(lvitem_buffer), ctypes.sizeof(lvitem_buffer), p_copied)
# iterate items in the SysListView32 control
num_items = win32gui.SendMessage(hwnd, LVM_GETITEMCOUNT)
item_texts = []
for item_index in range(num_items):
win32gui.SendMessage(hwnd, LVM_GETITEMTEXT, item_index, pLVI)
target_buff = ctypes.create_string_buffer(4096)
ReadProcessMemory(hProcHnd, pBuffer, ctypes.addressof(target_buff), 4096, p_copied)
item_texts.append(target_buff.value)
VirtualFreeEx(hProcHnd, pBuffer, 0, MEM_RELEASE)
VirtualFreeEx(hProcHnd, pLVI, 0, MEM_RELEASE)
win32api.CloseHandle(hProcHnd)
return item_texts
def getSelectedListViewItem(hwnd):
return win32gui.SendMessage(hwnd, LVM_GETNEXTITEM, -1, LVNI_SELECTED)
def getSelectedListViewItems(hwnd):
items = []
item = -1
while True:
item = win32gui.SendMessage(hwnd, LVM_GETNEXTITEM, item, LVNI_SELECTED)
if item == -1:
break
items.append(item)
return items
def getEditText(hwnd):
# api returns 16 bit characters so buffer needs 1 more char for null and twice the num of chars
buf_size = (win32gui.SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0) +1 ) * 2
target_buff = ctypes.create_string_buffer(buf_size)
win32gui.SendMessage(hwnd, WM_GETTEXT, buf_size, ctypes.addressof(target_buff))
return target_buff.raw.decode('utf16')[:-1]# remove the null char on the end
def _normaliseText(controlText):
'''Remove '&' characters, and lower case.
Useful for matching control text.'''
return controlText.lower().replace('&', '')
def _windowEnumerationHandler(hwnd, resultList):
'''Pass to win32gui.EnumWindows() to generate list of window handle,
window text, window class tuples.'''
resultList.append((hwnd, win32gui.GetWindowText(hwnd), win32gui.GetClassName(hwnd)))
def searchChildWindows(currentHwnd,
wantedText=None,
wantedClass=None,
selectionFunction=None):
results = []
childWindows = []
try:
win32gui.EnumChildWindows(currentHwnd,
_windowEnumerationHandler,
childWindows)
except win32gui.error:
# This seems to mean that the control *cannot* have child windows,
# i.e. not a container.
return
for childHwnd, windowText, windowClass in childWindows:
descendentMatchingHwnds = searchChildWindows(childHwnd)
if descendentMatchingHwnds:
results += descendentMatchingHwnds
if wantedText and \
not _normaliseText(wantedText) in _normaliseText(windowText):
continue
if wantedClass and \
not windowClass == wantedClass:
continue
if selectionFunction and \
not selectionFunction(childHwnd):
continue
results.append(childHwnd)
return results
w=win32gui
while True:
time.sleep(5)
window = w.GetForegroundWindow()
print("window: %s" % window)
if (window != 0):
if (w.GetClassName(window) == 'CabinetWClass'): # the main explorer window
print("class: %s" % w.GetClassName(window))
print("text: %s " %w.GetWindowText(window))
children = list(set(searchChildWindows(window)))
addr_edit = None
file_view = None
for child in children:
if (w.GetClassName(child) == 'ComboBoxEx32'): # the address bar
addr_children = list(set(searchChildWindows(child)))
for addr_child in addr_children:
if (w.GetClassName(addr_child) == 'Edit'):
addr_edit = addr_child
pass
elif (w.GetClassName(child) == 'SysListView32'): # the list control within the window that shows the files
file_view = child
if addr_edit:
path = getEditText(addr_edit)
else:
print('something went wrong - no address bar found')
path = ''
if file_view:
files = [item.decode('utf8') for item in readListViewItems(file_view)]
indexes = getSelectedListViewItems(file_view)
print('path: %s' % path)
print('files: %s' % files)
print('selected files:')
for index in indexes:
print("\t%s - %s" % (files[index], os.path.join(path, files[index])))
else:
print('something went wrong - no file view found')
so what this does is keep checking if the active window is of the class the explorer window uses, then iterates through the children widgets to find the address bar and the file list view. Then it extracts the list of files from the listview and requests the selected indexes. it also gets and decodes the text from the address bar.
at the bottom the info is then combined to give you the complete path, the folder path, the file name or any combination thereof.
I have tested this on windows xp with python3.4, but you will need to install the win32gui and win32 conn packages.
# Import Statement.
import subprocess
# Trigger subprocess.
subprocess.popen(r'explorer /select,"C:\path\of\folder\file"'

Get url from chrome using python

I'm very new to python and I'm trying to print the url of an open websitein Chrome. Here is what I could gather from this page and googeling a bit:
import win32gui, win32con
def getWindowText(hwnd):
buf_size = 1 + win32gui.SendMessage(hwnd, win32con.WM_GETTEXTLENGTH, 0, 0)
buf = win32gui.PyMakeBuffer(buf_size)
win32gui.SendMessage(hwnd, win32con.WM_GETTEXT, buf_size, buf)
return str(buf)
hwnd = win32gui.FindWindow(None, "Chrome_WidgetWin_1" )
omniboxHwnd = win32gui.FindWindowEx(hwnd, 0, 'Chrome_OmniboxView', None)
print(getWindowText(hwnd))
I get this as a result:
<memory at 0x00CA37A0>
I don't really know what goes wrong, whether he gets into the window and the way I try to print it is wrong or whether he just doesn't get into the window at all.
Thanks for the help
Only through win32 can only get the information of the top-level application. If you want to get the information of each component located in the application, you can use UI Automation.
Python has a wrapper package Python-UIAutomation-for-Windows, and then you can get the browser's address bar url through the following code:
import uiautomation as auto
def get_browser_tab_url(browser: str):
"""
Get browser tab url, browser must already open
:param browser: Support 'Edge' 'Google Chrome' and other Chromium engine browsers
:return: Current tab url
"""
if browser.lower() == 'edge':
addr_bar = auto.EditControl(AutomationId='addressEditBox')
else:
win = auto.PaneControl(Depth=1, ClassName='Chrome_WidgetWin_1', SubName=browser)
temp = win.PaneControl(Depth=1, Name=browser).GetChildren()[1].GetChildren()[0]
for bar in temp.GetChildren():
last = bar.GetLastChildControl()
if last and last.Name != '':
break
addr_bar = bar.GroupControl(Depth=1, Name='').EditControl()
url = addr_bar.GetValuePattern().Value
return url
print(get_browser_tab_url('Edge'))
print(get_browser_tab_url('Google Chrome'))
print(get_browser_tab_url('Cent Browser'))
This should work:
import uiautomation as auto
control = auto.GetFocusedControl()
controlList = []
while control:
controlList.insert(0, control)
control = control.GetParentControl()
control = controlList[0 if len(controlList) == 1 else 1]
address_control = auto.FindControl(control, lambda c, d:
isinstance(c, auto.EditControl))
print('Current URL:')
print(address_control.GetValuePattern().Value)

Categories