NVDA Add-on 開発者ガイド

NVDAアドオン開発者ガイドへようこそ。このガイドは、NVDAアドオンの開発方法と、アドオンを開発する時に役に立つNVDAコアのソースコードについて解説したワンステップガイドです。

NVDA開発について詳細は、NVDA開発コミュニティーのページをご覧ください。アドオンの開発を始めるために重要事項と基本に慣れるために[NVDA開発者ガイド][2]を必ずよくお読みください。

対象者

このガイドは、Python及びその他のプログラム言語に精通している方や、NVDAソースコードの構造に精通しているエキスパート、パワーユーザー、及びプログラマはもちろんのこと、一般のPythonユーザー、またはNVDA開発をするのは初めてというビギナーの両者のために書かれています。

もしNVDAアドオンまたはコアの開発をするのが初めてならば、まず最初にPythonを勉強すれば、このガイドを理解するための基礎知識を得ることができます。あなたがPythonプログラマであるけれどもNVDAの開発をするのが初めてならば、NVDA開発者ガイドと設計概要の文書(両方ともNVDAコミュニティのウェブサイト上に掲載されています)をお読みください。

作者、貢献者と著作権

このガイドはジョセフ・リーによって書かれ、NVDAユーザと開発コミュニティによってまとめられます。私達はあなたのフィードバックと貢献を歓迎します。

Copyright: NVDA is copyright 2006-2016 NV Access. Microsoft Windows, Microsoft Office, Win32 API and other MS products are copyright Microsoft Corporation. IAccessible package is copyright IBM and Linux Foundation. Python is copyright Python Foundation. Other products mentioned are copyrighted by authors of these products.

システム要件

NVDAアドオンを作成するためには、以下のシステム要件を満たしていることをご確認ください:

  • NVDAのバージョンは、ポータブル版、インストール版のどちらでもかまいませんが、開発を行うコンピュータにNVDAをインストールしておくことを推奨します。
  • Python2.7シリーズ : version 2.7.x 32-bit for Windows.
  • SCons 2, version 2.3.0 : アドオンパッケージを生成する際に使用します。
  • Markdown 2.0.1以降 : アドオンのドキュメントの生成に使用します。
  • GNU Gettext package for Windows : メッセージの多言語化をサポートする際に使用します。
  • Git 1.7.9 以降 : アドオンをアップロードする際に使用します。Git Bash、Cygwin's Git、Tortoise Gitなどなどの様々なGitクライアントが利用可能です。
  • NVDAコミュニティのアドオンテンプレート。アドオンのファイル及びフォルダーのパッケージ管理が容易になります。(必須ではありません。アドオンテンプレートをダウンロードするには[ここをクリック][3]してください。)
  • あなたが作成するアドオンに必要なPython追加モジュール。

アドオンとは

アドオンとは、NVDAの機能を拡張したり、NVDAがアプリケーションをサポートするための追加パッケージです。アドオンはグローバルな機能の追加、アプリケーションへのサポートの強化、新たな点字ディスプレイまたは音声エンジンへの対応などを実現できます。

ひとつのアドオンは以下のひとつまたは複数のコンポーネントを含むことができます。

  • グローバルプラグイン:どの場面でも使うことができるプラグインで、例えばOCR等、NVDAの可能性を広げる機能を追加することができます。
  • アプリモジュール:オーディオ編集ソフトのようなプログラムの特定のウィンドウやコントロールなどへの対応を改善できます。
  • ドライバー:ハードウェアと通信するためのプログラムです。現在、新しい点字ディスプレイまたは音声合成エンジンのためのドライバーを作成できます。

ひとつのNVDAアドオンパッケージは、1個または複数のアドオンモジュールから構成されます。パッケージは拡張子 .nvda-addon という名前を持つzipファイルです。これはアドオンマネージャー経由でインストールされます。アドオンマネージャーはNVDA 2012.2以降のバージョンで利用できます。さらにNVDA 2012.3以降では Windows のファイルマネージャーからアドオンをインストールできます。

このガイドでは、標準のNVDAモジュールを、アドオンモジュールと区別するために、「NVDAコア」と呼びます。

アドオン開発環境の構築

以下の手順に従って、アドオン開発環境を整えてください。

依存パッケージのインストール

  1. NVDA がインストールされていなければダウンロードしてインストールします。
  2. Python 2.7.x Windows 32ビット版をインストールします。
  3. Markdown および SCons のWindows版パッケージをインストールします。
  4. もしアドオンのソースコードを他の開発者と共有する予定があるならば、Git クライアントをインストールします。
  5. Gettext 実行ファイルを、アドオン開発フォルダーにコピーします(アドオン開発フォルダーについては次のセクションをお読みください)。
  6. 音声エンジンまたは点字ディスプレイをサポートするプログラムを作成する場合は、必要なソフトウェアおよびハードウェアを用意します。

アドオン開発フォルダー

アドオンを作成する時には、1つのアドオンについて専用の1個のフォルダーを作り、そこにアドオンのプログラムを置くことをお勧めします。アドオンテンプレートをダウンロードして使用する場合は、フォルダー構造は自動的に作成されます。

必要な依存パッケージ(上記参照)をインストールしたら、このアドオン開発フォルダーの中にGettextパッケージの実行形式ファイルをコピーします。

アドオンフォルダーの構造

