can anyone help me with this simple problem.. I want to embed program into the my vb form..
is it possible?

its kinda like in the picture.

Attachments help.png 108.45 KB

Is this a separate application or just another form in your program? If it's the latter then you can do what you want with an MDI setup. If it's the former then I'm not going to say you can't do it, but the concept is like saying "I want to subvert the design of Windows and do something completely different using the system's API", which is likely to be either not possible or wholely impractical.

I'll welcome any corrections, because that would be a nifty feature, but it strikes me as the wrong approach to whatever problem you have.

It can be done. However, the sucess of the implementation depends on how dependent the hosted program is on being parented to the Desktop Window and how good the developer is at developing workarounds for those dependencies. A program like Notepad is trival while hosting MS Word can make you want to cry out for your mamma.

That said, here is an example of my attempt at writing a generic Panel derived control for hosting an application.

Use this code at your own risk, Do not expect me to provide any support or explanation of its workings.

I have relegated further work on this type of endeavor to only be done when I have nothing better to do, like beat myself in the head with a lead pipe.

Start off with a new WinForm application. Add new class and replace its generated code with this.

Imports System.Runtime.InteropServices

Public Class HostApplicationPanel
   Inherits Panel
   Private Const WM_Close As Int32 = &H10
   Private AppProcess As Process
   Private AttachedToFormClosing As Boolean = False

   Public Sub StartApplication()
      If Not AttachedToFormClosing Then
         AttachedToFormClosing = True
         AddHandler Me.FindForm.FormClosing, AddressOf MyFormClosing
      End If

      If AppProcess IsNot Nothing AndAlso Not String.IsNullOrEmpty(AppProcess.MainModule.FileName) Then
         Select Case MessageBox.Show("Terminate " & AppProcess.MainModule.FileName & " ?", "Panel Has Application", MessageBoxButtons.YesNoCancel)
            Case DialogResult.Yes
               CloseApplication()
               AppProcess.Close()
            Case DialogResult.No
               Exit Sub
         End Select
      End If
      ApplicationStartInfo.CreateNoWindow = False
      ApplicationStartInfo.WindowStyle = ProcessWindowStyle.Maximized
      Try
         AppProcess = Process.Start(ApplicationStartInfo)

      Catch ex As Exception
         MsgBox(ex.Message)
         Exit Sub
      End Try

      AppProcess.WaitForInputIdle(5000) 'Give application a max of 5 seconds to return InputIdle
         'Debug.WriteLine(Me.Name.Trim & ", MainHwnd = " & AppProcess.MainWindowHandle.ToString)

      If AppProcess.HasExited Then
         Dim p() As Process = Process.GetProcesses
         For i As Int32 = 0 To UBound(p)
            Debug.WriteLine(i.ToString & " - " & p(i).ProcessName)
         Next
         Dim wd() As Process = Process.GetProcessesByName(ApplicationStartInfo.FileName)
         'don't attach to a terminated process
         Exit Sub
      Else
         Debug.WriteLine(Me.Name.Trim & ", MainHwnd = " & AppProcess.MainWindowHandle.ToString)
         SetWindowForNoResize(AppProcess.MainWindowHandle)
         Dim NewStyle As Int32
         NewStyle = GetWindowLongPtr(AppProcess.MainWindowHandle, WindowLongFlags.GWL_STYLE).ToInt32
         'Remove Caption, MaximizeBox, Minimize Box
         'Caption is removed in some apps like Notepad, but not MSWord
         'Removal of Minimize & Maximize is to prevent wierd behavior of 
         'Maximizing the form versus the application as Word does.
         'This does not prevent the double clicking in the caption (if it persists) to 
         'perform the maximization/restore function
         NewStyle = NewStyle And (Not WS_CAPTION) And (Not WS_MAXIMIZEBOX) And (Not WS_MINIMIZEBOX)
         SetWindowLongPtr(AppProcess.MainWindowHandle, WindowLongFlags.GWL_STYLE, New IntPtr(NewStyle))

         'Set App Parent Window to Me
         Dim OldParent As IntPtr = SetParent(AppProcess.MainWindowHandle, Me.Handle)
         ResizeAppToFitInMe()
      End If


   End Sub

   Private _ApplicationStartInfo As New ProcessStartInfo With {.WindowStyle = ProcessWindowStyle.Minimized}
   <MonitoringDescription("ProcessStartInfo"), System.ComponentModel.Browsable(True), _
   System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Content)> _
   Public Property ApplicationStartInfo() As ProcessStartInfo
      Get
         Return _ApplicationStartInfo
      End Get
      Set(ByVal value As ProcessStartInfo)
         _ApplicationStartInfo = value
      End Set
   End Property 'ApplicationStartInfo

   Private OriginalWindowStyle As Int32
   Private _AllowResizingofPanel As Boolean = False
   Public Property AllowResizingofPanel() As Boolean
      Get
         Return _AllowResizingofPanel
      End Get
      Set(ByVal value As Boolean)
         _AllowResizingofPanel = value
         If value Then
            SetWindowForResize(Me.Handle, True, OriginalWindowStyle)
         Else
            SetWindowForResize(Me.Handle, False, OriginalWindowStyle)
         End If
      End Set
   End Property 'AllowSizePanle

   Friend Const SWP_NOSIZE As Int32 = &H1
   Friend Const SWP_NOZORDER As Int32 = &H4
   Friend Const SWP_NOMOVE As Int32 = &H2
   Friend Const SWP_DRAWFRAME As Int32 = &H20
   Friend Const SWP_FRAMECHANGED As Int32 = &H20
   Friend Const SWP_NOOWNERZORDER As Int32 = &H200

   Friend Sub SetWindowForResize(ByVal handle As IntPtr, ByVal allowresize As Boolean, ByRef OriginalStyleSetting As Int32)
      Dim NewStyle As Int32 = GetWindowLong(handle, GWL_STYLE)
      If allowresize Then
         NewStyle = NewStyle Or WS_SIZEBOX
      Else
         NewStyle = OriginalStyleSetting
      End If
      OriginalStyleSetting = SetWindowLong(handle, GWL_STYLE, NewStyle)
      SetWindowPos(handle, IntPtr.Zero, 0, 0, 0, 0, _
                   SWP_NOZORDER Or SWP_NOSIZE Or SWP_NOMOVE _
                   Or SWP_FRAMECHANGED Or SWP_NOOWNERZORDER)

   End Sub

   Friend Sub SetWindowForNoResize(ByVal handle As IntPtr)
      Dim NewStyle As Int32 = GetWindowLongPtr(handle, WindowLongFlags.GWL_STYLE).ToInt32 And (Not WS_SIZEBOX)
      SetWindowLongPtr(handle, WindowLongFlags.GWL_STYLE, New IntPtr(NewStyle))
      SetWindowPos(handle, IntPtr.Zero, 0, 0, 0, 0, _
                   SWP_NOZORDER Or SWP_NOSIZE Or SWP_NOMOVE _
                   Or SWP_FRAMECHANGED Or SWP_NOOWNERZORDER)

   End Sub

   <DllImport("user32.dll", ExactSpelling:=True, CharSet:=CharSet.Auto)> _
   Private Shared Sub SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Int32, ByVal Y As Int32, ByVal CX As Int32, ByVal CY As Int32, ByVal wFlags As Int32)
   End Sub

   Private Const WS_MAXIMIZEBOX As Int32 = &H10000
   Private Const WS_MINIMIZEBOX As Int32 = &H20000
   Private Const GWL_STYLE As Int32 = (-16)
   Private Const WS_CAPTION As Int32 = &HC00000
   Private Const WS_SIZEBOX As Int32 = &H40000

   <DllImport("user32.dll", SetLastError:=True)> _
   Private Shared Function GetWindowLong(ByVal hWnd As IntPtr, _
                                         <MarshalAs(UnmanagedType.I4)> ByVal nIndex As Int32) _
                                         As Int32
   End Function

   <DllImport("user32.dll")> _
   Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, _
                                         <MarshalAs(UnmanagedType.I4)> ByVal nIndex As Int32, _
                                         ByVal dwNewLong As Int32) As Int32
   End Function

   Private Sub MyFormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
      If AppProcess IsNot Nothing AndAlso Not AppProcess.HasExited Then
         CloseApplication()
      End If
   End Sub

   Private Sub CloseApplication()
      SendMessage(AppProcess.MainWindowHandle, WM_Close, IntPtr.Zero, IntPtr.Zero)
   End Sub

   Protected Overrides Sub OnResize(ByVal eventargs As System.EventArgs)
      MyBase.OnResize(eventargs)
      If AppProcess IsNot Nothing Then ResizeAppToFitInMe()
   End Sub

   Sub ResizeAppToFitInMe()
      MoveWindow(AppProcess.MainWindowHandle, 0, 0, Me.ClientSize.Width, Me.ClientSize.Height, True)
   End Sub

    <DllImport("user32.dll")> _
    Public Shared Function MoveWindow(ByVal hWnd As IntPtr, ByVal x As Int32, ByVal y As Int32, ByVal nWidth As Int32, ByVal nHeight As Int32, ByVal bRepaint As Boolean) As Boolean
    End Function

   <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
   Public Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
   End Function

   <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
   Private Shared Function SendMessage( _
            <MarshalAs(UnmanagedType.SysUInt)> ByVal hWnd As IntPtr, _
            <MarshalAs(UnmanagedType.U4)> ByVal Msg As Int32, _
            <MarshalAs(UnmanagedType.SysUInt)> ByVal wParam As IntPtr, _
            <MarshalAs(UnmanagedType.SysUInt)> ByVal lParam As IntPtr) As IntPtr
   End Function


#Region "SetWindowLongPtr"
   <System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="SetWindowLong")> _
   Private Shared Function SetWindowLong32(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.I4)> ByVal nIndex As WindowLongFlags, ByVal dwNewLong As Integer) As Integer
   End Function

   <System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="SetWindowLongPtr")> _
   Private Shared Function SetWindowLongPtr64(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.I4)> ByVal nIndex As WindowLongFlags, ByVal dwNewLong As IntPtr) As IntPtr
   End Function

   Private Shared Function SetWindowLongPtr(ByVal hWnd As IntPtr, ByVal nIndex As WindowLongFlags, ByVal dwNewLong As IntPtr) As IntPtr
      If IntPtr.Size = 8 Then
      Return SetWindowLongPtr64(hWnd, nIndex, dwNewLong)
      Else
      Return New IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32))
      End If
   End Function
#End Region

#Region "GetWindowLongPtr"
   <DllImport("user32.dll", EntryPoint:="GetWindowLong")> _
   Private Shared Function GetWindowLong32(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.I4)> ByVal nIndex As WindowLongFlags) As IntPtr
   End Function

   <DllImport("user32.dll", EntryPoint:="GetWindowLongPtr")> _
   Private Shared Function GetWindowLongPtr64(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.I4)> ByVal nIndex As WindowLongFlags) As IntPtr
   End Function

   Private Shared Function GetWindowLongPtr(ByVal hWnd As IntPtr, ByVal nIndex As WindowLongFlags) As IntPtr
      If IntPtr.Size = 8 Then
         Return GetWindowLongPtr64(hWnd, nIndex)
      Else
         Return GetWindowLong32(hWnd, nIndex)
      End If
   End Function
#End Region

   Public Enum WindowLongFlags As Integer
      GWL_EXSTYLE = -20
      GWLP_HINSTANCE = -6
      GWLP_HWNDPARENT = -8
      GWL_ID = -12
      GWL_STYLE = -16
      GWL_USERDATA = -21
      GWL_WNDPROC = -4
      DWLP_USER = &H8
      DWLP_MSGRESULT = &H0
      DWLP_DLGPROC = &H4
   End Enum
End Class

Build the project. Go back to Form1 and open the Toolbox; you should now see a "HostApplicationPanel" control neat the top of the Toolbox. Drag it to the Form like a normal Panel control. Double left-click on the form to bring up the Form's Load handler code and add the statements shown below to it.

Public Class Form1
   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      With HostApplicationPanel1
         .ApplicationStartInfo = New ProcessStartInfo("notepad.exe")
         .AllowResizingofPanel = True ' Allows you use the resizing grips
         .StartApplication()
      End With
   End Sub
End Class

Run the program and enjoy.

SetParent() is evil (at least the way most people try to use it). It's throwback support for a Windows 3.1 hack, and the behavior is especially wacky in WinForms. Strongly not recommended, which is why I didn't even mention it. ;)

This article has been dead for over six months. Start a new discussion instead.