ユーザーコントロールの作成

はじめに

Aurora Vision StudioのHMIシステムでは、準備されたコンポーネント(コントロールと呼ばれる)からユーザーインターフェースを設計することができます。ユーザーコントロールのメカニズムを使用して、新しい外部コントロールを追加することで、この機能を拡張することができます。

HMIは、.NET Framework 4.0のWindows Formsライブラリに基づいています。含まれるコントロールは、Windows Formsコントロールと互換性があり、適切に拡張されてAurora Vision Studioで使用するためのものです。

新しいHMIコントロールを設計する際は、主にWindows Formsシステム用の正しいコントロールを作成することが主な作業です。これには、ドキュメントDeveloping Custom Windows Forms Controls with the .NET Frameworkで指定された要件に準拠する必要があります。ユーザーコントロールを作成するための3つのアプローチがあります:

  • コンポジットコントロール(複数のコントロールを1つの新しいコントロールに組み合わせる)
  • コントロールの拡張(既存のコントロールに新しい機能を追加する)
  • カスタムコントロール(ゼロから作成されたコントロール)

これらの手法の実装の詳細は、Varieties of Custom Controlsのドキュメントで説明されています。

単一のHMIコントロールは、System.Windows.Forms.Controlまたはその派生クラスから派生した、単一で完全で公開されたクラスで表されます。作成されたコンポーネントはユーザーコントロールと呼ばれていますが、System.Windows.Forms.UserControlから派生させる必要はありません。このクラスは、コンポジットコントロールを実装する場合にのみ使用されます。

コントロールのファイルへの直列化

HMIのレイアウトとコントロールの設定は、.avhmi拡張子のファイルに保存されます。コントロールは、Windows Formsの原則と一貫性のある方法でファイルに保存されます。コントロールの保存は、その公開プロパティから値を保存することによって実現されます。保存するプロパティはその目的のために設計されたものだけで、その値がデフォルト値と異なる場合にのみ保存されます。

プロパティが直列化の対象であるかどうかを制御するには、System.ComponentModel.DesignerSerializationVisibilityAttribute属性を使用します。

コントロールは、次の2つの方法のいずれかで、プロパティがデフォルト値と異なる値に変更されたことを示すことができます:

上記のメカニズムから1つだけを使用する必要があります。どれも使用しない場合、コントロールのプロパティは常に直列化され、エディタでその値をリセットすることができなくなります。

HMIをファイルからロードする際、コントロールのプロパティは指定された順序で初期化されます。コントロールがプロパティが誤った値で設定されると不適切な状態になる可能性がある場合や、コントロールのプロパティ値が他のプロパティに依存している場合(例:値を最小値と最大値の間の指定された範囲に制限する場合)、コントロールはSystem.ComponentModel.ISupportInitializeインターフェースを実装する必要があります。これにより、HMIサブシステムがプロパティを単一のトランザクションで初期化します。

プロパティの値はXML形式のファイルに直列化され、すべての値はXMLノードに保存できるテキストに変換する必要があります。それを可能にするためには、公開プロパティで使用されるデータの型は、ローカライゼーションに依存しないテキストへの変換をサポートする必要があります。そのためには、型コンバータを割り当てる必要があります。この型コンバータは、System.String型との変換を両方の方向でサポートできる必要があります。ほとんどのシンプルな組み込み型および.NET Frameworkが提供する型(System.IntegerまたはSystem.Drawing.Sizeなど)は、既にそのような変換をサポートしており、追加の注意が必要ありません。

コントロールへの説明の追加

Controlクラスだけでなく、コントロールの各公開プロパティには、エンドユーザー向けの説明を含むSystem.ComponentModel.DescriptionAttribute属性でマークできます。説明はHMIを設計する際にエディタで表示されます。

Controlクラスは、エディタのカタログに表示されるアイコン画像を指定するSystem.Drawing.ToolboxBitmapAttribute属性でマークできます。

HMIデザイナーでのプロパティの編集

エディタは、コントロールのレイアウト(配置とサイズ)に加えて、コントロールの公開プロパティも編集できるようにします。公開プロパティの値は、HMIアプリケーションのコントロールの構成と初期状態を指定します。

すべてのプロパティをHMIエディタで変更できるわけではありません。プロパティを編集可能にするには、プロパティはpublicであり、そのデータ型がAMRデータへの変換を許可する必要があります。プロパティの値は、Aurora Vision Studio環境内でAMR表現で編集され、HMIおよびプログラムエディタに共通のツールを使用します。このデータはAMRデータへの変換の方法を制御することで、編集の方法に影響を与えることができます(例:許可された範囲を設定するなど)。AMRへの変換に関する詳細な説明は、この記事の後半にあります。

HMIエディタは、エディタでのプロパティの表示可否を決定するために独自のルールを使用します。プロパティがエディタで表示されるか非表示にするかを制御するには、HMI.HMIBrowsableAttribute属性でプロパティにマークし、bool型の値でそのエディタでの可視性を指定します。コントロールの公開プロパティがこの属性でマークされていない場合、エディタは自動的にその可視性を決定します。

ユーザーコントロールのモジュールの作成

前提条件

ユーザーコントロールのモジュールを作成するためには、次の前提条件が満たされている必要があります:

  • インストールされたAurora Vision Studio環境(バージョン4.3以上)。
  • Microsoft Visual Studio環境(バージョン2015以上)がインストールされており、.NETプラットフォームの選択した言語のツールがインストールされていること(または.NET Framework 4.0を基にしたMicrosoft .NETプラットフォーム向けのアプリケーションを作成できる他の環境)。

コントロールのモジュールの作成

コントロールのモジュールを作成するには、.NET環境向けのDLLライブラリ(Class Library)を作成し、.NET Framework 4をベースにする必要があります。ライブラリは、コントロールクラスを公開タイプとして利用可能にする必要があります。さらに、ライブラリは、任意の名前のpublicクラス1つを公開し、このクラスはHMI.IUserHMIControlsProviderインターフェースを実装する必要があります。このクラスはGetCustomControlTypesメソッドを実装し、ライブラリを介して利用可能なコントロールのクラスタイプを示すSystem.Typeクラスの配列を返さなければなりません。Aurora Vision Studio環境は、このクラスのインスタンスを作成してモジュールを介して利用可能なコントロールのリストを取得します。

HMIネームスペースからの必要なデータ型は、Aurora Vision Studioのインストールディレクトリに含まれるHMI.dllライブラリを介して利用可能です。ユーザーHMIコントロールプロジェクトは、このファイルへの参照を追加する必要があります。

このように準備されたDLLファイルは、適切なAurora Vision製品のインストールフォルダのHMIControlsフォルダか、ユーザードキュメント内のAurora Vision製品フォルダのサブフォルダのHMIControlsフォルダに配置する必要があります。モジュールの読み込みには、Aurora Vision Studio/Executor環境の再起動が必要です。

異なるプロセッサプラットフォーム向けのAurora Vision Studioエディションで使用できるように、「any CPU」プラットフォームを使用してユーザーコントロールプロジェクトをコンパイルすることをお勧めします。特定のプロセッサアーキテクチャを使用する必要がある場合は、32ビット環境用にコンパイルされたモジュールをAurora Vision 32ビット環境で、64ビット環境用にコンパイルされたモジュールを64ビット環境で使用するように確認する必要があります。

Microsoft Visual Studioでのユーザーコントロールプロジェクトの作成手順

ユーザーコントロールモジュールのプロジェクトを作成するには:

  • Microsoft Visual Studioで、選択した.NETプラットフォームのプログラミング言語(たとえば、C#)向けのWindows Forms Class Libraryタイプの新しいプロジェクトを作成します。これは.NET Framework 4をベースにしています。
  • 新しいプロジェクトを作成する際に、Microsoft Visual Studio環境は最初のコントロールとして「UserControl1」という名前のコンポジットコントロールを追加します。他のメソッドを使用してコントロールを作成する場合は、このクラスを削除して適切な実装タイプのクラスに置き換える必要があります。
  • プロジェクトに、Aurora Vision Studioインストールディレクトリに配置されているHMI.dllモジュールへの参照を追加します。
  • プロジェクトで、必要に応じてコントロールクラス定義を作成します。各コントロールクラスは、publicアクセスであり、System.Windows.Forms.Controlまたはその派生クラスから派生している必要があります。
  • プロジェクトに、HMI.IUserHMIControlsProviderインターフェースを実装する1つのpublicクラスを追加し、その中でGetCustomControlTypesメソッドを実装します。
  • プロジェクトをDLLライブラリにコンパイルします。生成されたDLLファイルは、適切なAurora Vision製品のHMIControlsフォルダに配置する必要があります。

Aurora Vision Studio環境で追加のHMIコントロールを使用するプロジェクトが作成された場合、そのプロジェクトをAurora Vision Executor環境で実行するには、対象のコンピュータにもすべての必要なユーザーコントロールモジュールが適切なフォルダに追加されていることを覚えておく必要があります。

コントロールポートの定義

コントロールポートを使用すると、HMIとビジョンプログラム間で接続を作成し、データ同期を実行できます。HMIのコントロールポートは、コントロールのパブリックプロパティに基づいています。1つのコントロールプロパティは、1つの入力ポートおよび/または出力ポートを作成できます。たとえば、コントロール内のMyPropertyプロパティは、inMyPropertyおよびoutMyPropertyの入力ポートおよび/または出力ポートを作成できます。ビジョンプログラムとのデータ同期は、HMIサブシステムによってプログラム値をコントロールプロパティに書き込むこと(setアクセサを使用)によって実現されます。HMIとビジョンプログラム間のデータ同期は、コントロールプロパティから値を読み取り(getアクセサを使用)プログラムに渡すことで実現されます。

コントロールプロパティの出力ポートを作成するには、読み取りを許可する必要があります(パブリックなgetアクセサを実装する必要があります)。入力ポートを作成するには、読み取りおよび書き込みの両方を許可する必要があります(getおよびsetパブリックアクセサの両方を実装する必要があります)。

特定のプロパティを基にコントロールポートを作成するには、プロパティにHMI.HMIPortPropertyAttribute属性を指定し、属性引数としてポートの表示タイプを渡す必要があります。属性引数は、HMI.HMIPortDirection列挙型のビットフラグの値であり、次の値を受け入れます:

  • HMI.HMIPortDirection.Input - プロパティはエディタで制御の入力ポートとして表示され、プログラムと接続する準備が整っています。デフォルトではポートは表示され、ユーザーがポートの可視性エディタを使用して非表示にできます。
  • HMI.HMIPortDirection.Output - プロパティはエディタで制御の出力ポートとして表示され、プログラムと接続する準備が整っています。デフォルトではポートは表示され、ユーザーがポートの可視性エディタを使用して非表示にできます。
  • HMI.HMIPortDirection.HiddenInput - プロパティはエディタで制御の入力ポートとして利用可能ですが、ポートはデフォルトで非表示です。ユーザーはポートの可視性エディタを使用してポートの可視性を設定できます。
  • HMI.HMIPortDirection.HiddenOutput - プロパティはエディタで制御の出力ポートとして利用可能ですが、ポートはデフォルトで非表示です。ユーザーはポートの可視性エディタを使用してポートの可視性を設定できます。
  • HMIPortDirection.None - プロパティはポートではなく(プロパティをポートとして使用することは禁止されています)、エディタで利用できません。

上記の値の論理和を使用して双方向のポートを作成することもできます。

パブリックプロパティがHMI.HMIPortPropertyAttribute属性でマークされていない場合、場合によっては、プロパティの型が基本型である場合、そのプロパティは自動的にポート可視性エディタに表示される場合があります。これは、エンドユーザーがいくつかのプロパティを、ビジョンアプリケーションに接続できるポートに昇格させる可能性があることを意味します。コントロールのパブリックプロパティがHMIポートとして使用されない場合は、そのようなプロパティをHMI.HMIPortPropertyAttribute属性でマークし、値をHMIPortDirection.Noneに設定する必要があります。

プロパティの値が(ユーザーによるコントロールのコンテンツの編集などの)コントロールの内部アクションの結果として変更される可能性がある場合、コントロールはプロパティ値変更通知メカニズムを実装する必要があります。そのようなプロパティごとに、プロパティ名に「Changed」サフィックスを付けた名前と一致するEventHandler型(またはその派生型)のパブリックイベントを作成する必要があります。たとえば、プロパティの名前がMyPropertyの場合、MyPropertyChangedイベントを作成し、ユーザーコントロールの実装によってプロパティ値が変更されるたびにこのイベントが呼び出されます。このメカニズムは、特に指定されたプロパティが入力および出力ポートの両方を実現し、コントロール自体またはビジョンアプリケーションからの書き込み操作によって変更できる場合に必要です。

コントロールのプロパティがビジョンアプリケーションに接続できるポートを作成できるようにするには、そのデータ型がAMR表現への変換をサポートしている必要があります。ポートは、変換が可能なデータ型にのみ接続できます(プロパティデータ型に割り当てられたAMRコンバータでサポートされている場合)。AMR変換についての詳細は以下にあります。

条件付きポートのデータ型

ビジョンプログラムの型システムには、条件付きおよびオプションの型の概念が含まれています。このような型は、追加の特別なシンボル Nil を取り、値が存在しないことを示します(空の値)。HMIコントロール内では、.NETデータ型を基にした場合、Nil シンボルは null 値として表されます。プロパティが条件付きおよびオプションの型との接続を明示的に受け入れるためには、そのプロパティは null 値の割り当てが可能なデータ型である必要があります(参照型または System.Nullable<T> で構築された型)。

基本的な値型および参照型のプロパティは、デフォルトでは条件付きデータを受け入れることや生成することができません(デフォルトでは型が条件付きでないため)。プロパティが条件付きの型を受け入れ、条件付きの型を生成し、接続されたフィルタの条件付き実行を引き起こすためには、そのプロパティは明示的に条件付きとしてマークする必要があります。プロパティを条件付きとしてマークするには次の手順があります:

  • 値型(単純な型または構造体など)を使用する場合、null 値を保持できる型のプロパティを定義する必要があります(System.Nullable<T> として構築された型)。たとえば、Integer? ポート型を達成するには、int? (System.Nullable<System.Int32>) 型のプロパティを宣言する必要があります。
  • 参照型を使用する場合(例:System.String)、すでに null 値を保持できるため、プロパティは HMI.AmrTypeAttribute 属性でマークする必要があります。属性の引数として、必要なAMR型の基本(非条件付き)名を指定し、IsNillable 引数を true に設定します。

コントロールイベントからのデータポート

.NETコントロールイベントを基にHMI出力データポートを作成することも可能です。これにより、Windows Formsで知られている標準のコントロールイベント通知スキーマとの対話が容易になります。イベントポートを作成するには、コントロールクラスによって EventHandler デリゲート型(またはその派生型)の公開イベントを実装する必要があります。プロパティポートと同様に、イベントには HMI.HMIPortPropertyAttribute 属性を指定する必要があります(ただし、出力ポート方向のみが許可されています)。一部の種類のイベントについては、イベントが自動的にポート表示エディタに表示される可能性もあります。

次のコードは、HMIコントロールに outMyEvent ポートを作成します:

[HMI.HMIPortProperty(HMI.HMIPortDirection.Output)]
public event EventHandler MyEvent;

イベントポートはAVS環境では Bool 型です。通常の操作中は False の値が返されます。コントロールによって基になるイベントが呼び出された後、ポートは単一の読み取り操作のために True の値を返し、実質的には単一のビジョンプログラムの反復の時間にわたる True の値のパルスを生成します。これは、Variant Step マクロフィルタ内でのフロー制御などに使用できます。

AMRへの変換

オーロラビジョン環境のビジョンアプリケーションでは、内部のAMR形式でデータが表されます。.NET実行環境を基にしたHMIコントロールのデータは、.NET型の静的型付きデータの形で表されます。データをビジョンプログラムとやり取りするだけでなく、編集ツールでコントロールのプロパティデータを編集するためには、データを.NET型とAMR表現の間で変換する必要があります。このタスクは、AMRコンバータのシステムによって実行されます。1つの.NET型に対して1つのコンバータが割り当てられ、データを1つまたは複数のAMR型に変換できるようにします(Componentsシステムのコンバータと同様)。

コントロールのプロパティをビジョンプログラムに接続できるようにし、開発中に編集できるようにするには、プロパティのデータ型にAMRコンバータが必要です。HMIシステムには、以下の標準的な型を処理する組み込みのコンバータが備わっています。

.NET型 デフォルトのAMR型 変換可能なAMR型
int (System.Int32) Integer Integer, Real
float (System.Single) Real Real, Integer
decimal (System.Decimal) Double Real, Double, Integer, Long
bool (System.Boolean) Bool Bool
string (System.String) String String, Integer, Long, Real, Double
System.Drawing.Size Size Size
System.Drawing.Point Point2D Point2D, Location
System.Drawing.Rectangle Box Box
System.Drawing.Color Pixel Pixel
List<int> (System.Collections.Generic.List<System.Int32>) IntegerArray IntegerArray
List<bool> (System.Collections.Generic.List<System.Boolean>) BoolArray BoolArray
List<string> (System.Collections.Generic.List<System.String>) StringArray StringArray, IntegerArray, LongArray, RealArray, DoubleArray, BoolArray, String?Array, Integer?Array, Long?Array, Real?Array, Double?Array, Bool?Array

すべての値の型を、System.Nullable<T>を許容する対応する型に変換することも可能です。

また、Aurora Vision Studio環境での編集時には、エディターが列挙型やSystem.Drawing.ImageSystem.Windows.Forms.AnchorStylesSystem.Drawing.Fontなどのコントロールの外観と動作を定義するために必要な型のプロパティグリッドでの編集を有効にします。

ビジョンプログラムとHMIコントロールのポート間で接続を確立する場合、コントロールのポートのAMRデータ型を厳密に指定する必要はありません。代わりに、コントロールのプロパティに割り当てられたAMRコンバーターが、ビジョンプログラムのポートとコントロールのプロパティの間で最適な変換を選択します。これにより、例えば、System.Decimal型のプロパティとInteger型およびReal型の両方を編集するために必要な範囲と精度の普遍的な表現を可能にします。

プロパティグリッドでの編集中、AMRコンバーターによってコントロールのプロパティのデフォルトのAMRデータ型が提案されます。コントロールのプロパティのデフォルトのAMRデータ型を変更することが可能です。そのためには、プロパティにHMI.AmrTypeAttribute属性を指定し、新しいデータ型の名前をAMR規約で引数として指定する必要があります。AMRコンバーターでサポートされている型またはそれらの型の名前のエイリアスのみがサポートされます(例:System.String型のプロパティに対して "File" または "Directory" というAMRデータ型を割り当てる場合、どちらもString型のエイリアスです)。HMI.AmrTypeAttribute属性はまた、次のようなことも可能にします:

  • 数値型の場合に許容範囲(min...max)を割り当てる(MinおよびMaxパラメータを使用)
  • 指定された型が条件付き(T?)の形式で表されるか、特別な値Nilを受け入れることができるかを定義する(プロパティのデータ型はnull値の割り当てを許可する必要があります)

コントロールの状態保存

HMIサブシステムは、アプリケーションの状態(アプリケーションのエンドユーザーによって選択された設定)を保存する機能を提供します。状態の保存は、各コントロールの設定を保存することによって実現されます。単一のコントロールの状態を保存することは、avhmiファイルへの保存時のコントロールのプロパティのシリアライゼーションメカニズムと同じです。コントロールの状態は、選択されたコントロールのプロパティに表示される値によって定義されます。コントロールがその状態の要素(その設定)を保存できるようにするためには、その状態が完全に公開された双方向プロパティで表され、そのデータ型がテキストに変換可能である必要があります(型変換機能がSystem.String型の変換を処理します)。アプリケーションの状態と一緒にコントロールのプロパティの値を保存するためには、そのようなプロパティにHMI.HMIStatePortAttribute属性が付けられている必要があります。

プロパティは指定されていない順序でシリアライズされ、他のプロパティのさまざまな状態のコンテキストで行われます。そのため、コントロールはこれらのプロパティ間でエラーを引き起こす可能性がある依存関係が現れないように、状態を表すプロパティを実装する必要があります。コントロールがそのようなプロパティの入力値をエラーを引き起こさずに修正できることが推奨されます(たとえば、状態の保存ファイルでエラーが発生した場合や、アプリケーションの状態が保存および読み込みの間に変更された場合など)。

特定のコントロールの状態が1つ以上のプロパティに表示される場合(たとえば、数値状態はTextプロパティでもテキスト形式で読み取り/書き込みできる場合)、状態を保存するプロパティは1つだけにすべきです。状態を保存するプロパティは、ビジョンアプリケーションと接続を有効にするコントロールのポートである必要がありますが、なくても構いません。同様に、コントロールのポートを実現するプロパティは、その状態を保存する必要がありますが、なくても構いません。

拡張HMIサービスとの相互運用性

コントロールは、そのポートをビジョンプログラムに接続する能力や、型属性を解釈する能力を超えるHMIシステムの要素と協力する必要があるかもしれません。そのような協力は、HMIシステムの特定の拡張サービスとの通信になります。このようなサービスの例には、プログラムの実行制御やアプリケーションの状態保存システムなどがあります。

各拡張サービスは、HMIシステムによって提供され、コントロールに渡されるインターフェースインスタンスを介して利用できます。コントロールがサービスインターフェースへの参照を取得できるようにするには、HMI.IServiceConsumer インターフェースを実装する必要があります。このインターフェースは、コントロールがvoid SetHMIServiceProvider( System.IServiceProvider provider )メソッドを実装することを要求します。HMIサブシステムは、コントロールの初期化中(デザインモード外)にこのメソッドを1回呼び出し、System.IServiceProvider インターフェースの形で拡張HMIサービスプロバイダインスタンスを渡します。コントロールはその後、プロバイダのGetServiceメソッドを呼び出し、アクセスしたいサービスのインターフェースタイプを引数として指定します。プロバイダは要求されたインターフェースの参照を返すか、要求されたサービスが利用できない場合はnullを返します。

以下は、プログラム実行制御サービスインターフェースへのアクセス方法の例です:

public class MyControl : Control, HMI.IServiceConsumer
{
    private HMI.IProgramControlService programControlProvider;

    public void SetHMIServiceProvider( IServiceProvider provider )
    {
        programControlProvider = (IProgramControlService)provider.GetService(typeof(IProgramControlService));
    }
}

プログラム実行の制御とプログラム実行の変更への対応

プログラムの実行制御には、プログラムの開始、一時停止、開始/再開、停止、繰り返しなどが含まれます。また、これらの操作の実行後のプログラムが特定の状態に遷移するイベントも発生します。

どんなHMIコントロールもプログラム制御に影響を与え、またプログラム実行状態の変更をフォローすることができます。これを行うためには、コントロールはプログラム制御サービスにアクセスする必要があります。これはHMI.IProgramControlService インターフェースを取得することで可能です。このインターフェースには以下の要素が提供されます:

  • ProgramStateChanged イベント:これを使用して、コントロールはプログラム実行状態の変更に関する通知を受け取ります。呼び出しの一部として、プログラム実行フラグ IsExecuting が渡されます(つまり、プログラムが実行中である場合、フィルタが現在処理されているかどうかにかかわらずです。例:プログラムはアクティブな作業または一時停止状態で実行中であるが、停止した後や読み込みが完了していない状態では実行されていません)。残りのイベントパラメータは、適切な実行状態に切り替える能力について通知します。
  • ProgramEvent イベント:コントロールの視点から興味深いアプリケーションライフサイクルイベントについて通知します。
  • StartProgramIterateProgramPauseProgramStopProgram メソッド:これらを使用して、コントロールはプログラム実行状態を適切に変更できます。

HMIアプリケーションの状態保存を管理するコントロール

アプリケーション全体の状態を保存または読み込むための仕組みを介して、コントロールを作成することができます。これを行うには、コントロールはHMI.IStateManager インターフェースを取得する必要があります。このインターフェースには、アプリケーション全体を指定されたファイルに保存し、指定されたファイルからアプリケーション全体を読み込むためのメソッド、およびローカルファイルシステム内のプロジェクトの位置を見つけるためのメソッドが用意されています。

オンスクリーン仮想キーボードの制御

HMIサブシステムでは、タッチパネルを備えたシステムで便利なオンスクリーンキーボードを表示することができます。キーボードは、HMI環境によってある程度自動的に表示および非表示になります。必要な場合、HMIコントロールはオンスクリーン仮想キーボードの表示および非表示を明示的に制御できます。これを行うには、コントロールはHMI.IVirtualKeyboardService インターフェースを取得する必要があります。このインターフェースには、指定された種類のキーボードを表示し、指定されたコントロールまたは画面の特定の部分の表示を妨げずにキーボードを非表示にするためのメソッド、およびキーボードを非表示にするためのメソッドが提供されています。

オンスクリーンキーボードの明示的な制御は、HMIアプリケーションのデザインユーザーが特定のHMIアプリケーション用にキーボードを有効にした場合のみ機能します。キーボードがアプリケーションでアクティブでない場合、キーボードの表示および非表示に関するすべてのリクエストはエラーなしに無視されます。