我们需要UI Automation
使用Window SDK中的Inspect工具,我们可以得到Chrome地址栏的属性名:
Name: "Address and search bar"
ControlType: UIA_EditControlTypeId
我们将寻找UIA_EditControlTypeId,因为它与语言无关。
但是 html 文档中可以有另一个编辑框,它可能会显示在主工具栏之前。因此,我们需要跳过 html 文档,找到包含地址栏的“窗格”。此窗格称为“Google Chrome”,应该只有其中一个。地址栏是这个独特的“Google Chrome 窗格”的子项。
如果浏览器处于全屏模式,则没有地址栏。我们需要一种备份方法来查找地址。例如,您可以在文档中查找它。但该文档也可能不可用,例如当 Chrome 已最小化时。
以下示例使用 ATL COM 类,它需要 Visual Studio
#define UNICODE
#include <Windows.h>
#include <stdio.h>
#include <AtlBase.h>
#include <AtlCom.h>
#include <UIAutomation.h>
//this method fails if browser is in full-screen mode
bool find_url(IUIAutomation* uia, IUIAutomationElement* root)
{
// The root window has several childs,
// one of them is a "pane" named "Google Chrome"
// This contains the toolbar. Find this "Google Chrome" pane:
CComPtr<IUIAutomationElement> pane;
CComPtr<IUIAutomationCondition> pane_cond;
uia->CreatePropertyCondition(UIA_ControlTypePropertyId,
CComVariant(UIA_PaneControlTypeId), &pane_cond);
CComPtr<IUIAutomationElementArray> arr;
if FAILED(root->FindAll(TreeScope_Children, pane_cond, &arr))
return false;
int count = 0;
arr->get_Length(&count);
for (int i = 0; i < count; i++)
{
CComBSTR name;
if SUCCEEDED(arr->GetElement(i, &pane))
if SUCCEEDED(pane->get_CurrentName(&name))
if (wcscmp(name, L"Google Chrome") == 0)
break;
pane.Release();
}
if (!pane)
return false;
//look for first UIA_EditControlTypeId under "Google Chrome" pane
CComPtr<IUIAutomationElement> url;
CComPtr<IUIAutomationCondition> url_cond;
uia->CreatePropertyCondition(UIA_ControlTypePropertyId,
CComVariant(UIA_EditControlTypeId), &url_cond);
if FAILED(pane->FindFirst(TreeScope_Descendants, url_cond, &url))
return false;
//get value of `url`
CComVariant var;
if FAILED(url->GetCurrentPropertyValue(UIA_ValueValuePropertyId, &var))
return false;
if (!var.bstrVal)
return false;
wprintf(L"find_url: %s\n", var.bstrVal);
//set new address ...
IValueProvider* pattern = nullptr;
if (FAILED(url->GetCurrentPattern(UIA_ValuePatternId, (IUnknown**)&pattern)))
return false;
//pattern->SetValue(L"somewhere.com");
pattern->Release();
INPUT input[2] = { INPUT_KEYBOARD };
input[0].ki.wVk = VK_RETURN;
input[1] = input[0];
input[1].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(2, input, sizeof(INPUT));
return true;
}
int main()
{
//find the first visible chrome window
HWND hwnd = nullptr;
while (true)
{
hwnd = FindWindowEx(nullptr, hwnd, L"Chrome_WidgetWin_1", nullptr);
if (!hwnd)
return 0;
if (IsWindowVisible(hwnd) && GetWindowTextLength(hwnd) > 0)
break;
}
//CoInitializeEx(nullptr, COINIT_MULTITHREADED);//<- pick the right one
CoInitialize();
CComPtr<IUIAutomation> uia;
if SUCCEEDED(uia.CoCreateInstance(CLSID_CUIAutomation))
{
CComPtr<IUIAutomationElement> root;
if SUCCEEDED(uia->ElementFromHandle(hwnd, &root))
find_url(uia, root);
uia.Release();
}
CoUninitialize();
return 0;
}