用SetParent函数,非常简单:
【函数】
SetParent【操作系统】
Win9X:Yes
WinNT:Yes【声明】
SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long【说明】  指定一个窗口的新父(在vb里使用:利用这个函数,vb可以多种形式支持子窗口。例如,可将控件从一个容器移至窗体中的另一个。用这个函数在窗体间移动控件是相当冒险的,但却不失为一个有效的办法。如真的这样做,请在关闭任何一个窗体之前,注意用SetParent将控件的父设回原来的那个) 【返回值】  Long,前一个父窗口的句柄 【其它】  可用这个函数在运行期将vb控件置入容器控件内部(比如将一个按钮设成图象或窗体控件的子窗口),或者将控件从一个容器控件移至另一个。控件移至另一个父后,它的位置将由新父的坐标系统决定。这样一来,有必要重新规定控件的位置,使其能在目标位置显示出来【参数表】
  hWndChild ------  Long,子窗口的句柄  hWndNewParent --  Long,hWndChild的新父
--------------------------------------------------------------------
用法非常简单:
SetParent FormChild.HWnd, MDIForom.HWnd
--------------------------------------------------------------------
API-Guide实例(Start In):
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Long, ByVal lpWindowName As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function Putfocus Lib "user32" Alias "SetFocus" (ByVal hwnd As Long) As Long
Const GW_HWNDNEXT = 2
Dim mWnd As Long
Function InstanceToWnd(ByVal target_pid As Long) As Long
    Dim test_hwnd As Long, test_pid As Long, test_thread_id As Long
    'Find the first window
    test_hwnd = FindWindow(ByVal 0&, ByVal 0&)
    Do While test_hwnd <> 0
        'Check if the window isn't a child
        If GetParent(test_hwnd) = 0 Then
            'Get the window's thread
            test_thread_id = GetWindowThreadProcessId(test_hwnd, test_pid)
            If test_pid = target_pid Then
                InstanceToWnd = test_hwnd
                Exit Do
            End If
        End If
        'retrieve the next window
        test_hwnd = GetWindow(test_hwnd, GW_HWNDNEXT)
    Loop
End Function
Private Sub Form_Load()
    Dim Pid As Long
    'Lock the window update
    LockWindowUpdate GetDesktopWindow
    'Execute notepad.Exe
    Pid = Shell("c:\windows\notepad.exe", vbNormalFocus)
    If Pid = 0 Then MsgBox "Error starting the app"
    'retrieve the handle of the window
    mWnd = InstanceToWnd(Pid)
    'Set the notepad's parent
    SetParent mWnd, Me.hwnd
    'Put the focus on notepad
    Putfocus mWnd
    'Unlock windowupdate
    LockWindowUpdate False
End Sub
Private Sub Form_Unload(Cancel As Integer)
    'Unload notepad
    DestroyWindow mWnd
    'End this program
    TerminateProcess GetCurrentProcess, 0
End Sub
--------------------------------------------------------------------
Made by Thirdapple's Studio

