• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 779
  • Last Modified:

CONSOLE and WINDOWS

I have always done CONSOLE or WINDOWS applications, now I need both in one application.

But when I use {$APPTYPE CONSOLE} a console and a form is open.

My program can use a flag to run in console mode (I have only disable form).
Then I use “Writeln” to write information in Console, this command only work if
I use {$APPTYPE CONSOLE}.

Question:

Is it possibly to use {$APPTYPE CONSOLE} and not show Console window from start if I not want.

OR

Is it possibly to write to Console windows other then use “Writeln” and not use
{$APPTYPE CONSOLE}  
0
Dark_King
Asked:
Dark_King
  • 8
  • 4
1 Solution
 
Slick812Commented:
hello Dark_King, ,  you can create your program as a normal Delphi project with a Main Form ( I did not change the .DPR file in any way), then in your forms code you can use the API AllocConsole( ) function to start a console, you will get the standard Input and Output handles to read and write the console. Here is the code for a button click in a normal Delphi Form that will create a console and read and write to it, However this console will BLOCK all windows message functioning of the form while it is showing -



procedure TForm1.sbut_ConsoleClick(Sender: TObject);
var
First, Third: PChar;
Input: Array[0..255] of Char;
hStdout, hStdin: Cardinal;
cRead, cWritten, fdwMode, fdwOldMode: Cardinal;
Str1: String;

begin
// during this console the Form1 will not process messages and be frozen
if not AllocConsole then
  begin
  MessageBox(0,'Error, no Console',
    'ERROR',MB_OK or MB_ICONERROR);
  Exit;
  end;
First := 'Type something and press Enter:'#10;
Third := 'You typed - ';
hStdin := GetStdHandle(STD_INPUT_HANDLE);
hStdout := GetStdHandle(STD_OUTPUT_HANDLE);

if (hStdin = INVALID_HANDLE_VALUE) or
        (hStdout = INVALID_HANDLE_VALUE) then
  begin
  MessageBox(0,'Error, no Handles',
    'Monkey Wrench',MB_OK or MB_ICONERROR);
  Exit;
  end;
Str1 := 'Type in a q and press Enter to Quit this console'#10;
WriteFile(hStdout,Str1[1],
            Length(Str1),cWritten,nil);
repeat
    if not WriteFile(
            hStdout,  // output handle
            First^,  // prompt string
            lstrlen(First), // string length

            cWritten, // bytes written
            nil) then
        break;
    if not ReadFile(
            hStdin,    // input handle
            Input,  // buffer to read into
            255,       // size of buffer
            cRead,    // actual bytes read
            nil) then    // not overlapped
        break;
Str1 := 'Number of Characters typed - '+IntToStr(cRead-2)+#10;
WriteFile(hStdout,Str1[1],
            Length(Str1),cWritten,nil);
until Input[0] = 'q';
FreeConsole;
end;

 = = = = = = = = = = = = = = = = = = = = = = = = = = = =

if you require both the program and the form to work at the same time then you will need to use a separate thread for this console.
ask questions if you need more info
0
 
Dark_KingAuthor Commented:
My program runs in 2 deferens way, but it starts from CMD or Command Console always.

1: I run program in graphic mode it show form and user give inputs.

2: I run program with a flag and some information, form is not showing now
    but information must be given user back in same Console windows that’s
    program started from.

I COLD NOT HAVE A SECOND CONSOLE WINDOWS open and user have to
Write “Exit” to close.

Is there any way to send messages back to Console, that program stared from.
0
 
Slick812Commented:
The window's system "Console" is  NOT  in the windows system message system, do you can not normally get windows mesages in console code, there is no break in the console code progression to have messages be received, the console code moves down line by line, when it is waiting for user input the thread is frozen. . . .. . . you may be able to call my methods with AllocConsole( ) in a new thread created in the DPR file or a separate unit used in the dpr file, but then things could get less than easy for executing the Application or not and keeping the program thread alive
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
Slick812Commented:
I am not sure what you are trying to do, you say something about running your program 2 different ways, but I do not understand it very well. . . .

It seems like a poor display to the user to have both a console and a graphical window (Form) GUI at the same time? Shouldn't you only use a console or a Form but not both?

