主窗体是个MDI窗体,现在想要把MDI子窗体都封装在dll中。
如果把dll中的窗体设为mdichild的话,运行时就说没有MDI窗体,因为dll的工程中确实没有MDI窗体;如果把dll中的窗体不设为mdichild的话,调用后又不能作为mdi子窗体运行。
调用时使用SetParent将dll中的窗体的父窗体指向主窗体,这样的效果也没有完全达到MDI子窗体的那种效果。
哪位高手告诉下怎么解决啊!

解决方案 »

  1.   

    已经有很多人发过类似的贴,
    微软提示的解决方案是SetParent,
    但这个根本不理想。另外一个开源的示例,无法正确显示窗体风格,比如子窗体设置的风格,进去后不是这个风格。还有一个控件,比较满意,但不开源,弹出对话框什么的,需要购买。总之,我到现在没有找到满意的。
      

  2.   

    给你一个纯VB的方案:
    将你需要实现的MDI子窗体全部做成UserControl,主工程中加一个空白的子窗体frmChild;
    打开某个子窗体界面只要新建frmChild实例,然后通过它的Controls.Add()创建对应的UserControl实例。
      

  3.   

    记得唯一的问题是:由于控件全部包含再一个UserControl,用Tab、Shift+Tab到达最后、最前一个焦点控件后无法循环焦点,必须在键盘事件中编程设置焦点。
      

  4.   

    在窗口创建前更改窗体风格,并自定义MDI子窗体窗体过程几百年前,我曾经写过一个无聊的类CVBWindowCreationHooker,用以拦截vb窗体的创建过程。而将普通窗体改为mdi窗体即是
    当时用以说明此类用法的例子。
      

  5.   

    我在网上找了找CVBWindowCreationHooker,提供下载的链接已经下不了了,能不能给我发一份?我邮箱是[email protected],谢谢先!
      

  6.   

    三星老大,几百年前的东西你还能找到吗?
    留传一下有缘人啊。
    Email:[email protected]
      

  7.   

    今早试了UserControl的方法,可行。
    果然是焦点到最后不管用。
      

  8.   

    在运行时,设置为传入的MDI句柄为父窗体!第三方控件:MDIExtender,我们公司就使用这!
      

  9.   

    VB多工程划分MDI子窗体的问题我n年前(这可是上个世纪的事了——:-P)就碰到了,在许多方案中:
    ·MDIExtender是最方便的,就是要花钱
    ·在不花钱的方案中,用 UserControl 是对现有程序改动最小的方案,除了对 Tab、Shift+Tab 按键消息的额外处理,剩下的就是依葫芦画瓢没什么难度。
      

  10.   

    下载地址: 
    http://econet.zjgsu.edu.cn/cy_filesxxx/vbsrc/MDIFormSnapIn.rar因为是硬编码,所以理论上会有一些几率出现XX说明: 1.因为这个窗体拦截类(g_oWCHooker)会拦截所有的窗体创建过程,所以,务必要指定需要处理的目标窗体(Form1)。具体方法就是在设计环境中为目标窗体(Form1)指定一个约定的窗体标题(即Caption属性设为我模块中写的那个TARGET_WINDOW_CAPTION常量的值“frmTargetWindow”)2.完事之后记得在MDIForm_Unload事件中卸载目标窗体(Form1)
    Private Sub (Cancel As Integer)
        Unload Form1
    End Sub3.有事先闪,下次再说
      

  11.   

    昨晚研究了一下,不错,是可以将窗体变为子窗体,
    但这个是程序本身的窗体。现在的要求是将DLL里出来的窗体变为自己的子窗体。我一上来就加个DLL工程,把FORM2加了进来。
    结果不行,原来FORM2里还有代码。搞了一下,没成功,太晚了,休息。
    今天继续。
      

  12.   

    我做过类似的控件,MDIExtender没有用过,网上有一个开源的程序(用VB写的),其原理就是在你的程序窗体运行之前新建一个子窗体(用API函数),然后把程序窗体加载为其子窗体。然后通过子类进行消息的处理。只用SetParent是实现不了的,需要几个与MDI相关的API。
      

  13.   

    搞到现在,VB挂掉N次,没能成功。楼上,用SetParent可以成功。步骤来重现行为
    1. VisualBasic 中创建新的标准 EXE 项目。 默认情况下创建 Form 1。 
    2. 在 项目 菜单上, 单击 Form 1 删除 。 
    3. 在 项目 菜单上, 单击 添加 MDI 窗体 。 MDIForm1 添加到 Project 1。 
    4. 在 项目 菜单上, 单击 Project 1 属性 , 并设置到 MDIForm1 Startup 对象。 
    5. 添加下列代码后面 MDIForm1:Private Sub MDIForm_Click()
        Dim x As Class1
        Set x = New Class1
        x.ShowChildForm MDIForm1.hWnd
    End Sub

     
    6. 在 文件 菜单上, 单击 AddProject@@@ 。 要创建项目组, 添加一个新的 ActiveXDLL 项目。 默认情况下创建 Class 1。 
    7. 以下代码添加到 Class 1:
    Private Declare Function GetWindowLong Lib "user32" _
            Alias "GetWindowLongA" _
            (ByVal hwnd As Long, ByVal nIndex As Long) As LongPrivate Declare Function SetParent Lib "user32" _
            (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As LongPrivate Declare Function SetWindowLong Lib "user32" _
            Alias "SetWindowLongA" _
            (ByVal hwnd As Long, ByVal nIndex As Long, _
            ByVal dwNewLong As Long) As LongConst GWL_STYLE = (-16)
    Const WS_POPUP = &H80000000Public Function ShowChildForm(ByVal hWndMDIForm As Long)
        Dim Ret As Long
        Dim CurrentStyle As Long
        
        Ret = SetParent(Form1.hwnd, hWndMDIForm)
        CurrentStyle = GetWindowLong(Form1.hwnd, GWL_STYLE)
        Ret = SetWindowLong(Form1.hwnd, GWL_STYLE, CurrentStyle Or WS_POPUP)
        Form1.Show
    End Function

     
    8. 在 项目 菜单上, 单击 添加窗体 。 Form 1 添加到 Project 2。 
    9. 在 @ @ @ ProjectExplorer@@, 单击 Project 1 以激活 Project 1 
    10. 在 项目 菜单上, 单击 References , 并添加一个引用到 Project 2 。 
    11. 按 F 5 键运行该程序。 
    12. 单击 MDIForm1 的客户端区域。 注意 Form 1 (从 Project 2) 在工作区的 MDI 窗体是立即可见。 
    以下列表包括一部分, 实现 SetParent 方法时可能遇到问题: ? MDI 父级的标题栏不显示从动态链接库 (DLL) 窗体具有焦点时, 它是活动窗口。 
      不从 DLL 中窗体菜单不合并与的 MDI 父窗体菜单。 
      当窗体从 DLL 是最大化, DLL 表单的标题栏是仍然可见。 
      MDI 子窗体是 MDI 项目的一部分收到焦点, 时它们不从 DLL 出现顶部窗体。 
      可通过 MDI 项目中存在一个工具栏移动窗体从 DLL。 
      当 DLL 表单出的可见区域的 MDI 窗体, 移动滚动条不显示 MDI 父级上。 
      

  14.   

    20楼的方法是不行,多年前就已经试验过了。要从如下方法入手。dll窗体加载前先创建了个MDI子窗体1(使用CreateWindowEx(WS_EX_MDICHILD)创建),然后加载dll窗体2,把窗体2设置为MDI子窗体1的子窗体(setparent方法),当然还需要很多其他代码,比较消息处理,窗体样式等,因为MDI子窗体有一些特殊的地方是普通窗体所没有的。这样就可以了,如果处理的好结果与MDI子窗体一样(虽然每显示一个窗体实际是两个窗体)。此过程中还需要MDICLIENT。简单使用setparent是不行的。上面的方法比较复杂,如果能在dll窗体加载前使用WS_EX_MDICHILD参数可能更好。但没有研究过,不知如何处理。
      

  15.   

    supergreenbean 的代码大概要编译成 exe 运行才行。
      

  16.   

    又见邪恶的豆子
    这代码偶测试通过 XP(SP2)
      

  17.   

    很久前我有一个把窗体封装到ActiveX中的源码,貌似跟楼主的需求类似。
    也不知道抛到哪里去了
      

  18.   

    各位找不到代码的就不要说了,我还记得MDIExtender在收费前还有一个功能不全的源代码版本呢。
    这些对搂在没帮助。