Код, который вы пытаетесь использовать, использует заголовки отдельных кнопок для их идентификации.Например, он использует следующий код для получения дескриптора кнопки «1»:
hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "Button", "1");
, который указывает «Button» для имени класса окна и «1» для имениокно (в случае кнопки, это то же самое, что текст заголовка, отображаемый на самой кнопке).
Этот код прекрасно работал в Windows XP (и предыдущих версиях), где кнопки калькулятора были идентифицированы кактекстовые подписи.Кнопка «1» имела название окна «1», и, таким образом, «1» отображалось как заголовок кнопки.
Однако, похоже, что все изменилось под Windows 7 (возможно, под Vista,хотя я не могу проверить это, потому что у меня нет доступа к такой системе).Использование Spy ++ для исследования окна калькулятора подтверждает, что кнопка «1» больше не имеет названия окна «1».На самом деле, у него вообще нет названия окна;заголовок NULL.Предположительно, новый причудливый вид калькулятора требовал, чтобы кнопки были нарисованы на заказ, поэтому подписи больше не нужны, чтобы указать, какая кнопка соответствует какой функции.Пользовательские процедуры рисования позаботятся о том, чтобы нарисовать необходимые заголовки.
Поскольку ни одна кнопка не может быть найдена с указанным вами текстом окна, для дескриптора окна возвращается значение 0 (NULL
).
Документация для функции FindWindowEx
указывает, что вы можете указать NULL
для параметра lpszWindow
, но это, конечно, будет соответствовать всем окнамуказанный класс.Вероятно, не то, что вы хотите в этом случае, так как приложение калькулятора имеет кучу кнопок.
Я не знаю хорошего обходного пути.Калькулятор не был разработан, чтобы быть «автоматизированным» таким образом, и Microsoft никогда не гарантировала, что они не изменят его внутреннюю работу.Это риск, которым вы рискуете, используя этот подход, чтобы связываться с окнами других приложений.
РЕДАКТИРОВАТЬ: Код, на который вы ссылаетесь, также неверен в другом довольно серьезном смыследаже на более ранних версиях Windows.Он объявляет переменную hwnd
как тип int
, а не как тип IntPtr
.Поскольку дескриптор окна - это указатель , вы всегда должны хранить его как тип IntPtr
.Это также исправляет уродливое приведение при вызове функции FindWindowEx
, которое должно было отправлять красные флаги.
Вам также необходимо исправить объявление SendMessage
, чтобы его первый параметр имел тип IntPtr
.
Код должен быть написан так:
IntPtr hwnd = IntPtr.Zero;
IntPtr hwndChild = IntPtr.Zero;
//Get a handle for the Calculator Application main window
hwnd = FindWindow(null, "Calculator");
if(hwnd == IntPtr.Zero)
{
if(MessageBox.Show("Couldn't find the calculator" +
" application. Do you want to start it?",
"TestWinAPI",
MessageBoxButtons.YesNo) == DialogResult.Yes)
{
System.Diagnostics.Process.Start("Calc");
}
}
else
{
//Get a handle for the "1" button
hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Button", "1");
//send BN_CLICKED message
SendMessage(hwndChild, BN_CLICKED, 0, IntPtr.Zero);
//Get a handle for the "+" button
hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Button", "+");
//send BN_CLICKED message
SendMessage(hwndChild, BN_CLICKED, 0, IntPtr.Zero);
//Get a handle for the "2" button
hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Button", "2");
//send BN_CLICKED message
SendMessage(hwndChild, BN_CLICKED, 0, IntPtr.Zero);
//Get a handle for the "=" button
hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Button", "=");
//send BN_CLICKED message
SendMessage(hwndChild, BN_CLICKED, 0, IntPtr.Zero);
}