アドオンフォルダーは、最低限、以下のファイルとフォルダーを含まなければなりません:

  • manifest.ini : アドオンの名前や制作者等の情報を記述します。
  • "addon" サブフォルダー : この下に appModules, globalPlugins, synthDrivers, brailleDisplays 等のアドオンモジュールのフォルダーを置きます。1個または複数のモジュールを持つことができます。

アドオンテンプレートを使っているなら、フォルダー構造は自動的に作成されますから、このフォルダーの中のaddonサブフォルダーとアドオンモジュールフォルダー(複数可)とコードだけを作成する必要があります。テンプレートファイルを使ってアドオンを作成したりカスタマイズする方法についての詳細な説明は、テンプレートフォルダーの中のreadmeファイルをご覧ください。

アドオンのパッケージング

アドオンをパッケージングするには2つの方法があります:

  1. 手動でアドオンをパッケージングするには、アドオンフォルダーをzipファイルとして圧縮したあと、そのファイルの拡張子を.zipから.nvda-addonにリネームしてください。
  2. アドオンテンプレートとSConsを使って作成するには、まず管理者モード(Windows Vistaまたはそれ以降の場合)でコマンドプロンプトを開き、アドオンフォルダーに移動して、 scons とタイプしてください。

アドオン管理における詳細については、このガイドの管理の章をご覧ください。

さあ始めましょう:実際例

それでは、あなたはアドオンの冒険の旅に出発する準備ができていると思いますが、どのようにして最初の一歩を踏み出せばよいか、まだ確信していませんね?もしそうならどうぞ、この章に目を通してください。アドオンの開発の初歩、開発の秘訣など、基礎知識を得られることでしょう。

メモ:この章では、実際のアドオンパッケージは使用しません。代わりに、プラグインフォルダーを使います。つまりNVDAのユーザー設定フォルダーの中の特定の場所にこの例のPythonファイルを格納します。NVDAがインストールされた環境ではスタートメニューからユーザー設定フォルダーを参照できます。

拡張子.pyのファイルを編集するために、.pyファイルに対応したテキストエディタが必要です。我々が推奨するのはNotepad++(ノートパッドプラスプラス)です。

アドオンプログラムの構成

アドオンのプログラムは1つまたは複数のPythonファイル(.pyファイル)として格納します。世の中にはさまざまな種類のアドオンが存在しますが、それらはみな同じような構成で書かれています。

まずアドオンのソースコードにヘッダを書きます。開発者の名前、1行か2行くらいの簡単なアドオンの説明などを書きます。これは省略可能ですが、作りたいアドオンの目的をいつも意識するために、備忘録としてヘッダを書くことを勧めます。

次に、アドオンが必要とするPythonモジュールをNVDAに指示します。プログラムの中で使いたいのが module という名前であれば import module と記述します。例えば、アドオンで音をならしたい場合は、import tones と書きます。一般的なアドオンでは1つあるいは2つ以上のモジュールをインポートする必要があるでしょう。(特定の種類のアドオンのために必要なモジュールについては後述します)

必要なモジュールをインポート宣言したあと、アドオンのプログラム(クラス定義、変数、メソッドなど)を書きます。最も重要な部分はアドオンクラスの定義で、それは、あなたが作るアドオンの種類を決定づけます。

例えば、あるプログラムのためのアプリモジュールは appModuleHandler やその他必要なモジュールをインポートした後に、次のように書きます:

class appModule(appModuleHandler.AppModule):

その後に記述するのはPythonプログラムです。Pythonのプログラムの書き方については、Pythonのドキュメントを参照してください。

サンプルの実行方法

この章のサンプルアドオンを実行するために、スタートメニューやエクスプローラーで、NVDAユーザー設定フォルダーを探してください。そして、その中の適切なフォルダに拡張子.pyのファイルをコピーしてください:アップモジュールのサンプルは appModules フォルダーに、グローバルプラグインのサンプルは globalPlugins フォルダーにコピーします。

サンプル1:NVDA+Aキーを押したときに音をならす

それでは簡単なサンプルから始めましょう:NVDA+Aを押したとき、どのプログラムからでも1秒間音をならします。どのアプリからでもこの機能を使いたいので、グローバルプラグインを作ります。

まず、ユーザー設定フォルダーを開き、その中の globalPlugins フォルダーを開きます。新規の.pyファイルを作成し、それに、example1.pyなどの名前を付けてください。グローバルプラグインのファイルには短くて説明的な名前を付けることを強く推奨します。そして、テキストエディタで新しく作成した.pyファイルを開いてください。

下記にソースコードを示します。これを正確に.pyファイルに入力してください:

# coding: UTF-8
# 訳注: ソースコードに日本語を使う場合は coding の指定が必要。文字コード UTF-8 で保存すること。
# アドオン開発の最初のサンプル

import globalPluginHandler
import tones # ビープ音を聴きたい

class GlobalPlugin(globalPluginHandler.GlobalPlugin):

    def script_doBeep(self, gesture):
        tones.beep(440, 1000) # 中央のラの音程を1秒間ピーとならす

    __gestures={
        "kb:NVDA+A":"doBeep"
    }

