Skip to content

Instantly share code, notes, and snippets.

@kumatti1

kumatti1/ui.cpp Secret

Last active February 9, 2016 23:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kumatti1/78cb31abab7903881afd to your computer and use it in GitHub Desktop.
Save kumatti1/78cb31abab7903881afd to your computer and use it in GitHub Desktop.
//http://www.moug.net/faq/viewtopic.php?t=65909
//yayadonさんのコードをVBAからC++へ変換
#define UNICODE
#import "UIAutomationCore.dll"
#include <windows.h>
#include <string>
#include <vector>
HRESULT InvokeElement(UIAutomationClient::IUIAutomationElementPtr InvokePatternElem);
HRESULT SelectComboBoxItem(UIAutomationClient::IUIAutomation2Ptr UIA2,
UIAutomationClient::IUIAutomationElementPtr DesktopWnd,
UIAutomationClient::IUIAutomationElementPtr AncestorElem,
std::wstring strComboBoxName,
std::wstring strListItemName);
HRESULT ClickButton(UIAutomationClient::IUIAutomation2Ptr UIA2,
UIAutomationClient::IUIAutomationElementPtr AncestorElem,
std::wstring strButtonName);
HRESULT UIAutomation_Test1();
// Element を Invoke する。(クリックする);
HRESULT InvokeElement(UIAutomationClient::IUIAutomationElementPtr InvokePatternElem)
{
try {
UIAutomationClient::IUIAutomationInvokePatternPtr InvokePtn;
InvokePtn = InvokePatternElem->GetCurrentPattern(UIAutomationClient::UIA_InvokePatternId);
if (!InvokePtn)
{
OutputDebugString(L"InvokePattern を取得できなかった。");
throw S_FALSE;
}
//クリック
InvokePtn->Invoke();
}
catch (_com_error& e) {
return e.Error();
}
catch (HRESULT hr){
return hr;
}
return S_OK;
}
// ComboBox のリスト項目を選択する。
HRESULT SelectComboBoxItem(UIAutomationClient::IUIAutomation2Ptr UIA2,
UIAutomationClient::IUIAutomationElementPtr DesktopWnd,
UIAutomationClient::IUIAutomationElementPtr AncestorElem,
std::wstring strComboBoxName,
std::wstring strListItemName)
{
try {
// 探索条件用
UIAutomationClient::IUIAutomationConditionPtr CtrlTypeCdn; //コントロール タイプ
UIAutomationClient::IUIAutomationConditionPtr NameCdn; //名前
UIAutomationClient::IUIAutomationConditionPtr Condition; //コントロール タイプ And 名前
// strComboBoxName コンボボックスを探索。
CtrlTypeCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_ControlTypePropertyId,
UIAutomationClient::UIA_ComboBoxControlTypeId);
NameCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_NamePropertyId,
_variant_t(_bstr_t(strComboBoxName.c_str())));
Condition = UIA2->CreateAndCondition(CtrlTypeCdn, NameCdn);
UIAutomationClient::IUIAutomationElementPtr ComboboxElem;
ComboboxElem = AncestorElem->FindFirst(UIAutomationClient::TreeScope_Subtree, Condition);
if (!ComboboxElem)
{
std::wstring tmp(strComboBoxName);
tmp += L" コンボボックスが見つからなかった。";
OutputDebugString(tmp.c_str());
throw S_FALSE;
}
UIAutomationClient::IUIAutomationValuePatternPtr ValuePtn;
ValuePtn = ComboboxElem->GetCurrentPattern(UIAutomationClient::UIA_ValuePatternId);
_bstr_t bstr;
ValuePtn->get_CurrentValue(bstr.GetAddress());
std::wstring strCurrentValue((LPWSTR) bstr.GetBSTR());
if (strCurrentValue == strListItemName)
{
std::wstring tmp(strComboBoxName);
tmp += L" コンボボックスの現在の値と同じ\t";
tmp += strCurrentValue;
OutputDebugString(tmp.c_str());
}
// コンボボックスをドロップダウン。【必須】
UIAutomationClient::IUIAutomationExpandCollapsePatternPtr ExpandPtn;
ExpandPtn = ComboboxElem->GetCurrentPattern(UIAutomationClient::UIA_ExpandCollapsePatternId);
ExpandPtn->Expand();
// リストを探索。
CtrlTypeCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_ControlTypePropertyId,
UIAutomationClient::UIA_ListControlTypeId);
NameCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_NamePropertyId, _variant_t(_bstr_t(strComboBoxName.c_str())));
Condition = UIA2->CreateAndCondition(CtrlTypeCdn, NameCdn);
UIAutomationClient::IUIAutomationElementPtr ListElem; // List Control Type
ListElem = DesktopWnd->FindFirst(UIAutomationClient::TreeScope_Descendants, Condition);
if (!ListElem)
{
std::wstring tmp(strComboBoxName);
tmp += L" コンボボックスでリストが見つからなかった。";
OutputDebugString(tmp.c_str());
throw S_FALSE;
}
// リスト項目をすべて探索。
CtrlTypeCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_ControlTypePropertyId,
UIAutomationClient::UIA_ListItemControlTypeId);
UIAutomationClient::IUIAutomationElementArrayPtr ElemArray;
ElemArray = ListElem->FindAll(UIAutomationClient::TreeScope_Children, CtrlTypeCdn);
if (!ElemArray)
{
std::wstring tmp(strComboBoxName);
tmp += L" コンボボックスでリスト項目が見つからなかった。";
OutputDebugString(tmp.c_str());
throw S_FALSE;
}
int n;
ElemArray->get_Length(&n);
for (int i = 0; i < n; i++)
{
UIAutomationClient::IUIAutomationElementPtr ListItemElem; // ListItem Control Type
ListItemElem = ElemArray->GetElement(i);
_bstr_t bstr;
ListItemElem->get_CurrentName(bstr.GetAddress());
std::wstring tmp2((LPWSTR) bstr.GetBSTR());
if (tmp2 == strListItemName)
{
InvokeElement(ListItemElem);
}
}
//Windows10 build 14257以降 ComboBoxに変わる
HWND h = (HWND) ComboboxElem->CurrentNativeWindowHandle;
HWND hParent = GetParent(h);
SendMessageW(hParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(h), CBN_SELCHANGE), (LPARAM) h);
}
catch (_com_error& e) {
return e.Error();
}
catch (HRESULT hr){
return hr;
}
return S_OK;
}
// ボタンをクリックする
HRESULT ClickButton(UIAutomationClient::IUIAutomation2Ptr UIA2,
UIAutomationClient::IUIAutomationElementPtr AncestorElem,
std::wstring strButtonName)
{
try {
// 探索条件用
UIAutomationClient::IUIAutomationConditionPtr CtrlTypeCdn; //コントロール タイプ
UIAutomationClient::IUIAutomationConditionPtr NameCdn; //名前
UIAutomationClient::IUIAutomationConditionPtr Condition; //コントロール タイプ And 名前
// strButtonName ボタンを探索。
CtrlTypeCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_ControlTypePropertyId,
UIAutomationClient::UIA_ButtonControlTypeId);
NameCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_NamePropertyId, _variant_t(_bstr_t(strButtonName.c_str())));
Condition = UIA2->CreateAndCondition(CtrlTypeCdn, NameCdn);
UIAutomationClient::IUIAutomationElementPtr ButtonElem;
ButtonElem = AncestorElem->FindFirst(UIAutomationClient::TreeScope_Subtree, Condition);
if (!ButtonElem)
{
throw S_FALSE;
}
// ボタンが有効かを確認。
long lngRet;
ButtonElem->get_CurrentIsEnabled(&lngRet);
if (!lngRet)
{
std::wstring tmp(strButtonName);
tmp += L" ボタンが有効でない状態。";
OutputDebugString(tmp.c_str());
throw S_FALSE;
}
HRESULT rc;
rc = InvokeElement(ButtonElem);
if (rc != S_OK)
{
std::wstring tmp(strButtonName);
tmp += L" ボタンをクリックできなかった。";
OutputDebugString(tmp.c_str());
throw S_FALSE;
}
}
catch (_com_error& e) {
return e.Error();
}
catch (HRESULT hr){
return hr;
}
return S_OK;
}
// デスクトップ項目を 12 に変えてみる。
HRESULT UIAutomation_Test1()
{
try {
// 条件用
UIAutomationClient::IUIAutomationConditionPtr CtrlTypeCdn; //コントロール タイプ
UIAutomationClient::IUIAutomationConditionPtr NameCdn; //名前
UIAutomationClient::IUIAutomationConditionPtr Condition; //コントロール タイプ And 名前
HRESULT rc;
UIAutomationClient::IUIAutomation2Ptr UIA2;
HRESULT hr = UIA2.CreateInstance(__uuidof(UIAutomationClient::CUIAutomation8));
if (FAILED(hr))
throw hr;
// デスクトップ ウィンドウを取得。
UIAutomationClient::IUIAutomationElementPtr DesktopWnd;
DesktopWnd = UIA2->GetRootElement();
// [ディスプレイ]トップレベル ウィンドウを探索。
CtrlTypeCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_ControlTypePropertyId,
UIAutomationClient::UIA_WindowControlTypeId);
NameCdn = UIA2->CreatePropertyCondition(UIAutomationClient::UIA_NamePropertyId, _variant_t(_bstr_t(L"ディスプレイ")));
Condition = UIA2->CreateAndCondition(CtrlTypeCdn, NameCdn);
UIAutomationClient::IUIAutomationElementPtr DisplayWnd;
DisplayWnd = DesktopWnd->FindFirst(UIAutomationClient::TreeScope_Children, Condition);
if (!DisplayWnd)
{
MessageBox(0, L"[ディスプレイ]ウィンドウが見つかりません。", 0, MB_OK);
throw S_FALSE;
}
const WCHAR *s [] = { L"タイトル バー",
L"メニュー",
L"メッセージ ボックス",
L"パレット タイトル",
L"アイコン",
L"ヒント" };
int length = _countof(s);
std::vector<std::wstring> arr(length);
std::copy(s, s + length, arr.begin());
for (int i = 0; i < length; i++){
// [デスクトップ項目]コンボボックス選択
rc = SelectComboBoxItem(UIA2, DesktopWnd, DisplayWnd, L"デスクトップ項目", arr[i].c_str());
if (rc != S_OK)
{
MessageBox(0, L"[デスクトップ項目]コンボボックスの値の選択に失敗しました。", 0, MB_OK);
throw S_FALSE;
}
// [フォント サイズ]コンボボックス ---> L"12" に
rc = SelectComboBoxItem(UIA2, DesktopWnd, DisplayWnd, L"フォント サイズ", L"12");
if (rc != S_OK)
{
MessageBox(0, L"[フォント サイズ]コンボボックスの値の選択に失敗しました。", 0, MB_OK);
throw S_FALSE;
}
}
// [適用(A)]ボタン --- クリック
rc = ClickButton(UIA2, DisplayWnd, L"適用(A)");
if (rc != S_OK)
{
std::wstring tmp2(L"[適用(A)]ボタンをクリックできませんでした。\n");
tmp2 += L"すでに現在の値である可能性があります。";
MessageBox(0, tmp2.c_str(), 0, MB_OK);
}
}
catch (_com_error& e) {
return e.Error();
}
catch (HRESULT hr){
return hr;
}
}
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow)
{
HRESULT hr = CoInitialize(nullptr);
if (FAILED(hr))
return -1;
UIAutomation_Test1();
CoUninitialize();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment