65.9K
CodeProject 正在变化。 阅读更多。
Home

绕过困难的自动化,并将应用程序“原样”添加到你的 .NET 应用程序中

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.40/5 (29投票s)

2004年11月29日

CPOL

4分钟阅读

viewsIcon

158241

downloadIcon

2953

厌倦了自动化? 需要将组件原样添加到你的应用程序中? 试试这个。

引言

我被赋予了很多自动化的任务,我真的厌倦了它们。 有一次,我的经理要求我自动化 IE,使其在我们的应用程序中,让用户感觉它就是应用程序的 IE 浏览器。 还有一天,我被要求添加 Word 控件,并在应用程序中创建一个具有 Word 外观和相同工具栏的窗口。 所以我当时认为,一定有一种方法可以在 Dotnet 中“原样”添加应用程序,并与它们进行某种通信。

注意:当然,通过自动化实现的那种灵活性无法通过这种方式实现。 但是,"根据需求",它可以缩短上市时间,并防止添加繁重的自动化代码和 DLL。

使用代码

我展示了如何轻松地将不同的应用程序添加到控件或窗体中。 如果你将其添加到窗体中,用户会感觉到它将变成一种 MDI 应用程序,其中包含其他应用程序。 第一个演示应用程序展示了如何添加命令提示符、Internet Explorer、Windows Media Player 和 WinWord。 第二个应用程序展示了如何与它们交互。

添加应用程序演示

在这种情况下使用的主要函数来自 user32。 它们是 SetParentShowWindowSetForegroundWindow。 其余的帮助由托管的 ProcessProcessInfoSendKeys 类提供。

Declare Function ShowWindow Lib "user32" (ByVal hWnd As System.IntPtr, 
        ByVal nCmdShow As Integer) As Boolean
Declare Function SetParent Lib "user32" (ByVal hWndChild As System.IntPtr,
        ByVal hWndNewParent As System.IntPtr)
        As System.IntPtr
Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As System.IntPtr)
                As Integer

以下代码写在 "Open -> Command Prompt -> Open as Normal and Add as Min" 菜单上。 它使用 Process.Start() 正常打开命令窗口,然后使用 ShowWindow 函数将其作为子窗口添加到父窗口(这是一个 .NET 窗口)并使其状态最小化。

Dim pinfo As New ProcessStartInfo("cmd")
Dim p As Process = System.Diagnostics.Process.Start(pinfo)
SetParent(p.MainWindowHandle, Me.Handle)
ShowWindow(p.MainWindowHandle, SW_MINIMIZE)

第二个菜单是 Open -> Get Running Browser and make it full screen。 你必须至少打开一个 IE 窗口才能使用此功能。 它捕获它并将其作为最大化添加到主窗体中。 关闭应用程序也会关闭此窗口。

Dim p As Process() = System.Diagnostics.Process.GetProcessesByName("iexplore")
Try
    SetParent(p(0).MainWindowHandle, Me.Handle)
    ShowWindow(p(0).MainWindowHandle, SW_MAXIMIZE)
Catch ex As Exception
    MessageBox.Show("No IE window open - Please open one")
End Try

第三个菜单是打开 Media Player 并将其添加到按钮并播放 XP Media 目录中存在的文件。 Open -> Media Player - in a Button - Max。 另一个有趣的点是,Media 文件夹没有列在 Enviornment.SpecialFolders 中。 所以你必须像我下面使用的那样获取它

Dim p As Process = System.Diagnostics.Process.Start("mplayer2", 
Environment.GetEnvironmentVariable("WINDIR") + "\\Media\\Windows XP Startup.wav")
p.WaitForInputIdle()
SetParent(p.MainWindowHandle, Me.Button1.Handle)
ShowWindow(p.MainWindowHandle, SW_MAXIMIZE)

第四个也是最后一个菜单是添加 WinWord 并将其添加到 Label 中。 Open -> WinWord - In a Label。 WaitForInputIdle 有助于使 Winword 进入空闲状态。

Dim pinfo As New ProcessStartInfo("WINWORD")
Dim p As Process = System.Diagnostics.Process.Start(pinfo)
p.WaitForInputIdle()
SetParent(p.MainWindowHandle, Me.Label1.Handle)

与应用程序交互 (Calc.exe 和 IE)

运行演示。 使用演示外部的 IE 窗口打开任何网站。 单击“Get Running IE Window”。 它将获取正在运行的 IE 窗口实例并将其添加到控件,并获取其 HTMLDocument 并在 TextBox 中显示所有源。 它还将在按钮旁边的标签上显示其标题。 单击“Open Calc”按钮。 它将在用户窗口中打开计算器。 进行所有计算并关闭计算器。 结果将返回到“Open Calc”按钮旁边的 TextBox。

IE 演示重要点

IE 演示使用 IEDom 类来检索 IE 窗口的 DOM。 IsIEServerWindow 函数查找 Internet Explorer_Server 类。 使用 RegisterWindowMessage Win32 调用将 WM_HTML_GETOBJECT 消息发送到 Windows 句柄。 然后使用 ObjectFromLresult 函数获取 IHTMLDocument 对象。

If Not IsIEServerWindow(hWnd) Then

   ' Get 1st child IE server window
   win32.EnumChildWindows(hWnd, AddressOf EnumChild, hWnd)

End If

If Not hWnd.Equals(0) Then

  ' Register the message
  lMsg = win32.RegisterWindowMessage("WM_HTML_GETOBJECT")

  ' Get the object
  Call win32.SendMessageTimeout(hWnd, lMsg, 0, 0, _
  win32.SMTO_ABORTIFHUNG, 1000, lRes)

  If lRes Then

    ' Get the object from lRes
    hr = ObjectFromLresult(lRes, IID_IHTMLDocument, 0, IEDOMFromhWnd)

    If hr Then Throw New COMException(hr)

     End If 
  End If
End If

还使用 RemoveMenuBar 函数来删除 IE Rebar。

If ClassName.ToString() = "ReBarWindow32" Then
  ' Hide menuBar
  win32.ShowWindow(hWnd, 0)
  Return 0
Else
  Return 1
End If
Calc 演示重要点

ExteranlCalc 窗体在加载时打开 calc.exe 并将其添加到自身。 removeTitleBarAndRescale 函数用于删除标题栏,停止调整大小。 SetWindowPos 函数用于设置窗口的位置并将其放置在隐藏 calc 菜单栏的方式中。

win32.SetParent(p.MainWindowHandle, Me.Handle)
win32.removeTitleBarAndRescale(p.MainWindowHandle)
win32.SetWindowPos(p.MainWindowHandle, Me.Handle, -LEFT_CONST,
             -TOP_CONST, Me.Width + LEFT_CONST + RIGHT_CONST, 
             Me.Height + TOP_CONST + BOTTOM_CONST, 
win32.SWP_FRAMECHANGED Or win32.SWP_NOZORDER)
注意:我已经在标准计算器上进行了测试。 如果你想显示科学计算器,请调整 ExternalCalc 窗体的大小。 你也可以使用 SendKeys 以任何形式显示计算器。 演示中尚未完成所有场景中的错误检查。

关注点

这是一种在基于 .NET 的应用程序中添加应用程序的非常简单的方法。 感谢微软做出了这样的东西 :)

修订历史

12-29-2004:

  • 添加了一张带有计算器和 IE 控件及其交互的图片。
  • 添加了计算器和 IE 演示的源代码。

11-29-2004:

  • 原文
© . All rights reserved.