How can I maximize a specific window with Python? - python

I'm trying to maximize a specific window with python...
Here is the deal:
I have a script that opens 2 firefox windows (selenium rc), and I need to maximize the second window, the last one that opens...
How can I do it?
I'm using this command
window = win32gui.GetForegroundWindow()
win32gui.MoveWindow(window, 0, 0, 1440, 900, True)
that works perfectly, but only with the focus window... and the second window of firefox witch opens with the script doesnt get focused...

This should work
import win32gui, win32con
hwnd = win32gui.GetForegroundWindow()
win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE)

If you don't want to install separate modules you could use the inbuilt ctypes module. The usage is not that different from the accepted answer above, except that you interact with the DLLs themselves and don't have to install anything else.
First here is the code:
import ctypes
user32 = ctypes.WinDLL('user32')
SW_MAXIMISE = 3
hWnd = user32.GetForegroundWindow()
user32.ShowWindow(hWnd, SW_MAXIMISE)
Now the explanation:
Get ctypes module.
Get the appropriate runtime, for reference use the Windows documentation and look under "Requirements".
Set the SW_MAXIMISE value to 3 since this is the value (indicated in the documentation) to set the window to maximum.
hWnd = user32.GetForegroundWindow() retrieves the foreground window (the window that is in front of all the others) - see here for the complete description on the function.
Use ShowWindow() to control the windows show state. This takes two arguments, the handle to the window (defined above as hWnd) and how the window should be seen (set as 3 in SW_MAXIMISE = 3). You can see the documentation for a more complete list of the various options.
You could of course put this into a function to make it easy to use.
Another approach:
Since in this case there are no worries about being cross platform, you could build a C or C++ extension instead.
Benefits:
no ctypes (which is sometimes worth considering, see the answers to this question)
Downfalls:
needs to be compiled (since it's on Windows only, you only need to worry about compiling for x32 bit and x64 bit)
must be a module (i.e. you can't intergrate it in one file)
requires a minimum knowlege of either C or C++ as well as the Python api itself
The actual function to be called should not be that difficult:
static PyObject * max_win(PyObject *self, PyObject *args) {
ShowWindow(GetForegroundWindow(), SW_MAXIMISE);
return Py_BuildValue(""); // Return nothing
}
Note that this is only a fragment of the actual code needed

Related

Getting the instance handle of a window in python (ctypes)

I've been trying to create a simple window using win32api but in python using the ctypes lib.
Now the first thing i need is the programs console windows instance handle.
For getting that i need to get a handle to the console window which is doable by using Kernel.dll GetConsoleWindow() Function. Then i pass that to the GetWindowLongA() Function of the User32.dll library which should return the python equivalent of HINSTANCE in windows.h header of C which should be an int. but all i get is 0 which means it has failed.
The code i currently have is:
windows = windll.LoadLibrary("User32.dll")
kernel = windll.LoadLibrary("Kernel32.dll")
consoleHandle = kernel.GetConsoleWindow()
print(f"Console HWND : {consoleHandle}")
instanceHandle: ctypes.wintypes.HINSTANCE = windows.GetWindowLongA(consoleHandle, c_int(-6))
print(f"Console HINSTANCE : {instanceHandle}")
print(f"LAST FUNCTION ERROR : {kernel.GetLastError()}")
OUTPUT :
Console HWND : 198610
Console HINSTANCE : 0
LAST FUNCTION ERROR : 1413
now error 1413 is ERROR_INVALID_INDEX (based on System error codes) which is probably caused cause i passed c_int(-6) as the int nIndex argument which must represent the GWL_HINSTANCE macro defined in windows.h (based on this windows doc) but it doesnt work.
What should i do to fix it and why doesnt it work?
Console Windows are not the same as GUI Windows. GetActiveWindow() is what you want, and needs to be run for a GUI Python IDE, not a console window.
Assuming 64-bit Windows and Python, you also need GetWindowLongPtrA() (or W) to retrieve handles.
To ensure you retrieve the last error cause by a Windows API failure using ctypes, use the use_last_error=True parameter and call ctypes.get_last_error() to retrieve it. The error code is only valid after the specific Windows call that failed, ctypes will capture that with this method. Otherwise, you don't know what Windows APIs might be called by the Python implementation between the ctypes API call to the function that failed and the ctypes GetLastError() API call. I got 1400 (invalid window handle) when calling GetWindowLongPtrA() with a console handle.
It's also good practice to fully specify .argtypes and .restype, esp. for 64-bit Windows as the default return type is c_int (32-bit) and handles are 64-bit in that architecture.
Below works for a 64-bit Python IDE:
import ctypes as ct
from ctypes import wintypes as w
GWLP_HINSTANCE = -6
# LONG_PTR isn't defined by wintypes.
# LPARAM is long on 32-bit, longlong on 64-bit,
# which matches LONG_PTR type.
LONG_PTR = w.LPARAM
u32 = ct.WinDLL('user32', use_last_error=True)
GetWindowLongPtrA = u32.GetWindowLongPtrA
GetWindowLongPtrA.argtypes = w.HWND, ct.c_int
GetWindowLongPtrA.restype = LONG_PTR
GetActiveWindow = u32.GetActiveWindow
GetActiveWindow.argtypes = ()
GetActiveWindow.restype = w.HWND
hwnd = GetActiveWindow()
print(f'hwnd = {hwnd:#x}')
instanceHandle = GetWindowLongPtrA(hwnd, GWLP_HINSTANCE)
print(f'instanceHandle = {instanceHandle:#x}')
Output:
hwnd = 0xd044c
instanceHandle = 0x7ff700250000

Interacting with AURA_SDK.dll through python using ctypes

I'm trying to control my ASUS ROG Flare keyboard LED colors using python.
I downloaded the Aura Software Developer Kit from the ASUS website.
link here: https://www.asus.com/campaign/aura/us/SDK.php
inside the kit there is a menu guide and a dll file called AURA_SDK.dll. The guide says that with the mentioned dll the keyboard can be controlled.
I'm using the ctypes python package and succeeded in loading the package, but when I'm calling the first function to obtain control on the keyboard the program fails because I don't fully understand the argument the function needs to run.
Documentation from the guide:
Code I am trying:
import ctypes
path_dll = 'AURA_SDK.dll'
dll = ctypes.cdll.LoadLibrary(path_dll)
res = dll.CreateClaymoreKeyboard() # fails here
Any ideas on how to create this argument?
Thanks in advance.
This should do it. A good habit to get into is always define .argtypes and .restype for the functions you call. This will make sure parameters are converted correctly between Python and C types, and provide better error checking to help catch doing something incorrectly.
There are also many pre-defined Windows types in wintypes so you don't have to guess what ctype-type to use for a parameter.
Also note that WINAPI is defined as __stdcall calling convention and should use WinDLL instead of CDLL for loading the DLL. On 64-bit systems there is no difference between standard C calling convention (__cdecl) and __stdcall, but it will matter if you are using 32-bit Python or desire portability to 32-bit Python.
import ctypes as ct
from ctypes import wintypes as w
dll = ct.WinDLL('./AURA_SDK') # Use WinDLL for WINAPI calls.
dll.CreateClaymoreKeyboard.argtypes = ct.POINTER(ct.c_void_p), # tuple of arguments
dll.CreateClaymoreKeyboard.restype = w.DWORD
handle = ct.c_void_p() # Make an instance to pass by reference and receive the handle.
res = dll.CreateClaymoreKeyboard(ct.byref(handle))
# res is non-zero on success

How can I use Python 3.3 to continuously update my MouseSpeed in Windows?

I am developing a python script to drive a prototype I'm developing, and my current stumbling block is attempting to continuously write to the MouseSensitivity register in Windows. I'm using Windows 7, for specificity.
Unfortunately, I've hit some dead ends.
I've attempted to use pywin32 to write to the registry, but have not succeeded. After some searching, I've come across the SystemParametersInfo Function, but have not had any success with that either.
Essentially, for the purpose of solving this crisis, I've installed pyserial, pywin32, and ctypes (it appears that pywin32 may not be required). Assume I have an integer variable that will be between (and including) 1 to 20.
What I have for code right now is listed below. Much of it has been modified from here, as it appears that the author was using python, ctypes, user32.dll, and the SystemParametersInfo Function. However, when I run the code below, the shell enters a loop where the next line gets two tabs of space, and the cursor sits blinking until I keyboard interrupt. Any ideas?
import sys
import ctypes
import ctypes.wintypes
num = 12 # Between 1 and 20
SystemParametersInfo = ctypes.windll.user32.SystemParametersInfoW
SystemParametersInfo.argtypes = (
ctypes.wintypes.UINT,
ctypes.wintypes.UINT,
ctypes.c_void_p,
ctypes.wintypes.UINT,
)
SPI_SETMOUSESPEED = 0x0071
SystemParametersInfo(SPI_SETMOUSESPEED, 0, ctypes.cast(num, ctypes.c_void_p, 0)

system wide shortcut for Mac OS X

So I was asked to port some internal helper applications to Mac OS X 10.7.
Works all quite welll as the platform dependent code is minimal anyhow, but one application needs a system wide shortcut to function (i.e. RegisterHotkey functionality) and I can't find any documentation on how I'd do this on a Mac.
The program is using a PyQt gui with Python 3.2. and the corresponding code for windows is basically:
def register_hotkey(self):
hwnd = int(self.winId())
modifiers, key = self._get_hotkey()
user32.RegisterHotKey(hwnd, self._MESSAGE_ID, modifiers, key)
and then to receive the hotkey events:
def winEvent(self, msg):
if msg.message == w32.WM_HOTKEY:
self.handle_hotkey()
return True, id(msg)
return False, id(msg)
Note that I don't need a python variant, I can easily write a simple c extension - so C/objective-c solutions are welcome as well.
I recently coded up an extension to quodlibet capturing multimedia keys (since absorbed into quodlibet itself); for your setup the same process applies.
I used the Quartz CGEventTapCreate hook and event loop, and the Cocoa AppKit framework to decipher key codes to achieve this.
The following code registers a python callback which is passed global key presses, and starts the event loop:
import Quartz
from AppKit import NSKeyUp, NSSystemDefined, NSEvent
# Set up a tap, with type of tap, location, options and event mask
tap = Quartz.CGEventTapCreate(
Quartz.kCGSessionEventTap, # Session level is enough for our needs
Quartz.kCGHeadInsertEventTap, # Insert wherever, we do not filter
Quartz.kCGEventTapOptionListenOnly, # Listening is enough
Quartz.CGEventMaskBit(NSSystemDefined), # NSSystemDefined for media keys
keyboardTapCallback,
None
)
runLoopSource = Quartz.CFMachPortCreateRunLoopSource(None, tap, 0)
Quartz.CFRunLoopAddSource(
Quartz.CFRunLoopGetCurrent(),
runLoopSource,
Quartz.kCFRunLoopDefaultMode
)
# Enable the tap
Quartz.CGEventTapEnable(tap, True)
# and run! This won't return until we exit or are terminated.
Quartz.CFRunLoopRun()
I defined a tap for system defined keys only (media keys); you'll have to specify a different event mask (CGEventMaskBit with one or more Event Types); e.g. Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp) for key up events.
The callback should have the following signature (it implements the CGEventTapCallBack method from the Quartz API:
def keyboardTapCallback(proxy, type_, event, refcon):
# Convert the Quartz CGEvent into something more useful
keyEvent = NSEvent.eventWithCGEvent_(event)
I converted the Quartz event into a NSEvent, because all the information I could find on Mac multimedia keys was referring to that class.
In principle you can achieve the same thing with the AppKit APIs too, but then your Python application is treated as a Mac Application (visible in the Dock with an icon and everything), while I wanted this to be kept in the background altogether.
Using the power of google, I found this snippet of code, which allows the registration of global hotkeys for Mac OS X
You'll need to add the Carbon framework, and probably a bridged cast for ARC when passing the Objective-C self pointer to the C function.
At a minimum, you'll also need to:
#import <Carbon/Carbon.h>
The keycodes can be seen on this page explaining the virtual key codes.
Why has nobody ever mentioned the hammerspoon, which supports custom global system shortcuts, which can invoke shell command or launch UI application like Safari, PHOTOSHOP.
The following is an example written by me demonstrating how to invoke shell function with global hotkeys.
https://gist.github.com/BigSully/0e59ab97f148bc167ea19dbd42ebef4b
Use hs.execute to execute shell command, either non-interactive or interactive.
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "P", function()
local output = hs.execute("toggleProxy", true)
hs.alert.show(output)
end)
or
Use hs.application.launchOrFocus to launch application
hs.application.launchOrFocus("Safari")

Finding the Current Active Window in Mac OS X using Python

Is there a way to find the application name of the current active window at a given time on Mac OS X using Python?
This should work:
#!/usr/bin/python
from AppKit import NSWorkspace
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName
Only works on Leopard, or on Tiger if you have PyObjC installed and happen to point at the right python binary in line one (not the case if you've installed universal MacPython, which you'd probably want to do on Tiger). But Peter's answer with the Carbon way of doing this will probably be quite a bit faster, since importing anything from AppKit in Python takes a while, or more accurately, importing something from AppKit for the first time in a Python process takes a while.
If you need this inside a PyObjC app, what I describe will work great and fast, since you only experience the lag of importing AppKit once. If you need this to work as a command-line tool, you'll notice the performance hit. If that's relevant to you, you're probably better off building a 10 line Foundation command line tool in Xcode using Peter's code as a starting point.
The method in the accepted answer was deprecated in OS X 10.7+. The current recommended version would be the following:
from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print(active_app_name)
First off, do you want the window or the application name? This isn't Windows—an application process on Mac OS X can have multiple windows. (Furthermore, this has also been true of Windows for a few years now, although I have no idea what the API looks like for that.)
Second, Carbon or Cocoa?
To get the active window in Cocoa:
window = NSApp.mainWindow()
To get the name of your process in Cocoa:
appName = NSProcessInfo.processInfo().processName()
Edit: Oh, I think I know what you want. The name of the frontmost process, right?
I don't think there's a way to do it in Cocoa, but here's how to do it in Carbon in C:
ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
/*error check*/
CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
/*error check*/
Remember to CFRelease(processName) when you're done with it.
I'm not sure what that will look like in Python, or if it's even possible. Python doesn't have pointers, which makes that tricky.
I know PyObjC would translate the latter argument to CopyProcessName into err, processName = CopyProcessName(…), but the Carbon bindings don't rely on PyObjC (they're part of core Python 2), and I'm not sure what you do about the PSN either way.
I needed the current frontmost application in a Python script that arranges the windows nicely on my screen (see move_window).
Of course, the complete credit goes to Peter! But here is the complete program:
#include <Carbon/Carbon.h>
int main(int, char) {
ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
printf("%s\n", CFStringGetCStringPtr(processName, NULL));
CFRelease(processName);
}
Build with gcc -framework Carbon filename.c

Categories