Link to home
Start Free TrialLog in
Avatar of BeginnerVB_Net
BeginnerVB_Net

asked on

open external application inside picture box

hi ,

iam trying to open an external software like MATLAB  inside one of my form and  i want to open the software inside a frame or picture box  and get it fixed to the picture box or frame.

this is my second question regarding this issue please help me out

ricky
Avatar of mcsd2001
mcsd2001

Hey,

You need to use the API SetParent to change the program parent handle to your form or picture handle....
The trick is getting the right handle for the program....I found that if you start the application using the Process class and get the title and process ID you can get the proper handle for the program.....once thats done you can set the parent....also if you dont want the caption bar at the top you can change the window style to remove it...Ill try to find my code for it...

Hope this helps

Curtis
Avatar of BeginnerVB_Net

ASKER



hey thanks for the reply , can u please mail the sample code to do that , its real urgent for me .

thank you

ricky
Heres the code:

Example: (Code Below)

        Private m_objProcess As ExtProcess

        m_objProcess = New ExtProcess(FileName)
        m_objProcess.Start(ProcessWindowStyle.Hidden)
        m_objProcess.PromptToSaveOnExit = False
        m_objProcess.HideApplication()
        m_objProcess.SetParent(Me.Handle.ToInt32)
        m_objProcess.MoveWindow(0, 0, Me.ClientSize.Width, Me.ClientSize.Height)
        m_objProcess.ShowApplication()

NOTE: You should also call MoveWindow when you resize the form....

Hope this helps


Curtis


***********************************************

Imports System.Runtime.InteropServices

