Read Windows Forms login fields and associate their labels
This commit is contained in:
1 parent
d7ea005a1f
commit
25e38907d3
9 files changed
+149
-25
No files matched your search
@@ -5,6 +5,7 @@
|
||||
#include "edit_hook.h"
|
||||
#include "msaa_states.h"
|
||||
#include "list_view.h"
|
||||
#include "control_class.h"
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <gio/gio.h>
|
||||
@@ -162,12 +163,41 @@ void find_control_label(HWND window, wchar_t *text, int capacity) {
|
||||
HWND previous = window;
|
||||
wchar_t className[64] = {};
|
||||
text[0] = L'\0';
|
||||
// Managed controls need not be created in label/control order. Prefer a
|
||||
// visible static label immediately to the left on the same row, among
|
||||
// siblings only. Keep the existing native-control ordering below.
|
||||
if (GetClassNameW(window, className, std::size(className)) &&
|
||||
lstrcmpiW(className, L"Edit") != 0 && wine_access_class_matches(className, L"Edit")) {
|
||||
RECT controlRect{};
|
||||
if (GetWindowRect(window, &controlRect)) {
|
||||
HWND label = nullptr;
|
||||
LONG bestGap = 201;
|
||||
HWND sibling = GetWindow(GetParent(window), GW_CHILD);
|
||||
for (int hop = 0; sibling && hop < 128; ++hop, sibling = GetWindow(sibling, GW_HWNDNEXT)) {
|
||||
RECT labelRect{};
|
||||
if (sibling == window || !IsWindowVisible(sibling) ||
|
||||
!GetClassNameW(sibling, className, std::size(className)) ||
|
||||
!wine_access_class_matches(className, L"Static") || !GetWindowRect(sibling, &labelRect))
|
||||
continue;
|
||||
const LONG gap = controlRect.left - labelRect.right;
|
||||
if (gap >= 0 && gap < bestGap && labelRect.top < controlRect.bottom &&
|
||||
labelRect.bottom > controlRect.top) {
|
||||
label = sibling;
|
||||
bestGap = gap;
|
||||
}
|
||||
}
|
||||
if (label && get_control_text(label, text, capacity)) {
|
||||
tidy_text(text, true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int hop = 0; hop < 3; ++hop) {
|
||||
previous = GetWindow(previous, GW_HWNDPREV);
|
||||
if (previous == nullptr ||
|
||||
!GetClassNameW(previous, className, std::size(className)))
|
||||
return;
|
||||
if (lstrcmpW(className, L"Static") != 0 && lstrcmpW(className, L"Button") != 0)
|
||||
if (!wine_access_class_matches(className, L"Static") && !wine_access_class_matches(className, L"Button"))
|
||||
continue;
|
||||
if (get_control_text(previous, text, capacity))
|
||||
tidy_text(text, true);
|
||||
@@ -211,14 +241,14 @@ ControlDescription describe_standard_control(HWND window) {
|
||||
if (!GetClassNameW(window, className, std::size(className)))
|
||||
return control;
|
||||
const LONG_PTR windowStyle = GetWindowLongPtrW(window, GWL_STYLE);
|
||||
const bool isEdit = lstrcmpW(className, L"Edit") == 0 ||
|
||||
lstrcmpW(className, L"RICHEDIT50W") == 0 ||
|
||||
lstrcmpW(className, L"RichEdit20W") == 0 ||
|
||||
lstrcmpW(className, L"RichEdit20A") == 0;
|
||||
const bool isEdit = wine_access_class_matches(className, L"Edit") ||
|
||||
wine_access_class_matches(className, L"RICHEDIT50W") ||
|
||||
wine_access_class_matches(className, L"RichEdit20W") ||
|
||||
wine_access_class_matches(className, L"RichEdit20A");
|
||||
if (!isEdit || !(windowStyle & ES_PASSWORD))
|
||||
get_control_text(window, text, std::size(text));
|
||||
|
||||
if (lstrcmpW(className, L"Button") == 0) {
|
||||
if (wine_access_class_matches(className, L"Button")) {
|
||||
control.name = to_utf8(text);
|
||||
const LONG_PTR style = GetWindowLongPtrW(window, GWL_STYLE);
|
||||
DWORD_PTR checked = 0;
|
||||
@@ -262,8 +292,8 @@ ControlDescription describe_standard_control(HWND window) {
|
||||
return control;
|
||||
}
|
||||
|
||||
if (lstrcmpW(className, L"ComboBox") == 0 ||
|
||||
lstrcmpW(className, L"ComboBoxEx32") == 0) {
|
||||
if (wine_access_class_matches(className, L"ComboBox") ||
|
||||
wine_access_class_matches(className, L"ComboBoxEx32")) {
|
||||
find_control_label(window, label, std::size(label));
|
||||
control.name = to_utf8(label);
|
||||
control.role = "combo box";
|
||||
@@ -287,8 +317,8 @@ ControlDescription describe_standard_control(HWND window) {
|
||||
return control;
|
||||
}
|
||||
|
||||
if (lstrcmpW(className, L"ListBox") == 0 ||
|
||||
lstrcmpW(className, L"ComboLBox") == 0) {
|
||||
if (wine_access_class_matches(className, L"ListBox") ||
|
||||
wine_access_class_matches(className, L"ComboLBox")) {
|
||||
find_control_label(window, label, std::size(label));
|
||||
control.name = to_utf8(label);
|
||||
control.role = "list";
|
||||
@@ -320,7 +350,7 @@ ControlDescription describe_standard_control(HWND window) {
|
||||
return control;
|
||||
}
|
||||
|
||||
if (lstrcmpW(className, L"msctls_trackbar32") == 0) {
|
||||
if (wine_access_class_matches(className, L"msctls_trackbar32")) {
|
||||
find_control_label(window, label, std::size(label));
|
||||
control.name = to_utf8(label);
|
||||
control.role = "slider";
|
||||
@@ -331,7 +361,7 @@ ControlDescription describe_standard_control(HWND window) {
|
||||
return control;
|
||||
}
|
||||
|
||||
if (lstrcmpW(className, L"Static") == 0) {
|
||||
if (wine_access_class_matches(className, L"Static")) {
|
||||
control.name = to_utf8(text);
|
||||
control.role = "static text";
|
||||
return control;
|
||||
@@ -437,6 +467,9 @@ void present_text_event(const WineAccessTextEvent &event) {
|
||||
std::string text = to_utf8(event.text);
|
||||
ControlDescription control;
|
||||
if (event.kind == WINE_ACCESS_TEXT_PASSWORD) {
|
||||
wchar_t label[256] = {};
|
||||
find_control_label(window, label, std::size(label));
|
||||
control.name = to_utf8(label);
|
||||
control.role = "edit";
|
||||
control.description = "password";
|
||||
} else if (event.kind == WINE_ACCESS_TEXT_FOCUS) {
|
||||
|
||||
Reference in new issue
Block a user