Здравствуйте!
Переду сразу к делу, столкнулся с такой проблемой:
Как правильно нажать на кнопку в радной программе "Удаленный помощник" из Windows7.
Пытаюсь ее нажать следующим образом:
Освновной код:
namespace ConsoleFindWindows {
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
internal sealed class Program {
static void Main(string[] args) {
Process[] ms = Process.GetProcessesByName("msra");
Process msra = ms.Length > 0 ? ms[0] : Process.Start("msra", "/offerra");
//Дожидаемся запуска
Thread.Sleep(300);
IntPtr hWndParent = msra.MainWindowHandle;
#region Тут отрабатывает нажатие на кнопку Обзор в открытом окне Выполнить, если заранее его открыть
IntPtr runWindowHandle = WinApi.FindWindow(null, "Выполнить");
if (runWindowHandle != IntPtr.Zero) {
IntPtr hButton = WinApi.FindWindowEx(runWindowHandle, IntPtr.Zero, "Button", "Об&зор...");
PushButton(hButton);
}
#endregion
//Получение списка всех handle-ов процесса
List<IntPtr> handles = WinApi.GetChildWindows(hWndParent);
//Перебераем список в поиска нужного handle
foreach (IntPtr intPtr in handles) {
//Поиска handle нужной кнопки
IntPtr hWndChild = WinApi.FindWindowEx(intPtr, IntPtr.Zero, "Button", "Отмена");
//Нашли нужный нам handle
if (hWndChild != IntPtr.Zero) {
WinApi.SetForegroundWindow(hWndChild);
//Отправляем сообщение о нажатие кнопки
PushButton(hWndChild);
}
}
Console.WriteLine("Нажмите любую клавишу для закрытия процесса");
Console.ReadKey();
}
private static void PushButton(IntPtr handle) {
//Переводим фокус на кнопку
WinApi.SetFocus(handle);
WinApi.PostMessage((Int32)handle, (int)WinApi.ButtonControlMessages.BM_CLICK, 0, IntPtr.Zero);
}
}
}
Вспомогательный код:
namespace ConsoleFindWindows {
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public static class WinApi {
#region Delegates
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
#endregion
#region Enums
public enum ButtonControlMessages : uint {
BM_GETCHECK = 0x00F0,
BM_SETCHECK = 0x00F1,
BM_GETSTATE = 0x00F2,
BM_SETSTATE = 0x00F3,
BM_SETSTYLE = 0x00F4,
BM_CLICK = 0x00F5,
BM_GETIMAGE = 0x00F6,
BM_SETIMAGE = 0x00F7
}
public enum GetWindow_Cmd : uint {
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
public enum WindowsMessage : uint {
WM_KEYDOWN = 256,
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_SETFOCUS = 0x0007,
WM_ACTIVATE = 0x0006,
WM_ENABLE = 0x000A
}
#endregion
#region Public Methods
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(
IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
public static List<IntPtr> GetChildWindows(IntPtr parent) {
var result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try {
EnumWindowProc childProc = EnumWindow;
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally {
if (listHandle.IsAllocated) {
listHandle.Free();
}
}
return result;
}
[DllImport("user32.dll", SetLastError = true)]
public static extern int PostMessage(int hWnd, int msg, int wParam, IntPtr lParam);
[DllImport("user32.dll")] //, CharSet = CharSet.Auto)]
public static extern int SendMessage(int hWnd, UInt32 msg, Int32 wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
#endregion
#region Methods
private static bool EnumWindow(IntPtr handle, IntPtr pointer) {
GCHandle gch = GCHandle.FromIntPtr(pointer);
var list = gch.Target as List<IntPtr>;
if (list == null) {
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
#endregion
}
}
В чем может быть нюанс при отправке события о нажатии кнопки в "Удаленном помощнике"?