Pythonでコメントを記述するには、ハッシュ記号(#)を注釈行の始めに書きます。

サンプル1の説明

この最初のサンプルは 、NVDA+Aを押したとき、1秒間ビープ音をならします。しかし上記のプログラムの意味はまだ説明していません。ソースコードを順番に見ていくことにしましょう。

  1. ファイルの一番最初には、これがサンプルアドオンであるとヘッダを書きました。
  2. これはグローバルプラグインなので、重要なモジュールであるグローバルプラグインハンドラーをインポートするために、import globalPluginHandlerと記述します。
  3. それから、NVDAに内蔵されている tones モジュールをインポートするために、import tones と記述しました。インポートはロードまたはインクルードともいいますが、あるモジュールからメソッドを使いたいときには、必要なモジュールをインポートしてください。
  4. 次に GlobalPlugin クラスを定義します。カッコの中の記述は、このクラスが何に由来するか(詳細は後述)を指定します。クラスは、プログラミングにおいて、人、机、プログラム、およびその他のオブジェクト(対象)を記述しています。
  5. クラスの中に script_doBeepというメソッド(関数)を書きました。これは、スクリプトの一例です。スクリプトとはコマンドが入力された時に実行されるメソッドです。このスクリプトの中で、1秒間ラの音程の音を鳴らすために、tones.beep(440, 1000) と記述しました。プログラミングにおいて、メソッドは、引数またはパラメーターを取ることができ、メソッドは引数に基づいて何かを実行します(詳しくは後述)。あなたがこれから書くことになる多くのメソッドと同じように、私達のdoBeepスクリプトは一個以上の引数を取ります。スクリプトについては後ほど詳しく述べます。
  6. 最後に、doBeepスクリプトにコマンド(スクリプト)を割り当てるために、単純なディクショナリ(コレクション)を書きました。具体的には NVDA+A コマンドを doBeep スクリプトに割り当てるように指示しました。

このファイルを保存してから、NVDAを再起動してください。NVDA+Aを押すたびに1秒間音が鳴ります。将来あなたのアドオンが完成して、きちんとした方法でインストールできるようになったら、ここで作成した.pyファイルは削除することができます。

ここまでの用語の説明

「クラス」「メソッド」という用語は初めて聞くかもしれません。これらの用語はアドオンの開発において基本的なことなので、これらの用語について詳しく解説しましょう:

  • クラス:クラスとはオブジェクトの記述です。クラスは人、机、NVDAアドオン、その他、なんでも記述できます。クラスはNVDAや他のプログラムに必要です。実際、多くのプログラマは、クラスを作り出すことが上手です。
  • メソッド:メソッドは、音を鳴らす、数を計算する、NVDAアドオンをロードする、など何かをするための短いプログラムです。メソッドは「関数」とも呼ばれます。
  • スクリプト:ユーザが、キーボードの特定のキーを押すなどのコマンドを実行する時に実行されるメソッドです。例えば、あなたがNVDA+F12を押したときに、NVDAは dateTime スクリプトを実行します。これは Global Commands という名前の NVDA コアモジュールの中のスクリプトです。スクリプトは2つの引数を取ります:第1の引数はスクリプトが実行される場所を参照するオブジェクト(通常は self )です(詳しくは後述します)。第2の引数はスクリプトを呼び出したジェスチャー gesture です(これも後述します)。
  • 変数:変数とは書き換え可能な値を格納するものです。人の名前、実行しているNVDAアドオンの名前、使用中のNVDAのバージョンなどが変数の値になり得ます。ひとつのアドオンファイルには複数の変数を格納できます。変数は文字列など共通の定数を定義するためにも使われます。
  • モジュール:モジュールとはひとつのファイルに格納されたメソッドや変数の集合です。アドオンの開発とは、実際には、NVDA の実行中に呼び出されるモジュールの開発です。

他の用語のいくつかは、このあとすぐ説明します。

サンプル2:メモ帳に切り換えた時に音をならす

下記のソースコードの大部分はNVDA開発者ガイドからの引用です。

NVDAではグローバルなコマンドの追加だけでなく、アプリモジュール (app module) によって、特定のプログラムの機能を拡張できます。アプリモジュールも Python ソースコードファイルですが、ファイル名の拡張子 .py の前の部分には、プログラムの実行ファイルの名前を使います。例えば、メモ帳 (notepad.exe) のためのアプリモジュールは notepad.py という名前にします。

NVDA開発者ガイドの下記のソースコードは典型的なアプリモジュールの簡単な例です。アクティブなプログラムをメモ帳に切り換えた時に短いビープをならします。下記のソースコードを notepad.py として保存し、 NVDA ユーザー設定フォルダーの中の appModules フォルダーにコピーしてください。

# An example app module.

import appModuleHandler
import tones

class AppModule(appModuleHandler.AppModule):

    def event_gainFocus(self, obj, nextHandler):
        tones.beep(256, 200)
        nextHandler()

サンプル2の解説

新しいソースコードが出てきました。ふたたび順番に説明します。

  1. 最初のサンプル1と違うところは、重要なモジュールは appModuleHandler だということです。
  2. 使っているクラスは AppModule です。
  3. 前回と違い、イベントを使っています。これはコントロールの名前が変わる時など、特定の出来事が起きたときに実行されるメソッドです。イベントは引数としてオブジェクトを受け取ります。これはそのイベントを処理しているオブジェクト、よく使われる言い方をするなら「イベントを発火したオブジェクト」です。
  4. イベントメソッドの中で、nextHandler を呼び出しています。この呼び出しをするとNVDAがこのイベントの処理を引き継ぎます。例えばビープ音を鳴らしたあとでコントロールの名前を通知する、といった処理が行われます。

新しい用語の説明

新しい用語の説明です:

  • イベント:プログラムにフォーカスが当たる、コントロールの名前が変わるなど、いくつかのイベントが起こる時に、実行されるメソッドです。
  • 呼び出し(コール):あるメソッドの中で別のメソッドが実行されるときに、メソッド(関数)が別のメソッドを「呼び出す(コールする)」と言います。例えば、最初のサンプルで、私たちが書いたスクリプトのメソッドからtones.beepメソッドを呼び出しています。
  • オブジェクト:オブジェクトはあるクラスのインスタンスです。すなわち、プログラムの実行時にクラスから生成されるものです。アドオンにおいて、あなたがクラスを記述して、あなたのアドオンが実行された時に、そのクラスのオブジェクトが作られます。オブジェクトは一般的にobjと略されます。NVDAにおいては、オブジェクトはコントロールを意味することもあれば、あるプログラムの一部分を指すこともあります。
  • self:Pythonにおける self は、現在のクラス(定義中のクラス、例えば実装中のアドオン)、あるいは、メソッドを定義する対象となるクラスを指します。例えば numbers クラスにおいて、add メソッドの第1引数を self とします。これは add メソッドが numbers クラスの一部であるためです。NVDA開発において、self は通常、現在のNVDAオブジェクト(後述します)またはアドオン開発における、アドオンのインスタンスを意味します。あなたが書くメソッドの多くは第1引数としてself を取るでしょう。

ちょうどサンプル1のように、あなたのアプリモジュールの開発が落ち着いたら、notepad アプリモジュールを削除したいと思うでしょう。そうでなければメモ帳に切り換えるたびにビープを聞き続けなくてはなりません。グローバルプラグインとアプリモジュールの実際の違いは、このガイドの続きで詳細に説明します。

初心者のための豆知識

アドオン開発の経験者からの助言をいくつか紹介します:

  • メッセージをしゃべる、音をならすなど、簡単なアドオンの開発から勉強を始めてください。
  • メソッドはひとつずつ書いてテストしてください。
  • アプリモジュールまたはドライバを開発しているなら、サポートしようとするプログラム、音声エンジン、または点字ディスプレイを十分に理解してください。例えば、ドキュメントを読んだり、実際に動かして情報を収集しましょう。
  • コマンド(特にグローバルプラグインにおいて)を定義する時、まずはNVDAや他のアドオンで使われているコマンド操作を確認してください。これはアドオンの中で新しいコマンドを割り当てるときに既存の操作との衝突を防ぐためです。

NVDAコアの有益なモジュール

アドオンを開発していると、NVDAコアにはアドオン開発に役立つモジュールがたくさんあります。この節では有益なNVDAコアのモジュールやメソッドを説明します。

有益なNVDAコアモジュールとメソッドのリスト

利用可能なNVDAコアのモジュールとそれらの中で利用可能な有益なメソッドのリストです:

  • Addon Handler (addonHandler.py): アドオンサブシステムを実装するモジュール。addonHandler.initTranslation() メソッドはアドオンの国際化サポートの初期化です。
  • NVDAの基本的なAPI(api.py):NVDA全体にわたって使われるコアメソッドの集合です。フォーカスやナビゲーターオブジェクトの情報の取得、フォーカスの設定などが含まれます。このモジュールの有益なメソッドは次のリストを参照してください。
  • APP モジュールサブシステム(appModuleHandler.py、 appModules):APP モジュール(詳細についてはAPP モジュールの章を見てください)を処理することを担当しているサブシステム。
  • ARIAサポート(aria.py):アクセシブル・リッチ・インターネット・アプリケーション(ARIA)のサポートを実装しています。
  • ベースオブジェクトのコレクション(baseObject.py):スクリプト可能オブジェクトなどの有益なベースオブジェクトを含んでいます。(詳細はNVDAオブジェクトやオーバーレイオブジェクトの章を参照してください)
  • 点字入出力サブシステム(braille.py, brailleInput.py) : 点字ディスプレイへの出力と点字ディスプレイからの入力を制御します。点字ディスプレイドライバのアドオンが必要とする機能です。
  • 組み込みモジュール(builtin.py):アドオンからビルトインモジュールへのアクセスを可能にします。
  • 設定(config):設定とプロファイル(プロファイルは2013.3以降で利用可能)を管理します。
  • コントロールと状態のコレクション(controltypes.py):コントロールタイプ(ロール)とそのコントロールが取り得る状態の辞書
  • イベント(eventHandler.py):フォーカス取得などの様々なイベントを処理します。
  • グローバルコマンドのコレクション(globalCommands.py):NVDAで利用可能なグローバルコマンドのリスト(詳細はスクリプトスコープに関する章を参照してください)。
  • グローバルプラグインのサブシステム(globalPluginHandler.py):グローバルプラグインを制御するために必要なモジュール。
  • NVDA GUI (gui): メッセージを視覚的に表示するためにNVDAが使うクラスのコレクション。NVDAメニュー、アドオンマネージャー、その他のためのGUIを含みます。
  • ハードウェアポートユーティリティ(hwPortUtils.py):ハードウェアのシリアルポート、及びその他のハードウェアポートと通信を行うアドオンを開発するさいに有益なユーティリティセット。
  • IAccessibleサポート(IAccessibleHandler.py、IAccessibleオブジェクト):IAccessibleコントロールをサポートするために使います。
  • 入力管理(inputCore.py):ユーザからの入力を管理します。
  • JavaAccess Bridge サポート(JABHandler.py):Javaアプリケーションを使用するためにJABサブシステムをサポートするメソッドのコレクション。
  • キーボード入力(keyboardHandler.py):キーボードからコマンドを入力する動作をサポートします。
  • ロギングファシリティー(logHandler.py):モジュールにログへの書き込み許可を与え、それを開発者またはユーザはログ ビュアー経由で閲覧することができます。
  • マウスサポート(mouseHandler.py):マウスコマンドをサポートします。
  • NvDAオブジェクトコレクション(NVDAObjects):多くのアプリケーションと、UIA(ユーザー・インターフェイス・オートメーション)のような一般的なユーザーインターフェースで使われるNvDAオブジェクト、またはコントロールのコレクション。
  • スクリプトサポート(scriptHandler.py):キーボード入力やその他のコマンドをスクリプト上から実行できるメソッドが収められています。
  • 音声出力(speech.py):音声出力をコントロールします。
  • 音声エンジンドライバサポート(synthDriverHandler.py):これは音声エンジンドライバアドオンのために必要であったコアモジュールです。
  • ウィジェットテキストアクセス(textInfos):ウィジェットドキュメントのためにテキストへのアクセスを許可します。
  • タッチスクリーンサポート(touchHandler.py):タッチスクリーン入力のサポートを提供します。(インストールバージョンのみ)
  • 音出力(tones.py):ユーザが音を聞くことを可能にします。
  • ユーザー・インターフェース・メッセージ(ui.py):音声、または点字ディスプレイにメッセージを出力するときに使用する、ui.messageメソッドをインクルードします。
  • バーチャルバッファー(virtualBuffers):バーチャルバッファーハンドルはウェブサイトなどのドキュメントを処理します。

.py拡張子のないモジュールはディレクトリーであり、専門のモジュールを含んでいます。

有益なメソッド

ここではアドオンの中で使用できるいくつかの有益なメソッドのリストを挙げます。それらがどう実装されるかについての詳細については、NvDAソースコードドキュメントをご覧ください。具体的なサンプルについては、このガイドのアドオンセクションの節をご覧ください。

From addonHandler:

  • addonHandler.initTranslation(): Gettext経由でアドオンのために翻訳サブシステムを設定します。

api.py:

  • api.getFocusObject(): フォーカスが当たっているオブジェクトを返します(オブジェクトとフォーカスが戻ります)。
  • api.getNavigatorObject(): クライアントのナビゲーターオブジェクトを取得します。NvDAが、システムフォーカスに追随するように設定されているなら、フォーカスとナビゲーターオブジェクトは同じになるでしょうし、そうでない場合は異なるオブジェクトが返されます。
  • api.getForegroundObject(): クライアントのアプリケーションのフォアグランドウィンドウを返します(このオブジェクトの親はアプリケーション自身です)。
  • これらは、一定のオブジェクトをフォーカスまたはナビゲーターオブジェクトと取り決めるメソッドを持っています。

logHandler:

  • logHandler.Log: ロギング機能を実装するクラス。

tones:

  • tones.beep(音程(Hz) , 音の長さ(MS), 左チャンネルのボリューム, 右チャンネルのボリューム):指定の長さ、及び音程の音をならします。最初の2つの引数は必須、残りの2つはオプションです。

ui:

  • ui.message(音声または点字で出力するメッセージ): メッセージを音声出力、もしくは点字ディスプレイに出力します。文字列はダブルコーテーションで囲む必要があります。

他にも有益なメソッドがありますが、これまで挙げたものが最も有益なものです。他のメソッドについてはNVDAソースコードドキュメントをご覧いただくか、これらのメソッドとその他の有効範囲については、下記の例をご覧ください。

アドオンモジュールコンポーネントと開発のヒント

アドオンモジュールは多くのコンポーネントから成り立っています。これは入出力を取り扱う、別のNVDAオブジェクトを操作する、イベントに反応する、文字列を設定するなどといった操作が含まれています。

この章では、NVDAオブジェクト、スクリプト、扱えるイベント、およびアドオン開発に用いられるキーコンポーネントとコンセプト、追加のトピックなどと例を紹介します。

NVDAコア開発者ガイドでは下記のコンセプトに基づいて紹介することに注意してください。この章はそのドキュメントの拡張を意図して書かれています。短く紹介するためNVDA開発者ガイドを参照してください。

画面上のオブジェクトに働きかける

オブジェクトはクラスのインスタンスです - すなわち、プログラムが動いている間有効なクラスです。例えば、ボタンというクラスが定義されたなら、スクリーンのボタンはこのボタンクラスのオブジェクトです。

NVDAの中で、オブジェクトはプログラムのコントロールまたはその集合の表現です。これはボタン、チェックボックス、エディットフィールド、ツールバー、スライダ、およびアプリケーションウィンドウを含みます。これらは階層的に構成されるか、オブジェクトが複数の子オブジェクトを含むかもしれません。例えば、Windowsエクスプローラの中のリストオブジェクトは一個以上リストを含むかもしれませんし、このリストの親はWindowsエクスプローラウィンドウであるかもしれません。あなたがちょうど今調査しているオブジェクトは「ナビゲーターオブジェクト」といいます。

NVDA オブジェクト(または単にオブジェクト)は、多くの有益なプロパティや属性を含んでいます。これらはオブジェクトの名前、その値(チェック状態、編集ウィンドウのテキストなど)、ロール(チェックボックス、ウィンドウ、埋め込みオブジェクトなど)、場所(スクリーン座標)などです。NVDAオブジェクトはまた、オブジェクトの値を変更する、オブジェクトのイベントに反応する(フォーカスの移動、値の変化など)、といった処理のための有益なメソッドを含んでいます。

多くの状況において、NvDAオブジェクトは関連したオブジェクトのクラスに属するかもしれません。それぞれのために、オブジェクトクラス、NvDAは、これらを扱う方法を提供します。これらのクラスにはIAccessible、JAB、UIAなどを含みます。あなたが、使っている(例えば、あなたがIAccessibleオブジェクト、impore NVDAObjects.IAccessibleに働きかけているならば。)オブジェクトのために、オブジェクトのクラスが、あなたのアドオンの中でNvDAソースコードと使用へのそれらの中のNVDAObjectsダイレクトリーの中で定義したことであるそれぞれのためのこれらのクラスと反応は適切なオブジェクトクラスハンドラをインポートします。

バーチャルバッファーと、ツリーインターセプターのオブジェクトクラスの2つは特別な言及に値しています。1つのオブジェクトであるかのように、ツリーインターセプターは、NvDAがオブジェクトの"tree"によって働くことを可能にします。ツリーインターセプターの特殊な場合はバーチャルバッファーです(それは、NVDAがPDFドキュメントなどの複合ドキュメントによって動作することを可能にします)。

オブジェクトの階層構造を調べる

与えられたプログラムのオブジェクト階層構造を見るために利用できる多くの方法があります:

  1. 簡易レビューモードを無効にしてオブジェクトナビゲーションコマンド(NvDA+テンキー 2/4/5/6/8)を使う。
  2. Pythonコンソールを使って、obj.next/previous/parent/firstChild/lastChild アトリビュートを使う。参照可能なすべてのプロパティをPythonコンソールから見たいならば、dir(obj)とタイプしてください。

ナビゲーターオブジェクトについてさらに詳細な説明をご覧になりたい場合は、NvDA+F1を押してログビュアーを起動してください。Windowsの中のすべてのオブジェクトのルートはデスクトップまたは空のオブジェクトです。

フォーカスとナビゲーターオブジェクト

アドオンを使って様々なオブジェクトによって操作する ことを望むかもしれません。これらは、フォーカスが当たった、オブジェクトを入れ替える、ナビゲータオブジェクトとフォーカスオブジェクトを同期させる、オブジェクトロールを変更するなどといった操作を含むかもしれません。

フォーカスオブジェクトは、現在フォーカスが当たっているフォーカスをコントロールします。これらはキーボードの位置と結び付きます - つまり、それはハイライトされたコントロールにリンクしています。対照的に、ナビゲーターオブジェクトは、あなたが注目しているオブジェクトです。ナビゲータオブジェクトはどこにでも移動することができるので、すぐにフォーカスオブジェクトとナビゲーターオブジェクトの2つのオブジェクトを調査することができます。例えば、ナビゲーターオブジェクトとしてタイトル・バーを調査しているときに、エディットフィールドにフォーカスが合うかもしれません。

アドオンの中で、フォーカスによってオブジェクトを取得するには、someObj = api.getFocusObject() と記述します。someObjは別の名前にすることができます - 書き方は、name "obj" を使うことになっています。ナビゲーターオブジェクト(フォーカスが合ったオブジェクトと違うかもしれません)を取得するために、obj = api.getNavigatorObject() を使用します。

他の有益なオブジェクト

ここには他のメソッドがあります、すべてapi.pyモジュールに格納されており、NVDAオブジェクトとして動作します:

  • フォアグラウンドの目標(フォアグラウンドウィンドウのある子オブジェクトを見たいなら便利です)を達することを望むならば、obj = api.getForegroundObject() を使用します。
  • オブジェクトが含んでいる(例えばフォアグランドウィンドウの子またはウィジェット)子オブジェクトの数を見るには、Pythonコンソールから、obj.childCount とをタイプします。値0は、もう、子オブジェクトがないことを意味しています。
  • あるオブジェクトを新しいフォーカスまたはナビゲーターオブジェクトと指定するには、api.setFocusObject(obj) またはapi.setNavigatorObject(obj) を使用してください。
  • プロパティを閲覧すること、 希望するアトリビュートであるobj.propertyを指定することによってオブジェクトの様々なプロパティを取得することができます。(例えば obj.value)

サンプル1:プログラムのスライダの値を取得する

あなたがユーザから、使っているプログラムの中のスライダの値を通知するようにしてほしいと頼まれたとします。オブジェクトツリー構造他のプロパティーを見た後に、あなたは、ツールバーがフォアグランドオブジェクトの最後の子供であると分かりました。

下記にその機能を実装するコードを示します:

# オブジェクトサンプル 1

import api
import appModuleHandler

class AppModule(appModuleHandler.AppModule):

    sliderChildIndex = -1 # 子インデックスを格納する変数。

    def getSliderValue(self):
        fg = api.getForegroundObject()
        sliderVal = fg.children[self.sliderChildIndex].value
        return sliderVal

このコードの中で、fg.children[index] メソッドは、与えられたインデックスを持つ子供を指定ために使われます(ここでは、ツールバーが最後の子供ということなので、インデックスはマイナス1、またはまさに最後の子供、fg.lastChild)を用いるかもしれません)

