“绑架”窗体技术及其应用

马文骞

“绑架窗体”:顾名思义,就是将其它应用程序甚至系统程序的窗体活生生地拖进本程序的窗体内。这种未征得其它程序同意的强行“绑架”行为在某些场合下却能发挥出非常独特的作用。本文将讨论“绑架”窗体的技术及应用,并给出了一个完整的“强盗”程序的例子。
一、“绑架”的可行性
为了增加直观效果,让我们首先来看一看“强盗”程序的运行情况:图一是空白的“强盗”程序以及三个IE浏览窗口;图二显示的是三个IE窗口被“强盗”程序“绑架”后的情形。

图略...
从技术上讲,为了实现“绑架”,“强盗”程序中必须要有一个 MDIForm对象。MDI(多文档接口)窗体是可作为应用程序背景的窗口,也是 MDIChild属性设为True的其它普通窗体的容器。在“工程”菜单中选择“添加 MDI 窗体”就可以创建一个MDIForm 对象。一个应用程序只能有一个 MDIForm对象。MDIForm 对象只包含 Menu和PictureBox控件以及具有 Align属性的自定义控件。为把其它的控件放入MDIForm,可以在窗体上填加一个图片框,然后在图片框上增加其它控件。
实现“绑架”的第二个条件,是必须知道被“绑架”窗体的句柄。做到这一点并不难。比如,当鼠标在屏幕上滑动时,我们可以用 API函数GetCursorPos来获得鼠标指针的当前位置坐标,然后用另一个 API函数 WindowFromPoint来获得指定点窗口的句柄。本文后面的例子由于是要“绑架”IE窗口,为了简洁,采用ShellWindows对象技术来解决这个问题。ShellWindows能返回 Windows级所有活动窗口的集合,例如Internet Explorer(IE)以及 Windows Explorer(资源管理器)等。我们可以用ShellWindows的Count属性得到所有活动窗口的个数,再用ShellWindows的Item方法来访问每个活动窗口。如果某窗口的档案类型(Document Type)是“HTMLDocument”,我们即可判定该窗口为IE窗口。在VB中使用ShellWindows对象,须打开“菜单->工程->引用”,选中“Microsoft Internet Controls”。
有了上述两个条件,“强盗”程序就可以开始实施“绑架”了:首先用 API函数GetWindow 的GW_CHILD命令来寻找本程序第一个子窗口的句柄;然后用另一个 API函数 SetParent为被“绑架”窗体指定一个“新父”,即指向上面的子窗口的句柄。立刻,两个原本毫无关系的窗体具有了“父子”关系:被“绑架”窗口出现在“强盗”窗体内部!
二、“绑架”的安全性
不分青红皂白地进行“绑架”是非常危险的。但只要遵守以下两个原则就可以保证安全性:
第一,在关闭“强盗”程序之前,把被“绑架”窗体用 SetParent函数“释放”掉,即恢复被“绑架”者的原来的“父亲”。
第二,不要“绑架”系统窗口。系统窗口一般有:任务栏窗口、按下“开始”产生的窗口、按下“Ctrl+Alt+Del”产生的窗口,点击鼠标右键产生的窗口,等等。
三、“绑架”的实用性
“绑架”技术在VB中有广泛的应用,例如,可在程序运行中将控件置入容器控件内部(比如将一个按钮设成图象或窗体控件的子窗口),或者将控件从一个容器移至窗体中的另一个。
本文的示例程序则给出了一个非常有用和现实的功能:当系统中的IE浏览窗口过多时非常不便于管理,而且会把任务栏搞得很乱。将所有IE窗口放入一个主窗口中不失为一个好想法,它至少可带来以下好处:
1/ 你可以平铺或层叠这些IE窗口;
2/ 根据拨号线路的状态,让它们全体同时开始刷新或全部停止刷新;
3/ 还有,你一定曾经为一一最小化所有IE窗口伤过脑筋,现在,把主窗口最小化就意味着全部IE窗口的最小化;
4/ 当IE窗口过多时,你一定望着任务栏上那些根本显示不全标题的最小化窗口叹息过,而现在你可以在主窗口内建一个下拉式组合框,将所有IE窗口的标题放进去,以便于根据完整的标题选择相应窗口;
5/ 另外还有一个很大的好处,就是你可以为主窗口加一个密码,每当主窗口从最小化状态恢复时就询问密码。这意味着你有机会用最快的速度保护所有的浏览画面----最小化主窗口即可!
许多网民对美国 Opera软件公司的 Opera浏览器一直情有独钟,一个很重要的原因就是 Opera浏览器将所有的浏览窗口集成到一个主窗口内。因此一直到最新的 4.x版, Opera始终执着地保留了这种风格。
现在,使用下面的程序,你就既有了集成的主窗口环境,又不必舍弃你熟悉的IE浏览器!
四、示例程序:有密码安全机制的IE集成环境
' MDI窗体部分的代码(MDIForm1.frm)
Option Explicit
Const GW_CHILD = 5 ' 此参数的意义是返回当前窗口的第一个子窗口的句柄
Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
Dim IE() As InternetExplorer
Dim Hwnd_IE() As Long ' 保存所有IE窗口的句柄
Dim Hwnd_Old_Parent() As Long ' 保存所有IE窗口原有的父指针
Dim Total_W As Integer
Dim Minimized As Boolean