I tried to create a console app and create the Application in another thread, however, the Application will not exit in another thread without calling GUI finishing , and perfoming an illegal operation. . . So I had to create a normal Form program and then run the console in another thread, The main Form starts hidden, so all you see is the console, then if you need the Main Form to be seen you just post a message to it and it will Show.
Here is some code you can try,  first the code for a unit that runs a Thread that shows a console called  ConsoleThread.pas Unit -




unit ConsoleThread;

interface

uses Classes;

type

TConThread = class(TThread)
  protected
    procedure Execute; override;
  public
    constructor Create;
  end;


implementation

uses
  Windows, SysUtils, FormUnit1;
        // FormUnit1 has a normal delphi Main Form called Form1

var
aSelf: TConThread;



constructor TConThread.Create;
begin
FreeOnTerminate := True;
inherited Create(False);
if aSelf <> nil then
  Raise Exception.Create('Create Failed - There can only be one instance of TFormThread');
aSelf := Self;
end;

procedure TConThread.Execute;
var
Str1: String;
hStdOut, hStdIn: Cardinal;

  procedure WriteLn1(InText: String);
  var
  cWrite: Cardinal;
  begin
  InText := InText+#10;
  WriteFile(hStdOut,InText[1],
            Length(InText),cWrite,nil);
  end;

  procedure ReadLn1(var OutText: String);
  var
  cRead: Cardinal;
  Input: Array[0..511] of Char;
  begin
  ReadFile(hStdIn, Input,SizeOf(Input),cRead,nil);
  OutText := Input;
  end;

begin
if not AllocConsole then
  begin
  MessageBox(0,'Error, no Console',
    'No Go',MB_OK or MB_ICONERROR);
  Exit;
  end;

hStdIn := GetStdHandle(STD_INPUT_HANDLE);
hStdOut := GetStdHandle(STD_OUTPUT_HANDLE);

if (hStdin = INVALID_HANDLE_VALUE) or
        (hStdout = INVALID_HANDLE_VALUE) then
  begin
  MessageBox(0,'Error, NO Standard  Handles',
    'No Go',MB_OK or MB_ICONERROR);
  Exit;
  end;

WriteLn1('Here we go');
WriteLn1('Another one');
ReadLn1(Str1);
WriteLn1('Starting Application');
// When you need the Form to be seen, use the PostMessage below
PostMessage(Form1.Handle, MsgThread, ShowParm, 0);
// DO NOT call any Form1 procedures or functions like Form1.Show
// from this thread, it is not thread safe
ReadLn(Str1);
FreeConsole; // kill the console
aSelf := nil;

// this next PostMessage will close the form and end this program
PostMessage(Form1.Handle, MsgThread, CloseParm, 0);
end;

end.


 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =  =

next is some code that is in the main form


unit FormUnit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons;

const
 MsgThread = WM_USER + 2341;
 ShowParm = 76543;
 CloseParm = 34567;

type

    TForm1 = class(TForm)
whatever code here


  private
    { Private declarations }
    procedure ThreadMsg(var Msg : TMessage); message MsgThread;
    procedure CloseMsg(var Msg : TMessage); message WM_CLOSE;
  public
    { Public declarations }
  protected
    procedure CreateHandle; override;
  end;


var
  Form1: TForm1;

implementation

{$R *.DFM}

uses ConsoleThread;

var
ConThread1: TConThread;


procedure TForm1.CreateHandle;
begin
Inherited;
// I guess you could place some code like
// if ParamStr(1) = '/Con' then
// to start the console
ConThread1 := TConThread.Create;
end;

procedure TForm1.ThreadMsg(var Msg : TMessage);
begin
if Msg.WParam = ShowParm then
  Show
  else
  if Msg.WParam = CloseParm then
  Close;
end;

procedure TForm1.CloseMsg(var Msg : TMessage);
begin
// you did not really say if you wanted to end the console if the form is closed
// I added this to keep the console alive if you click the upper Close X button
// if you do not change this here the console dies when the form is closed
Hide;
end;

 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

here is the code in the program file, the only difference from normal is the -
Application.ShowMainForm := False;
line



program Program1;

uses
  Forms,
  FormUnit1 in 'FormUnit1.pas' {Form1};

{$R *.RES}

begin
  Application.Initialize;
// I guess you could place some code like
// if ParamStr(1) <> '/Form' then
// to let the main form start visible
  Application.ShowMainForm := False;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.



= = = = = = = = = = = = = = = = = = = = = = =

