C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

全過去ログを検索

<< 0 >>
■22878  Re[2]: みなさま…(;;)お励ましを…(::)
□投稿者/ t6_kana -(2008/08/05(Tue) 10:44:47)
    みなさま

    ありがとうございます!!
    (__)
    今は返信できませんので、あとで返信させてください!!
記事No.22867 のレス /過去ログ43より / 関連記事表示
削除チェック/

■48195  Re[8]: ファイルのコピー・移動について
□投稿者/ 中の上くらいの初心者 -(2010/03/26(Fri) 16:54:28)
    ディレクトリ名+ファイル名という意見が多いんですけど、
    移動先のディレクトリの中に、ファイルが存在しない状態(元のファイルを上書きで保存するという形ではありません)で、実行したいんです。
記事No.48181 のレス /過去ログ81より / 関連記事表示
削除チェック/

■55165  Re[3]: ボタンコントロールの形状変更
□投稿者/ 柚子饅頭 -(2010/11/18(Thu) 17:27:59)
    ■囚人さん

    返信ありがとうございます。

    WPFというものがあるのですね・・・。

    調べてみることにします。

    ありがとうございました。
記事No.55154 のレス /過去ログ92より / 関連記事表示
削除チェック/

■83365  Re[4]: これらの引数で呼び出されるアクセス可能なNewがないため・・
□投稿者/ 惹起 -(2017/03/19(Sun) 14:18:08)



    ありがとうございます。

    Dim ccc = DirectCast(bbb, Class_Name)
    の間違いです

    TaskでObject以外の引数を受ける方法は分かったのですが

    MultiProgram_run = New Thread(AddressOf Program_runxx) With {.IsBackground = True}
    MultiProgram_run.Start(hiki)


    という用法でもObject以外の引数を受ける方法があれば教えてください。

    それとCallByName メソッドというのは何でしょうか?
    これを使ったWshShell オブジェクトの呼び出し方をできれば教えていただけないでしょうか?




記事No.83350 のレス /過去ログ142より / 関連記事表示
削除チェック/

■90068  ユーザーコントロールの使い方
□投稿者/ ルパン -(2019/02/04(Mon) 10:24:15)

    分類:[.NET 全般] 

    VisualStudio C#
    Windows10
    にて、
    以下のようなプログラム(重要部分のみ表示)を作成しています。

    フォーム上にはユーザコントロールを切り替えて表示するように
    ユーザーコントロール呼び出し用のボタンがあり、
    ユーザーコントロール上にはラベル、ボタン(終了)など
    他に複数のコントロールが配置しています。

    ユーザーコントロールのコントロールボックスの×ボタンや
    終了ボタンを押した場合はlblTime.Text の値が保存されるのですが、

    フォーム上のユーザーコントロール呼び出しボタンを押すと
    lblTime.Text が "" になって保存されてしまいます。

    どうすればよいのでしょうか?


    ≡呼び出し側

    private void Button_Click(object sender, EventArgs e)
    {
     foreach (Control cnt in pnlSub.Controls)
     {
      pnlSub.Controls.Remove(cnt);
      cnt.Dispose();
     }
     if (SelectButton == btnTime) AddUserControl(new ucTime());
    }

    private void AddUserControl(Control cnt)
    {
     cnt.Dock = DockStyle.Fill;
     pnlSub.Controls.Add(cnt);
    }

    ≡ユーザーコントロール
    private void ucTime_Disposed(object sender, EventArgs e)
    {
     Properties.Settings.Default.ucTime = lblTime.Text;
     Properties.Settings.Default.Save();
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
     this.ParentForm.Close();
    }
親記事 /過去ログ155より / 関連記事表示
削除チェック/