Public Class ExtProcess
    Inherits System.Diagnostics.Process

    <DllImport("user32.dll")> _
    Private Shared Function GetClassName(ByVal hwnd As Integer, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function IsWindowVisible(ByVal hwnd As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function SetForegroundWindow(ByVal hwnd As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function ShowWindow(ByVal hwnd As Integer, ByVal nCmdShow As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function GetWindowThreadProcessId(ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function GetWindow(ByVal hwnd As Integer, ByVal wFlag As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function SetParent(ByVal hWndChild As Integer, ByVal hWndNewParent As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function GetWindowLong(ByVal hwnd As Integer, ByVal nIndex As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function SetWindowLong(ByVal hwnd As Integer, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function MoveWindow(ByVal hwnd As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Integer) As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function PostMessage(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    End Function

    Private Const GWL_STYLE = (-16)
    Private Const WS_DLGFRAME = &H400000
    Private Const WS_CHILD = &H40000000
    Private Const WS_CHILDWINDOW = (WS_CHILD)
    Private Const WS_VSCROLL = &H200000
    Private Const WS_CAPTION = &HC00000
    Private Const WS_BORDER = &H800000
    Private Const WS_THICKFRAME = &H40000
    Private Const WS_SIZEBOX = WS_THICKFRAME
    Private Const GW_HWNDNEXT = 2
    Private Const SW_HIDE = 0
    Private Const SW_RESTORE = 9
    Private Const WM_CLOSE = &H10

    Private m_lngWindowStyle As System.Diagnostics.ProcessWindowStyle
    Private m_lngHandle As Integer
    Private m_blnPromptSave As Boolean

    Public Property PromptToSaveOnExit() As Boolean
        Get
            Return m_blnPromptSave
        End Get
        Set(ByVal Value As Boolean)
            m_blnPromptSave = Value
        End Set
    End Property

    Public ReadOnly Property AppHandle() As Integer
        Get
            Return m_lngHandle
        End Get
    End Property

    Public Sub New(ByVal FileName As String)
        Me.StartInfo.FileName = FileName
    End Sub

    Public Sub New(ByVal FileName As String, ByVal Style As System.Diagnostics.ProcessWindowStyle)
        Me.StartInfo.FileName = FileName
        Me.StartInfo.WindowStyle = Style
        Call StartApplication(Style)
    End Sub

    Public Overloads Sub Start(ByVal Style As System.Diagnostics.ProcessWindowStyle)
        Call StartApplication(Style)
    End Sub

    Public Overloads Sub Start(ByVal FileName As String, ByVal Style As System.Diagnostics.ProcessWindowStyle)
        Me.StartInfo.FileName = FileName
        Me.StartInfo.WindowStyle = Style
        Call StartApplication(Style)
    End Sub

    Public Sub ShowApplication()
        On Error Resume Next
        If Not IsWindowVisible(Me.AppHandle) Then
            ShowWindow(Me.AppHandle, SW_RESTORE)
        End If

        SetForegroundWindow(Me.AppHandle)
    End Sub

    Public Sub HideApplication()
        On Error Resume Next
        If IsWindowVisible(Me.AppHandle) Then
            ShowWindow(Me.AppHandle, SW_HIDE)
        End If
    End Sub

    Private Sub StartApplication(ByVal Style As System.Diagnostics.ProcessWindowStyle)
        On Error Resume Next
        Me.StartInfo.WindowStyle = ProcessWindowStyle.Minimized
        Me.StartInfo.CreateNoWindow = True
        Me.StartInfo.UseShellExecute = True
        Me.Start()
        Me.WaitForInputIdle()

        m_lngHandle = GetAppHandle(Me)

        If Style = ProcessWindowStyle.Hidden Then
            Me.HideApplication()
        Else
            Me.HideApplication()
            Me.ShowApplication()
        End If
    End Sub

    Private Function GetAppHandle(ByRef Process As Process) As Integer
        Dim lngHandle As Integer

        lngHandle = -1

        Do Until lngHandle <> -1
            lngHandle = FindWindow(Process)
            If lngHandle <> -1 Then
                Exit Do
            End If
            Application.DoEvents()
        Loop

        GetAppHandle = lngHandle
    End Function

    Private Function FindWindow(ByRef Process As Process, Optional ByVal Loading As Boolean = True) As Integer
        Dim hWndNext As Integer
        Dim hWnd As Integer
        Dim lngAssocProcessID As Integer
        Dim lngReply As Integer
        Dim strClassName As String

        FindWindow = -1

        If Loading Then If Not WaitForProcess(Process) Then Exit Function

        hWndNext = FindWindow(vbNullString, vbNullString)

        Do
            lngReply = GetWindowThreadProcessId(hWndNext, lngAssocProcessID)

            If lngAssocProcessID = Process.Id Then
                strClassName = GetClassName(hWndNext)
                hWnd = FindWindow(strClassName, Process.MainWindowTitle)
                If hWnd <> 0 Then
                    FindWindow = hWnd
                    Exit Function
                End If
            End If

            hWndNext = GetWindow(hWndNext, GW_HWNDNEXT)

        Loop Until hWndNext = 0

    End Function

    Private Function GetClassName(ByVal hWnd As Integer) As String
        Dim strBuffer As New System.Text.StringBuilder(256)
        GetClassName(hWnd, strBuffer, 256)
        GetClassName = strBuffer.ToString
    End Function

    Private Function WaitForProcess(ByRef Process As Process) As Boolean
        Dim lngTimeout As Long

        lngTimeout = CLng(Now.Ticks / System.TimeSpan.TicksPerSecond) + 30

        Do Until Process.MainWindowTitle <> ""
            Application.DoEvents()
            If CLng(Now.Ticks / System.TimeSpan.TicksPerSecond) > lngTimeout Then Exit Function
        Loop

        WaitForProcess = True
    End Function

    Public Sub SetParent(ByVal NewParentHandle As Integer)
        Dim lngStyle As Integer
        On Error Resume Next

        SetParent(Me.AppHandle, NewParentHandle)

        lngStyle = GetWindowLong(Me.AppHandle, GWL_STYLE)
        lngStyle = lngStyle Xor WS_CAPTION
        lngStyle = lngStyle Xor WS_SIZEBOX

        SetWindowLong(Me.AppHandle, GWL_STYLE, lngStyle)
    End Sub

    Public Sub MoveWindow(ByVal Left As Integer, ByVal Top As Integer, ByVal Width As Integer, ByVal Height As Integer)
        On Error Resume Next
        Call MoveWindow(Me.AppHandle, Left, Top, Width, Height, 1)
    End Sub

    Public Sub StopProcess()
        On Error Resume Next
        PostMessage(m_lngHandle, WM_CLOSE, IIf(m_blnPromptSave, 1, 0), 0)
        m_lngHandle = FindWindow(Me, False)
        If m_lngHandle <> -1 Then
            Me.Kill()
        End If
        m_lngHandle = 0
    End Sub

    Protected Overrides Sub Finalize()
        Call StopProcess()
        MyBase.Finalize()
    End Sub
End Class


thanks for the code ill try it out  and let u know


ricky


hello curtis ,

The code works perfectly i just need to know how to do little change in it , i am trying to open an external software (PSPICE)
inside the picture box, so i  created a picture box and changed the code replacing "me"  "with picturebox1" in the intial code.

             The problem i face now is that the application does not fit exactly to the size of the picture box and it opens in some other location inside the picture box so i need to open the application window to the size of the picture box.

one more thing i want to do is to show the title bar to the user with a new caption  , hiding all the min,max and close button.

ricky

Ricky,

Ill make the changes and send you the new code.

Curtis
ASKER CERTIFIED SOLUTION
Avatar of mcsd2001
mcsd2001

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial


hi curtis thanks for the new code it works perfectly , the window resizes exactly to the size of the picture box,
but i have the  same problem now which i had in the beginnning when i first put the query in this forum .

The application which opens in the picture box is not embedded or fixed to the form , the application is such that it can be movable by the user by dragging the application using the title bar inside the picture box itself.
          The application just moves inside the picture box .

One more thing is when the form is run , iam able to see the application opening in the taskbar and then it gets hidden
can it be opened in the invisible mode itself.

thank u
ricky
Ricky,

I am trying to see if i can open invisible without seeing it in the taskbar...i will let you know asap....for the other problem, im not getting what you would like it to do...do you want the program to move inside the form like a mdi form of just be fixed..

Let me know,

Curtis



hi curtis,

yes i want the program which opens in the picture box to be fixed and should not move inside the mdi form

ricky


hello curtis ,

did u find the code , let me know

ricky