5

I'm trying to get the properties of a button but when I drag the spy++'s find window tool it doesn't reach the button (of caption "iniciar gravação" in that case) but rather the button grid parent, like this:

enter image description here

Why is that and how can I get the button properties? I tried with auto it info tool but I get the same behavior.

I tried get that button properties from C# code, like this:

    public class WindowHandleInfo
    {
        private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);

        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);

        private IntPtr _MainHandle;

        public WindowHandleInfo(IntPtr handle)
        {
            this._MainHandle = handle;
        }

        public List<IntPtr> GetAllChildHandles()
        {
            List<IntPtr> childHandles = new List<IntPtr>();

            GCHandle gcChildhandlesList = GCHandle.Alloc(childHandles);
            IntPtr pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList);

            try
            {
                EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
                EnumChildWindows(this._MainHandle, childProc, pointerChildHandlesList);
            }
            finally
            {
                gcChildhandlesList.Free();
            }

            return childHandles;
        }

        private bool EnumWindow(IntPtr hWnd, IntPtr lParam)
        {
            GCHandle gcChildhandlesList = GCHandle.FromIntPtr(lParam);

            if (gcChildhandlesList == null || gcChildhandlesList.Target == null)
            {
                return false;
            }

            List<IntPtr> childHandles = gcChildhandlesList.Target as List<IntPtr>;
            childHandles.Add(hWnd);

            return true;
        }
    }


 void printWindows(IntPtr parent, int tabLevel)
        {
            var w = new WindowHandleInfo(parent);
            foreach (IntPtr h in w.GetAllChildHandles())
            {
                string caption = GetTextBoxText(h) ?? "not found";
                Debug.Write(new string('\t', tabLevel));
                Debug.WriteLine(caption);
                printWindows(h, tabLevel + 1);
            }
        }

 int GetTextBoxTextLength(IntPtr hTextBox)
        {
            // helper for GetTextBoxText
            const int WM_GETTEXTLENGTH = 0x000E;
            int result = SendMessage(hTextBox, WM_GETTEXTLENGTH, 0, IntPtr.Zero);
            return result;
        }

        string GetTextBoxText(IntPtr hTextBox)
        {
            const int WM_GETTEXT = 0x000D;
            int len = GetTextBoxTextLength(hTextBox);
            if (len <= 0) return null;  // no text
            StringBuilder sb = new StringBuilder(len + 1);
            SendMessage(hTextBox, WM_GETTEXT, len + 1, sb);
            return sb.ToString();
        }

using like this:

 IntPtr parent = FindWindow(IntPtr.Zero, "my app title");
 printWindows(parent, 0);

But I can't see anyhing related to Iniciar gravação button.

user834697
  • 235
  • 6
  • 15
  • is it really a button? could it be drawn? – Daniel A. White Jul 08 '16 at 19:39
  • @DanielA.White I don't know. How can I know for sure? I know that application was build using Qt interface, if matters... – user834697 Jul 08 '16 at 19:47
  • other tools such a Windows Inspector have same behavior as spy++/auto it info tool – user834697 Jul 08 '16 at 19:47
  • that makes a big difference im sure. qt has to do things in a skinable, platform independant way. – Daniel A. White Jul 08 '16 at 19:47
  • 2
    Not everything that looks like a control, is backed by a native control. It is common to use the system to render widgets, but implement custom behavior. In a case like this, you'd need to use [UI Automation](https://msdn.microsoft.com/en-us/library/ms747327.aspx) to reach an *accessible* child. Use the [Inspect](https://msdn.microsoft.com/en-us/library/windows/desktop/dd318521.aspx) tool to verify, that the control implements the required interfaces. (You're out of luck, if it doesn't. There's nothing you can do.) – IInspectable Jul 08 '16 at 19:49
  • I'll try that inspect tool and back to say if worked. The application is open source, assuming I manage to open it succesfully on my editor (VS or Qt creator, probably) if it's custom-draw, using `SendMessage()` to send a `BN_CLICKED` will not work, isn't? my goal is click on that button – user834697 Jul 08 '16 at 19:58
  • I only know about the interface which is done using Qt... – user834697 Jul 08 '16 at 20:07
  • Spy++ doesn't read WPF controls either, and for the same reason. It's an obsolete tool. – Kuba hasn't forgotten Monica Jul 08 '16 at 20:16
  • What is used instead of now? – user834697 Jul 08 '16 at 20:17
  • 1
    @KubaOber: That's bullshit, sorry. Spy++ is not obsolete. It's still actively supported by MS, and the latest version of Visual Studio (2015) ships with a new version. It is limited to native controls, but that doesn't make it obsolete. – IInspectable Jul 08 '16 at 20:19
  • @IInspectable It is actively supported inasmuch as the native controls still work, the resource compiler still works, etc. Doesn't make it not obsolete. – Kuba hasn't forgotten Monica Jul 08 '16 at 20:37
  • @KubaOber: There is nothing in as much widespread use as native controls, be it in straight C applications, Borland's VCL wrappers, Microsoft's MFC, or Windows Forms. Based on what information do you call it off as *"obsolete"*? – IInspectable Jul 08 '16 at 21:15
  • @IInspectable As far as I understand it, all of these are useful if you're supporting existing projects, but I doubt that any new development would be using MFC or WinForms. Even VCL is on life support at this point. I'd think that if a technology isn't suitable for new, state-of-the-art designs, the correct term to use is obsolete. It doesn't mean there's anything inherently wrong with it other than that, of course. – Kuba hasn't forgotten Monica Jul 08 '16 at 21:58
  • @KubaOber: What sort of *"state-of-the-art designs"* do you believe the native Windows controls weren't suitable for? If keyboard support is on your list of features you want to support, then there is not even a single competing technology available. Obviously, as a Qt proponent, you do not care about keyboard UIs anyway, so your view may be different. At any rate, calling native Windows controls *"obsolete"* is a ludicrous, unfounded statement. – IInspectable Jul 09 '16 at 10:33

1 Answers1

8

Qt UI controls (widgets, in Qt lexicon. Aka buttons, line edits, comboboxes, etc.) are not backed by native controls. They just steal the native UI look and feel from them and mimic it.

For this reason, you won't find those controls using some of those "spy" tools -- you may still find them through accessibility, though (*).

Or, you can inspect your application using other Qt-specific tools, such as GammaRay for debugging or Squish for UI testing.

(*) controls shipped with Qt are accessibile, but if someone manually reimplements something that looks like a button and doesn't provide it with accessibility then you can't do much about that.

peppe
  • 21,934
  • 4
  • 55
  • 70
  • 1
    I don't see a GammaRay pre-build binary for Windows. Must I really compile it myself? Squish is processing my request, I'll get the result within 24h. Is there any other alternative tool? my goal is send a click message to application, equivalent of `SendMessage(btn, BN_CLICKED, 0, IntPtr.Zero);` in native controls. – user834697 Jul 08 '16 at 21:51
  • But for what purpose, if I may ask? Scripting? Debugging? (Anyhow, the answer is yes, you must compile it yourself for now.) – peppe Jul 08 '16 at 22:18
  • Automation. This application do something I couldn't do myself, so I do use an external application and control it by setting its configuration files and hit a button to process start. I'm not creating any kind of virus. – user834697 Jul 08 '16 at 22:26