this code seems to work for me, but I am not really sure waht you might need
0
 
Dark_KingAuthor Commented:
I wile look into your cod and see if there is something to use.

My program work like this..

From CMD a start my program

Pqdel. D215q

This while open printer queue D215q  in novell and graphic show all documents,
From here you can select some documents or you can remove all.

Pqdel –c D215q

Now it removes all documents from queue and it show nothing to user.
Here when my program has remove all documents and is exiting I want user to now
Something has happen.


If this is not working I while make 2 program.

I now my English writing is not very good, sorry for that.
0
 
Slick812Commented:
?? The code I posted will NOT work in a  CMD   console window. . .
As I said, I would not try to have both  Console  and  Window  output, in the same program, so your suggestion of having 2 different programs seems like a better (safer) way to do this. . . However if you have some reason for needing both user display types (window and console)  I have some code for that. . . I could NOT get The Delphi TApplication to run without illegal operation in a separate thread, so I  had to use API methods for window creation in my  WinThread.pas unit

Here is the code for WinThread.pas  - -


unit WinThread;

interface

uses Classes;

type

TWinThread = class(TThread)
  protected
    procedure Execute; override;
  public
    constructor Create;
  end;

var
hShowWnd: Integer = 0;

implementation

uses
  Windows, Messages, SysUtils;

const
ID_OkBut = 1000;
ID_Label1 = 2000;
ID_Label2 = 2001;

var
aSelf: TWinThread = nil;



function WndProc(hWnd,Msg,wParam,lParam:Integer):Integer; stdcall;
begin
case Msg of
  WM_DESTROY: PostQuitMessage(0);
  WM_COMMAND:
    if LOWORD(wParam) = ID_OkBut then
      PostMessage(hWnd, WM_CLOSE, 0, 0);
  end;
Result := DefWindowProc(hWnd,Msg,wParam,lParam);
end;


constructor TWinThread.Create;
begin
FreeOnTerminate := True;
inherited Create(False);
if aSelf <> nil then
  Raise Exception.Create('Create Failed - There can only be one instance of TFormThread');
aSelf := Self;
end;

procedure TWinThread.Execute;
var
wClass:   TWndClass;
mainMsg: TMSG;

begin
ZeroMemory(@wClass, SizeOf(wClass));

with wClass do
  begin
  hInstance := sysInit.hInstance;
  hIcon := LoadIcon(0,IDI_INFORMATION);
  lpfnWndProc := @WndProc;
  hbrBackground := COLOR_BTNFACE+1;
  lpszClassName := 'My window Class';
  hCursor := LoadCursor(0,IDC_ARROW);
  end;

Windows.RegisterClass(wClass);

hShowWnd := CreateWindowEX(0,wClass.lpszClassName,'Show Window',
          WS_VISIBLE or WS_SYSMENU or WS_DLGFRAME or WS_CAPTION,
          140,50,260,150,0,0,hInstance,nil);

CreateWindow('Button','O K',
    WS_VISIBLE or WS_CHILD or BS_PUSHBUTTON or BS_TEXT,
    96,86,62,24, hShowWnd, ID_OkBut, hInstance, nil);

CreateWindow('Static', 'This is an Information Window',
 WS_VISIBLE or WS_CHILD or SS_CENTER,2,6,252,18,hShowWnd,ID_Label1,hInstance,nil);

SendMessage(CreateWindow('Static', 'Some Text to read here for information'#10+
    'Next line of TEXT to read'#10'Line 3', WS_VISIBLE or WS_CHILD,4,28,
    250,50,hShowWnd,ID_Label2,hInstance,nil),
    WM_SETFONT, GetStockObject(ANSI_VAR_FONT), 0);

if hShowWnd <> 0 then
while GetMessage(mainMsg,0,0,0) do
  begin
  TranslateMessage(mainMsg);
  DispatchMessage(mainMsg);
  end;

end;

end.


 = = = = = = = = = =  = = = = = = = = = = = = = = = = = = = =

here is some code that is in the normal delphi Console program -


program ColorConsole;
{$APPTYPE CONSOLE}
uses
  Windows, Messages,
  SysUtils, WinThread;

var
ConStr: String;
WinThread1: TWinThread;

begin
WriteLn('type   start    to run window');
ReadLn(ConStr);
if ConStr = 'start' then
  begin
  WinThread1 := TWinThread.Create;
  WriteLn('Window started');
  end;

