Здравствуйте!
Переду сразу к делу, столкнулся с такой проблемой:
Как правильно нажать на кнопку в радной программе "Удаленный помощник" из 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
}
}
В чем может быть нюанс при отправке события о нажатии кнопки в "Удаленном помощнике"?
Точно не скажу, но может нужно WM_LBUTTONDOWN отсылать?
Попробуйте послушать через утилиту Spy++ (входит в состав Visual Studio) какие сообщения приходят к кнопке и отошлите ей те же самые события.
Здравствуйте, StarLancer, Вы писали:
В свое время для КПК шника делал
http://rsdn.ru/forum/pda/2953653.aspxАвтор: Serginio1
Дата: 16.05.08
Попробуй нажатие через паузу. И поищи в гугле "Не срабатывает SendMessage кнопка"
Например
http://www.delphisources.ru/forum/showthread.php?t=6815
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, StarLancer, Вы писали:
S>В свое время для КПК шника делал
S>http://rsdn.ru/forum/pda/2953653.aspxАвтор: Serginio1
Дата: 16.05.08
S>Попробуй нажатие через паузу. И поищи в гугле "Не срабатывает SendMessage кнопка"
S>Например http://www.delphisources.ru/forum/showthread.php?t=6815
Пробывал по разному отправлять сообщения, и через KEYDOWN, KYEUP не доходит он в очередь и все....SPY++ не показывает.
В других программ работает а тут нет.....может влият отправка сообщений, если у родительского окна много дочерних окон, в котором и находится эта кнопка? Или должно быть побарабану, т.к. имею ее handle?
Ссылки посмотрю
Код заработал....НО только с АДМИНИСКИМИ ПРАВАМИ, отсюда соответсвенно вопрос, как проделать этот фокус из под пользователя?
ОСь Windows 7 x64....почему для нажатия это вшивой кнопки нужны админские права?
Если после вызова воспользоваться GetLastError, то под пользователем получаем код ошибки Access Denied....че за бред??