| ■No88449 (ソニン さん) に返信
>>通常の SDI における「子.Show(親)」で表示させる方法ではなく、
>>あくまでも親のクライアント領域内に子を表示させる画面構成でしょうか。
> これはどういう画面構成のことをさしていますか?
> 自分としては、
> 通常の MDI における「子.Show(親)」で表示させる方法を使うつもりですので
> 異なる方法でしょうか?
親フォームが「Owner プロパティ」と「MdiParent プロパティ」の
いずれで管理されているのか、ということです。
たとえば、
MDIParentForm.Show()
MDIChildForm.MdiParent = MDIParentForm
MDIChildForm.Show(MDIParentForm)
のような記述はエラーになりますよね。
※ MDIParentForm.Show(他フォーム) は OK
>> 検索して調べたところ、恐らくこの方法を使えばいけると思います。
>> https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1475227379
> 翻訳サイトを使ってVBに変換したのですが
意訳してみました。
MDI 親フォームに「MdiClientScrollBars プロパティ」を実装しています。
Option Strict On
Option Explicit On
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Partial Public NotInheritable Class MDIParent1
Inherits System.Windows.Forms.Form
#Region "MdiClientScrollBars プロパティ / IsMdiContainer が True の時に、MdiClient にスクロールバーが表示されるかどうかを示す値を取得または設定します"
''' <summary>
''' <see cref="IsMdiContainer"/>が<code>True</code>の時に、<see cref="MdiClient"/>にスクロールバーが表示されるかどうかを示す値を取得または設定します
''' </summary>
<DefaultValue(False)>
Public Property MdiClientScrollBars As Boolean
Get
Return IsMdiContainer AndAlso _MdiClientScrollBars
End Get
Set(value As Boolean)
_MdiClientScrollBars = MdiClientProcWithoutScrollbars(value)
End Set
End Property
Private _MdiClientScrollBars As Boolean = False
#End Region
#Region "API 宣言"
Private Const GWL_WNDPROC As Integer = -4
Private Delegate Function WndProcDelegate(hWnd As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
Private Declare Auto Function SetWindowLongPtr32 Lib "user32" Alias "SetWindowLong" (hWnd As HandleRef, nIndex As Integer, dwNewLong As IntPtr) As IntPtr
Private Declare Auto Function SetWindowLongPtr64 Lib "user32" Alias "SetWindowLongPtr" (hWnd As HandleRef, nIndex As Integer, dwNewLong As IntPtr) As IntPtr
Private Declare Auto Function CallWindowProc Lib "user32" (lpPrevWndFunc As IntPtr, hWnd As IntPtr, Msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr
Private Shared ReadOnly SetWindowLongPtr As Func(Of HandleRef, Integer, IntPtr, IntPtr)
Shared Sub New()
If IntPtr.Size = 8 Then
SetWindowLongPtr = AddressOf SetWindowLongPtr64
Else
SetWindowLongPtr = AddressOf SetWindowLongPtr32
End If
End Sub
#End Region
#Region "MdiClient の取得処理"
'MdiClient を保持する変数。OnControlAdded / OnControlRemoved で更新される。
Private MdiClientHandle As HandleRef = New HandleRef(Nothing, IntPtr.Zero)
'本来のプロシージャ
Private MdiClientOriginalProc As IntPtr = IntPtr.Zero
'CallbackOnCollectedDelegate 対策のため、GC されないよう保持しておく
Private MdiClientProc As WndProcDelegate = Nothing
Protected Overrides Sub OnControlAdded(e As ControlEventArgs)
MyBase.OnControlAdded(e)
If TypeOf e.Control Is MdiClient Then
MdiClientHandle = New HandleRef(e.Control, e.Control.Handle)
End If
End Sub
Protected Overrides Sub OnControlRemoved(e As ControlEventArgs)
If TypeOf e.Control Is MdiClient Then
If MdiClientOriginalProc <> IntPtr.Zero Then
'MdiClient が削除される前にサブクラス化を解除しておく
SetWindowLongPtr(MdiClientHandle, GWL_WNDPROC, MdiClientOriginalProc)
MdiClientOriginalProc = IntPtr.Zero
End If
MdiClientHandle = New HandleRef(Nothing, IntPtr.Zero)
End If
MyBase.OnControlRemoved(e)
End Sub
#End Region
#Region "MDI のスクロールバー制御"
Private Function MdiClientProcWithoutScrollbars(visible As Boolean) As Boolean
If Not IsMdiContainer OrElse MdiClientHandle.Handle = IntPtr.Zero Then
Return False
End If
Dim mc = TryCast(MdiClientHandle.Wrapper, MdiClient)
If mc Is Nothing Then
Return False
End If
If visible Then
If MdiClientOriginalProc <> IntPtr.Zero Then
'サブクラス化解除
SetWindowLongPtr(MdiClientHandle, GWL_WNDPROC, MdiClientOriginalProc)
MdiClientOriginalProc = IntPtr.Zero
End If
Else
If MdiClientOriginalProc = IntPtr.Zero Then
'サブクラス化
MdiClientProc = New WndProcDelegate(AddressOf MdiClientProcWithoutScorollbars)
MdiClientOriginalProc = SetWindowLongPtr(MdiClientHandle, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(MdiClientProc))
End If
End If
'リサイズすることで、スクロールバーを強制再描画させる
'(ただし mc.Dock は Fill なので、実際にはリサイズされない)
mc.Width -= 1
Return visible
End Function
Private Function MdiClientProcWithoutScorollbars(hWnd As IntPtr, uMsg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr
'サブクラス化して WM_NCCALCSIZE を無視する
Const WM_NCCALCSIZE As UInteger = 131UI
Return If(uMsg = WM_NCCALCSIZE, IntPtr.Zero, CallWindowProc(MdiClientOriginalProc, hWnd, uMsg, wParam, lParam))
End Function
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
'MdiClient のスクロールバーの状態を更新する
_MdiClientScrollBars = MdiClientProcWithoutScrollbars(IsMdiContainer AndAlso _MdiClientScrollBars)
End Sub
#End Region
End Class |