2

在C++中,控制台应用程序可以有在其WINMAIN procedure.Like这样的消息处理程序:如何创建不终止的控制台应用程序?

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 
    HWND hwnd; 
    MSG msg; 

    #ifdef _DEBUG 
    CreateConsole("Title"); 
    #endif 

    hwnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc); 
    PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); 
    while(msg.message != WM_QUIT) 
    { 
     if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
     { 
      if(IsDialogMessage(hwnd, &msg)) 
       continue; 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 

    } 

    return 0; 
} 

这使得该方法不关闭,直到控制台窗口已经接收WM_QUIT消息。我不知道如何在delphi中做类似的事情。

我的需求并非完全是一个消息处理程序,而是一个使控制台应用程序像使用线程的GUI应用程序一样工作的轻量级“技巧”。因此,例如,两台Indy TCP服务器可以在控制台应用程序没有终止进程的情况下进行处理。

我的问题:这怎么能完成?

+2

这是**不是**控制台应用程序,它是没有可见顶级窗口的标准GUI应用程序。否则,你不需要调用'CreateConsole()',一个控制台应用程序总是有一个控制台连接到它。或者你想让空的控制台窗口停留在应用程序运行时? – mghie 2010-04-07 11:05:13

+0

我希望在应用程序运行时保留空的控制台窗口,但我不希望它终止。我必须用两个TCP服务器用一个控制台替换一个gui应用程序,其操作方式与gui相同(不终止)与两个tcp服务器。 – 2010-04-07 11:11:07

+0

如果你真的在编写一个TCP服务器,那么它应该是一个**服务**,在这种情况下,console和gui是无关的,因为它的用户界面永远不会被看到。 – 2010-04-07 16:08:20

回答

8

我不知道我理解你需要做什么,但也许这样的事情

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    Forms, 
    Unit1 in 'Unit1.pas' {DataModule1: TDataModule}; 

begin 
    Application.Initialize; 
    Application.CreateForm(TDataModule1, DataModule1); 
    while not Application.Terminated do 
    Application.ProcessMessages; 
end. 

让你开始了吗?它是一个控制台应用程序,它将在控制台关闭时终止。您可以在数据模块中使用Indy组件。

编辑:

没有Forms单元的另一种方法是:

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    Windows; 

var 
    Msg: TMsg; 
begin 
    while integer(GetMessage(Msg, 0, 0, 0)) <> 0 do begin 
    TranslateMessage(Msg); 
    DispatchMessage(Msg); 
    end; 
end. 

我想,但是这不会与大多数Delphi组件工作 - 我不知道印,但如果其中一个单元无论如何都带有Forms单位,那么第一个版本是IMO更好。

+0

+1这工作得很好!我只会等待更好的答案,因为我不想包含'Forms',因为它会使exe太大。但是我保证在别人没有这样的解决方案时接受你的答案。谢谢! – 2010-04-07 12:24:42

+0

已接受,谢谢! – 2010-04-07 13:01:31

1

所有你需要一个永不终止的程序是一个无限循环(或无限循环)。您的C++程序包含一个无限循环:while(msg.message != WM_QUIT)块。 Delphi的TApplication包含一个非常相似的无限循环。如果您使用的是控制台应用程序而不是TApplication,那么您只需编写自己的无限循环并将​​其放入调用堆栈底部的过程中即可。

确定终止条件并创建一个说while not condition do的while循环。或者如果你真的不希望它终止,说while true do。然后将你的TCP服务器逻辑放入循环体中。

编辑:不会在100挂在CPU的实现:

while true do 
begin 
    DoSomethingWithTCP; 
    Sleep(0); 
end; 

睡眠(0)调用手中的CPU后退到Windows的时间片的其余部分,这使它从挂钩CPU到100.每个时间片大约有16毫秒长,如果你在主线程中所做的只是接收消息并将它们交给其他线程,这应该是足够的,除非你在之下非常重的

+0

我不确定我是否理解一切正确。我试过这个:“虽然(真)做;” ,但CPU达到100%。请你详细解释一下,或者告诉我它是怎么样的?我会很感激!从现在开始+1。 :) – 2010-04-07 12:26:49

+0

@John:好的,更新了我的答案。 – 2010-04-07 12:46:22

+0

对不起,浪费时间了,Mason.I的CPU仍然占用了90%的代码。但是我非常感谢你帮助我。想我多次不止一次。 – 2010-04-07 13:02:31

0

您可以使用SyncObjs单元和它们的类如TEvent来保持它等待,并且一直处于打开状态,直到事件对象从您的Indy线程发出信号通知为止。

0
program YourConsoleProgram; 

uses 
    System.SysUtils, 
    Winapi.Windows; 

var 
    Msg: TMsg; 
    bRet: LongBool; 

begin 
    try 
    { your program logic here } 
    { start your own threads, tcp servers, etc. } 

    // And this is Win32 Native Console Message Loop: 
    repeat 
     bRet := Winapi.Windows.GetMessage(Msg, 0, 0, 0); 

     if Int32(bRet) = -1 then 
     begin 
     // Error 
     Break; 
     end 
     else 
     begin 
     TranslateMessage(Msg); 
     DispatchMessage(Msg); 
    end; 
    until not bRet; 
except 
    on E: Exception do 
    begin 
     // do something with exception 
     Writeln(E.Classname, ': ', E.Message); 
    end; 
    end; 
end.