Home Technical Talk

Alt tabbing via code from maya

polycounter lvl 10
Offline / Send Message
gilesruscoe polycounter lvl 10
Currently working with Pymel inside of Maya. I'm struggling to find a way to "alt-tab"/switch onto another open application after running a script.
Say if i clicked an "export to desktop" button, the script would then tab me onto my desktop.
Any input would be really useful, as Im very much flying blind at the moment.

Replies

  • ProperSquid
    Options
    Offline / Send Message
    ProperSquid polycounter lvl 12
    Looks like the module that you're looking for is something called subprocess.

    http://docs.python.org/2.7/library/subprocess.html

    Quick example: Let's say that you want to open up a texture in photoshop.
    import subprocess

    photoshop = r"/path/to/photoshop/photoshop.exe" # The r before the quotes lets Python know to not treat any of the / as special characters.
    texture = r"/path/to/awesome_texture.png"

    subprocess.call((photoshop, texture))
    Quick note: Subprocess requires you to have the arguments in a tuple or list. So, something like "spam eggs" would cause an error, while or ('spam', 'eggs') would work. This is why my example code has double brackets.

    As for showing the desktop, there's apparently some Windows scripting that you can do, but I haven't figured it out yet.
  • ProperSquid
    Options
    Offline / Send Message
    ProperSquid polycounter lvl 12
    Quick note that I forgot to mention. The script will stop will stop and wait for the program to close. So, in the case of Photoshop, you would have to quit out of Photoshop in order to resume with the Python script in Maya (and possibly interacting in Maya too). Subprocess will also give you the exit code of the program (0 means everything is okay, and any other number means bad things.)
  • gilesruscoe
    Options
    Offline / Send Message
    gilesruscoe polycounter lvl 10
    Awesome. This worked really well for initiating the program if its not already open. One issue is that I'm using unity as the targeted application and if Unity is already open and you try to open another instance it throws an error dialog. Is there a way to check if the Unity process is already running, and if so, bring it to the front? Or if not, a way to check if unity is already open and then do nothing.
    Cheers!
  • alfalfasprossen
    don't know if this works out of the box, just typed it down using some of my codes as a reference, maybe i missed something. I can't test it now, i'm on a mac :D

    you can of course extend that to open the program like you already did, if the window is not found etc.

    i'm using global variables to get the string to the windows callback function, you COULD use the lParam value to pass an object that contains the string for a more elegant approach, but yeah, a bit more complicated ;)
    import ctypes
    
    EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
    EnumWindows = ctypes.windll.user32.EnumWindows
    GetWindowText = ctypes.windll.user32.GetWindowTextW
    GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
    
    # the hwnd of the window, if found, None otherwise
    gTheWindow = None
    # a string that is contained in your window's title
    gWindowTitle = None
    
    def _enumWindowsCallback(hwnd, lParam):
        """ will be called from windows for every top-level window
        """
        global gTheWindow # we need to write to that global var later
        length = GetWindowTextLength(hwnd)
        buff = ctypes.create_unicode_buffer(length + 1)
        GetWindowText(hwnd, buff, length + 1)
        if gWindowTitle in buff.value:
            print "found the window"
            gTheWindow = hwnd
            return False # break the enumeration loop
        return True # check the next window
        
    def findWindow():
        """ return True if window is found
        the windows hwnd will be saved in `gTheWindow`
        """
        EnumWindows(EnumWindowsProc(_enumWindowsCallback), 0)
        if gTheWindow is None:
            print "no window with title %s found" % windowTitle
        return (gTheWindow is not None)
    
    # this is the function you want to call
    def bringWindowToFront(title):
        """ try to set focus (should automatically bring to front) on the
        window that has `title` in it's title
        """
        global gWindowTitle
        gWindowTitle = title
        if findWindow():
            ctypes.windll.user32.SetFocus(gTheWindow)
    
  • gilesruscoe
    Options
    Offline / Send Message
    gilesruscoe polycounter lvl 10
    Found some neat stuff you can do with Win32 module.
    win32gui.GetForegroundWindow() has a few tricks based around it.
    HOWEVER. For the life of me i cannot get the win32 module to install now...
    fuuuu.jpg
  • alfalfasprossen
    never used it, and depending on non-standard packages is always bad if you have to install them becaue they come in some kind of compiled form...

    use ctypes, it is a standard-module and you can do everything with it that you can do with Win32 module, maybe with a little bit more work on your side ;)
  • passerby
    Options
    Offline / Send Message
    passerby polycounter lvl 12
    Comtypes is a good alternative I find to the win32 one which can be buggy, I have had great success controling Photoshop with maya's python interpreter this way.

    Actually if you look in my SIG at the psLink video that was all done with the openmaya api and comtypes with maya's built in python.
Sign In or Register to comment.