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.