2010-06-15 3 views
0

winexec (...)와 같은 사용자 지정 함수를 만드는 데 사용합니다. 실행 된 응용 프로그램 핸들을 다시 실행하는 Hwnd입니다.winexec 또는 shellexecute에서 실행되는 핸들을 얻는 방법은 무엇입니까?

필자는 findwindow()를 사용했지만 윈도우 캡션을 변경하면 문제가 발생했습니다.

+0

SetWindowText()를 사용 했습니까? 커스텀 함수에서? SetWindowText(); 자막을 원하는대로 다시 바꿀 것입니다. 사용자 정의 함수를 공유하면 을 (를) 도울 수 있고 내 영어가 유감 스럽습니다. –

+0

어떤 창을 처리합니까? 메인 윈도우? 응용 프로그램 핸들? 시작하는 앱에 따라 특정 핸들은 절대로 존재하지 않으며 잠시 후에 만 ​​존재한다는 점에 유의하십시오. –

+0

@Omair, 그가 원하는대로 캡션을 다시 설정하려면 SetWindowText를 호출 할 수 있다면 그는 이미 윈도우 핸들을 가졌다는 것을 의미합니다. 그는 창 핸들을 찾고 있기 때문에 아직 가지고 있지 않으므로 SetWindowText를 호출 할 수 없다고 확신 할 수 있습니다. 게다가 다른 프로그램의 창 캡션을 변경하는 것은 좋지 않습니다. –

답변

8

어떤 프로그램이 하나 개의 창을 가지고 있다는 보장이 없기 때문에 응용 프로그램의 "는"창 핸들을 얻을 수있는 일반적인 방법은 없습니다 핸들. 프로그램에는 많은 최상위 핸들 (즉, Microsoft Word, 각 문서 당 하나)이 있거나 윈도우가 전혀 없을 수도 있습니다. 창 핸들을 정말로 필요로하는지 질문 할 수 있습니다. 특정 창 핸들을 필요로하지 않으려 고 시도하고있는 모든 작업을 더 나은 방법으로 수행 할 수 있습니다.

WinExec (약 15 년간 사용되지 않으므로 더 이상 사용하지 않는 것이 좋습니다.) ShellExecute 실제로 시작하는 프로그램에 대한 정보는 절대 반환되지 않습니다. (ShellExecute은 DDE를 사용하여 이미 실행중인 응용 프로그램 인스턴스에 명령을 보낼 수 있습니다.) 응용 프로그램을 시작하면 프로그램이 더 이상 실행되기 전에 실행을 마칠 수 있습니다.

대신 CreateProcess 또는 ShellExecuteEx을 사용할 수 있습니다. 프로그램을 시작하면 시작한 프로그램을 나타내는 프로세스 핸들을 제공합니다. 이를 사용하여 창 목록과 같은 프로그램에 대한 추가 정보를 얻을 수 있습니다. 귀찮게하지 마십시오 FindWindow; 캡션 및 윈도우 클래스가 고유하다고 보장 할 수는 없습니다. 프로그램은 많은 다른 창에 대해 동일한 클래스 이름을 사용할 수 있으며 프로그램의 여러 인스턴스는 실제로 원하는 것을 선택하기 위해 동일한 클래스 이름을 사용합니다.

EnumWindows은 후보 창 핸들 목록을 가져 오는 데 사용할 수있는 함수입니다. 함수 포인터를주고, 데스크톱의 각 최상위 창마다 해당 함수를 한 번 호출합니다. 관심있는 프로세스와 결과 목록을 반환하는 방법을 알려주는 방법이 필요합니다.

type 
    PWindowSearch = ^TWindowSearch; 
    TWindowSearch = record 
    TargetProcessID: DWord; 
    ResultList: TWndList; 
    end; 

TWndList 내가 HWnd 값의 목록을 유지하기 위해 만들어 유형은 다음과 같습니다 매개 변수가 더 많은 정보를 보유하는 구조에 대한 포인터해야 할 것이다 있도록 기능은, 하나 개의 매개 변수를 받아들입니다. Delphi 2009 이상을 사용하는 경우 TList<HWnd>을 사용할 수 있습니다. 이전 버전에서는 TList 자손 또는 선택한 항목을 사용할 수있었습니다.

CreateProcessTProcessInformation 기록의 dwProcessID 구성원에 새 프로세스 ID를 알려줍니다. ShellExecuteEx은 프로세스 핸들 만 반환하므로 GetProcessID을 사용하십시오.

function GetWindowListByProcessID(pid: DWord): TWndList; 
var 
    SearchRec: TWindowSearch; 
begin 
    Result := TWndList.Create; 
    try 
    SearchRec.TargetProcessID := pid; 
    SearchRec.ResultList := Result; 
    Win32Check(EnumWindows(SelectWindowByProcessID, LParam(@SearchRec))); 
    except 
    Result.Free; 
    raise; 
    end; 
end; 

당신은이 같은 콜백 함수를 구현하는 것입니다 :

function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall; 

당신은이 같은 핸들의 목록을 얻으려면 EnumWindows를 사용할 수 있습니다 창 - 열거 기능이 서명과 일치하는 콜백 함수를 필요로

function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall; 
var 
    SearchRec: PWindowSearch; 
    WindowPid: DWord; 
begin 
    SearchRec := PWindowSearch(Param); 
    Assert(Assigned(SearchRec)); 
    GetWindowThreadProcessID(Wnd, WindowPid); 
    if WindowPid = SearchRec.TargetProcessID then 
    SearchRec.ResultList.Add(Wnd); 
    Result := True; 
end; 

일단 목록이 있으면 실제로 어떤 것이 있는지 확인하기 위해 창의 다른 속성을 검사 할 수 있습니다. 창 제목이나 클래스 이름 또는 해당 창 중 하나 인 다른 컨트롤에 의해 결정할 수 있습니다.

프로세스 핸들 사용을 마쳤 으면 OS가 프로세스의 부기 정보를 정리할 수 있도록 CloseHandle으로 전화하십시오.

0

이 페이지의 예제 6을 (http://delphidabbler.com/tips/134) 사용해 보시고 조금 수정하십시오. 그게 내가 한 짓이야. 당신이 확인 어디에 분할하려는 당신이 당신의 결과를 검토 어디에 당신은 내가 당신의 일부가 절전()에서 던지는이에 증오 메일을 삭제합니다 실현

var 
    //... 
    runNext : Boolean; 
    //... 

begin 
{ startup code from other sample here } 

// but instead of if 
runNext := ShellExecuteEx(@SEInfo); 

{ some more code here } 

    // need delay before running next process 
    // run loop until window with Handle is closed 
if runNext then 
    with SEInfo do 
    repeat 
     GetExitCodeProcess(SEInfo.hProcess, ExitCode); 
     Sleep(20); 
     Application.ProcessMessages; 
     CheckSynchronize(); 
    until (ExitCode <> STILL_ACTIVE) or Application.Terminated; 

{ next process code here } 
end; 

그런 짓을하지만 할 수있는 경우

보트로드를 처리하고 기다릴 때까지 실행을 마칠 때까지 창을 잠그지 마십시오.