AHK Cannot ControlClick on hidden elements in nested child window - windows

I'm trying to automate a many clicking process, just to narrow it to the user input.
I encountered problems in controlClicking interface elements, which seems not to be standard Windows GUI elements.
When pointing them with WinSpy they don't appear as separate buttons, but I can point the whole child Window which is drawn in the main program window.
As on pic1, I pointed the whole window and I can find each tab/button by it's text inside and on pic2 I can inspect the ClassNN of that element and it's ID.
As far as clicking other buttons in the main menu bar of the program works, a simple:
ControlClick, ClaTab_01000000H26, WindowName
doesn't work. I think during the day, and many possibilities I tried, I could ControlClick the above button by pointing it with its ID, but that ID changes every instance. I could confirm that tomorrow if it works by ID.
Of course I tried SetControlDelay -1 and ,NN option. But don't take that for granted, I can try any of your suggestions tomorrow.
Both tabs marked with purple color, are to find in the Windows->SiblingWindows tab. I really don't want using x,yCoords (that actually work), but I need the script to be as reliable as possible.
So my questions are:
Am I missing something or you have any suggestions how to click that elements?
Is it correct, that no matter how deep the child windows get (one has buttons to open another on top of it), all the time the WinName stays the same pointing to the main program ***.exe?
Could you provide an example from the web or yours, to find an element's ID by providing the text attached to the button (pic1-red line and also pic2 in "text")?
I also cannot maximize the child window. Double clicking it works, but I can't find the appropriate ClassNN of the window to call.
Could you provide an example, how to use the Messages tab? I assume, if I find the button as on the pictures, I could send a message with controlClick and see if there's a reaction?

