Wie kann man durch UIauTomation bestimmen, ob eine Taste gedrückt wird oder nicht?
-
27-10-2019 - |
Frage
Ich möchte herausfinden, ob eine Taste gedrückt wird oder nicht. Dies scheint keine offizielle Eigenschaft einer Schaltfläche zu sein (kein Kontrollkästchen im Button-Stil!), Aber er scheint zugänglich zu sein, es gibt die BM_GetState-Nachricht, die zum Beispiel das gewünschte Ergebnis erzielen sollte.
Das Problem ist häufig, dass ich keine Fenstergrenzen für meine Schaltflächen bekomme (sie sind nur ein Teil einer anderen Symbolleiste, obwohl sie durch die Automatisierung von Bedeutung unterscheiden können). Und ich würde einen solchen Griff für die SendMessage -Funktion brauchen.
Also .. Gibt es eine Möglichkeit für mich, auf diese Immobilie zuzugreifen? Ich weiß, dass es zugänglich ist, da ich es in anderen Automatisierungsprogrammen gesehen habe, ich bin einfach nicht, wie ich es dazu bringen soll.
Ich werde C#verwenden, aber jeder C -Code wäre in Ordnung.
Danke vielmals
Lösung
(Bearbeiten: Also habe ich es endlich geschafft, das Codeformat hier richtig zu erstellen. Fügen Sie zu Beginn einfach 4 Leerzeichen ein.)
Genieße es, ich habe eine ganze Reihe lang gebraucht, um es zum Laufen zu bringen. Aber jetzt habe ich Lust, ein neues Niveau erreicht zu haben. :)
(Bitte sagen Sie mir, wie ich es richtig formatieren kann - Sowohl Zitat als auch Code sind bei mir fehlgeschlagen)
int res;
#region direct method
int hwnd = ae.Current.NativeWindowHandle;
if (hwnd != 0)
{
const UInt32 BM_GETSTATE = 0x00F2;
res = SendMessage(hwnd, BM_GETSTATE, 0, 0);
}
#endregion
else
#region method via toolbar
{
AutomationElement parent = TreeWalker.RawViewWalker.GetParent(ae);
while ((parent != null) && (parent.Current.ControlType != ControlType.ToolBar))
parent = TreeWalker.RawViewWalker.GetParent(ae);
if (parent != null)
{
int toolBarHandle = parent.Current.NativeWindowHandle;
#region defines
const int WM_USER = 0x400;
const int TB_GETSTATE = (WM_USER + 18);
const int TB_GETBUTTON = (WM_USER + 23);
const int TB_BUTTONCOUNT = (WM_USER + 24);
#endregion
#region get correct child number
int numButtons = SendMessage(toolBarHandle, TB_BUTTONCOUNT, 0, 0);
AutomationElement sibling = ae;
int cnt = -1;
while (sibling != null)
{
sibling = TreeWalker.RawViewWalker.GetPreviousSibling(sibling);
++cnt;
}
if (cnt >= numButtons)
cnt = 0; // nonsense value, but pass a valid one
#endregion
#region get command id
TBBUTTON butInfo = new TBBUTTON();
butInfo.idCommand = 1234;
uint pid;
GetWindowThreadProcessId((IntPtr)toolBarHandle, out pid);
IntPtr process = OpenProcess(ProcessAccessFlags.VMOperation | ProcessAccessFlags.VMRead |
ProcessAccessFlags.VMWrite | ProcessAccessFlags.QueryInformation, false, pid);
IntPtr p = VirtualAllocEx(process, IntPtr.Zero, (uint)Marshal.SizeOf(typeof(TBBUTTON)), AllocationType.Commit
, MemoryProtection.ReadWrite);
int _res = SendMessage(toolBarHandle, TB_GETBUTTON, cnt, p.ToInt32());
#region getresult
int read;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TBBUTTON)));
Marshal.StructureToPtr(butInfo, ptr, true);
bool __res = ReadProcessMemory(process, p, ptr, Marshal.SizeOf(typeof(TBBUTTON)), out read);
System.Diagnostics.Debug.Assert(read == Marshal.SizeOf(typeof(TBBUTTON)));
butInfo = (TBBUTTON)Marshal.PtrToStructure(ptr, typeof(TBBUTTON));
#endregion
int commandId = butInfo.idCommand;
VirtualFreeEx(process, p, 0, FreeType.Release);
#endregion
//!define BST_UNCHECKED 0
//!define BST_CHECKED 1
//!define BST_INDETERMINATE 2
//!define BST_PUSHED 4
//!define BST_FOCUS 8
#region get state
res = SendMessage(toolBarHandle, TB_GETSTATE, commandId, 0);
#endregion
}
}
#endregion
EDIT: Hier http://www.andreas-reiff.de/2011/06/c-speicher-ander-prozess-befulen-lassenchecken-ob-ein-button-gedruckt/ Mit lesbarem Code und Erklärungen in einer seltsamen Fremdsprache. Code -Kommentare sind jedoch Englisch. Ich hoffe, Sie finden es nützlich. Außerdem hätte ich dies nicht ohne die Informationen hier lösen können Wie kommt es, dass einige Steuerelemente keinen Windows -Handle haben?.