Author Topic: Check window "show" state  (Read 4507 times)

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Check window "show" state
« on: December 18, 2017, 12:35:54 PM »
Currently the "Perform a Window Function" actions allow the user to change the "show" state of a given window or process based on its title information or process name, respectively. However there is not a way to obtain the show state of a given window. Below you will find a profile and associated C# inline function code for doing just that. The use cases may be narrow, but I figured I'd share it anyway.

Please note:
  • In its current state this profile will not be able to search for hidden windows. An example of this is making the command search for "VoiceAttack" when VoiceAttack is minimized to the system tray. This is because the window handle (which is needed to make the inline function work) for a hidden window is more difficult to obtain than for a non-hidden window. There are ways around this, but I choose not to include this functionality at this time for the sake of simplicity.
  • The profile is set up so that if there are multiple windows that have titles that match your search term only the last match (whatever is programmatically encountered last by the inline function) will be outputted to the event log. Though I've included some code lines (commented out) in the inline function that would output every result to the log. I figured folks would have a reasonably specific search term and then would want to pass that information back to VoiceAttack for further actions. Obviously feel free to change it however you see fit.
Cheers! :)

VoiceAttack Command Code:
Code: [Select]
// Define window title text you want to search for
Set Text [TitleSearchText] to 'Notepad'

// Define type of text search you want to perform (case sensitive or insensitive)
Set Boolean [TitleSearchSensitivity] to True

// C# inline function for obtaining window state for all windows containing title text matching TitleSearchText
Inline C# Function: Get window state for all windows matching search term, wait until execution finishes

// Output result of window title search and window state (if available)
// If the inline function finds multiple matches only the final match will be outputted here
Write '[Blue] Window Title = {TXT:FullWindowTitle} ; Window State = {TXT:WindowShowState}' to log

Inline Function Code:
Referenced Assemblies = System.dll;System.Drawing.dll;
Code: [Select]
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

public class VAInline
{
    public void main()
    {
        string searchTerm = VA.GetText("TitleSearchText"); // Retrieve window title text to search for from VoiceAttack text variable
        bool CaseSensitiveSearch = (bool)VA.GetBoolean("TitleSearchSensitivity"); // Retrieve desired search case sensitivity from VoiceAttack boolean variable
        string windowState = ""; // Initialize string variable for storing window state information
        string FullWindowTitle = ""; // Initialize string variable for storing complete window title

        foreach (Process pList in Process.GetProcesses()) // Loop through all active processes
        {
            // Check if searchTerm is found in window title
            bool WindowSearchResult; // Initialize boolean variable for storing result of the window title search
            if (CaseSensitiveSearch == true) // Check if case sensitive search was requested
                WindowSearchResult = pList.MainWindowTitle.Contains(searchTerm); // Case-sensitive searchTerm comparison
            else
                WindowSearchResult = pList.MainWindowTitle.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0; // Case-insensitive searchTerm comparison
           
            if (WindowSearchResult) // Check if the searchTerm was found within a window's title text
            {
                WINDOWPLACEMENT placement = new WINDOWPLACEMENT(); // Create new WINDOWPLACEMENT instance
                StringBuilder title = new StringBuilder(256); // Create new StringBuilder instance
                GetWindowPlacement(pList.MainWindowHandle, ref placement); // Get the WINDOWPLACEMENT data using the inputted window handle
                GetWindowText(pList.MainWindowHandle, title, 256); // Get the window title using the inputted window handle
                FullWindowTitle = title.ToString(); // Store full title of found window

                switch (placement.showCmd) // switch statement for processing different window "show" states
                {
                    case 1: // Window placement code "1"
                        windowState = "Normal";
                        break; // Terminate switch statement
                    case 2: // Window placement code "2"
                        windowState = "Minimized";
                        break; // Terminate switch statement
                    case 3: // Window placement code "3"
                        windowState = "Maximized";
                        break; // Terminate switch statement
                }
                VA.SetText("FullWindowTitle", FullWindowTitle); // Store full window title text in VoiceAttack variable
                VA.SetText("WindowShowState", windowState); // Store window show state in VoiceAttack variable
                //VA.WriteToLog("Window Title = " + FullWindowTitle + " ; Window State = " + windowState, "green"); // Output info to VoiceAttack event log
            }
        }

        if (windowState == "") // Check if windowState still is blank
        {
            FullWindowTitle = "Not Found"; // Store search result in VoiceAttack variable
            windowState = "N/A"; // Store search result in VoiceAttack variable
            VA.SetText("FullWindowTitle", FullWindowTitle); // Store full window title text in VoiceAttack variable
            VA.SetText("WindowShowState", windowState); // Store window show state in VoiceAttack variable
            //VA.WriteToLog("Window Title = " + FullWindowTitle + " ; Window State = " + windowState, "red"); // Output info to VoiceAttack event log
        }
    }

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

    private struct WINDOWPLACEMENT
    {
        public int length;
        public int flags;
        public int showCmd;
        public System.Drawing.Point ptMinPosition;
        public System.Drawing.Point ptMaxPosition;
        public System.Drawing.Rectangle rcNormalPosition;
    }
}

// References:
// https://stackoverflow.com/questions/1003073/how-to-check-whether-another-app-is-minimized-or-not
// https://stackoverflow.com/questions/13547639/return-window-handle-by-its-name-title
// https://stackoverflow.com/questions/444798/case-insensitive-containsstring
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms632611(v=vs.85).aspx