2012-09-05 4 views
5

मैं डेल्फी से एक एप्लिकेशन शुरू करना चाहता हूं, और इसे एक हैंडल प्राप्त करना चाहता हूं, इसलिए मैं एक प्रकार के फ्रेम TFrame पर कहा गया अनुप्रयोग की मुख्य विंडो एम्बेड कर सकता हूं। अब तक मैं कोशिश की है:डेल्फी के साथ एक एप्लिकेशन कैसे शुरू करें और इसे संभालें?

Function TFrmEmbeddedExe.StartNewApplication : Boolean; 
var 
    SEInfo: TShellExecuteInfo; 
    ExitCode : DWORD; 
begin 

    FillChar(SEInfo, SizeOf(SEInfo), 0) ; 
    SEInfo.cbSize := SizeOf(TShellExecuteInfo) ; 
    with SEInfo do 
    begin 
    fMask := SEE_MASK_NOCLOSEPROCESS; 
    Wnd := self.Handle; 
    lpFile := PChar(self.fexecuteFileName) ;// Example could be 'C:\Windows\Notepad.exe' 
    nShow := SW_SHOWNORMAL;//SW_HIDE; 
    end; 

    if ShellExecuteEx(@SEInfo) then 
    begin 
    sleep(1500); 
    self.fAppWnd := FindWindow(nil, PChar(self.fWindowCaption)); //Example : 'Untitled - Notepad' 
    if self.fAppWnd <> 0 then 
    begin 
     Windows.SetParent(self.fAppWnd, SEInfo.Wnd); 
     ShowWindow(self.fAppWnd, SW_SHOWMAXIMIZED); 
     result := true; 
    end 
    else 
     result := false; 

    end 

    else 
    result := false; 
end ; 

ऊपर कोड वास्तव में काम करता है, लेकिन FindWindow आवेदन मैंने शुरू के किसी भी instans मिल जाएगा। मैं उन सटीक इंस्टेंस को एम्बेड करना चाहता हूं जिन्हें मैंने शेलेक्सेटेड किया था। तो अगर नोटपैड दो बार शुरू किया गया था, तो FindWindow का उपयोग करके मैं सही तरीके से कोई रास्ता नहीं प्राप्त कर सकता हूं।

मैं कोशिश की है:

Function TfrmEmbeddedExe.CreateProcessNewApplication : Boolean; 
var 
zAppName: array[0..512] of char; 
StartupInfo: TStartupInfo; 
ProcessInfo: TProcessInformation; 
Res : DWORD; 
DoWait : Boolean; 
begin 
    DoWait := False; 
    StrPCopy(zAppName, self.fexecuteFileName); //'C:\Windows\Notepad.exe' 
    FillChar(StartupInfo, Sizeof(StartupInfo), #0); 
    StartupInfo.cb := Sizeof(StartupInfo); 
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW; 
    StartupInfo.wShowWindow := SW_SHOWNORMAL; 

    if CreateProcess (zAppName, 
    nil, { pointer to command line string } 
    nil, { pointer to process security attributes } 
    nil, { pointer to thread security attributes } 
    false, { handle inheritance flag } 
    CREATE_NEW_CONSOLE or { creation flags } 
    NORMAL_PRIORITY_CLASS, 
    nil, { pointer to new environment block } 
    nil, { pointer to current directory name } 
    StartupInfo, { pointer to STARTUPINFO } 
    ProcessInfo) then { pointer to PROCESS_INF } 
    begin 
    if DoWait then //just set it to false... so it will never enter here 
    begin 
     WaitforSingleObject(ProcessInfo.hProcess, INFINITE); 
     GetExitCodeProcess(ProcessInfo.hProcess, Res); 
    end 
    else 
    begin 
     self.fAppWnd := ProcessInfo.hProcess; 

     Windows.SetParent(self.fAppWnd, self.Handle); 
     ShowWindow(self.fAppWnd, SW_SHOWMAXIMIZED); 
     CloseHandle(ProcessInfo.hProcess); 
     CloseHandle(ProcessInfo.hThread); 


    end; 

    result := true; 
    end 
    else begin 
    Result := false; 
    end; 
end; 

कृपया उपरोक्त कोड भागो मत! यह अजीब परिणाम उत्पन्न करता है जिसमें सभी चल रहे अनुप्रयोगों में कहीं भी एक यादृच्छिक विंडो चुनना शामिल है और एम्बेड करना (यहां तक ​​कि विंडोज़ स्टार्ट मेनू से मेनू-आइटम ..)

तो मूल रूप से मुझे जो चाहिए वह है कि मैं एप्लिकेशन कैसे शुरू करूं और पकड़ूं अनुप्रयोगों की मुख्य खिड़की के लिए एक हैंडल।

किसी भी मदद अत्यधिक सराहना की

सादर

जेन्स फज

+5

एक प्रक्रिया संभाल खिड़की संभाल नहीं है। Http://stackoverflow.com/questions/1888863/how-to-get-main-window-handle-from-process-id –

+0

शीर्षक पढ़ना, मैं अंदर आने वाला था और आग्रह करता हूं कि यह * होना चाहिए * डुप्लिकेट करें, लेकिन यह देखने के बाद कि आप इस एप्लिकेशन को अपने आप में एम्बेड कर रहे हैं, जो इसे अलग करता है। महान सवाल –

+0

कृपया अपनी पोस्ट में हस्ताक्षर जोड़ें न करें। [StackOverflow पहले से ही आपके लिए एक दिखाता है] (http://stackoverflow.com/faq#signatures)। – Deanna

उत्तर

9

यहाँ आप क्या करने की जरूरत के किसी न किसी रूपरेखा है। मैं तुम्हें करने के लिए कोडिंग ऊपर छोड़ देंगे:

  1. या तो ShellExecuteEx या CreateProcess के साथ अपने प्रक्रिया प्रारंभ करें। यह एक प्रक्रिया संभाल पैदा करेगा।
  2. प्रक्रिया संभाल पर WaitForInputIdle पर कॉल करें। यह प्रक्रिया को लोड करने और अपना संदेश लूप शुरू करने का मौका देता है।
  3. प्रक्रिया आईडी प्राप्त करने के लिए प्रक्रिया संभाल GetProcessId पर पास करें।
  4. शीर्ष स्तर की विंडो को गिनने के लिए EnumWindows का उपयोग करें।
  5. इन विंडो में से प्रत्येक को GetWindowThreadProcessId पर यह जांचने के लिए पास करें कि आपको अपनी लक्षित प्रक्रिया की शीर्ष स्तर की विंडो मिली है या नहीं।
  6. एक बार जब आपको एक विंडो मिलती है जिसकी प्रक्रिया आईडी आपकी लक्षित प्रक्रिया से मेल खाती है, तो आप कर चुके हैं!

एक बार जब आप उनके साथ काम कर लें तो अपनी प्रक्रिया को संभालने के लिए मत भूलना।

+0

डेविड हेफ़र्नन, जो वास्तव में आगे बढ़ने के तरीके की तरह लग रहा है, और जब मैं समय प्राप्त करता हूं तो मैं ऐसा करूँगा। व्याख्या करने के लिए बहुत बहुत धन्यवाद। –

संबंधित मुद्दे