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);
User contributions licensed under CC BY-SA 3.0