例えばフォームデザインでフォームにpictureBoxを登録し、Dock=Fillに設定、
その後にstatusStripを登録するとpictureBoxの下側がstatusStripにより
隠れてしまう。
逆順に登録していればこのような現象は起こらないが、実際登録してしまった場合は
どのように登録順番を変えるか。
それはフォームにコントロールをAddする順番を変えればいい。
その場合の順番は優先度が低いものから先に登録する。
CLRフォームを作成すると作られるForm.h内では以下のようにコントロールが
登録されてるはずだが、
this->Controls->Add(this->pictureBox);
this->Controls->Add(this->statusStrip);
こうするとstatusStripが配置され、その中にpictureBoxがDock=Fill状態で
配置されることになる。
見た目と実際の順番が異なるので注意。
通常、キーイベントはフォーム上のフォーカスを持つコントロールに発生するので、
何も考えずにFormのKeyDownイベントとかをチェックしてもイベントは発生しない。
ただ、例えばESCキーを押したらフォームを閉じたいなど、キーを取得したい場合も多々ある。
その場合はFormのKeyPreviewをTrueに設定してやることで、キーイベントが
フォーカスを持つコントロールに渡される前に、フォーム側で検知することができるようになる。
イベント処理に渡されるKeyEventArgsもしくはKeyPressEventArgsのプロパティである
Handledにtrueを設定することで、コントロールではイベントを発生しないようにできる。
ただし、例えばtextBoxなどで使う場合、イベントが発生しなくなるだけで、ユーザーの入力は
そのまま反映されてテキストボックスに書き込まれる。
それすら制御したい場合はSuppressKeyPressプロパティを仕様する。
話がわき道に逸れたが、フォームがキーイベントを検知した場合、どのキーが押されたかを知るには
void textBox1_KeyDown( Object^ /*sender*/,System::Windows::Forms::KeyEventArgs^ e )
{
if( e->KeyCode == Keys::Escape ) {
...
}
}
のような感じでKeyCodeプロパティとKeys列挙体を使用する。
.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つ配置した状態のフォームを生成したときのイベント順は以下のとおり。
- Button : [ParentChanged]
- Form : [Load]
- Form : [Layout]
- Button : [Enter]
- Form : [Activate]
- Form : [Shown]
- Form : [Paint]
- Form : [Paint]
- Button : [Paint]
- Button : [Validating]
- Button : [Validated]
検証したイベントは
Form |
Button |
Activated |
|
Deactivate |
|
Enter |
Enter |
Leave |
Leave |
Validated |
Validated |
Validating |
Validating |
Load |
|
Shown |
|
Layout |
Layout |
Paint |
Paint |
|
LocationChanged |
|
ParentChanged |
|
Move |
ちなみに、フォームデザイナで登録すると、コントロールの位置やサイズなどは
イベント登録前にやってしまうコードになるので、LocationChanged や Moveイベントは発生しない
クラスには規定プロパティと呼ばれるものが設定でき、記述時にそのプロパティは省略できる。
例えばTextBoxの規定プロパティはTextであり、
TextBox = "てきすと";
みたいな記述をすると、コンパイル時に解決されてTextプロパティに値が代入される。
よくCollection系クラスにある事なのだが、Itemプロパティにアクセスしようとすると
既定プロパティ (インデクサ) にアクセスするためには 'default' を使用してください
というコンパイルエラーが発生する。
ためしに
Collection->default[idx];
にしてみると、コレクションが持つオブジェクトにアクセスできる。
また、規定プロパティなので、
Collection[idx];
という記述でもアクセスできる。
ただ、なぜItem[]という形ではアクセスできないのかは謎。
規定プロパティを自分で指定するのにはdefaultを使ってプロパティを宣言する。
最終更新:2009年03月03日 18:40