Приложение WinForms отображается в Windows как окно. Чтобы проверить, являются ли контролы также окнами Windows, надо каким-то образом получить информацию об окне приложения и обо всех дочерних окнах.
Как это можно сделать на C#?
Т.е. нужен метод на C#, который на основе имени окна или номера процесса окна вернет информацию об окне и вложенных окнах.
Этот метод поможет дать точный ответ на вопрос возникший тут: форма/диалог/меню/всплывающее окно/поиск кортаны (Win+S) - это окно или нет?
Asked
Active
Viewed 4,591 times
4
Stack
- 9,452
3 Answers
7
Для получения списка окон вам придется прибегнуть к WinApi функции EnumWindows. Описание к этой функции вы можете найти здесь.
Полагаю вы хотите найти конкретное окошко, по этому прилагаю пример:
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
// Delegate to filter which windows to include
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
/// <summary> Get the text for the window pointed to by hWnd </summary>
public static string GetWindowText(IntPtr hWnd)
{
int size = GetWindowTextLength(hWnd);
if (size > 0)
{
var builder = new StringBuilder(size + 1);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
/// <summary> Find all windows that match the given filter </summary>
/// <param name="filter"> A delegate that returns true for windows
/// that should be returned and false for windows that should
/// not be returned </param>
public static IEnumerable<IntPtr> FindWindows(EnumWindowsProc filter)
{
IntPtr found = IntPtr.Zero;
List<IntPtr> windows = new List<IntPtr>();
EnumWindows(delegate(IntPtr wnd, IntPtr param)
{
if (filter(wnd, param))
{
// only add the windows that pass the filter
windows.Add(wnd);
}
// but return true here so that we iterate all windows
return true;
}, IntPtr.Zero);
return windows;
}
/// <summary> Find all windows that contain the given title text </summary>
/// <param name="titleText"> The text that the window title must contain. </param>
public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
{
return FindWindows((wnd, param) => GetWindowText(wnd).Contains(titleText));
}
Применение:
var windows = FindWindowsWithText("Notepad");
Для получения позиции курсора можно использовать WinAPI функцию GetCursorPos
Использование:
POINT p;
if (GetCursorPos(&p))
{
//позиция курсора: p.x p.y
}
Что бы определить позицию курсора внутри окна можно воспользоваться этой функцией:
if (ScreenToClient(hwnd, &p))
{
//p.x и p.y относительны вашего окна
}
Мстислав Павлов
- 6,777
-
а как получить окно под мышью? т.е. я запускаю программу, она topmost, небольшого размера, в ней textbox. мышь может находиться над любым другим окном, а в textbox выводится hwnd под мышью. – Stack Jan 11 '16 at 11:04
-
1@Stack обновил ответ. По идее с помощью этого набора функций должно хватит для решения вашей задачи, но на практике не решал такую задачу. – Мстислав Павлов Jan 11 '16 at 11:44
-
hwnd под мышью можно получить вызвав функцию WindowFromPoint. пример тут – Stack Jan 12 '16 at 05:49
1
Возможно для вас подойдёт что-то вроде:
using System.Diagnostics;
...
Process[] ProcessesList = Process.GetProcesses();
Это список всех процессов. Теперь можно сделать так, чтобы получить заголовок окна:
ProcessesList[i].MainWindowTitle;
если что-то другое, то вы наверняка найдёте нужный метод на MSDN
Makrushin Evgenii
- 618
- 4
- 15
1
Обязательно ли делать это на C#? Есть же такая программа, как Spy++:

Pavel Mayorov
- 58,537
-
1Вы не поверите, я предложил то же самое - и получил возмущение от топиастера - мол, я забалтываю вопрос, и ответ мой ответом не является. пришлось удалить :) – Jan 11 '16 at 11:12
-
spyxx.exe есть не у всех. и как с ее помощью получить hwnd для окна поиска Win+S? или любого другого диалога или меню? – Stack Jan 11 '16 at 11:13
-
@PashaPash "я предложил то же самое - и получил возмущение от топиастера - мол, я забалтываю вопрос, и ответ мой ответом не является. пришлось удалить :)" -- но вы же тратили время. и выбросили ответ в урну. теперь вы опять начнете требовать у меня переделать свой вопрос? :) – Stack Jan 11 '16 at 11:19
-
1@Stack нет, но я считаю что этот вопрос создан с целью показать всем что я (якобы!) не знал что диалоги - это окна (я ведь утверждал что не все окна - диалоги, а это ведь одно и то же!). и да, ваш комментарий выше - о чем он? какое отношение он имеет к ответу? – Jan 11 '16 at 11:25
-
если надо получить инфу по контекстному меню, то в spyxx.exe это невозможно. т.к. если в нем вызвать Find, то контекстное меню закроется. такой проблемы нет в HWndSpy - исходник тут – Stack Jan 12 '16 at 14:18