WriteLn('Type in somethig else - to end this');
ReadLn(ConStr);
PostMessage(hShowWnd, WM_CLOSE, 0,0);
WaitForSingleObject(WinThread1.Handle, 40);
end.


 = = = = = = = = = = = = = = = = = = = = = = = = = = = =

I tried this in a CMD input console, and it worked for me
0
 
Dark_KingAuthor Commented:
I while give you the points but before I do that I need to feel you understand what my problem was, I don’t want to make a new console or windows. I se this separate thread as interesting and while give this I try.

You say:
It seems like a poor display to the user to have both a console and a graphical window (Form) GUI at the same time?

And I don’t want this at the same time!!!!!

My program is used bye support them and regular user.

Supports team do not need to see graphic mode, the only need from cmd to execute the program and let it do the job

Regular user need the graphic mode to select watt the need to be done.

Properly the 2 program solution is the best?

Now to the stuff that’s I hope gives this a clear mind between us.

100% virus free with Norton anti virus…
And I have removed all function so it only type text to you.

http://big.park.se/files/extra/Slick812/

This is running like I want it to, except from short cuts.

Test it like this

From CMD type this

pqdel.exe hello
This show form in my program…

pqdel.exe –q hello

You see it stay in console here and it give information back to user.

Now the wrong thing, try to make a short cut to pqdel.exe and start from that.
You while now see it open both the window and a new console window this is watt I don’ want it to do.
I use {$APPTYPE CONSOLE} in this program and think that’s make it open console, and I use this only to use the command “Writeln” to give use information in console.
0
 
Slick812Commented:
???   :-(
I wish you would have told me about the -

And I don’t want this at the same time!!!!

before now, , , I thought you wanted them at the same time, , , , , You say in your original question -

 I have always done CONSOLE or WINDOWS applications, now I need both in one application.

Which seem like the same time to me. . . seems like I was wasting my time here. . .any way, if I have some time I will look at your app and do some more code AGAIN
0
 
Slick812Commented:
I tried to do several things, and the following code is the best working code i coild do. I could NOT fild a way to have the Delphi compiler turn On or OFF the  {$APPTYPE CONSOLE}  compilier directive, so inorder to have the program do either a Console or a Form GUI, I developed a Normal Delphi Form program with the Form1 code in EETest1.pas. .  I had to ADD the compilier directive   -
   {$APPTYPE CONSOLE}

to the .DPR file of the Form1 program, I then added a test of the first parameter string  ParamStr(1) and if it is a certain string the app will start in console mode. .  if ther is no parameter string or it is not -con then the program will close the Console window with  -
FreeConsole;

and do a normal TApplication progran start with  Application.Initialize;

the Form uses normal form codeing methods
here is the code for the program  .DPR file, ,



program EETest;
// this is a Normal Delphi Form GUI development program with Form1 in EETest1.pas

// I add the next line to tell the compilier to make this a Console program
{$APPTYPE CONSOLE}
uses
  Forms, Windows, // add Windows to uses
  EETest1 in 'EETest1.pas' {Form1};

{$R *.RES}

var
Str1: String;

begin
// I use a parameter string of  -con  ONLY to start the console mode
if ParamStr(1) = '-con' then
  begin
  // console mode using the usual WriteLn( ) methods
  WriteLn('This is now in Console Mode');
  WriteLn('Standard WriteLn Output');
  ReadLn(Str1);
  end else
  begin
  FreeConsole; // Closes the standard Console input and output before TApplication starts

  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
  end;
end.
0
 
Slick812Commented:
when you start it as a Form GUI window program, you will see the Console window appear and then quickly dissapear. .  I could not find a way to have the console window not ever show, but at least it worked both in CMD with the parameter string and in windows Form GUI without problems
0
 
Dark_KingAuthor Commented:
// I have always done CONSOLE or WINDOWS applications, now I need both in one // application.
//> Which seem like the same time to me. . . seems like I was wasting my time here

Need both and showing both at same time is different way for me..

Sorry if you feel you have wasting time on me, I still think you help me and gladly give you an “A” and 500 points.
0
 
Slick812Commented:
no, I do not so much feel that it is  a waste of time to help you, only to do things that are not useful or helpful. . .

Good Luck !
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 8
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now