1

I can't get the "Edit" field handle when selecting a photo in a third-party application.

Spy++ shows everything correctly, but FindWindow fails. I can get the handle of the window itself, the parent. I assume I need to look for child windows. I can get some handles with GetWindow but but it's not clear what they are. The window title is empty. FindWindowEx doesn't work at all, returns 0. I indicate it like this:

IntPtr hwndchild = (hwnd, IntPtr.Zero, null, "Edit")

enter image description here

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Микка
  • 21
  • 4
  • You are probably looking for [EnumChildWindows](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumchildwindows). – 500 - Internal Server Error Aug 22 '19 at 13:02
  • 1
    If that invalid line of C# code is supposed to represent the parameters to `FindWindowEx`, then the class is the third parameter, not the fourth. – GSerg Aug 22 '19 at 13:07
  • [FindWindow](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowa) - *Retrieves a handle to the **top-level** window*.. you have to enumerate children to get lower-level window as on screenshot. – Sinatr Aug 22 '19 at 13:16
  • @500-InternalServerError Ok, i know, but how get child-handle by class? – Микка Aug 22 '19 at 13:46
  • Call [GetClassName](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassname) for each handle returned, and compare with what you are looking for. Note that there'll typically be multiple child windows of the same class. – 500 - Internal Server Error Aug 22 '19 at 13:49

3 Answers3

3

Based on the screenshot you provided, and using just the FindWindow/Ex() functions, you can get the HWND of the Edit control like this:

IntPtr hwndDlg = FindWindow(null, "Choose an image");
IntPtr hwndCBEx = FindWindowEx(hwndDlg, IntPtr.Zero, "ComboBoxEx32", null);
IntPtr hwndCB = FindWindowEx(hwndCBEx, IntPtr.Zero, "ComboBox", null);
IntPtr hwndEdit = FindWindowEx(hwndCB, IntPtr.Zero, "Edit", null);

However, once you have the HWND to the ComboBoxEx control, the correct way to get the HWND of its Edit control is to use the CBEM_GETEDITCONTROL message:

const int CBEM_GETEDITCONTROL = 1031;
IntPtr hwndDlg = FindWindow(null, "Choose an image");
IntPtr hwndCBEx = FindWindowEx(hwndDlg, IntPtr.Zero, "ComboBoxEx32", null);
IntPtr hwndEdit = SendMessage(hwndCBEx, CBEM_GETEDITCONTROL, 0, 0);

Note, for a standard ComboBox control (which you can get from a ComboBoxEx control using the CBEM_GETCOMBOCONTROL message), you can use the CB_GETCOMBOBOXINFO message or the GetComboBoxInfo() function. The HWND of the Edit control is returned in the COMBOBOXINFO.hwndItem field.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

If you are looking for a child window of a parent you should use EnumChildWindows. The following is C++ code but could be pinvoked easily: you can marshal delegates as function pointers for the callback.

std::vector<HWND> FindChildrenByClass(HWND parent, const std::string& target_class)
{
    struct EnumWndParam {
        std::vector<HWND> output;
        std::string target;
    } enum_param;

    enum_param.target = target_class;

    EnumChildWindows(
        parent,
        [](HWND wnd, LPARAM lparam) -> BOOL {
            auto param = reinterpret_cast<EnumWndParam*>(lparam);
            char class_name[512];
            GetClassName(wnd, class_name, 512);
            if (param->target == class_name)
                param->output.push_back(wnd);
            return TRUE;
        },
        reinterpret_cast<LPARAM>(&enum_param)
    );

    return enum_param.output;
}

int main()
{
    auto windows = FindChildrenByClass( reinterpret_cast<HWND>(0x0061024A), "Edit");
    for (auto wnd : windows) {
        std::cout << std::hex << wnd << std::endl;
    }
}

Note in the above that I do not recursively call FindChildrenByClass in the callback lambda. This is not a mistake. EnumChildWindows already performs this recursion. It runs over a parent window's children and grand children, etc., out of the box without you having to specify this behavior or implement it.

jwezorek
  • 8,592
  • 1
  • 29
  • 46
-5

Like someone already assumed. Try the EnumChildWindow method. Here is an complete sample already on stackoverflow

Kinimod
  • 166
  • 1
  • 15