- PR -

TextBox のVisibleプロパティを False に設定するとプログラムから書き込みも参照も出来なくなる。

投稿者投稿内容
nakaP
大ベテラン
会議室デビュー日: 2005/09/27
投稿数: 138
お住まい・勤務地: 高知
投稿日時: 2007-12-12 15:26
Jittaさん、テクニカルサポートまで使って頂きありがとうございます。
引用:

仕様は、文書化されていなさそうです。


今日また気になってMSDNを見回してたら、以下の文を見つけました。
これが今回の根源なのかな?って思ってしまいました。(今更ですが)
Control.CreateControlメソッド(System.Windows.Forms)より
引用:

CreateControl メソッドは、コントロールおよび子コントロールに対して強制的にハンドルを作成します。コントロールまたはその子の操作のためすぐにハンドルが必要なときに、このメソッドが使用されます。単純にコントロールのコンストラクタを呼び出しても、Handle は作成されません。

コントロールの Visible プロパティが false に設定されている場合、CreateControl はコントロール ハンドルを作成しません。コントロールの表示状態に関係なく、コントロールのハンドルを作成するには、CreateHandle メソッドを呼び出すか、Handle プロパティにアクセスします。ただし、この場合、コントロールの子に対してウィンドウ ハンドルは作成されません。


内部的にどうなってるのかまでは分かりませんが、Controlのコンストラクタが終了した後にCreateControlが呼び出され、そのControlに対してハンドルが作成されているのではないか?と予想します。

そして今回の場合、Form->TextBoxの順でCreateControlが呼び出される為、デザイナでVisibleを操作するとFormのコンストラクタ以前での操作となってしまい、結果TextBoxのハンドルが作成されないのではないかと。
(試しにCreateHandleメソッドを呼び出そうとしましたが、Protectedな為明示的に呼び出すことが出来ませんでした。)

引用:

「Form_Load後にVisible=Trueにするとハンドルが作成されBindも有効となる」
これが納得できないですね。


Visible=trueにする事によってCreateControlメソッドが完了するとした場合、Bindにハンドルを使用していると仮定すると、私はなんとなく納得できるような気がします。(少し無理があるかもしれませんが)

引用:

 タイミングが定かではありませんが、ハンドルが作成された後(実験的には Form.Load イベントから後)なら、Visible プロパティの値に関係なく、バインドされます。


これに関しては、Controlのハンドルが作成された後(今回ではTextBox.HandleCreatedイベント後)となりました。でもまあForm.Loadイベントで操作するのが分かりやすいですね。


#なんかここまで書いてて、まだまだ奥までいけるんじゃないか?って気がしてきました。
#(ApplicationContextの場合とか)
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-12-12 16:35
引用:

Controlのコンストラクタが終了した後にCreateControlが呼び出され、そのControlに対してハンドルが作成されているのではないか?と予想します。



直後ではないですね。必要に応じて、です。

通常は、フォームを Show() した時にフォームの実体であるウィンドウが作成(実体化)され、次いでフォーム上に配置された各コントロールが連鎖的に実体化されます。この時、Visible=false な子コントロールの実体化は行われません。

Show() した時以外でも、ハンドル無いとつじつまの合わないような操作を行うと、フォームやコントロールの実体化が行われるようです。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2007-12-12 16:55
引用:
(試しにCreateHandleメソッドを呼び出そうとしましたが、Protectedな為明示的に呼び出すことが出来ませんでした。)

TextBoxを継承したクラスを作成して実験してみました。
コンストラクタとCreateHandleをオーバーライドしてブレークをはってデバッグしてみたところ、
確かに、Visible=trueの場合は、Form(TextBoxの親)のCreateHandleが実行される際に、
TextBoxのCreateHandleが呼び出され、Visible=falseの場合は呼び出されていませんでした。

また、外部からCreateHandleを実行するためのpublicメソッドを(TextBoxに)作成し、
インスタンスが作られてからVisible=falseと設定するまでの間によびだした(まあ、
Designer.csいじったわけですが)ところ、確かにバインドされました。
(またはTextBoxのコンストラクタでCreateHandleを呼び出しても確認できます)
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-12-12 22:32
引用:

J.J.さんの書き込み (2007-12-12 15:26) より:
Jittaさん、テクニカルサポートまで使って頂きありがとうございます。


 いえいえ。コミュニティ内での問題を解決する助けとなるようにいただいているインシデントです。むしろ、使わせてください。


引用:

引用:

「Form_Load後にVisible=Trueにするとハンドルが作成されBindも有効となる」
これが納得できないですね。


Visible=trueにする事によってCreateControlメソッドが完了するとした場合、Bindにハンドルを使用していると仮定すると、私はなんとなく納得できるような気がします。(少し無理があるかもしれませんが)


 ええ、わからないでもないのですが、
無いものを本当はあったように見せかけるための仕様
のような気がします。。。

 開発者の「作った」と一致していないものがある、というのが、なんとも、気持ち悪い...
nakaP
大ベテラン
会議室デビュー日: 2005/09/27
投稿数: 138
お住まい・勤務地: 高知
投稿日時: 2007-12-12 23:07
引用:

引用:

Controlのコンストラクタが終了した後にCreateControlが呼び出され、そのControlに対してハンドルが作成されているのではないか?と予想します。


直後ではないですね。必要に応じて、です。



一応、直後だとは思ってなかったです。
ProgramのMainで
コード:
using(MainForm f = new MainForm())
{
    Application.Run(f);
}


としてて、Application.Run実行手前の時点でブレークをはって、ハンドルが作成されてないことは確認してました。
ただ、Application.Run実行後ににHandleCreatedイベントが発生してたので、そこでいろいろしてくれてるのかなーと思ってましたけど(^^;

引用:

無いものを本当はあったように見せかけるための仕様
のような気がします。。。

開発者の「作った」と一致していないものがある、というのが、なんとも、気持ち悪い...


.Net Frameworkを触りだして間もない人には、混乱の元になるでしょうね。特にVBerな人たちに。
便利になった代償の不便、てとこでしょうかね...
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2007-12-13 00:25
タスクトレイものを作った時にアイコンの設定で例外になり、
Handle プロパティの説明に「参照すれば強制的に作成される」とあったので次のようなコードになりました。

コード:
Public Shared Main()
    Dim MainForm As New Form1
    Dim dummy As IntPtr = MainForm.Handle
    With NotifyIcon1
        .Icon = MainForm.Icon
    End With    


スキルアップ/キャリアアップ(JOB@IT)