Panelを継承したクラスで、AutoScrollをTrueにすると子コントロールが縮む
詳細はここ。
環境
WindowsXP Pro SP3
VisualStudio 2008
.NET Framework3.5
現象
Public Class MyPanel Inherits System.Windows.Forms.Panel End Class
のように単純にパネルを継承したクラスを作成し、パネル内にコントロールを配置。
コントロールのAnchorをTop, Left, Rightに設定しておく。
さらに、MyPanelのAutoScrollプロパティをTrueにするとパネル内の子コントロールが縮む。
どうやらスクロールバーの分が2重にリサイズされている模様。
対応策 (以下はベストではない。最新情報は後日 または ここを参照)
とりあえず、パネル側にISupportInitializeを実装してやって回避することに。
Public MustInherit Class MyPanelBase Inherits System.Windows.Forms.Panel Implements System.ComponentModel.ISupportInitialize Private _RightAnchorControls As List(Of Control) Private _BottomAnchorControls As List(Of Control) Protected Overridable Sub BeginInit() Implements System.ComponentModel.ISupportInitialize.BeginInit ' Do nothing End Sub Protected Overridable Sub EndInit() Implements System.ComponentModel.ISupportInitialize.EndInit If (Me.AutoScroll) Then _RightAnchorControls = New List(Of Control) _BottomAnchorControls = New List(Of Control) For Each ctrl As Control In Me.Controls ' 継承コントロールの場合は、ここでctrl.Nameがクラス名になっている。何故? ' まぁ、継承コントロールのインスタンスが取得できていないのは間違いない。 If ((ctrl.Anchor And (AnchorStyles.Right Or AnchorStyles.Left)) = _ (AnchorStyles.Right Or AnchorStyles.Left)) Then ' Anchor が LeftかつRightのコントロールをリストアップ _RightAnchorControls.Add(ctrl) ' Anchor が LeftかつRightのコントロールからRightアンカーを外す ' HandleCreatedイベントで戻す ctrl.Anchor = (ctrl.Anchor Xor AnchorStyles.Right) End If If ((ctrl.Anchor And (AnchorStyles.Top Or AnchorStyles.Bottom)) = _ (AnchorStyles.Top Or AnchorStyles.Bottom)) Then ' Anchor が TopかつBottomのコントロールをリストアップ _BottomAnchorControls.Add(ctrl) ' Anchor が TopかつBottomのコントロールからBottomアンカーを外す ' HandleCreatedイベントで戻す ctrl.Anchor = (ctrl.Anchor Xor AnchorStyles.Bottom) End If Next End If End Sub Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs) MyBase.OnHandleCreated(e) If (_RightAnchorControls IsNot Nothing) Then ' Anchor が LeftかつRightであったコントロールのRightアンカーを戻す For Each ctrl As Control In _RightAnchorControls If (Me.Controls.Contains(ctrl)) Then ctrl.Anchor = (ctrl.Anchor Or AnchorStyles.Right) Next _RightAnchorControls = Nothing End If If (_BottomAnchorControls IsNot Nothing) Then ' Anchor が TopかつBottomであったコントロールのBottomアンカーを戻す For Each ctrl As Control In _BottomAnchorControls If (Me.Controls.Contains(ctrl)) Then ctrl.Anchor = (ctrl.Anchor Or AnchorStyles.Bottom) Next _BottomAnchorControls = Nothing End If End Sub End Class
だがしかし、これだけでは不十分であった。
標準のTextBox等を配置する分には問題ないが、
UserControlを継承したコンポーネントを配置するとやはり縮んでしまう。*1
カスタムコントロール側にも以下のような仕込みを入れてやることにする。
Public Class MyControl Inherits System.Windows.Forms.UserControl Inherits System.ComponentModel.ISupportInitialize ' HACK : ISupportInitializeNotificationの実装も検討した方が良いのか…? Private _Size As Size private _IsInitialized As Boolean Protected Sub BeginInit() Implements System.ComponentModel.ISupportInitialize.BeginInit _IsInitialized = False End Sub Protected Sub EndInit() Implements System.ComponentModel.ISupportInitialize.EndInit _Size = Me.Size _IsInitialized = True End Sub Private Sub MyControl_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize If (_IsInitialized = True AndAlso Me.IsHandleCreated = False) Then Me.Size = _Size End If End Sub End Class
これで何とか解決。
でも、
DataGridViewとかはISupportInitializeを実装済みな上に隠蔽されている。
どうしようかな…。
*1:TextBox等を継承したコントロールでは試していないが、多分同様であろう