Find and click default button on modal dialog?

-1

I started with the code found here - https://color-of-code.de/programming/c-sharp/detect-waiting-for-user-input. I can find a modal dialog if one is open. I'm looking for a modal dialog that is open in a different app, not sure if that matters or not. Now what I want to do it click the default button. Calling var dwButtonDef = SendMessage(hWnd, DM_GETDEFID, IntPtr.Zero, IntPtr.Zero); gives me a control id. But calling var btHwnd = GetDlgItem(hWnd, dwButtonDef); isn't working like I thought it would. I get error 1421 Control ID not found. I'm sure I'm overlooking something obvious or just or misunderstanding how these methods work. But I'm stuck.

void Main()
{

    Console.WriteLine(ModalChecker.IsWaitingForUserInput(12768));
}

public class ModalChecker
{
    public static Tuple<bool, string> IsWaitingForUserInput(int processId)
    {
        Process process = Process.GetProcessById(processId);
        ModalChecker checker = new ModalChecker(process);
        return checker.WaitingForUserInput;
    }

    // The process we want the info from
    private Process _process;
    private Boolean _waiting;
    private StringBuilder _modalText;

    private ModalChecker(Process process)
    {
        _process = process;
        _waiting = false; //default
        _modalText = new StringBuilder();
    }

    private Tuple<bool, string> WaitingForUserInput
    {
        get
        {
            EnumWindows(new EnumWindowsProc(this.WindowEnum), 0);
            return new Tuple<bool, string>(_waiting, _modalText.ToString());
        }
    }

    private int WindowEnum(IntPtr hWnd, int lParam)
    {
        if (hWnd == _process.MainWindowHandle)
            return 1;

        IntPtr processId;
        GetWindowThreadProcessId(hWnd, out processId);
        if (processId.ToInt32() != _process.Id)
            return 1;

        uint style = GetWindowLong(hWnd, GWL_EXSTYLE);
        if ((style & WS_EX_DLGMODALFRAME) != 0)
        {
            _waiting = true;

            int captionLength = GetWindowTextLength(hWnd);
            StringBuilder caption = new StringBuilder(captionLength + 1);
            if (GetWindowText(hWnd, caption, caption.Capacity) > 0)
            {
                _modalText.Append(caption.ToString() + " ");
            }

            var dwButtonDef = SendMessage(hWnd, DM_GETDEFID, IntPtr.Zero, IntPtr.Zero);
            Console.WriteLine(dwButtonDef);
            var btHwnd = GetDlgItem(hWnd, dwButtonDef);
            Console.WriteLine(btHwnd);

            int error = Marshal.GetLastWin32Error();
            Console.WriteLine("The last Win32 Error was: " + error);

            return 0; // stop searching further
        }
        return 1;
    }
}

///////////////////

[DllImport("user32")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32")]
static extern bool GetMenuItemInfo(IntPtr hMenu, UInt32 uItem, bool fByPosition, [In, Out] MENUITEMINFO lpmii);
[DllImport("user32", SetLastError = true)]
static extern IntPtr GetDlgItem(IntPtr hDlg, IntPtr nIDDlgItem);

[Flags]
enum MIIM
{
    BITMAP = 0x00000080,
    CHECKMARKS = 0x00000008,
    DATA = 0x00000020,
    FTYPE = 0x00000100,
    ID = 0x00000002,
    STATE = 0x00000001,
    STRING = 0x00000040,
    SUBMENU = 0x00000004,
    TYPE = 0x00000010
}
[StructLayout(LayoutKind.Sequential)]
public class MENUITEMINFO
{
    public int cbSize;
    public uint fMask;
    public uint fType;
    public uint fState;
    public uint wID;
    public IntPtr hSubMenu;
    public IntPtr hbmpChecked;
    public IntPtr hbmpUnchecked;
    public IntPtr dwItemData;
    public IntPtr dwTypeData;
    public uint cch;
    public IntPtr hbmpItem;

    public MENUITEMINFO()
    {
        cbSize = Marshal.SizeOf(typeof(MENUITEMINFO));
    }
}
const int WM_NULL = 0x0000;
const int SC_CLOSE = 0xF060;
const int MIIM_STATE = 0x00000001;
const int MIIM_STRING = 0x00000040;
const int MFT_STRING = 0x00000000;
const int WM_USER = 0x0400;
const int DM_GETDEFID = (WM_USER + 0);
const int DM_SETDEFID = (WM_USER + 1);
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;

///////////////////

const int WM_CLOSE = 0x0010;
const int WM_GETTEXT = 0x000D;
const int WM_GETTEXTLENGTH = 0x000E;
private const int WS_EX_DLGMODALFRAME = 0x00000001;
private const int GWL_EXSTYLE = (-20);
private delegate int EnumWindowsProc(IntPtr hWnd, int lParam);


[DllImport("user32")]
private extern static int EnumWindows(EnumWindowsProc lpEnumFunc, int lParam);

[DllImport("user32", CharSet = CharSet.Auto)]
private extern static uint GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32")]
private extern static uint GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);

[DllImport("User32", SetLastError = true)]
private extern static IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

[DllImport("User32", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, StringBuilder sb);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);

[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

[DllImport("user32.dll")]
static extern uint IsDlgButtonChecked(IntPtr hDlg, int nIDButton);

[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
c#
pinvoke
ui-automation
asked on Stack Overflow Apr 25, 2021 by nickfinity • edited Apr 26, 2021 by nickfinity

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0