しかし、このコードには問題があります:スライダの値が実際のスライダコントロールの最初の子供の中にある場合はどうでしょうか?これを直す1つの方法は、オブジェクトのロールをチェックすることです。修正されたコードはこのようになります:

def getSliderValue(self):
    from controltypes import ROLE_SLIDER # メソッドをインポートしています
    fg = api.getForegroundObject()
    slider = fg.lastChild
    if slider.role == ROLE_SLIDER: return slider.firstChild.value

従って、スライダーとやりとりしていると確かに分かっているときには、メソッドは、スライダの最初の子供の値を戻します(このケースの場合)。1つの等号と同等に、2つの対照的な等号についても言及してください。

あなた自身でオブジェクトナビゲーションとマニピュレーションに慣れるために、他にもサンプルがあります:

  • 他のどこかあるいはプログラム内にあるオブジェクトの名前を取得します。
  • ナビゲータをフォアグランドオブジェクトに移動させます。
  • フォーカスを別のプログラムに設定します。

NvDAオブジェクト上の例は、NvDAソースコードまたは様々なコミュニティアドオンのソースコードを参照してください。

専門のオブジェクトとオーバーライドされたオブジェクトのランタイムのプロパティ

時々、省略時デフォルトの動作では十分ではないことがあります。例えば、プログラムのいくつかの部分にはカスタムのゼスチャーが必要かもしれませんし、あるいはウィンドウのロールボタンをそれに変更する必要があるかもしれません。