1.Ugh. I found the solution, which is awesome, but a little frustrating that with a bit of luck I tried another aproach that's not that logical for a newbie like me:
instead:
ControlClick, ClaTab_01000000H6, ahk_class ClaWin01000000H_2,,,, NA
it's just
ControlFocus, ClaTab_01000000H6, ahk_class ClaWin01000000H_2,,,, NA
2._Yep. One child window creates another and another and another, but winTitle stays the same. In my case:
ahk_class ClaWin01000000H_2
3._Code below returns the handle/ID of the element you specify. Change ClaTab and ClaWin to your chouice.
ControlGet, OutputVar, hwnd,, ClaTab_01000000H1, ahk_class ClaWin01000000H_2
MsgBox, %OutputVar%`
Probably to be continued.
I highly recomend to both use
WinSpy https://www.autohotkey.com/boards/viewtopic.php?t=28220
SimpleSpy https://www.the-automator.com/downloads/simple-spy/
First one has lots of useful information and the window tab provides information of hidden buttons/windows. Second one in a more clear way indicates the parent window and its class.

Related

wxWidgets pprogrammaticaly move to next input control

I originally had code that set the focus to the first widget in a dialog, in the onInit method. But there were problems with it: if I pressed TAB, indeed focus moved to next control (wxTextCtrl), which got the blue 'focus' color, but the 'focus' color/highlight was not removed from previous focus widget. So now it looked like both first and second control had focus at the same time...
When cycling manually (by pressing TAB) full circle (till last control and then wrap around to the first), suddenly all worked well. That is, when moving focus from first control to next one, the first visually lost focus (blue color was removed) as it should. From now on, only one item had the focus color/highlight.
So instead of setting focus on the first control, I tried a different approach: I set the focus to the last control in the dialog, which is always the OK button. Next, I want to emulate programmatically that a TAB is pressed and received by the dialog. So I wrote this (inside Dialog::onInit):
m_buttonOK->SetFocus();
wxKeyEvent key;
key.SetEventObject(this);
key.SetEventType(wxEVT_CHAR);
key.m_keyCode=WXK_TAB;
ProcessWindowEvent(key);
Now the focus indeed moves away from the OK button, but it does not wrap around to the first control.
Only when I manually press TAB after the dialog opened, the first item gets focus.
Question: why does this wrapping around to set focus on first widget not work with the code shown above?
First of all, your initial problem is almost certainly related to not calling event.Skip() in one of your event handlers, see the note in wxFocusEvent documentation.
Second, you can't send wx events to the native windows, they don't know anything about it. In this particular case you can use wxWindow::Navigate() to do what you want, but generally speaking what you're doing simple can't, and won't, work reliably.

Save and Restore Pane-Specific Information in DockPanelSuite

So I have looked through existing answers tagged with dockpanel-suite and have not found what I am looking for (as I type this, it is also not appearing in the Similar Questions area). For starters, note that I am NOT asking about saving and restoring the entire Workspace.
So here is the scenario. I have a graphical window (we will call it "Timeline") that is added upon user request. When it is added, it is automatically docked to the bottom-most area of the main form. The user then takes the Timeline window and redocks it somewhere else (could be docked to an edge, or within another docking pane) and changes its docking behavior (floating, auto-hide, tab, etc.).
A demonstrable example is in Visual Studio. If you have the Solution Explorer on a tab within an docked pane on the right and close Solution Explorer, you can go to View -> Solution Explorer and bring it back up again, and it restores to the correct location.
Now the user closes the Timeline window entirely by hitting the [x] on its pane, and in the future, they request to add it to the application again. I want to bring it back in the last dock state and position it was in when it was last closed.
Now, I appear to be able to catch the closing of the pane with the ContentRemoved event, but in there e.Content.DockHandler.Pane, e.Content.DockHandler.PanelPane and e.Content.DockHandler.FloatPane are all null so I have no obvious way to get the previous dock geometry. e.Content.DockHandler.DockPanel is valid, but it is the parent/root docking panel, and calling SaveAsXml(...) does nothing for me because it would get the entire workspace.
Even if I were able to capture it here, information I need. However, I do not appear to be able to simply call LoadFromXml(...) on anything either.
If I try to do it before the DockContent object is added to the DockPanel, DockHandler.DockPanel member is null, so I appear to have no place to restore the XML into, even if I was able to get it.
There are no other events hanging off of DockPanel that seem to be able to help me here.
So - is there a way to do this, and what is the correct way to do it? I want to make sure I am not barking up the wrong tree with trying to capture the dock information as XML when closed and restore it later.
I have toyed with the idea of not actually closing the window but just undocking and hiding it, but have not explored that very far yet. Same with hooking the DockChanged event, but it does not seem to fire on the DockContent objects being docked/floated/etc. and I am not sure why.
Also the solution needs to be robust enough so that I can correctly handle scenarios such as if the last docking parent no longer exists. For example, if it was docked as a tab somewhere, but now that parent window (containing the tabs) has also been closed. I do not know if LoadFromXml, presuming it is the right way to do, is robust enough to handle this scenario, as I have not been able to test it yet.
If I understand the question, what I do is to trap the Closing or FormClosing event, .Hide() the form and set e.Cancel = true. If you are using DockContent, then there is a HideOnClose() that does the work for you. Then when you want to "re-open" the window, you simply use an empty .Show(), and it will Show right where it was when you "closed" it.
As far as saving if the last docking parent no longer exists, I agree with Lex Li, that will take a hack.

what happen at background when you click inside a textbox?

Inside a MFC dialog, I have 2 overlapping rows of text boxes (what user can see is only one row). when I clicked a button, i shifted down the row at bottom, so now user can see both rows.
The problem is if I have some data loaded in DoDataExchange() for the text boxes, I wouldn't be able to see them showing when the dialog boots up. But when I click inside the text box, the data shows.
I want to know what exactly happen when I clicked a UI? What drawing functions are invoked at backgrounds? So I can fix my problem.
Thank you.
ZQ
Nothing is drawn when you click, maybe you are seeing an Invalidate() being triggered for some reason that redraws the text boxes. Or maybe the parent control (dialog, I assume) doesn't have WS_CLIPCHILDREN set, or some other funny things are happening with the WS_CLIPXXX flags (they're somewhat of a black art).
More to the point, use Spy++ to check what 'happens' when you click - i.e. the messages that are posted at each point in time.

Get Context Menu text of specific TaskBar button

I've got some code that grabs the TaskBar buttons and their text from the windows TaskBar using User32.SendMessage with the TB_GETBUTTON message to retrieve a TBBUTTON structure (Win32 API via C# P/Invokes). But I'm trying to figure out how to then, once I have the handle to the button, grab the associated context menu text. There is some status information on there for a specific application that I would like to retrieve. The button text gets me some of it, but I need to the context menu text to complete it.
Any ideas?
This is not completely clear... Context menus don't have text, as such - they have menu items, each one of which will have text. By "context menu text", do you mean the text of the menu items in the taskbar button's popup/context menu? For example, "Restore", "Minimize" etc in the screenshot below?
If so, I suspect you're going about this the wrong way:
This menu doesn't belong to the button, but is the system menu of the window represented by the taskbar button. If the button has a context menu, this is probably for a grouped collection of windows, not one specific window (or even windows for one process.)
Making judgements based on the context menu of a window sounds like a dodgy approach to me, especially based on text since that will change depending on where in the world your user is located. Applications can also change the contents of this menu so there's no guarantee it will contain something you expect to be there. It would be better to check the window style, if it's minimized, etc, to find out the information that also affects the contents of the menu.
I'm going to answer this based on what your needs seem to be from the question, not what you've directly asked, since (a) it's not possible as asked and (b) I think you're trying to do something else. (As a general guideline, in a question it's good to state why you're trying to do something - and even maybe ask about that, ie 'how do I achieve X' - in case there's a better method than the one you're using. Here, X is probably 'find out information about this window' not 'get the text of the context menu', because that's probably only one possible method to get to X.) Also I think extracting data from the internals of a third-party application like Explorer (the taskbar is an Explorer window) is fragile and prone to break in future versions of Windows.
The system menu or window information (whichever one) belongs to application windows. Unless taskbar buttons are grouped (and then it's the subitems) one taskbar button corresponds to one specific window in the system. So what you want to do is find these windows. You do this by:
Using the EnumWindows function
Then for each window that is passed to the callback, checking the extended window style using GetWindowLong with GWL_EXSTYLE to see if the WS_EX_APPWINDOW bit is set
In addition, sometimes other windows are shown: these heuristics should help.
Each one of these windows is a window that should appear on the taskbar, Alt-Tab dialog, etc.
You say you're getting the text of the taskbar button - this is probably the window caption of the window, and GetWindowText is the canonical (read: probably a lot more reliable) way to get the caption of a window belonging to another process.
If you really want the popup menu, then:
Use GetSystemMenu to retrieve the handle for the system menu for the window. Applications can customise this, so if your app is doing this (and that's why you want the popup menu) ensure you pass false to the bRevert parameter
You can then get the number of menu items using GetMenuItemCount and for each one call GetMenuItemInfo to get info about each menu item. Pass true to the fByPosition parameter to indicate you're accessing the menus by position (since you know the count, you're getting item 0, 1, 2... count-1).
This fills a MENUITEMINFO structure, which (I think, I haven't ever had to code this so I haven't tested) will tell you the text associated with an item via the dwTypeData field "if the MIIM_STRING flag is set in the fMask member".
If you really want information about the window status, you can get this information using methods like IsIconic to see if it's minimized, GetWindowLong again to get other information, etc. I'd suggest you ask another SO question about how to get whatever specific information about a window for details.
Hope that helps!

Hide window until the top window is displayed

I am facing a little annoying design problem. Not easy to give a title of my question.
I must display two windows, one over another one. The first one is a Cocoa window, the second is made with Qt. In the second window, an action is performed, but the user can choose to close this window. He must fall back on the first window.
To display my first window, which is actually a SFAuthorizationPluginView, I do:
[myview displayView];
then, to display the window made with Qt on top of first window:
QWidget* w = openMyScreen();
NSView* v = (NSView*)w->winId();
[[v window] setLevel:2003];
This works well, however there is a small delay before the second window is displayed. We can thus see for a very short time the first window.
I need that the second window stays on top of the first window, because the user can close the second window and must have access to the first window.
Any ideas on a trick how to hide the first window, just the time, the second window appears?
Thanks in advance
NSDisableScreenUpdates and NSEnableScreenUpdates (link) might be useful in this situation. The documentation says:
You typically call this function so that operations on multiple windows appear atomic to the user.
which seems to describe your situation.
A word of unrelated advice though: Don't go setting window levels willy-nilly. A window level of 2003 will likely cause the window to appear over things like the dock or even the menu bar, which would definitely be strange. You should stick to the standard levels declared in NSWindow.h unless you have good reason. NSFloatingWindowLevel might be appropriate (although I'm not sure what level the SFAuthorizationPluginView window is displayed at).
Starting with MacOS 10.4, you can use :
[NSWindow disableScreenUpdatesUntilFlush];

Resources