トップ回答者
1つのツールボックスから2つのコントロール・コンポーネントを作成したい

質問
-
グレープシティ製のSPREAD for Windows Forms(以下SPREAD)がそうだったのですが、
1つのコントロールをツールボックスから選択してフォーム上へ設置した瞬間に、
選択したコントロールに加えてコンポーネントを1つ設置したいです。
SPREADでは、コントロール(FpSpread)を設置すると、自動的にコンポーネント(SheetView)が
作成され、コントロールのシート要素としてコンポーネントが追加されます。
コントロールが設置された時に設置されたフォームを取得してコンポーネントを追加すれば
いいのかなとは思いますが、そのようなタイミングはどこでコードすればよいのでしょうか?
回答
-
こんな?
public class TestDesigner : System.Windows.Forms.Design.ControlDesigner { public override void InitializeNewComponent(System.Collections.IDictionary defaultValues) { base.InitializeNewComponent(defaultValues); //System.Diagnostics.Debugger.Launch(); if (defaultValues.Contains("Parent") && defaultValues["Parent"] is System.ComponentModel.IComponent) { System.ComponentModel.IComponent component = (System.ComponentModel.IComponent)defaultValues["Parent"]; if (component.Site != null) { var host = (System.ComponentModel.Design.IDesignerHost)component.Site.GetService(typeof(System.ComponentModel.Design.IDesignerHost)); if (host != null) { //コンポーネントとしてシリアルポートを追加してみる var port = (System.IO.Ports.SerialPort)host.CreateComponent(typeof(System.IO.Ports.SerialPort)); //ついでにおまけのボタンも追加してみる if(component is Control) { var button2 =(Button) host.CreateComponent(typeof(Button)); button2.Text = "ぼたん2"; if (this.Control != null) { button2.Left = this.Control.Left + Control.Width; button2.Top = this.Control.Top; } ((Control)component).Controls.Add(button2); } } } } } } [System.ComponentModel.DesignerAttribute(typeof(TestDesigner))] class TestButton : Button { }
タイミングとかは以前の「コンポーネントを配置した瞬間を判断したい」でAzuleanさんがヒントになること書いてますよね。
あとはIDesignerHostを得る方法がわかれば追加する方法も見えてくるんじゃないかな。別解としてこんなのも
public class X : Button { public X() { if (Environment.StackTrace.Contains("System.Windows.Forms.Design.ControlDesigner")) { this.ParentChanged += new EventHandler(X_ParentChanged); } } void X_ParentChanged(object sender, EventArgs e) { if (this.Parent != null) { this.ParentChanged -= X_ParentChanged; var component = this.Parent as IComponent; if (component != null && component.Site != null && component.Site.DesignMode) { var host = (System.ComponentModel.Design.IDesignerHost)component.Site.GetService(typeof(System.ComponentModel.Design.IDesignerHost)); if (host != null) { var txb = (TextBox)host.CreateComponent(typeof(TextBox)); this.Parent.Controls.Add(txb); } } } } }
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2013年7月19日 14:18 2個目のコードのイベント解除ミス修正
- 回答の候補に設定 AzuleanMVP, Moderator 2013年7月20日 0:58
- 回答としてマーク takiru 2013年7月20日 9:01
すべての返信
-
こんな?
public class TestDesigner : System.Windows.Forms.Design.ControlDesigner { public override void InitializeNewComponent(System.Collections.IDictionary defaultValues) { base.InitializeNewComponent(defaultValues); //System.Diagnostics.Debugger.Launch(); if (defaultValues.Contains("Parent") && defaultValues["Parent"] is System.ComponentModel.IComponent) { System.ComponentModel.IComponent component = (System.ComponentModel.IComponent)defaultValues["Parent"]; if (component.Site != null) { var host = (System.ComponentModel.Design.IDesignerHost)component.Site.GetService(typeof(System.ComponentModel.Design.IDesignerHost)); if (host != null) { //コンポーネントとしてシリアルポートを追加してみる var port = (System.IO.Ports.SerialPort)host.CreateComponent(typeof(System.IO.Ports.SerialPort)); //ついでにおまけのボタンも追加してみる if(component is Control) { var button2 =(Button) host.CreateComponent(typeof(Button)); button2.Text = "ぼたん2"; if (this.Control != null) { button2.Left = this.Control.Left + Control.Width; button2.Top = this.Control.Top; } ((Control)component).Controls.Add(button2); } } } } } } [System.ComponentModel.DesignerAttribute(typeof(TestDesigner))] class TestButton : Button { }
タイミングとかは以前の「コンポーネントを配置した瞬間を判断したい」でAzuleanさんがヒントになること書いてますよね。
あとはIDesignerHostを得る方法がわかれば追加する方法も見えてくるんじゃないかな。別解としてこんなのも
public class X : Button { public X() { if (Environment.StackTrace.Contains("System.Windows.Forms.Design.ControlDesigner")) { this.ParentChanged += new EventHandler(X_ParentChanged); } } void X_ParentChanged(object sender, EventArgs e) { if (this.Parent != null) { this.ParentChanged -= X_ParentChanged; var component = this.Parent as IComponent; if (component != null && component.Site != null && component.Site.DesignMode) { var host = (System.ComponentModel.Design.IDesignerHost)component.Site.GetService(typeof(System.ComponentModel.Design.IDesignerHost)); if (host != null) { var txb = (TextBox)host.CreateComponent(typeof(TextBox)); this.Parent.Controls.Add(txb); } } } } }
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2013年7月19日 14:18 2個目のコードのイベント解除ミス修正
- 回答の候補に設定 AzuleanMVP, Moderator 2013年7月20日 0:58
- 回答としてマーク takiru 2013年7月20日 9:01
-
大変具体的なご回答ありがとうございます。
以前に「コンポーネントを配置した瞬間を判断したい」で教えて頂いた内容は把握していたのですが、
何がなんだか明確に理解できておらず、どういう風に実装すればという状態でした。
まだまだ分からないことが多いです。
本日は確認ができない為、明日調べながら実装し、確認してみます。ありがとうございました。