delphi – 如何从我的GUI应用程序启动控制台窗口的处理?

在我的GUI应用程序中,我运行控制台应用程序,需要其窗口的处理.我尝试使用Enum Windows(),看下面的代码,但它不起作用.在列表中没有我的控制台应用程序

 1 type
 2   TEnumWindowsData = record
 3     ProcessId: Cardinal;
 4     WinHandle: THandle;
 5     List: TStrings;                 // For test only
 6   end;
 7   PEnumWindowsData = ^TEnumWindowsData;
 8  
 9 function FindWindow(hWnd: THandle; lParam: LPARAM): BOOL; stdcall;
10 var
11   ParamData: TEnumWindowsData;
12   ProcessId: Cardinal;
13   WinTitle: array[0..200] of Char;  // For test only
14 begin
15   ParamData := PEnumWindowsData(lParam)^;
16   GetWindowThreadProcessId(hWnd,ProcessId);
17   if ProcessId <> ParamData.ProcessId then
18     Result := True
19   else begin
20     ParamData.WinHandle := hWnd;
21     Result := False;
22   end;
23   // For test only
24   GetWindowText(hWnd,WinTitle,Length(WinTitle) - 1);
25   ParamData.List.Add(IntToStr(ProcessId) + ' ' + IntToStr(hWnd) + ' ' + WinTitle);
26 end;
27  
28 procedure TForm1.Button1Click(Sender: TObject);
29  
30   function RunApp(const AProgram: string): Cardinal;
31   var
32     StartupInfo: TStartupInfo;
33     ProcessInformation: TProcessInformation;
34   begin
35     Result := 0;
36     ...
37     if CreateProcess(nil,PChar(AProgram),nil,False,NORMAL_PRIORITY_CLASS,StartupInfo,ProcessInformation)
38     then
39       Result := ProcessInformation.dwProcessId;
40     ...
41   end;
42  
43 var
44   ParamData: TEnumWindowsData;
45 begin
46   ParamData.ProcessId := RunApp('cmd.exe /C D:\TMP\TEST.exe');
47   ParamData.WinHandle := 0;
48   ParamData.List := Memo1.Lines;
49   EnumWindows(@FindWindow,THandle(@ParamData));
50  
51   FWindowHandle := ParamData.WinHandle;
52 end;

解决方法

以下代码只是创建进程(控制台应用程序),将您的进程通过 AttachConsole功能附加到新创建的控制台,并从该连接的控制台使用 GetConsoleWindow功能使用窗口句柄.

以下代码最大的缺点是CreateProcess函数在此时立即返回,当控制台尚未完全初始化时,当您尝试立即附加控制台后,您将失败.不幸的是,没有WaitForInputIdle功能for console applications,所以作为一种可能的解决办法,我会选择尝试在一些有限的循环计数中附加控制台,一旦成功,获取句柄并分离控制台.

代码中可能如下所示. RunApp函数应该返回控制台窗口的句柄(假设您只能运行控制台应用程序),并且应该等待大约. 1秒钟的控制台应用程序你开始可以附加.您可以通过更改尝试变量的初始值和/或更改睡眠间隔来修改此值.

 1 function GetConsoleWindow: HWND; stdcall;
 2   external kernel32 name 'GetConsoleWindow';
 3 function AttachConsole(dwProcessId: DWORD): BOOL; stdcall;
 4   external kernel32 name 'AttachConsole';
 5  
 6 function RunApp(const ACmdLine: string): HWND;
 7 var
 8   CmdLine: string;
 9   Attempt: Integer;
10   StartupInfo: TStartupInfo;
11   ProcessInfo: TProcessInformation;
12 begin
13   Result := 0;
14   FillChar(StartupInfo,SizeOf(TStartupInfo),0);
15   FillChar(ProcessInfo,SizeOf(TProcessInformation),0);
16   StartupInfo.cb := SizeOf(TStartupInfo);
17   StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
18   StartupInfo.wShowWindow := SW_SHOWNORMAL;
19   CmdLine := ACmdLine;
20   UniqueString(CmdLine);
21   if CreateProcess(nil,PChar(CmdLine),CREATE_NEW_CONSOLE,ProcessInfo) then
22   begin
23     Attempt := 100;
24     while (Attempt > 0) do
25     begin
26       if AttachConsole(ProcessInfo.dwProcessId) then
27       begin
28         Result := GetConsoleWindow;
29         FreeConsole;
30         Break;
31       end;
32       Sleep(10);
33       Dec(Attempt);
34     end;
35     CloseHandle(ProcessInfo.hThread);
36     CloseHandle(ProcessInfo.hProcess);
37   end;
38 end;

那么你可以以这种方式更改您的lauched应​​用程序的控制台窗口的标题

 1 procedure TForm1.Button1Click(Sender: TObject);
 2 var
 3   S: string;
 4   ConsoleHandle: HWND;
 5 begin
 6   ConsoleHandle := RunApp('cmd.exe');
 7   if ConsoleHandle <> 0 then
 8   begin
 9     S := 'Hello! I''m your console,how can I serve ?';
10     SendTextMessage(ConsoleHandle,WM_SETTEXT,S);
11   end;
12 end;

总结

以上是编程之家为你收集整理的delphi – 如何从我的GUI应用程序启动控制台窗口的处理?全部内容,希望文章能够帮你解决delphi – 如何从我的GUI应用程序启动控制台窗口的处理?所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

 
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
posted @ 2021-04-19 08:38  一梦五千年  阅读(471)  评论(0)    收藏  举报