Announcement

Collapse
No announcement yet.

Let any exe run in your DDT Dialog

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Let any exe run in your DDT Dialog

    Hi there,

    below is a code snippet which embeds the Explorer in a DDT dailog.
    Pls let me know what you think about it.

    rgds
    Ralph

    Code:
    $COMPILE EXE
    $REGISTER NONE
    $INCLUDE "WIN32API.INC"
    
    FUNCTION cbEnum(BYVAL hWnd AS LONG, lpszTitle AS ASCIIZ PTR) AS LONG
    
        GetWindowText hWnd, @lpszTitle, 256
        IF INSTR(@lpszTitle, "Explorer") THEN
           @lpszTitle = STR$(hWnd)
           FUNCTION = %false
           EXIT FUNCTION
        END IF
        FUNCTION = %true
    
    END FUNCTION
    
    
    CALLBACK FUNCTION dlg_main
        LOCAL  szTitle     AS ASCIIZ * 256
        LOCAL  styleSearch AS LONG
        LOCAL  R   AS Rect
    
        STATIC hwndSearch  AS LONG
    
        SELECT CASE CBMSG
            CASE %WM_initdialog
    '             try with iexplorer
    '             SHELL "C:\Programme\Internet Explorer\Iexplore.exe"
    '             apisleep 2000
                 ''' hardcoded path pls modify
                 SHELL "C:\WinNt\explorer.exe"
                 ''' give explorer time to start
                 apisleep 500
                 ''' find the explorer window handle
                 EnumWindows CODEPTR(cbEnum), VARPTR( szTitle )
                 hwndSearch  = VAL(szTitle)
                 
                 ''' make it parent of our dialog
    '             styleSearch = getwindowlong ( hwndSearch, %GWL_STYLE )
    '             styleSearch = styleSearch OR %WS_CHILD
                 Setwindowlong hwndSearch, %GWL_STYLE, %WS_CHILD OR %WS_VISIBLE ''styleSearch
                 setparent     hwndSearch, CBHNDL
       
    ''' cosmetics
                 getclientrect CBHNDL, r
                 SetWindowPos  hwndSearch, %HWND_TOP, 0,0, r.nright-r.nleft, r.nbottom - r.ntop, %SWP_FRAMECHANGED
    
            CASE %WM_SIZE
                 IF CBWPARAM = %SIZE_MINIMIZED THEN EXIT FUNCTION
                 MoveWindow hwndSearch, 0, 0, LOWRD(CBLPARAM), HIWRD(CBLPARAM), %true
    
        END SELECT
    
    END FUNCTION
    
    
    FUNCTION PBMAIN AS LONG
    
       LOCAL hDlg AS LONG
       DIALOG NEW 0, "PB captures Explorer",,, 400,200, %WS_CAPTION OR %WS_SYSMENU OR %WS_THICKFRAME TO hdlg
       DIALOG SHOW MODAL hdlg CALL dlg_main
    
       MSGBOX "END"
    
    END FUNCTION


    ------------------

  • #2
    Ralph --

    Your program didn't work for me until I changed the string "Explorer" to "Exploring - C:\" so the program could find the window. I also had to change the sleep from 500 to 1000 ms.

    Also, when you close Explorer your program is left running. You can see it if you start up Task Manager (Ctrl-Alt-Del) and look at the Processes tab.

    Also, the path to Explorer varies from version to version of Windows. There is, of course, no C:\WINNT directory on a 95/98 system.

    What purpose did you have in mind for this technique? It might be more useful if you were to create a smaller window that is a child of the main DDT dialog, and make Explorer a child of the smaller window. That way you could add buttons and other controls around the Explorer subwindow.

    However, it is not generally a good idea to make a window from one process the child of a window from another process. Windows doesn't usually like it when you do that.

    Hmmm... I wonder why the Explorer pulldown menu disappears when it becomes the child of another window.

    -- Eric

    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>



    [This message has been edited by Eric Pearson (edited July 26, 2000).]
    "Not my circus, not my monkeys."

    Comment


    • #3
      Ralph --
      I think, better to integrate a "gift".
      Compile Dll (before correct way to explorer, LCASE !)
      Code:
         #Compile Dll "HookS.Dll"
         #Register None
         #Dim All
         #Include "Win32Api.Inc"
      
         Global hDlg As Long, hHook As Long, hInstDLL As Long, nTest As Long
         Global TmpAsciiz As Asciiz * 256
         Function LibMain(ByVal hInstance As Long, ByVal fwdReason As Long, _
            ByVal lpvReserved As Long) Export As Long
             Select Case fwdReason
               Case %DLL_PROCESS_ATTACH:
                  hInstDLL = hInstance: LibMain = 1
               Case %DLL_PROCESS_DETACH: LibMain = 1
            End Select
         End Function
      
         Function HookProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) Export As Long
            Function = CallNextHookEx(ByVal hHook, ByVal nCode, ByVal wParam, ByVal lParam)
            If ncode = %HSHELL_WINDOWCREATED And nTest = 0 Then
               nTest = 1
               If hDlg = 0 Then
                  GetModuleFileName(GetModuleHandle(ByVal 0), TmpAsciiz, SizeOf(TmpAsciiz)
                  ' sample
                  Select Case LCase$(TmpAsciiz)
                     Case "f:\winnt\explorer.exe"
                        Local hWnd As Long
                        hWnd = FindWindow(ByVal 0&, "My Hook")
                        PostMessage hWnd, %WM_USER + 999, 0, 0
                        Local hDlg1 As Long
                        Dialog New 0, "Gift (at first close me, then explorer)", , , 500, 400, %WS_SYSMENU To hDlg1
                        Dialog Show Modal hDlg1 'Call DlgProc
                     Case Else
                        FreeLibrary hInstDll
                  End Select
               End If
            End If
         End Function
      
         Function SetHook Alias "SetHook" (hWnd As Long) Export As Long
            hDlg = hWnd
            hHook = SetWindowsHookEx (%WH_SHELL, CodePtr(HookProc), ByVal hInstDLL, ByVal 0)
         End Function
      
         Function UnHook Alias "UnHook" Export As Long
            UnhookWindowsHookEx hHook
         End Function
      and start Exe
      Code:
         #Compile Exe
         #Dim All
         #Register None
         #Include "Win32Api.Inc"
      
         Declare Function SetHook Lib "HookS.Dll" Alias "SetHook" (hWnd As Long) As Long
         Declare Function UnHook  Lib "HookS.Dll" Alias "UnHook" As Long
      
         CallBack Function DlgProc
            Local i As Long
            Select Case CbMsg
               Case %WM_INITDIALOG: SetHook CbHndl
                                    i = Shell ("Explorer.Exe", 1)
               Case %WM_SIZE: ShowWindow CbHndl, 0         
               Case %WM_USER + 999: Dialog End CbHndl, 0
               Case %WM_DESTROY   : Unhook
            End Select
         End Function
      
         Function PbMain()
            Local hDlg As Long
            Dialog New 0, "My Hook", 0, 0, 100, 20, %WS_SYSMENU Or %WS_CAPTION, %WS_EX_TOPMOST Or %WS_EX_TOOLWINDOW To hDlg
            Dialog Show Modal hDlg Call DlgProc
         End Function
      This code should explain, what I mean.
      (PS. What about JPG ?)



      [This message has been edited by Semen Matusovski (edited July 26, 2000).]

      Comment


      • #4
        Eric,

        i'd converted NASA's HDF to win32. Trying now to write a frontend.
        The hirarchic file system can store any type of data. My frontend
        should run the related app as plugin. There are many non MS progs
        which doesn't support ActiveX ore OLE. So i tried this way.

        Used hardcoded path- and prg. names for the demo. That causesd the
        trouble starting the program. It's not terminating because the
        %WM_CLOSE message isn't forwarded to the child win. Closing it
        via the system menu or ALT F4 will work.

        I'm not very familiar with shell programming. Posted the snippet
        because i'm looking for a way to open the plugin as hidden window
        before "pluging". Any ideas ?

        rgds,
        Ralph



        ------------------

        Comment


        • #5
          Semen,

          thank's for the code.

          Ralph

          ------------------


          [This message has been edited by Ralph Berger (edited July 27, 2000).]

          Comment


          • #6
            > My frontend should run the related app as plugin.
            > There are many non MS progs which doesn't support
            > ActiveX ore OLE. So i tried this way.

            The basic problem (as I see it) is that Windows requires that a window be "serviced" by a message loop that runs in the thread that created the window. So when you connect a window from one process to a window from another process (by making one the child of the other) if a message gets passed up the chain, it ends up being "seen" by a message loop in a different thread.

            > Closing it via the system menu or ALT F4 will work.

            Not on my NT4 system. No matter how I close the program, the Task Manager's "Processes" tab shows it still running after the window disappears.

            -- Eric

            ------------------
            Perfect Sync: Perfect Sync Development Tools
            Email: mailto:[email protected][email protected]</A>



            [This message has been edited by Eric Pearson (edited July 26, 2000).]
            "Not my circus, not my monkeys."

            Comment


            • #7
              Fernando,

              thank you for the code snippet. You told me that your asm routine
              makes any window a child of another window. Trying your source i
              always get a GPF on Windows 98 or Dr. Watson error on NT.

              The snippet below gave you access to whole thread's memory. Could
              you pls explain how you want to alter a createstruct on a already
              opened window ? Never heard about a hack like this.
              I'm very curious.

              Ralph
              Code:
              $COMPILE EXE
              $REGISTER NONE
              $INCLUDE "WIN32API.INC"
              
              
              FUNCTION pluginStart(BYVAL cmdline AS STRING, PI AS PROCESS_INFORMATION  ) AS LONG
              
                  LOCAL SI AS STARTUPINFO CreateProcess
                  LOCAL rc AS LONG, Ec AS LONG
              
                  SI.cb          = SIZEOF(SI)
                  SI.dwFlags     = %STARTF_USESHOWWINDOW
                  SI.wShowWindow = %SW_SHOWMINNOACTIVE
              
                  rc = CreateProcess(BYVAL %Null, _
                                     BYVAL STRPTR(cmdline), _
                                     BYVAL 0&, _
                                     BYVAL 0&, _                'ThreadAttribute
                                     BYVAL 1&, _                'InheritHandle
                                     %NORMAL_PRIORITY_CLASS, _  'CreationFlag
                                     BYVAL %Null, _             'Environment
                                     BYVAL %Null, _             'Current Directory
                                     SI, _                      'StartUpInfo
                                     PI)                        'ProcessInfo
              
                  FUNCTION = rc
              
              END FUNCTION
              
              
              FUNCTION pluginWaitEnd( PI AS PROCESS_INFORMATION  ) AS LONG
              
                 LOCAL lret AS LONG
                 LOCAL ec   AS LONG
              
                 lret = WaitForSingleObject(PI.hProcess, %INFINITE)
                 ec   = 256
              
                 lret = GetExitCodeProcess(PI.hProcess,Ec)
                 lret = CloseHandle(PI.hProcess)
                 FUNCTION = Ec
              
              END FUNCTION
              
              CALLBACK FUNCTION dlg_main
                  LOCAL  szTitle     AS ASCIIZ * 256
                  LOCAL  styleSearch AS LONG
                  LOCAL  R   AS Rect
                  LOCAL LPCREATESTRUCT AS CREATESTRUCT PTR
              
                  STATIC PI AS PROCESS_INFORMATION
              
                  SELECT CASE CBMSG
                      CASE %WM_initdialog
              
                           pluginStart "C:\WinNt\explorer.exe", pi
                           WaitForInputIdle    pi.hProcess, %INFINITE
              '            readprocessMemory   pi.hProcess, lpBaseAddress, lpBuffer, LEN(bUFFER), lpNumberOfBytesRead
                           '''' your code
                           
                           
              '            WriteProcessMemory  pi.hProcess, .........
              
                      CASE %WM_CLOSE
                           MSGBOX "byE"
                           pluginWaitEnd pi
              
                  END SELECT
              
              END FUNCTION
              
              FUNCTION PBMAIN AS LONG
              
                 LOCAL hDlg AS LONG
                 DIALOG NEW 0, "PB captures Explorer",,, 400,200, %WS_CAPTION OR %WS_SYSMENU OR %WS_THICKFRAME TO hdlg
                 DIALOG SHOW MODAL hdlg CALL dlg_main
              
                 MSGBOX "END"
              
              END FUNCTION


              ------------------

              Comment


              • #8
                Hello

                Did you try the WinLIFT "Universal Browser" demo?

                The WinLIFT "Universal Browser" illustrates two powerfull technologies:

                * Integration of ActiveX controls in PowerBASIC applications.
                * WinLIFT "Skin Engine" to give a professionnal touch to your applications.

                --------------------------------------------------------------------------------

                The IE ActiveX control used for the demo is more than a Web browser, it is a Universal Browser:
                It will let you display, print and even program such different types of documents as:

                * HTML pages,
                * Word documents,
                * Excel spreadsheets,
                * Visio drawings,
                * PowerPoint presentations,
                * Shockwave movies,
                * and more...

                ------------------
                Patrice Terrier
                mailto[email protected][email protected]</A>

                [This message has been edited by Patrice Terrier (edited July 28, 2000).]
                Patrice Terrier
                www.zapsolution.com
                www.objreader.com
                Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                Comment


                • #9
                  Hi Semen,

                  I got your hook program crash on my Windows 98 SE!

                  ???


                  ------------------

                  Comment


                  • #10
                    Aisin --
                    I took a hook, designed to log all started apps, and quickly modified it.
                    To demonstrate that DLL is in new process I added in DLL Dialog New.
                    Exactly this (Dialog New ; Dialog Show Modal) crashes Windows98
                    (under Win2000 - no troubles). So delete them and use something else.

                    In general to add modal dialog is wrong idea (it will be two modal loops) and my purpose was another.

                    I wanted to demonstrate that it's very easy to introduce own DLL into shelled process.
                    (BTW, there is a simple way to find top window in new process - wParam in hook procedure).

                    What to do further... (I guess)
                    My experiments, which I did some monthes ago, showed that appears a lot of troubles, if to try to declare external window as child of DDT.
                    But what exactly possible
                    1) to subclass this external window and to try to control it inside
                    (for example, moving/resizing).
                    2) it's easy to set connection beetween DDT and "child".

                    ------------------


                    [This message has been edited by Semen Matusovski (edited July 28, 2000).]

                    Comment


                    • #11
                      Hi there,

                      found this on Microsoft's KB. How about your Italien ?

                      rgds
                      Ralph

                      Code:
                      HOWTO: trasformare una top-level window in child window
                      
                      ID Articolo:       I14766
                      Data creazione:    06-apr-1998
                      Data revisione:    08-apr-1998
                      
                      
                      Le informazioni in questo articolo si applicano a: Microsoft Win32 SDK
                      
                      
                      SOMMARIO
                      Questo articolo illustra come e` possibile trasformare una top-level window
                      di un processo in una child window di un altro processo. Questa operazione
                      puo` essere utile quando si vuole riprodurre l'effetto di un controllo per
                      un'applicazione gia` realizzata e non modificabile.
                      
                      ULTERIORI INFORMAZIONI
                      I passi per eseguire questa operazione sono:
                      - cercare la finestra top-level che si vuole rendere child
                      - rendere la finestra figlia di una finestra della propria applicazione
                        tramite SetParent
                      - modificare lo stile della finestra: togliere WS_OVERLAPPEDWINDOW e
                        WS_BORDER (funzione SetWindowLong)
                      - muovere la finestra per farla coincidere con le dimensioni della finestra
                        parent
                      - forzare il ridisegno della finestra (Invalidate) Segue un esempio che
                        illustra come eseguire questa operazione in MFC con l'applicazione Blocco
                        Note (Notepad):
                      
                        void CSetParentDlg::OnSetChild() {
                          pWnd = CWnd::FindWindow(NULL, _T("Senza nome - Blocco Note"));
                          if (pWnd != NULL)
                              CWnd* pPrevParent = pWnd->SetParent(&m_Rect);
                              ASSERT(pPrevParent);
                              long Style = ::GetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE);
                              SetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE, Style & ~WS_BORDER &
                              ~WS_OVERLAPPEDWINDOW);
                              pWnd->SetMenu(NULL);
                              CRect r;
                              m_Rect.GetClientRect(&r);
                              pWnd->MoveWindow(&r, true);
                              pWnd->BringWindowToTop();
                              pWnd->Invalidate();
                          else
                              AfxMessageBox("Window not found");
                      }
                      
                      Questo codice funziona in Windows NT. In Windows 95 la finestra viene resa
                      figlia, ma la barra del titolo e i bordi della finestra rimangono perche`,
                      secondo le informazioni in Q83366, alcuni stili di finestra, fra cui
                      WS_CAPTION e WS_BORDER, non possono essere cambiati dopo che la finestra
                      e` gia` stata creata. Per togliere la barra del titolo anche in Windows 95
                      e` necessario intervenire tramite un hook in fase di creazione della
                      finestra (vedi oltre).
                      
                      MIGLIORAMENTO DEL REPAINT
                      La soluzione esposta evidenzia talvolta problemi di repaint. Questi problemi
                      possono essere risolti usando gli stili di clipping in modo opportuno. Segue
                      un esempio SDK:
                      
                      hNotePad = FindWindow("Notepad",NULL);
                      SetWindowLong(hNotePad,GWL_STYLE,WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
                      SetParent(hNotePad,hDlg);
                      SetWindowPos(hNotePad,NULL,10,30,300,200,SWP_NOACTIVATE|SWP_SHOWWINDOW);
                      
                      UTILIZZO DI UN HOOK
                      Per poter impostare a piacimento gli stili e` necessario poter intervenire
                      in fase di creazione della finestra. Questo puo` essere fatto tramite un
                      CBT hook. I passi da seguire sono i seguenti:
                      - installare un hook di tipo CBT nella propria applicazione (funzione SetWindowsHookEx
                        con argomento WH_CBT)
                      - far partire l'applicazione di cui si vuol rendere figlia la top-level window
                        nella hook procedure, monitorare i messaggi di tipo HCBT_CREATEWND
                      - quando il messaggio viene ricevuto, modificare gli stili della finestra e
                        renderla figlia disinstallare l'hook
                      
                      RIFERIMENTI
                      
                      Win32 Programmer's Reference, chapter 8: Hooks
                      Q83366 "Value Returned by GetWindowLong(hWnd, GWL_STYLE)" in Microsoft
                      Knowledge Base


                      ------------------

                      Comment


                      • #12
                        Ralph --
                        I don't know Italian language, but idea is obvious without translation.
                        Authors want to use WH_CBT hook.
                        I agree that it's very powerful hook, but performance ...
                        Ok, anyway this is CBT hook' sample.
                        Code:
                           #Compile Exe
                           #Dim All
                           #Register None
                           #Include "Win32Api.Inc"
                        
                           Global hHook As Long
                        
                           Function SBProc(ByVal lMsg As Long, ByVal wParam As Long, _
                              ByVal lParam As Long) As Long
                             If lMsg = %HCBT_ACTIVATE Then
                                SetWindowPos wParam, 0, 100, 100, 0, 0, _
                                   %SWP_NOSIZE Or %SWP_NOZORDER Or %SWP_NOACTIVATE
                                UnhookWindowsHookEx hHook
                             End If
                          End Function
                           
                           Function PbMain
                              Dim hInst As Long
                              hHook = SetWindowsHookEx(%WH_CBT, CodePtr(SBProc), GetModuleHandle(ByVal 0&), _
                                 GetCurrentThreadId)
                              MsgBox "This message box has been positioned at (100,100)."
                           End Function
                        ------------------

                        Comment


                        • #13
                          Ralph --
                          Just now I do approx., about what you asked.
                          In my app something another situation, but methods, which I used could be useful to solve a discussion question.
                          To demonstrate this technique I modified my hook sample (which doesn't exist in real app).

                          Could be problems exactly with this code, but looking to living app, can say that all questions have a decision.

                          If you will start under 9x, probably (I didn't test) you will need to add SetParent CaptWnd, 0 before exit (as I remember living app).

                          So, DLL:

                          Code:
                             #Compile Dll "Hook.Dll"
                             #Register None
                             #Dim All
                             #Include "Win32Api.Inc"
                          
                             $TrayWndNm = "Any unique name"
                             %NotifyId = %WM_USER + 401
                          
                             Global hHook As Long, hInstDLL As Long
                             Function LibMain(ByVal hInstance As Long, ByVal fwdReason As Long, _
                                ByVal lpvReserved As Long) Export As Long
                                 Select Case fwdReason
                                   Case %DLL_PROCESS_ATTACH: hInstDLL = hInstance: LibMain = 1
                                   Case %DLL_PROCESS_DETACH: LibMain = 1
                                End Select
                             End Function
                          
                             Function HookProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) Export As Long
                                Static hDlg As Long, NotFirstTime As Long
                                Function = CallNextHookEx(ByVal hHook, ByVal nCode, ByVal wParam, ByVal lParam)
                                If hDlg = 0 Then hDlg = FindWindow("", $TrayWndNm)
                                If IsWindow(hDlg) = %False Then
                                   FreeLibrary hInstDll
                                ElseIf (nCode = %HCBT_ACTIVATE) And (wParam <> hDlg) Then
                                   If IsFalse(NotFirstTime) Then
                                      NotFirstTime = %True
                                      Local pt As POINTAPI, hRgn As Long, rcW As RECT, rcC As RECT
                                      GetWindowRect wParam, rcW
                                      GetClientRect wParam, rcC
                                      ClientToScreen wParam, pt
                                      pt.x = pt.x - rcW.nLeft
                                      pt.y = pt.y - rcW.nTop
                                      hRgn = CreateRectRgn(pt.x, pt.y, pt.x + rcC.nRight, pt.y + rcC.nBottom)
                                      SetWindowRgn wParam, hRgn, %True
                                      PostMessage hDlg, %NotifyId, wParam, 0
                                   End If
                                End If
                             End Function
                          
                             Function SetHookWindow Alias "SetHookWindow" (hWnd As Long) Export As Long
                                hHook = SetWindowsHookEx (%WH_CBT, CodePtr(HookProc), ByVal hInstDLL, ByVal 0)
                             End Function
                          
                             Function UnHookWindow Alias "UnHookWindow" Export As Long
                                UnhookWindowsHookEx hHook
                             End Function
                          Exe

                          Code:
                             #Compile Exe
                             #Dim All
                             #Register None
                             #Include "Win32Api.Inc"
                          
                             $TrayWndNm = "Any unique name"
                             %NotifyId = %WM_USER + 401
                          
                             Declare Function SetHookWindow Lib "Hook.Dll" Alias "SetHookWindow" (hWnd As Long) As Long
                             Declare Function UnHookWindow Lib "Hook.Dll" Alias "UnHookWindow" As Long
                          
                             CallBack Function DlgProc
                                Static CaptWnd As Long
                                Select Case CbMsg
                                   Case %WM_INITDIALOG
                                      SetHookWindow CbHndl
                                      Dim i As Long
                                      i = Shell ("notepad.exe", 1)
                                   Case %WM_SYSCOMMAND
                                      If CbWparam = %SC_CLOSE Then DestroyWindow CaptWnd
                                   Case %NotifyId
                                      CaptWnd = CbWparam
                                      UnHookWindow
                                      SetParent CaptWnd, CbHndl
                                      ShowWindow CbHndl, %SW_SHOW
                                      Function = 1: Exit Function
                                End Select
                             End Function
                          
                             Function PbMain
                                Local hDlg As Long
                                Dialog New 0, $TrayWndNm, , , 200, 200, _
                                   %WS_CAPTION Or %WS_SYSMENU Or %WS_THICKFRAME Or %WS_CLIPCHILDREN Or %WS_CLIPSIBLINGS Or _
                                   %WS_MINIMIZEBOX Or %WS_MAXIMIZEBOX, %WS_EX_TOPMOST To hdlg
                                ShowWindow hDlg, %SW_MAXIMIZE
                                Dialog Show Modal hDlg Call DlgProc
                             End Function
                          ------------------
                          E-MAIL: [email protected]

                          Comment

                          Working...
                          X