NVDAは、専門クリエイターのための2つのメソッドを提供します、または違うニーズにそれぞれ適した反対のオーバーレイ(またはクラス)を作成します:

  • event_NvDAObject_init(self, 我々が扱っているオブジェクト ) : そのロールまたはラベル(名前)などの制御の一定のアトリビュートを無効にしたいときに、NvDAに初めから(または初期設定されている)オブジェクトと会う時にあなた"input"を記述するためにこのメソッドを使うことができます。例えば、コントロールが、TForm(多くのDelphiアプリケーション上で見られます)のウィンドウ・クラス名を持っているなら、NVDAに obj.role = ROLE_WINDOW (入手可能なロールのリストのために制御タイプ辞書を参考にしてください)を割り当てることによってこの制御を標準ウィンドウとして扱うことができます。
  • chooseNVDAObjectOverlayClasses(self, object, list of classes): これは、NVDAが一定のオブジェクトを扱う時にあなた自身のロジックを使うことを可能にします。例えば、カスタムジェスチャーを、APP モジュール(実のところ、プログラムの一定の部分を扱うために、多くのアプリモジュールはオブジェクトを作成し、そして、一定の条件が満たされている時に、正しいオブジェクトを選ぶために、chooseNvDAObjectOverlayClassesを使います)中のプログラムの一定の部分に割り当てたい場合に有益です。これらのカスタムのオブジェクトは、eealに対する堅固なオブジェクトに基づかなければなりません(たいてい、ほとんどのオーバーレイオブジェクトがそのオブジェクトから継承されるか、またはIAccessibleオブジェクトの子供またはスペシャリストクラスであるので、IAccessibleは十分です)。