Private Sub MDIForm_Load()
绑架.Enabled = True
释放.Enabled = False
End Sub

Private Sub 绑架_Click()
On Error Resume Next
Dim i As Integer
Dim Doc
Dim Hwnd_Child As Long
Dim SWs As New ShellWindows ' Windows级所有活动窗口的集合
绑架.Enabled = False
Total_W = SWs.Count
ReDim IE(Total_W) As InternetExplorer ' 根据窗口数目来动态定义
ReDim Hwnd_IE(Total_W) As Long
ReDim Hwnd_Old_Parent(Total_W) As Long
For i = 0 To Total_W - 1
Set IE(i) = SWs.Item(i)
Set Doc = IE(i).Document
If TypeName(Doc) = "HTMLDocument" Then ' 判断是否为IE窗口
Hwnd_IE(i) = IE(i).hWnd
' 返回当前窗口的第一个可用子窗口的句柄
Hwnd_Child = GetWindow(MDIForm1.hWnd, GW_CHILD)
' 实施“绑架”:即保留原有的父句柄、并设置新的父指针
Hwnd_Old_Parent(i) = SetParent(Hwnd_IE(i), Hwnd_Child)
End If
Next
释放.Enabled = True
End Sub

Private Sub 释放_Click()
Dim i As Integer
释放.Enabled = False
For i = 0 To Total_W - 1
If Hwnd_IE(i) > 0 Then
' 恢复原有的父指针:所有IE窗口都回到了本示例程序之外。
Call SetParent(Hwnd_IE(i), Hwnd_Old_Parent(i))
End If
Next
Total_W = 0
绑架.Enabled = True
End Sub
Private Sub 层叠_Click()
MDIForm1.Arrange 0
End Sub

Private Sub 水平平铺_Click()
MDIForm1.Arrange 1
End Sub

Private Sub 垂直平铺_Click()
MDIForm1.Arrange 2
End Sub

Private Sub 图标重排_Click()
MDIForm1.Arrange 3
End Sub

Private Sub MDIForm_Resize()
Dim i As Integer
If MDIForm1.WindowState = 1 Then
Minimized = True
For i = 0 To Total_W - 1
If Hwnd_IE(i) > 0 Then
' 最小化时将所有IE窗口上提,是为了今后提问密码时IE窗口不可见,
' 以保护所有的浏览画面。
IE(i).Top = -10000
End If
Next
Exit Sub
End If
If Minimized = True Then ' 从最小化状态恢复时执行
If InputBox("Input Password:", "Password Please!") <> "ccw" Then
MDIForm1.WindowState = 1 ' 若密码不是“ccw”,则继续最小化状态!
Else
Minimized = False
层叠_Click ' 将IE窗口恢复为可见位置
End If
End If
End Sub

Private Sub MDIForm_Unload(Cancel As Integer)
' 缺省设置是:退出时释放所有被“绑架”的IE窗口
If Check1.Value = 0 And 释放.Enabled = True Then 释放_Click
End Sub 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值