File: n_parent.sru
Size: 7074
Date: Tue, 13 Apr 2021 20:43:04 +0200
$PBExportHeader$n_parent.sru
forward
global type n_parent from nonvisualobject
end type
type process_information from structure within n_parent
end type
type startupinfo from structure within n_parent
end type
end forward

type process_information from structure
   long     hprocess
   long     hthread
   unsignedlong      dwprocessid
   unsignedlong      dwthreadid
end type

type startupinfo from structure
   unsignedlong      cb
   string      lpreserved
   string      lpdesktop
   string      lptitle
   unsignedlong      dwx
   unsignedlong      dwy
   unsignedlong      dwxsize
   unsignedlong      dwysize
   unsignedlong      dwxcountchars
   unsignedlong      dwycountchars
   unsignedlong      dwfillattribute
   unsignedlong      dwflags
   unsignedinteger      wshowwindow
   unsignedinteger      cbreserved2
   long     lpreserved2
   long     hstdinput
   long     hstdoutput
   long     hstderror
end type

global type n_parent from nonvisualobject autoinstantiate
end type

type prototypes
Subroutine SleepMS ( &
   ulong dwMilliseconds &
   ) Library "kernel32.dll" Alias For "Sleep"

Function long GetDesktopWindow ( &
   ) Library "user32.dll"

Function long GetWindow ( &
   long hWnd, &
   ulong uCmd &
   ) Library "user32.dll"

Function long GetWindowText ( &
   long hWnd, &
   Ref string lpString, &
   long nMaxCount &
   ) Library "user32.dll" Alias For "GetWindowTextW"

Function long GetWindowThreadProcessId ( &
   long hWnd, &
   Ref long lpdwProcessId &
   ) Library "user32.dll"

Function long SetParent ( &
   long hWndChild, &
   long hWndNewParent &
   ) Library "user32.dll"

Function boolean MoveWindow ( &
   long hWnd, &
   long xpos, &
   long ypos, &
   long nWidth, &
   long nHeight, &
   boolean bRepaint &
   ) Library "user32.dll"

Function boolean ShowWindow ( &
   long hWnd, &
   long nCmdShow &
   ) Library "user32.dll"

Function Long SetWindowLong( &
   long hWnd, &
   long nIndex, &
   ulong dwNewLong &
   ) Library "user32.dll" Alias For "SetWindowLongW"

Function boolean CreateProcess ( &
   string lpApplicationName, &
   Ref string lpCommandLine, &
   long lpProcessAttributes, &
   long lpThreadAttributes, &
   boolean bInheritHandles, &
   ulong dwCreationFlags, &
   long lpEnvironment, &
   string lpCurrentDirectory, &
   STARTUPINFO lpStartupInfo, &
   Ref PROCESS_INFORMATION lpProcessInformation &
   ) Library "kernel32.dll" Alias For "CreateProcessW"

Function Boolean CloseHandle ( &
   long hObject &
   ) Library "kernel32.dll"

end prototypes
type variables
Constant Long STARTF_USESHOWWINDOW  = 1
Constant Long CREATE_NEW_CONSOLE    = 16
Constant Long NORMAL_PRIORITY_CLASS = 32
Constant Long SW_HIDE      = 0
Constant Long SW_NORMAL    = 1
Constant Long GWL_STYLE    = -16
Constant ULong GW_HWNDNEXT = 2
Constant ULong GW_OWNER    = 4
Constant ULong GW_CHILD    = 5
Constant ULong WS_POPUP    = 2147483648
Constant ULong WM_SIZE     = 5
Constant ULong WM_CLOSE    = 16

Long il_hWnd
String is_commandline

end variables
forward prototypes
public subroutine of_resize (integer newwidth, integer newheight)
public subroutine of_close ()
public function string of_getwindowtext ()
public function boolean of_attach (window aw_parent, string as_commandline)
public function boolean of_attach (long al_hwnd, integer ai_width, integer ai_height, string as_commandline)
public function boolean of_attach (dragobject ado_parent, string as_commandline)
public subroutine of_resize (integer newwidth, integer newheight)
public subroutine of_close ()
public function string of_getwindowtext ()
public function boolean of_attach (window aw_parent, string as_commandline)
public function boolean of_attach (long al_hwnd, integer ai_width, integer ai_height, string as_commandline)
public function boolean of_attach (dragobject ado_parent, string as_commandline)
end prototypes