第2の方法の場合には、与えられた名前を持ったクラスがファイルの中にあることに注目し、どれがあるか、既知のベース・オブジェクト(Pythonでは、inheritenceのための構文はchildClass(baseClass)であり、また通常は読まれて、"この子どもクラスはその基底クラスから継承する""」後でこのようなコードに遭遇するでしょう)から継承されます。

オーバーレイクラスとロールの変更のサンプル

上記で議論した2つのオーバーレイと属性変更のメソッドの例です:

最初のケースのサンプル:アトリビュートを修正します。

# ウィンドウとしていくつかのDelphiフォームウインドウを再割り当てする。
    def event_NvDAObject_init(self, obj):
        if obj.windowClassName == "TForm": obj.role = ROLE_WINDOW

これは、"TForm" のクラス名を持つウィンドウに遭遇する時はいつでも、NvDAがこれを正常なウィンドウとして扱うということを意味しています。

サンプル2は、プログラムの具体的な部分を扱うために、2つのオブジェクトを持っているアプリモジュールを扱い、そして、ロジックを各コントロールに割り当てるために、chooseNVDAObjectOverlayClassesを使います。

#オーバーレイクラスのサンプル

class enhancedEdit(IAccessible):
    # ウィンドウ・クラス名がMyEditの時に実行されるコード。

class MainWindow(IAccessible):
    # プログラムの主要なウィンドウのために今回カスタムのゼスチャーを追加している別のコード。

# アプリモジュールの中身:

def chooseNVDAObjectOverlayClasses(self, obj, clsList):
    if obj.windowClassName == "myEdit": clsList.insert(0, enhancedEdit)
    elif obj.windowClassName == "TWindow": clsList.insert(0, mainWindow)

両方の場合に、私達がチェックするオブジェクトはclsListの第1エレメントとして挿入されなければなりません。効果は、これらのカスタムオブジェクトがオブジェクトのために、そして開発者情報においてゼスチャーまたはコード(反応)を探す時に優先するでしょうし、ナビゲーターオブジェクトのためのMRO(メソッド選択次数)が表示される時に、これらのカスタムオブジェクトが最初に来るであろうということです。

スクリプトとUIメッセージの入出力:

アドオンの別の重要な部分は、ユーザからコマンドを処理して、アドオンがなにをしているかを表示しています。これらはスクリプト(入力)とUIメッセージ(出力)経由でされます。

ユーザが一定のコマンドを実行した時に、スクリプトはメソッドを実行します。例えば、NvDA+Tを押した時、NVDAはグローバルコマンドモジュールのなかのSayTitleを呼びます。例えば、Poeditにおいて、翻訳者がControl+Shift+Aを押した時、NvDAは、トランスレータコメントが、与えられた翻訳可能である文字列を明確にするのを手助けするプログラマによって、このコマンドはネイティブのNvDAコマンドではないと記述されていますが、それは、この関数を実行するためにPoeditアプリモジュールの中で定義されています。

一般的に、スクリプトを受け入れるアドオンはモジュールの中にコマンド:関数のマップのリストをどこかに持っているでしょう。これらのキー(1より多くはキー入力するか、コマンドはスクリプトと結合することができます)のために、最も簡単なものは、ゼスチャー(コマンド)辞書、キーとしてコマンドを保持するPython辞書(一般に___gestures と名付けられる)、および値としてのスクリプトです。NvDAが終了するか、アプリモジュールのためのアプリのどちらかが、フォーカスを失う時(すなわち、ユーザは別のプログラムに切り換えたということ)、アドオンが読み込まれ、クリーンにされる時に、これらの辞書が読み込まれます。

スクリプトを関連づける別の方法はランタイム経由で挿入することです。これは、単独のコントロールを処理するなどのコンテキストに反応するゼスチャーを保持する __gestures 辞書とは別に、別のゼスチャー辞書を作成することによって行われます。そして、開発者は、一時の間一定のゼスチャーを定義し、それから追加されたゼスチャーを削除するために inputCore.clearGestures それから inputCore.bindGestures(__gestures) を使うために、 inputCore.bindGesture (または、複数のゼスチャー/スクリプトが定義されるならば inputCore.bindGestures )を使うでしょう。オーバーレイクラスについて述べるときに、特化したオブジェクトがスクリプトに関係しているより完結な方法がカバーされているでしょう。

現在、NvDAは点字キーボードがあるかどうかにかかわらず、キーボード、点字ディスプレイ、タッチスクリーンからの入力をサポートします。

サンプル2:基本的なスクリプト辞書

このサンプルは、"sayHello"と"GoodBye"という2つのスクリプトを定義し、2つの異なるゼスチャーにこれらを結びつけます。

# -*- coding: utf-8 -*-   
# 日本語を出力する場合に上記の4項が必要
# このファイルはUTF-8で保存してください。
# サンプルスクリプト指定のためのフラグメント。
import ui

def script_sayHello(self, gesture):
    ui.message(u"こんにちは!")

def script_sayGoodBye(self, gesture):
    ui.message(u"さようなら!")

__gestures={
    "kb:control+NVDA+1":"sayHello",
    "kb:Control+NVDA+2":"sayGoodBye"
}

今、Ctrl+NvDA+1を押すと、NvDAは"こんにちは!"というでしょう。また、Ctrl+NvDA+2を押すと、NVDAは"さようなら!"と言うでしょう。

サンプル3:ランタイムスクリプト挿入/削除

# 将来のセクション #

適切なセクションが実行される時、この通知を削除してください。

アドオンコンポーネントと開発のヒント

入力とスクリプトの紹介と、出力システム、オブジェクト、イベント、設定、アドオンの設定、および再読込されるプラグインを含みます。また、デバッグなどのアドオン開発についてのいくつかの秘訣を含みます。それはいくつかの役に立つ例と、正しい、間違っている例です。

計画中のセクション(このセクションにあなたの知識を寄与していてください):

  • NVDAオブジェクトを紹介します。
  • Python コンソールで使用できる試験オブジェクト属性。
  • 取得及び設定するオブジェクト。
  • 通常のおよび簡単なレビューモードとオブジェクト階層構造の違い。
  • event_NVDAObject_init メソッドと chooseNVDAObjectOverlayClasses メソッド.
  • イベントと入手可能なイベントのリスト。
  • Next handlers.
  • スクリプト経由でキーボード、点字ディスプレイ、マウス、およびタッチスクリーンからの入力。
  • スクリプトのルックアップ過程と競合について。
  • 静的かつ動的なスクリプト割り当て、ゼスチャー辞書、およびスクリプトカテゴリ。
  • 点字、音声、及び音の出力
  • アドオンのデバッグ。
  • もし何らかの警告(エラー及び例外)が発生したら。
  • 各トピックのうまく動く例とうまく動かない例。
  • これらのセクションの計画は変更されるかもしれません。

グローバルプラグイン

グローバルプラグインを解説する章。

計画中のセクション:

  • グローバルプラグインとは何か。
  • NvDAとアドオンを作成するときに重要なことは、コマンド競合を最小限にすることです。
  • グローバルプラグインを使うべきでない時。
  • 少し具体的な例。
  • これらのセクションは変更されるかもしれません。

アプリモジュール

アプリモジュールの章。

計画中のセクション:

  • アプリモジュールとはなにか。
  • アプリモジュールスクリプト。
  • プログラムのさまざまな部分に対応するオブジェクト。
  • あるプログラムのためにNVDAで音声を出さなくする。
  • どうすればアプリケーション開発者が、アクセシブルなアプリ設計を通してNVDAユーザを助けることができるのでしょうか。
  • NVDAコアそしてコミュニティから、既存のアプリモジュールの例を考え出しました。
  • これらのトピックは変更されるかもしれません。

ドライバー

ドライバ開発者のための章。

その他の項目

Bitbucketレポート、アドオンリスト、他のトピック、および連絡先を含んでいます。

http://community.nvda-project.org/documentation/developerGuide.html