解决方案 »

  1.   

    好像不是MDI子窗体的效果,比如窗体最大化、最小化时子窗体不会跟着变化,子窗体最大化时会留下难看的标题,而且最主要的字窗体得到焦点时,父窗体会失去焦点。如果再打开别的子窗体时,别的字窗体总是在他的后面!!
      

  2.   

    不过,还是非常谢谢你——thirdapple(第三只苹果)
      

  3.   

    Sorry,先没尝试就给你贴上来了,道歉!
    看来没有现成的API可以用了,还应该改改FormChild的属性,也许。
    --------------------------------------------------------------------
    Made by Thirdapple's Studio
      

  4.   

    对了运行时设FORM的MDIChild为TRUE看看行不行???
      

  5.   

    你可以在一个form里放一个picturebox
    然后用setwindowlong函数把picturebox的样式变为form
    你看看有什么效果
      

  6.   

    模块
    Option ExplicitPublic Const GWL_EXSTYLE = (-20)
    Public Const GWL_HINSTANCE = (-6)
    Public Const GWL_HWNDPARENT = (-8)
    Public Const GWL_ID = (-12)
    Public Const GWL_STYLE = (-16)
    Public Const GWL_USERDATA = (-21)
    Public Const GWL_WNDPROC = (-4)Public Const WS_BORDER = &H800000
    Public Const WS_CAPTION = &HC00000                  '  WS_BORDER Or WS_DLGFRAME
    Public Const WS_CHILD = &H40000000
    Public Const WS_CHILDWINDOW = (WS_CHILD)
    Public Const WS_CLIPCHILDREN = &H2000000
    Public Const WS_CLIPSIBLINGS = &H4000000
    Public Const WS_DISABLED = &H8000000
    Public Const WS_DLGFRAME = &H400000
    Public Const WS_EX_ACCEPTFILES = &H10&
    Public Const WS_EX_DLGMODALFRAME = &H1&
    Public Const WS_EX_NOPARENTNOTIFY = &H4&
    Public Const WS_EX_TOPMOST = &H8&
    Public Const WS_EX_TRANSPARENT = &H20&
    Public Const WS_GROUP = &H20000
    Public Const WS_HSCROLL = &H100000
    Public Const WS_MAXIMIZE = &H1000000
    Public Const WS_MAXIMIZEBOX = &H10000
    Public Const WS_MINIMIZE = &H20000000
    Public Const WS_MINIMIZEBOX = &H20000
    Public Const WS_OVERLAPPED = &H0&
    Public Const WS_POPUP = &H80000000
    Public Const WS_SYSMENU = &H80000
    Public Const WS_TABSTOP = &H10000
    Public Const WS_THICKFRAME = &H40000
    Public Const WS_VISIBLE = &H10000000
    Public Const WS_VSCROLL = &H200000
    Public Const WS_ICONIC = WS_MINIMIZE
    Public Const WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX)
    Public Const WS_POPUPWINDOW = (WS_POPUP Or WS_BORDER Or WS_SYSMENU)
    Public Const WS_SIZEBOX = WS_THICKFRAME
    Public Const WS_TILED = WS_OVERLAPPED
    Public Const WS_TILEDWINDOW = WS_OVERLAPPEDWINDOWPublic Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Public OldLng&
    Sub ChgWindowLong1(hwnd&)
        Dim WndLng&
        
        WndLng& = GetWindowLong(hwnd&, GWL_STYLE)
        
        WndLng& = WndLng& Or WS_BORDER _
                          Or WS_CAPTION _
                          Or WS_THICKFRAME _
                          Or WS_SYSMENU _
                          Or WS_MAXIMIZEBOX _
                          Or WS_MINIMIZEBOX _
                          Or WS_OVERLAPPED _
                          Or WS_SIZEBOX
        
        SetWindowLong hwnd&, GWL_STYLE, WndLng&
    End Sub
    在窗体里放一个picturebox
    以下为代码
    Option Explicit
    Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long
    Private Sub Form_Load()
    OldLng& = GetWindowLong(hwnd&, GWL_STYLE)
        ChgWindowLong1 picForm.hwnd
        SetWindowText picForm.hwnd, "Picture to Form"
        picForm.Width = picForm.Width + 8
    End Sub
      

  7.   

    这个代码可以解决以上问题
    只不过也存在一个问题:主窗体的标题会变灰点击“主窗体”会显示出“子窗体”
    点击“子窗体”会使它在 子窗体、普通窗体 中切换
    把下列代码复制到记事本,并保存为相应文件SetMDI.vbp
    ====================================================================
    Type=Exe
    Form=FrmChild.frm
    Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\WINDOWS\SYSTEM\stdole2.tlb#OLE Automation
    Form=MDIMain.frm
    Startup="MDIMain"
    HelpFile=""
    Command32=""
    Name="SetMDI"
    HelpContextID="0"
    CompatibleMode="0"
    MajorVer=1
    MinorVer=0
    RevisionVer=0
    AutoIncrementVer=0
    ServerSupportFiles=0
    VersionCompanyName="91290"
    CompilationType=0
    OptimizationType=0
    FavorPentiumPro(tm)=0
    CodeViewDebugInfo=0
    NoAliasing=0
    BoundsCheck=0
    OverflowCheck=0
    FlPointCheck=0
    FDIVCheck=0
    UnroundedFP=0
    StartMode=0
    Unattended=0
    Retained=0
    ThreadPerObject=0
    MaxNumberOfThreads=1
    MDIMain.frm
    ====================================================================
    VERSION 5.00
    Begin VB.MDIForm MDIMain 
       BackColor       =   &H8000000C&
       Caption         =   "主窗体"
       ClientHeight    =   3195
       ClientLeft      =   60
       ClientTop       =   345
       ClientWidth     =   4680
       LinkTopic       =   "MDIForm1"
       StartUpPosition =   3  '窗口缺省
    End
    Attribute VB_Name = "MDIMain"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = True
    Attribute VB_Exposed = False
    Option ExplicitPrivate Sub MDIForm_Click()
        FrmChild.Show
        
    End SubPrivate Sub MDIForm_Load()
        FrmChild.Show
        
    End SubPrivate Sub MDIForm_Unload(Cancel As Integer)
        Dim TempForm As Form
        
        For Each TempForm In Forms
            Unload TempForm
        Next TempForm
        
    End SubFrmChild.frm
    ====================================================================
    VERSION 5.00
    Begin VB.Form FrmChild 
       BorderStyle     =   1  'Fixed Single
       Caption         =   "子窗体"
       ClientHeight    =   2025
       ClientLeft      =   45
       ClientTop       =   330
       ClientWidth     =   3510
       LinkTopic       =   "Form1"
       MaxButton       =   0   'False
       ScaleHeight     =   2025
       ScaleWidth      =   3510
       ShowInTaskbar   =   0   'False
    End
    Attribute VB_Name = "FrmChild"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = True
    Attribute VB_Exposed = False
    Option Explicit
    Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As LongPrivate Declare Function GetDesktopWindow Lib "user32" () As Long
    Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As LongPrivate Const SWP_NOSIZE = &H1
    Private Const SWP_NOMOVE = &H2
    Private Const SWP_NOZORDER = &H4
    Private Const SWP_FRAMECHANGED = &H20
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPrivate Const GWL_STYLE = (-16)
    Private Const GWL_EXSTYLE As Long = (-20)Private Const WS_CHILD = &H40000000
    Private Const WS_CHILDWINDOW = (WS_CHILD)Private Const WS_EX_MDICHILD As Long = &H40&
    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPrivate Sub Form_Click()
        Dim TemphWnd As Long
        Dim TempStyle As Long
        Dim TempExStyle As Long
        
        TemphWnd = FindWindowEx(MDIMain.hwnd, 0, "MDIClient", vbNullString) '查找MDI客户区
        TempStyle = GetWindowLong(Me.hwnd, GWL_STYLE)
        TempExStyle = GetWindowLong(Me.hwnd, GWL_EXSTYLE)
        If GetParent(Me.hwnd) = TemphWnd Then
            Call SetParent(Me.hwnd, GetDesktopWindow)
            TempStyle = TempStyle And Not WS_CHILDWINDOW
            TempExStyle = TempExStyle And Not WS_EX_MDICHILD
        Else
            Call SetParent(Me.hwnd, TemphWnd)
            TempStyle = TempStyle Or WS_CHILDWINDOW
            TempExStyle = TempExStyle Or WS_EX_MDICHILD
        End If
        Call SetWindowLong(Me.hwnd, GWL_STYLE, TempStyle)
        Call SetWindowLong(Me.hwnd, GWL_EXSTYLE, TempExStyle)
        
        'Call SetWindowPos(Me.hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE Or SWP_NOZORDER Or SWP_FRAMECHANGED)
        Call SetWindowPos(Me.hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOZORDER Or SWP_FRAMECHANGED)
        
    End SubPrivate Sub Form_Load()
        '
    End Sub