Получить дескриптор окна без заголовка.. (C#)

Как мы можем получить дескриптор окна, у которого нет заголовка? Есть ли способ перечислить все окна на рабочем столе и отфильтровать окно, у которого нет заголовка (в моем случае есть только одно), и получить его дескриптор... или указав другие атрибуты, такие как окно, которое имеет конкретная кнопка или список и т.д...


person satya    schedule 13.11.2009    source источник
comment
Что-нибудь, что мешает вам передать пустую строку в FindWindow?   -  person Joey    schedule 13.11.2009
comment
Побочное примечание: вы не можете предполагать, что ваше окно единственное без заголовка.   -  person Philip Wallace    schedule 13.11.2009


Ответы (5)


Это должно сделать это:

    ...
    using System.Runtime.InteropServices;
    using System.Diagnostics;

    ...

public class foo()
{
    ...

    [DllImport ("user32")]
    internal static extern int GetWindowText (int hWnd, String text, int nMaxCount);

    [DllImport ("user32.dll")]
    public static extern int GetWindowTextLength (int hWnd);

    [DllImport ("user32.dll")]
    public static extern int FindWindow (String text, String class_name);

    [DllImport ("user32.dll")]
    public static extern int FindWindowEx (int parent, int start, String class_name);

    [DllImport ("user32.dll")]
    public static extern int GetWindow (int parent, uint cmd);

    public List<int> FindTitlelessWindows()
    {
        List<int> titleless = new List<int> ();

        Process [] procs = Process.GetProcesses ();
        IntPtr hWnd;

        foreach (Process proc in procs)
        {
            hWnd = proc.MainWindowHandle;
            if (hWnd != IntPtr.Zero)
            {
                TraverseHierarchy (hWnd.ToInt32 (), 0, titleless);

            }
        }

        foreach (int i in titleless)
        {
            System.Console.WriteLine (i);
        }

        return titleless;
    }

    public void TraverseHierarchy (int parent, int child, List<int> titleless)
    {
        String text = "";
        GetWindowText (parent, text, GetWindowTextLength (parent));
        if (String.IsNullOrEmpty (text))
        {
            titleless.Add (parent);
        }

        TraverseChildern (parent, titleless);
        TraversePeers (parent, child, titleless);

    }

    public void TraverseChildern(int handle, List<int> titleless)
    {
        // First traverse child windows
        const uint GW_CHILD = 0x05;
        int child = GetWindow (handle, GW_CHILD);
        if (0 != child)
        {
            TraverseHierarchy (child, 0, titleless);

        }
    }

    public void TraversePeers(int parent, int start, List<int> titleless)
    {
        // Next traverse peers
        int peer = FindWindowEx(parent, start, "");
        if (0 != peer)
        {
            TraverseHierarchy (parent, peer, titleless);
        }

    }
}
person Jerry Fernholz    schedule 13.11.2009
comment
Проще, если достаточно верхних окон, но также проверить, является ли окно частью определенной программы, например. твой: foreach (Process proc in procs) { hWnd = proc.MainWindowHandle; if (hWnd != IntPtr.Zero && proc.MainWindowTitle == "" && proc.ProcessName.StartsWith("my process name")) { titleless.Add(hWnd.ToInt32 ()); } } - person kjyv; 05.09.2015

Взгляните на функцию EnumChildWindows.

Я думаю, что если вы передадите указатель главного окна (т.е. рабочего стола) этой функции, вы сможете получить список всех окон и их дочерних окон.

В сочетании с FindWindow должна быть возможность получить дескриптор нужного окна после обнаружения ожидаемого дочернего элемента управления.

person Lee Meyers    schedule 13.11.2009

Что-то вроде этого должно работать, не тестировалось

[DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetWindowTextLength(IntPtr hWnd); 

....
Process[] procs = Process.GetProcesses();
IntPtr hWnd;
foreach(Process proc in procs)
{
    hWnd = proc.MainWindowHandle;
    if (hWnd != IntPtr.Zero)
    {
        int length = GetWindowTextLength(hWnd);
        StringBuilder sb = new StringBuilder(length + 1);
        GetWindowText(hWnd, sb, length);
        if (String.IsNullOrEmpty(sb.ToString())
        {
            // we have a window with no title!
        }
    }
}
person James    schedule 13.11.2009
comment
Это найдет только окна верхнего уровня без заголовка. Вам все еще нужно пройти через все дочерние окна и одноранговые узлы. - person Jerry Fernholz; 13.11.2009
comment
Вы предполагаете, что OP хочет включить дочерние окна (вероятно, нет). OTOH (как вы подразумеваете) не каждое окно верхнего уровня является MainWindow процесса... - person Roger Lipscombe; 17.11.2009

http://msdn.microsoft.com/en-us/library/ms633558(VS.85).aspx

WindowFromPoint возвращает дескриптор или null, если под курсором нет окна. Можно ли это использовать, или вы пытаетесь автоматизировать процесс?

person Akoi Meexx    schedule 13.11.2009

Здесь вы можете найти библиотеку для работы с Windows API в управляемом коде.
Загрузите dll и укажите его в своем проекте, и оттуда очень легко получить любую информацию о любом окне, которое вы хотите;

 void ForAllSystemWindows()
        {
            foreach (SystemWindow window in SystemWindow.AllToplevelWindows)
            {
                if (window.Title == string.Empty)
                {
                    //Found window without title

                    //Get window handle
                    IntPtr windowhandle  = window.HWnd;

                    //Do other stuff ..
                }
            }
        }
person Mez    schedule 13.11.2009