前の関連記事:Calc(66)AccessibleSpreadsheetDocumentViewのサービスとインターフェイスの一覧
AccessibleWindowの位置と大きさを取得するマクロ
import unohelper # オートメーションには必須(必須なのはuno)。 from itertools import zip_longest from com.sun.star.sheet import CellFlags as cf # 定数 DIC_ACCESSIBLEROLE = {'26': 'HEADING', '24': 'GROUP_BOX', '39': 'PAGE_TAB_LIST', '41': 'PARAGRAPH', '17': 'FILLER', '51': 'SCROLL_PANE', '48': 'ROW_HEADER', '29': 'INTERNAL_FRAME', '84': 'DOCUMENT_SPREADSHEET', '60': 'TEXT', '7': 'COMBO_BOX', '35': 'MENU_BAR', '36': 'MENU_ITEM', '70': 'CAPTION', '27': 'HYPER_LINK', '21': 'FRAME', '71': 'CHART', '11': 'DIRECTORY_PANE', '40': 'PANEL', '57': 'STATUS_BAR', '80': 'TREE_TABLE', '33': 'LIST_ITEM', '78': 'SECTION', '61': 'TEXT_FRAME', '32': 'LIST', '3': 'CANVAS', '0': 'UNKNOWN', '5': 'CHECK_MENU_ITEM', '20': 'FOOTNOTE', '64': 'TOOL_TIP', '13': 'DOCUMENT', '28': 'ICON', '69': 'BUTTON_MENU', '53': 'SEPARATOR', '81': 'COMMENT', '18': 'FONT_CHOOSER', '50': 'SCROLL_BAR', '56': 'SPLIT_PANE', '82': 'COMMENT_END', '45': 'PROGRESS_BAR', '38': 'PAGE_TAB', '47': 'RADIO_MENU_ITEM', '44': 'PUSH_BUTTON', '43': 'POPUP_MENU', '55': 'SPIN_BOX', '2': 'COLUMN_HEADER', '14': 'EMBEDDED_OBJECT', '72': 'EDIT_BAR', '49': 'ROOT_PANE', '77': 'RULER', '75': 'NOTE', '66': 'VIEW_PORT', '65': 'TREE', '79': 'TREE_ITEM', '19': 'FOOTER', '23': 'GRAPHIC', '67': 'WINDOW', '52': 'SHAPE', '34': 'MENU', '22': 'GLASS_PANE', '37': 'OPTION_PANE', '83': 'DOCUMENT_PRESENTATION', '8': 'DATE_EDITOR', '30': 'LABEL', '10': 'DESKTOP_PANE', '58': 'TABLE', '59': 'TABLE_CELL', '9': 'DESKTOP_ICON', '6': 'COLOR_CHOOSER', '85': 'DOCUMENT_TEXT', '46': 'RADIO_BUTTON', '76': 'PAGE', '68': 'BUTTON_DROPDOWN', '12': 'DIALOG', '1': 'ALERT', '25': 'HEADER', '42': 'PASSWORD_TEXT', '63': 'TOOL_BAR', '62': 'TOGGLE_BUTTON', '15': 'END_NOTE', '54': 'SLIDER', '74': 'IMAGE_MAP', '73': 'FORM', '31': 'LAYERED_PANE', '16': 'FILE_CHOOSER', '4': 'CHECK_BOX'} def macro(documentevent=None): # 引数は文書のイベント駆動用。 doc = XSCRIPTCONTEXT.getDocument() # 現在開いているドキュメントを取得。 controller = doc.getCurrentController() # コントローラの取得。 outputs = [("ComponentWindowChild",)] componentwindow = controller.ComponentWindow # コントローラーのアトリビュートからコンポーネントウィンドウを取得。 getAccessibleChildren((), componentwindow, outputs) outputs.append(("",)) outputs.append(("ContainerWindowChild",)) frame = controller.getFrame() # フレームを取得。 containerwindow = frame.getContainerWindow() getAccessibleChildren((), containerwindow, outputs) outputs.append(("",)) outputs.append(("FrameChild",)) accessiblecontextparent = containerwindow.getAccessibleContext().getAccessibleParent() # コンテナウィンドウの親AccessibleContextを取得する。 getAccessibleChildren((), accessiblecontextparent, outputs) outputs.append(("",)) outputs.append(("Frame",)) createOutput((), accessiblecontextparent, outputs) sheet = getNewSheet(doc, "ChildWindows") # 連番名の新規シートの取得。OnTitleChanged→OnModifyChangedが呼ばれてしまう。 rowsToSheet(sheet["A1"], outputs) controller.setActiveSheet(sheet) # 新規シートをアクティブにする。 def getAccessibleChildren(head, accessiblecontext, outputs): # AccessibleContextからAccessibleContextChildを取得。 outputs.append(head+("AccessibleRole", "X", "Y", "Width", "Height", "X onScreen", "Y onScreen")) accessiblecontext = accessiblecontext.getAccessibleContext() for i in range(accessiblecontext.getAccessibleChildCount()): accessiblechild = accessiblecontext.getAccessibleChild(i) createOutput(head, accessiblechild, outputs) def createOutput(head, xaccessible, outputs): # XAccessibleからAccessibleRole、位置、大きさなど取得する。 childaccessiblecontext = xaccessible.getAccessibleContext() bounds = childaccessiblecontext.getBounds() locationonscreen = childaccessiblecontext.getLocationOnScreen() accessiblerole = childaccessiblecontext.getAccessibleRole() outputrow = "{}={}".format(DIC_ACCESSIBLEROLE[str(accessiblerole)], accessiblerole), bounds.X, bounds.Y, bounds.Width, bounds.Height, locationonscreen.X, locationonscreen.Y outputs.append(head+outputrow) if accessiblerole==51: # SCROLL_PANEの時。 getAccessibleChildren(("",)*7, xaccessible, outputs)関数getNewSheet()とrowsToSheet()の表示は略しています。
コンポーネントウィンドウは通常はフレームから取得しますが、今回はコントローラのアトリビュートから取得しています(9行目)。
コンポーネントウィンドウ、コンテナウィンドウについてそれぞれAccessibleChildのAccessibleRole、親AccessibleWindowの左上角を原点とする位置、大きさ、画面左上角を原点とする位置、を出力しています。
SCROLL_PANE=51のAccessibleWindowについてはその子AccessibleWindowについても同様に出力しています。
さらにコンテナウィンドウの親についてその子と親について同様に出力しています。
AccessibleWindowPositions.ods
このマクロを埋め込んだCalcドキュメントです。
マクロセレクターからドキュメント内のAccessibleWindowPositions→macroを実行すると次のような結果が出力されます。
AccessibleWindowPositions.odsの実行結果
ドキュメントウィンドウを最大化してLibreOffice5.4で実行した結果です。
linuxBean14.04での実行結果
linuxBean14.04では左側に幅28pxのランチャを表示しているのでフレームFRAME=21の画面の左上角を原点とする座標(X onScreenとY onScreen)ではX=28Y=0になっています。
フレームの子要素はROOT_PANE=49だけで、ウィンドウのタイトルバーを除いた部分になっていました。
X onScreenとY onScreenの値から考えるとコンテナウィンドウはフレームの子要素のROOT_PANE=49に入っていることがわかります。
同様にしてコンポーネントウィンドウはコンテナウィンドウの子要素のPANEL=40の一つに入っていることがわかります。
行間が空いているのは右側にSCROLL_PANE=51の子要素を出力しているからです。
SCROLL_PANE=51の子要素です。
DOCUMENT_SPREADSHEET=84にはセルだけの部分が入っています。
このDOCUMENT_SPREADSHEET=84の子要素はTABLE=58が入っており、そのAccessibleChildCountは1073741824もありました。
さらにこの子要素がTABLE_CELL=59であるセルになっていました。
セルまでたどり着くとそれ以上の子要素はありませんでした。
Windows10での実行結果
Windows10のフレームの位置と、フレームの子ウィンドウのフレームに対する相対位置はどうもおかしいですね。
AccessibleRoleが同じ場合はそれ以外の方法で区別しないといけません。
SCROLL_BAR=50の場合はXScrollBarインターフェイスのgetOrientation()メソッドで縦スクロールバーか横スクロールバーかは区別できます(LibreOffice5(137)グリッドコントロールを使うマクロの例参照)。
「行と列の固定」をしたときと「ウィンドウの分割」をしたときのAccessibleWindow
4分割になるように「行と列の固定」をしたシートのSCROLL_PANE=51の子AccessibleWindowです。
シートが4分割になっているのでDOCUMENT_SPREADSHEET=84が4枠に増えています。
SCROLL_BAR=50も4つに増えていますが、「行と列の固定」のときにスクロールできるのは右下の枠だけなので、4つのスクロールバーのうち2つはHeightかWidthが0になって見えなくなっています。
(2018.9.8追記。縦スクロールバーのうちHeightが0になっているのが右上枠のスクロールバーでした。ということは左下枠の横スクロールバーはWidthが0になっているはずです。)
位置以外からどの枠になっているのかわかるかサービスとインターフェイス一覧をみてみましたが、どの枠の判別ができそうな情報はなさそうでした(Calc(66)AccessibleSpreadsheetDocumentViewのサービスとインターフェイスの一覧)。
「ウィンドウの分割」のときは「行と列の固定」と違ってSCROLL_BAR=50がすべて見えるようになっています。
参考にしたサイト
Accessibility - Apache OpenOffice Wiki
デベロッパーガイドのAccessibilityの解説。
OOoBasic/Window/Accessibility - ...?
Accessibilityを使うとボタンのクリックもできるようです。
0 件のコメント:
コメントを投稿