public subroutine of_resize (integer newwidth, integer newheight);// Resize the attached window

Long ll_width, ll_height

If il_hWnd > 0 Then
   ll_width  = UnitsToPixels(newwidth, XUnitsToPixels!)
   ll_height = UnitsToPixels(newheight, YUnitsToPixels!)
   MoveWindow(il_hWnd, 0, 0, ll_width, ll_height, True)
End If

end subroutine

public subroutine of_close ();// send the Close event

If il_hWnd > 0 Then
   Send(il_hWnd, WM_CLOSE, 0, 0)
   il_hWnd = 0
End If

end subroutine

public function string of_getwindowtext ();// Get the window text

String ls_wintext

ls_wintext = Space(255)

If GetWindowText(il_hWnd, ls_wintext, 255) = 0 Then
   ls_wintext = is_commandline
End If

Return ls_wintext

end function

public function boolean of_attach (window aw_parent, string as_commandline);// Run an external program and attach the window

Integer li_width, li_height
Long ll_hWnd

ll_hWnd   = Handle(aw_parent)
li_width  = aw_parent.WorkspaceWidth()
li_height = aw_parent.WorkspaceHeight()

Return of_Attach(ll_hWnd, li_width, li_height, as_commandline)

end function

public function boolean of_attach (long al_hwnd, integer ai_width, integer ai_height, string as_commandline);// Run an external program and attach the window

STARTUPINFO lstr_si
PROCESS_INFORMATION lstr_pi
Long ll_null, ll_loop
Long ll_hWnd, ll_hProcess, ll_hThread
ULong lul_CreationFlags
String ls_null

// can't run this twice
If il_hWnd > 0 Then Return False

// initialize arguments
SetNull(ls_null)
lstr_si.cb = 68
lstr_si.dwFlags = STARTF_USESHOWWINDOW
lstr_si.wShowWindow = SW_HIDE
lul_CreationFlags = CREATE_NEW_CONSOLE + NORMAL_PRIORITY_CLASS

// run the external program
If CreateProcess(ls_null, as_commandline, ll_null, &
         ll_null, False, lul_CreationFlags, ll_null, &
         ls_null, lstr_si, lstr_pi) Then
   // close process and thread handles
   CloseHandle(lstr_pi.hProcess)
   CloseHandle(lstr_pi.hThread)

   // find the external program's main window
   for ll_loop = 1 To 100
      // wait 10 milliseconds
      SleepMS(10)
      // walk through all open windows
      ll_hWnd = GetWindow(GetDesktopWindow(), GW_CHILD)
      do until ll_hWnd = 0
         // get the thread/process that owns the window
         ll_hThread = GetWindowThreadProcessId(ll_hWnd, ll_hProcess)
         If ll_hProcess = lstr_pi.dwProcessId Then
            // make sure it is a main window
            If GetWindow(ll_hWnd, GW_OWNER) = 0 Then
               il_hWnd = ll_hWnd
               is_commandline = as_commandline
               SetParent(il_hWnd, al_hWnd)
               SetWindowLong(il_hWnd, GWL_STYLE, WS_POPUP)
               ShowWindow(il_hWnd, SW_NORMAL)
               of_Resize(ai_width, ai_height)
               Return True
            End If
         End If
         ll_hWnd = GetWindow(ll_hWnd, GW_HWNDNEXT)
      loop
   next
End If

Return False

end function

public function boolean of_attach (dragobject ado_parent, string as_commandline);// Run an external program and attach the window

Integer li_width, li_height
Long ll_hWnd

ll_hWnd   = Handle(ado_parent)
li_width  = ado_parent.Width
li_height = ado_parent.Height

Return of_Attach(ll_hWnd, li_width, li_height, as_commandline)

end function

on n_parent.create
call super::create
TriggerEvent( this, "constructor" )
end on

on n_parent.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on