■90069  Re[1]: ユーザーコントロールの使い方
□投稿者/ 魔界の仮面弁士 -(2019/02/04(Mon) 10:43:36)
    2019/02/04(Mon) 11:21:16 編集(投稿者)

    No90068 (ルパン さん) に返信
    > ユーザーコントロール上にはラベル、ボタン(終了)など
    > 他に複数のコントロールが配置しています。
    親子関係がどうなっているのか読み取りきれませんでした…。
    コードから察すると、そこまでに登場した UI 部品としては、
     ・Form
     ・Button イベントハンドラに割り当てられた Button コントロール
     ・SelectButton フィールド変数に割り当てられた Button コントロール
     ・終了ボタン
     ・btnTime (Button コントロール)
     ・pnlSub (Panel コントロール)
     ・ucTime (UserControl コントロール)
     ・lblTime (Label コントロール)
    などがありそうですが。


    > foreach (Control cnt in pnlSub.Controls)
    > {
    >  pnlSub.Controls.Remove(cnt);
    >  cnt.Dispose();
    > }

    コレクションのループ中に、そのコレクション自身の要素を増減させると
    カウンターがずれるので避けてください。

    回避策としては、たとえば .ToArray() で配列にコピーしてから、
    それを列挙するという手が使えます。あるいは全削除なら、
    while ループで空になるまで繰り返し [0] 番を削っていくという手も。


    > private void ucTime_Disposed(object sender, EventArgs e)
    > {
    >  Properties.Settings.Default.ucTime = lblTime.Text;

    上記の処理ですが、処理順などを考慮した上で、
    ucTime が Diposed となったときに、
    lblTime がまだ Disposed 状態でないことは
    確実に保証できているのでしょうか。
記事No.90068 のレス /過去ログ155より / 関連記事表示
削除チェック/

■90070  Re[2]: ユーザーコントロールの使い方
□投稿者/ ルパン -(2019/02/04(Mon) 11:25:36)
    No90069 (魔界の仮面弁士 さん) に返信
    ありがとうございます。
    
    削除部分は以下のように変更しました。
    
    >ucTiem が Diposed となったときに、lblTime がまだ Disposed 状態でないことは
    >保証できているのでしょうか。
    保証できるようにするにはどうすればよいのでしょうか?
    
    フォームでは FormClose に入れていたのですが
    ユーザーコントロールではこれに該当するものがわからなかったので
    ネットで調べたら 「UserControl の後処理は Dispose で行う」とあったので、
    ユーザーコントロールのコンストラクタに
    this.Disposed += UcMakeAbilityTime_Disposed;
    を追加し Dispose のイベントに Properties への保存処理を入れました。
    
    現状以下のようになっています。
    
    frmMain.cs              ucTime.cs
    ┌──────┬─────────┐  ┌─────────┐
    │┌────┐│         │  │┌──┐┌───┐│
    ││btnTime ││         │  ││lbl ││btn  ││
    │└────┘│         │  ││Time││Close ││
    │      │         │  │└──┘└───┘│
    │pnlMain   │pnlSub      │  │UserControl    │
    └──────┴─────────┘  └─────────┘
    
    ≡ frMain.cs ≡
    private void Button_Click(object sender, EventArgs e)
    {
     SelectButton((Control)sender);
    }
    
    private void SelectButton(Control SelectButton)
    {
     while (pnlSub.Controls.Count > 0){
      pnlSub.Controls.Remove(pnlSub.Controls[0]);
      pnlSub.Controls[0].Dispose();
     }
     if (sender== btnTime) AddUserControl(new ucTime());
    }
    
    private void AddUserControl(Control cnt)
    {
     cnt.Dock = DockStyle.Fill;
     pnlSub.Controls.Add(cnt);
    }
    
    ≡ ucTime.cs ≡
    public ucTime()
    {
     InitializeComponent();
     this.Disposed += UcTime_Disposed;
    }
    
    private void UcMakeAbilityTime_Disposed(object sender, EventArgs e)
    {
     Properties.Settings.Default.ucMakeAbilityTime = lblTime.Text;
     Properties.Settings.Default.Save();
    }
    
    private void btnClose_Click(object sender, EventArgs e)
    {
     this.ParentForm.Close();     ←正しいかどうかわかりませんが、
    }                  この場合は正常に保存されている。
    
記事No.90068 のレス /過去ログ155より / 関連記事表示
削除チェック/

■90071  Re[3]: ユーザーコントロールの使い方
□投稿者/ 魔界の仮面弁士 -(2019/02/04(Mon) 13:47:10)
    2019/02/04(Mon) 14:32:50 編集(投稿者)

    No90070 (ルパン さん) に返信
    >   pnlSub.Controls.Remove(pnlSub.Controls[0]);
    >   pnlSub.Controls[0].Dispose();

    そのコードは正しくありません。
    1 行目が指している [0] と 2 行目が指している [0] が
    別のコントロールを指していることに注意してください。


    提示のコードだと、pnlSub 上の子コントロールが【奇数個】の場合に
    最後の 1 個が Remove されないことになってしまいます。
    ※例外:ArgumentOutOfRangeException

    また、【偶数個】であった場合、一見するとすべて Remove されるように
    見えますが、実際には偶数・奇数いずれの場合にも、
    「半数は Remove しただけ(Dispose していない)」
    「半数は Dispose しただけ(自動的に Remove される)」
    という動作に陥っていることに注意してください。



    代案1:削除対象のコレクションと列挙用のコレクションを分ける

    Control[] children = pnlSub.Controls.OfType<Control>().ToArray();
    foreach (Control c in children)
    {
     pnlSub.Controls.Remove(c);
     c.Dispose();
    }


    代案2:子アイテムを変数等に保持しておき、コレクションから除去後に破棄する
    while (pnlSub.Controls.Count > 0)
    {
     using (pnlSub.Controls[0])
     {
      pnlSub.Controls.RemoveAt(0);
     }
    }


    代案3:後ろから前に Dispose する
    for (int i = pnlSub.Controls.Count - 1; i >= 0; i--)
    {
     // Dispose されると自動的に Remove される
     pnlSub.Controls[i].Dispose();
    }



    > ネットで調べたら 「UserControl の後処理は Dispose で行う」とあったので、

    親コントロールが破棄される際には、それに先んじて
    子コントロールが破棄されますので、Disposed イベント中には
    他のコントロール(もちろん Label にも)アクセスすることはできません。

    故にたとえば Dispose 時には、「子コントロールそのもの」に
    アクセスするのではなく、予め保持しておいた
    「子コントロールが持っていた値」を使って処理するようにします。


    新規プロジェクトに下記を貼り、実行してフォームを閉じてみてください。


    using System.Diagnostics;
    public partial class Form1 : Form
    {
     private UserControl uc;
     public Form1()
     {
      InitializeComponent();
      Controls.Add(uc = new UC() { Dock = DockStyle.Fill });
     }
    }

    public class UC : UserControl
    {
     private Label lbl;
     private string _labelText = null;
     private string LabelText { get { return _labelText; } }
     public UC()
     {
      Controls.Add(lbl = new Label() { Text = "lbl", Dock = DockStyle.Fill });
      
      // Label が破棄された後でも Text を拾えるよう、保持しておく
      lbl.TextChanged += delegate { _labelText = lbl.Text; };
      _labelText = lbl.Text;

      //
      lbl.Disposed += delegate
      {
       Debug.WriteLine("Label.Disposed");
       Debug.WriteLine(" UserControl.Disposing = " + this.Disposing);
       Debug.WriteLine(" UserControl.IsDisposed = " + this.IsDisposed);
       Debug.WriteLine(" Label.Disposing = " + lbl.Disposing);
       Debug.WriteLine(" Label.IsDisposed = " + lbl.IsDisposed);
       Debug.WriteLine(" Label.Text = [" + lbl.Text + "]");
       Debug.WriteLine(" LabelText = [" + this.LabelText + "]");
      };
      this.Disposed += delegate
      {
       Debug.WriteLine("UserControl.Disposed");
       Debug.WriteLine(" UserControl.Disposing = " + this.Disposing);
       Debug.WriteLine(" UserControl.IsDisposed = " + this.IsDisposed);
       Debug.WriteLine(" Label.Disposing = " + lbl.Disposing);
       Debug.WriteLine(" Label.IsDisposed = " + lbl.IsDisposed);
       Debug.WriteLine(" Label.Text = [" + lbl.Text + "]");
       Debug.WriteLine(" LabelText = [" + this.LabelText + "]");
      };
     }
    }


    ---- 実行結果 ----
    Label.Disposed
     UserControl.Disposing = True
     UserControl.IsDisposed = False
     Label.Disposing = True
     Label.IsDisposed = False
     Label.Text = []
     LabelText = [lbl]
    UserControl.Disposed
     UserControl.Disposing = True
     UserControl.IsDisposed = False
     Label.Disposing = False
     Label.IsDisposed = True
     Label.Text = []
     LabelText = [lbl]
記事No.90068 のレス /過去ログ155より / 関連記事表示
削除チェック/

■90072  Re[4]: ユーザーコントロールの使い方
□投稿者/ ルパン -(2019/02/04(Mon) 15:25:16)
    No90071 (魔界の仮面弁士 さん) に返信

    Dispose すると
    配置されているコントロールのデータは破棄されているが
    プライベートで指定している各データは消えないんということですか?
    つまり、Dispose イベント内では完全にユーザーコントロールのデータが
    破棄されているわけではないということでいいのでしょうか?
    イベントを抜けた後に完全破棄されるということですね?


記事No.90068 のレス /過去ログ155より / 関連記事表示
削除チェック/

■90074  Re[5]: ユーザーコントロールの使い方
□投稿者/ 魔界の仮面弁士 -(2019/02/04(Mon) 16:57:35)
    2019/02/04(Mon) 20:03:33 編集(投稿者)

    No90072 (ルパン さん) に返信
    > Dispose すると
    > 配置されているコントロールのデータは破棄されているが

    コントロールのデータというよりは、コントロールそのものの破棄です。

    繰り返しになりますが、Control クラスにおいては、
    Dispose された際に、Controls プロパティに登録されている
    子コントロール群も Dispose されるように設計されています。
    (子がさらに子を持っていた場合も同様に連鎖します)

    このため UserControl の Disposed 時には、子 Label が既に処分されており、
    Label の Text プロパティが "" を返してしまうわけです。


    いずれにせよ、UserControl や Form や Panel 等の Disposed イベントが
    呼ばれたときには、それらの Controls に追加されていた子孫コントロールは
    「既に処分されていて利用不可能な状態」であるものとして扱うべきです。


    たとえば No90071 でお見せした LabelText プロパティを例に挙げると、
     string LabelText { get { return this._labelText; } }
    という実装の場合には、Dispose された後でも利用できますが、もしもこれを
     string LabelText { get { return this.lbl.Text; } }
    にしていた場合は、Dispose 後にはアクセスすべきでは無いということです。

    lbl 変数(Label クラス)は IDisposable なオブジェクトですが、
    _labelText 変数(String クラス) は IDisposable なオブジェクトでは無いわけで。


    > プライベートで指定している各データは消えないんということですか?

    Dispose された場合、そのクラスが管理していた情報のうち、
    アンマネージなオブジェクトは既に破棄されている状態になります。
    一方、マネージリソースの破棄についてはオプション扱いなのでケースバイケースです。

    また、幾つかのメンバーについては、破棄後にアクセスした場合に
    ObjectDisposedException の例外になるように設計されています。
    (たとえば Handle プロパティなど)



    参考までに Text プロパティの場合、CacheText フラグの付与有無でも動作が異なります。
    Label や TextBox 等の場合、Dispose 直後は "" が返却されるようになりますが、
    Button、TabPage、ToolStripPanel 等では、Dispose 直前の値が利用されます。

    CacheText の有無でどのように変化するか、実験コードを載せておきます。
    下記を実行すると、
      FormClosing:あいうえお/かきくけこ
      Disposed:/かきくけこ
    という結果になることを確認できます。


    public partial class Form1 : Form
    {
     private Class1 label1;
     private Class2 label2;
     public Form1()
     {
      InitializeComponent();
      Controls.Add(label1 = new Class1() { Text = "あいうえお", Top = 30 });
      Controls.Add(label2 = new Class2() { Text = "かきくけこ", Top = 90 });

      this.FormClosing += delegate { System.Diagnostics.Debug.WriteLine("FormClosing:" + label1.Text + "/" + label2.Text); };
      this.Disposed += delegate { System.Diagnostics.Debug.WriteLine("Disposed:" + label1.Text + "/" + label2.Text); };
     }
     private class Class1 : Label { public Class1() { SetStyle(ControlStyles.CacheText, false); } }
     private class Class2 : Label { public Class2() { SetStyle(ControlStyles.CacheText, true); } }
    }


    > つまり、Dispose イベント内では

    「Dispose イベント」ではなく、過去形表記の
    「Disposed イベント」ですね。



    > プライベートで指定している各データは消えないんということですか?

    private か public かは関係ないですよ。
    消えるかどうかは開発者の実装次第です。IDisposable でないオブジェクトは特に。


    .NET Framework 自身が提供しているクラス(Label や UserControl) 自体が持つメンバーではなく、
    それらを継承したクラス(あるいは自作の class 等)に対して追加したメンバーについては、
    Dispose 時にそのデータを処分するかどうかも、開発者自身が決める必要があります。

    もし Dispose された時に自作したメンバーの情報も処分する必要があるのなら、
    そのコントロールの protected な『void Dispose(bool)』メソッドを
    オーバーライドする必要があります。(あるいは Disposed イベントを利用する)
記事No.90068 のレス /過去ログ155より / 関連記事表示
削除チェック/

■94719  Re[1]: 同時再生したものを別々で停止する方法について
□投稿者/ Hongliang -(2020/05/09(Sat) 15:47:08)
    環境依存なのかもしれませんが、私のところでは、PlaySound関数でa.wavを非同期再生中にb.wavを非同期再生させようとすると、a.wavの再生が停止してしまって「同時再生」になりませんでした。
    PlaySound関数の引数的にも片方だけを識別して止めるなんてことはできなさそうなので、PlaySound関数でやるとしたら音を鳴らすだけの実行ファイルを作って、そのプロセス起動/終了で再生を制御するぐらいしかないと思います。
    (プロセスの制御はSystem.Diagnostics.Processクラスで可能です)

    標準ライブラリは音声のサポートが非常に少なく、System.Media.SoundPlayerのほかはSystem.Windows.Media.MediaPlayerぐらいしかないですね。
    System.Media.SoundPlayerはPlaySound関数のラッパ(オンメモリデータを再生する部分でバグあり)なので論外。
    System.Windows.Media.MediaPlayerはオンメモリのデータを再生する手段がなさそう。

    サードパーティ製の音声ライブラリで真っ先に思いつくのはNAudioです。
    WaveOutを複数作るのが正しいのかどうか分からないですが、とりあえずこれを使ってみてはいかがでしょうか。

    外部ライブラリは使えないとなると、MCIでオンメモリデータの再生も不可能ではないですが面倒ですね…。
    最低限の音楽再生機能部分だけならMedia Foundationをラップするのもまあ非現実的というほどではない、かな?
記事No.94708 のレス /過去ログ164より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -