简体   繁体   中英

C# Pinvoke can't find the Hwnd of Controls after List count was 0 at first time

I'm trying to click a Button in another Application (started from my Programm with Process.Start)

The problem: I need to wait until the Loading screen is disappeared and the GUI pop's up...

My idea was to read all (Hwnd)Controls until a specific Control (Button: "Kill Client") from the GUI was found (=GUI Opened).

But this only works if I wait manually for the GUI and press a "Search Control" button.

If I press the "Search Button" if the Loading Screen is aktive I get a Hwnd = 0 (List<'IntPtr> Count is also 0...) and if i press it again if the GUI is opened it is 0 again(List<'IntPtr> Count too...) !!!

Here my Code:

 public class WndSearcher
 {
    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

    public static List<IntPtr> GetChildWindows(IntPtr parent)
    {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try
        {
            EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
            EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
        }
        finally
        {
            if (listHandle.IsAllocated)
                listHandle.Free();
        }
        return result;
    }

    private static bool EnumWindow(IntPtr handle, IntPtr pointer)
    {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
        {
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
        }
        list.Add(handle);
        return true;
    }
}

My Button:

List<IntPtr> AllControlHandles = WndSearcher.GetChildWindows(selectedCharacter.Botprocess.MainWindowHandle);
IntPtr ControlHandle = AllControlHandles.Find(x => PInvoke.GetWindowTextRaw(x) == "Kill Client" ? true : false);
MessageBox.Show(ControlHandle.ToString());

Part of PInvoke (Class):

const int WM_GETTEXT = 0x000D;
const int WM_GETTEXTLENGTH = 0x000E;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] StringBuilder lParam);

public static string GetWindowTextRaw(IntPtr hwnd)
    {
        // Allocate correct string length first
        int length = (int)SendMessage(hwnd, WM_GETTEXTLENGTH, IntPtr.Zero, null);
        StringBuilder sb = new StringBuilder(length + 1);
        SendMessage(hwnd, WM_GETTEXT, (IntPtr)sb.Capacity, sb);
        return sb.ToString();
    }

Found no solution till now.

So I decided to use AutoHotKey in combination with C#.

In C# I start my AutoHotKey Script and wait until the Script is finished. (Then the external Programm is started completely)

Starting Arguments: 1.Processid 2.NewExternalProgramName

Here my AutoHotKey Script:

counter := 0
Loop, %0%  ; For each parameter:
{

    param := %A_Index%

    if (counter = 0) ; do sth with parameter 1
        winwait, ahk_pid %param% ; Not logged in ;wait until the text "Not logged in" can be read (Program started completely)

    if (counter = 1) ; do sth with parameter 2
        WinSetTitle, %param%

    counter += 1
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM