.Net Framework Tips




表示優先

例えばフォームデザインでフォームにpictureBoxを登録し、Dock=Fillに設定、
その後にstatusStripを登録するとpictureBoxの下側がstatusStripにより
隠れてしまう。
逆順に登録していればこのような現象は起こらないが、実際登録してしまった場合は
どのように登録順番を変えるか。

それはフォームにコントロールをAddする順番を変えればいい。
その場合の順番は優先度が低いものから先に登録する。
CLRフォームを作成すると作られるForm.h内では以下のようにコントロールが
登録されてるはずだが、

this->Controls->Add(this->pictureBox);
this->Controls->Add(this->statusStrip);

こうするとstatusStripが配置され、その中にpictureBoxDock=Fill状態で
配置されることになる。
見た目と実際の順番が異なるので注意。



フォームによるキーイベント処理

通常、キーイベントはフォーム上のフォーカスを持つコントロールに発生するので、
何も考えずにFormのKeyDownイベントとかをチェックしてもイベントは発生しない。
ただ、例えばESCキーを押したらフォームを閉じたいなど、キーを取得したい場合も多々ある。

その場合はFormのKeyPreviewをTrueに設定してやることで、キーイベントが
フォーカスを持つコントロールに渡される前に、フォーム側で検知することができるようになる。

イベント処理に渡されるKeyEventArgsもしくはKeyPressEventArgsのプロパティである
Handledtrueを設定することで、コントロールではイベントを発生しないようにできる。
ただし、例えばtextBoxなどで使う場合、イベントが発生しなくなるだけで、ユーザーの入力は
そのまま反映されてテキストボックスに書き込まれる。

それすら制御したい場合はSuppressKeyPressプロパティを仕様する。


話がわき道に逸れたが、フォームがキーイベントを検知した場合、どのキーが押されたかを知るには

void textBox1_KeyDown( Object^ /*sender*/,System::Windows::Forms::KeyEventArgs^ e )
{
        if( e->KeyCode == Keys::Escape ) {
                ...
        }
}

のような感じでKeyCodeプロパティとKeys列挙体を使用する。



Objectクラスのメソッドのオーバーライド

.NET Frameworkの全クラスの基本クラスであるObjectクラス。
このクラスのToStringメソッドは、特にオーバーライドしないで使用すると
クラス名が返ってくる。

例えば

public ref class Sample {
   public:
      String ^name;
}

というクラスを作った場合、ToStringメソッドは"Sample"を返す。
※Objectクラスの継承は暗黙に行われる

ここで、nameメンバをToString()の返り値にしたい場合は以下のようにする。

public ref class Sample {
   public:
      String ^name;
      
   public:
      virtual String^ ToString() override { return name; }
};

こうすることでnameの内容がToString()メソッドによって得られる。
注意したいのはoverrideキーワードである。
C++ではvirtualキーワードだけでオーバーライドできていたが、
C++/CLIではこのキーワードを使わなければならない。

ちなみにnewキーワードを使うと、
スーパークラス内で仮想関数として宣言されていないメンバ関数を上書きという形で
宣言しなおすことができるっぽい。


ちなみになんでこんなことをしたのかというと、ListBoxに要素を追加する際、
AddRange()メソッドはarray<Object^>を引数に受け取り、
要素をリストボックスに追加するのにToString()メソッドを使っていたからである。
配列の各要素を示す文字列を表示したかったため、ToString()をオーバーライドしてみたかった、
という話。



フォームデザインがエラーで表示されない!

いくつかの理由により簡単にフォームデザインがエラーで利用できなくなる…。

・#pragma region Windows Form Designer generated code ~ #pragma endregionをいじっちゃった
ここは触れないようにするのが無難。変更するのであればコンストラクタ等で。
ただ、コントロールの登録順を変えたい場合はいじるしかない…気がする。

・フォームのクラスよりも前に何かしらのクラスを宣言しちゃってる
ヘッダに記述してインクルドすべし。
同一ファイル内でフォームクラスよりも前にクラス宣言とかしたら駄目。



ボタンを1つ配置したフォーム生成時のイベント発生順

フォームデザイナでボタンを1つ配置した状態のフォームを生成したときのイベント順は以下のとおり。

  1. Button : [ParentChanged]
  2. Form : [Load]
  3. Form : [Layout]
  4. Button : [Enter]
  5. Form : [Activate]
  6. Form : [Shown]
  7. Form : [Paint]
  8. Form : [Paint]
  9. Button : [Paint]
  10. Button : [Validating]
  11. Button : [Validated]

検証したイベントは
Form Button
Activated
Deactivate
Enter Enter
Leave Leave
Validated Validated
Validating Validating
Load
Shown
Layout Layout
Paint Paint
LocationChanged
ParentChanged
Move

ちなみに、フォームデザイナで登録すると、コントロールの位置やサイズなどは
イベント登録前にやってしまうコードになるので、LocationChangedMoveイベントは発生しない



規定プロパティ

クラスには規定プロパティと呼ばれるものが設定でき、記述時にそのプロパティは省略できる。
例えばTextBoxの規定プロパティはTextであり、
TextBox = "てきすと";
みたいな記述をすると、コンパイル時に解決されてTextプロパティに値が代入される。


よくCollection系クラスにある事なのだが、Itemプロパティにアクセスしようとすると

既定プロパティ (インデクサ) にアクセスするためには 'default' を使用してください

というコンパイルエラーが発生する。
ためしに

Collection->default[idx];

にしてみると、コレクションが持つオブジェクトにアクセスできる。
また、規定プロパティなので、

Collection[idx];

という記述でもアクセスできる。
ただ、なぜItem[]という形ではアクセスできないのかは謎。


規定プロパティを自分で指定するのにはdefaultを使ってプロパティを宣言する。
最終更新:2009年03月03日 18:40
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。