dll封装MDI子窗体的问题

shenx33 2008-06-23 11:19:20
主窗体是个MDI窗体,现在想要把MDI子窗体都封装在dll中。
如果把dll中的窗体设为mdichild的话,运行时就说没有MDI窗体,因为dll的工程中确实没有MDI窗体;如果把dll中的窗体不设为mdichild的话,调用后又不能作为mdi子窗体运行。
调用时使用SetParent将dll中的窗体的父窗体指向主窗体,这样的效果也没有完全达到MDI子窗体的那种效果。
哪位高手告诉下怎么解决啊!
...全文
621 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
qinjueping 2010-06-23
  • 打赏
  • 举报
回复
mark
vansoft 2008-06-26
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 watt 的回复:]
20楼的方法是不行,多年前就已经试验过了。
[/Quote]

这是微软网站贴出来的解决方案。
代码我是测试过的,可行。

最后几点是列出的问题。
Tiger_Zhao 2008-06-26
  • 打赏
  • 举报
回复
各位找不到代码的就不要说了,我还记得MDIExtender在收费前还有一个功能不全的源代码版本呢。
这些对搂在没帮助。
watt 2008-06-25
  • 打赏
  • 举报
回复
我做过类似的控件,MDIExtender没有用过,网上有一个开源的程序(用VB写的),其原理就是在你的程序窗体运行之前新建一个子窗体(用API函数),然后把程序窗体加载为其子窗体。然后通过子类进行消息的处理。只用SetParent是实现不了的,需要几个与MDI相关的API。
迈克揉索芙特 2008-06-25
  • 打赏
  • 举报
回复
很久前我有一个把窗体封装到ActiveX中的源码,貌似跟楼主的需求类似。
也不知道抛到哪里去了
迈克揉索芙特 2008-06-25
  • 打赏
  • 举报
回复
又见邪恶的豆子
这代码偶测试通过 XP(SP2)
vansoft 2008-06-25
  • 打赏
  • 举报
回复
昨晚研究了一下,不错,是可以将窗体变为子窗体,
但这个是程序本身的窗体。

现在的要求是将DLL里出来的窗体变为自己的子窗体。

我一上来就加个DLL工程,把FORM2加了进来。
结果不行,原来FORM2里还有代码。

搞了一下,没成功,太晚了,休息。
今天继续。
Tiger_Zhao 2008-06-25
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 vansoft 的回复:]
搞到现在,VB挂掉N次,没能成功。
[/Quote]
supergreenbean 的代码大概要编译成 exe 运行才行。
watt 2008-06-25
  • 打赏
  • 举报
回复
20楼的方法是不行,多年前就已经试验过了。

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

上面的方法比较复杂,如果能在dll窗体加载前使用WS_EX_MDICHILD参数可能更好。但没有研究过,不知如何处理。
lovesoo 2008-06-25
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 myjian 的回复:]
引用 12 楼 CityBird 的回复:
Mark一下
[/Quote]
vansoft 2008-06-25
  • 打赏
  • 举报
回复
搞到现在,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 Long

Private Declare Function SetParent Lib "user32" _
(ByVal hWndChild As Long, ByVal hWndNewParent 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 Long

Const GWL_STYLE = (-16)
Const WS_POPUP = &H80000000

Public 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 父级上。
cacar2008 2008-06-24
  • 打赏
  • 举报
回复
在运行时,设置为传入的MDI句柄为父窗体!

第三方控件:MDIExtender,我们公司就使用这!
三楼の郎 2008-06-24
  • 打赏
  • 举报
回复
Mark一下
vansoft 2008-06-24
  • 打赏
  • 举报
回复
今早试了UserControl的方法,可行。
果然是焦点到最后不管用。
supergreenbean 2008-06-24
  • 打赏
  • 举报
回复
有阿,不过我还是修改下代码再拿出来吧,现在看看以前写的代码,我自己都直摇头,呵呵
vansoft 2008-06-24
  • 打赏
  • 举报
回复
下载研究先,闪。
supergreenbean 2008-06-24
  • 打赏
  • 举报
回复
下载地址:
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 Sub

3.有事先闪,下次再说
嗷嗷叫的老马 2008-06-24
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 CityBird 的回复:]
Mark一下
[/Quote]
Tiger_Zhao 2008-06-24
  • 打赏
  • 举报
回复
VB多工程划分MDI子窗体的问题我n年前(这可是上个世纪的事了——:-P)就碰到了,在许多方案中:
·MDIExtender是最方便的,就是要花钱
·在不花钱的方案中,用 UserControl 是对现有程序改动最小的方案,除了对 Tab、Shift+Tab 按键消息的额外处理,剩下的就是依葫芦画瓢没什么难度。
vansoft 2008-06-23
  • 打赏
  • 举报
回复
已经有很多人发过类似的贴,
微软提示的解决方案是SetParent,
但这个根本不理想。

另外一个开源的示例,无法正确显示窗体风格,比如子窗体设置的风格,进去后不是这个风格。

还有一个控件,比较满意,但不开源,弹出对话框什么的,需要购买。

总之,我到现在没有找到满意的。
加载更多回复(8)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