I found this article and tried to follow it to find the position of the caret in any Windows application:
How to get caret position in ANY application from C#?
However, I have a problem with following it.
This is the C# code I was following:
var guid = typeof(IAccessible).GUID;
object accessibleObject = null;
var retVal = WinApiProvider.AccessibleObjectFromWindow(hwnd, WinApiProvider.OBJID_CARET, ref guid, ref accessibleObject);
var accessible = accessibleObject as IAccessible;
accessible.accLocation(out int left, out int top, out int width, out int height, WinApiProvider.CHILDID_SELF);
But I have no idea how to put CHILDID_SELF
in the fifth parameter of the IAccessible::accLocation()
function:
Rect rect;
VARIANT varCaret;
varCaret.vt = VT_I4;
varCaret.lVal = CHILDID_SELF;
std::cout << object->accLocation(&rect.x, &rect.y, &rect.w, &rect.h, varCaret);
After some research, I found out that I should put CHILDID_SELF
in this way. But it's not working as expected.
I assume this should be able to get the position of the caret in Microsoft Edge or Chrome, but it just returns S_FALSE
.
The guy from the link also didn't get the caret position from Chrome or other windows, but made it work after adding CHILDID_SELF
. So, I guess the problem I have is related to the way that I'm using CHILDID_SELF
.
I'm also using 21H1 build 19043.1889, but still I'm using 21H1 so it shouldn't be the problem, in my opinion.
I also tried to just plug it in, but of course C didn't let me do that:
object->accLocation(&rect.x, &rect.y, &rect.w, &rect.h, CHILDID_SELF);
object->accLocation(&rect.x, &rect.y, &rect.w, &rect.h, (VARIANT)CHILDID_SELF);
What would be the solution of this problem? Am I doing something wrong?
FULL CODE
#include <iostream>
#include <Windows.h>
#include <oleacc.h>
#pragma comment(lib, "Oleacc.lib")
typedef struct {
long x;
long y;
long w;
long h;
} Rect;
int main(int argc, char* argv[]) {
HWND hwnd;
DWORD pid;
DWORD tid;
while (true) {
system("cls");
GUITHREADINFO info;
info.cbSize = sizeof(GUITHREADINFO);
hwnd = GetForegroundWindow();
tid = GetWindowThreadProcessId(hwnd, &pid);
GetGUIThreadInfo(tid, &info);
IAccessible* object = nullptr;
if (SUCCEEDED(AccessibleObjectFromWindow(info.hwndFocus, OBJID_CARET, IID_IAccessible, (void**)&object))) {
Rect rect;
VARIANT varCaret;
varCaret.vt = VT_I4;
varCaret.lVal = CHILDID_SELF;
object->accLocation(&rect.x, &rect.y, &rect.w, &rect.h, varCaret);
std::cout << rect.x << std::endl;
object->Release();
}
Sleep(10);
}
return 0;
}
Used Microsoft Visual Studio 2019, x86, Debug to build
CodePudding user response:
Your first code snippet is the correct way to pass CHILDID_SELF
in a VARIANT
parameter, per the documentation:
How Child IDs Are Used in Parameters
When initializing a
VARIANT
parameter, be sure to specifyVT_I4
in thevt
member in addition to specifying the child ID value (orCHILDID_SELF
) in thelVal
member.
So, the problem must be something else. For instance, one thing I notice is that you are not initializing the COM library before calling AccessibleObjectFromWindow()
. Try calling CoInitialize/Ex()
first and see if it makes a difference.
Also, you are not checking the return value of accLocation()
for failure before using the RECT
coordinates.
Try this:
#include <iostream>
#include <Windows.h>
#include <oleacc.h>
#pragma comment(lib, "Oleacc.lib")
typedef struct {
long x;
long y;
long w;
long h;
} Rect;
int main(int argc, char* argv[]) {
HWND hwnd;
DWORD pid;
DWORD tid;
CoInitialize(nullptr); // <-- add this
while (true) {
system("cls");
GUITHREADINFO info;
info.cbSize = sizeof(GUITHREADINFO);
hwnd = GetForegroundWindow();
tid = GetWindowThreadProcessId(hwnd, &pid);
GetGUIThreadInfo(tid, &info);
IAccessible* object = nullptr;
if (SUCCEEDED(AccessibleObjectFromWindow(info.hwndFocus, OBJID_CARET, IID_IAccessible, (void**)&object))) {
Rect rect;
VARIANT varCaret;
varCaret.vt = VT_I4;
varCaret.lVal = CHILDID_SELF;
if (SUCCEEDED(object->accLocation(&rect.x, &rect.y, &rect.w, &rect.h, varCaret))) {
std::cout << rect.x << std::endl;
}
object->Release();
}
Sleep(10);
}
CoUninitialize(); // <-- add this
return 0;
}