[Delphi] Aplikacje konsolowe a komponenty

0

Witam wszystkich. Chciałbym aby mój programik działał i wyglądał tak jak cmd.exe w systemie. Wiem że to po prostu aplikacja konsolowa którą można zrobić w Delphi, lecz co z komponentami? Mój program używa ich wiele, ich eventów itp, lecz są one w formie ikonki, nie pełnią funkcji wizualnych.

Zrobiłem sobie aplikacje konsolową i osobną formę. Na formie umieściłem idhttp i ją ukryłem. Zrobiłem w konsoli by program odwoływał się do formy i użył tamtego komponentu w pożądany sposób. Bo odpaleniu pojawia się okienko na ułamek sekundy i znika... Jak zrobię to samej formie bez konsoli na edicie i buttonie, to wszystko działa, tylko jak zamiast edita i memo mieć konsolę?

Można w jakiś sposób używać komponentów w konsoli i ich "ustawień" w object inspector?Czy ten numer który odwaliłem z dodatkową formą może wypalić czy to w ogóle nie ma sensu i nie może działać? A może jest jakiś komponent który przypomina konsolę którą można umieścić bezpośrednio na formie tak by w niej pisać i wyświetlać tekst?

Proszę o pomoc, gdyż chcę już prawie gotowy program przerobić z edita i memo na konsolę dla lepszego efektu i wygody.

Pozdrawiam

0

Niebardzo się da. Trzeba by program przerobić. Można używać komponentów w konsoli ich zdarzen także, ale
na przykład zrobiłem przed chwilą taki test. Poniższy kod się kompiluje i pokazuje tekst z Edita, ale już Timer,
ktory losuje liczbę i podstawia ją do zmiennej nie działa bo nie było Application.Run i konsola pokazuje ciągle zero - także musiał byś przerobić swój program tak aby tworzyć komponenty niewizualne bez Ownera czyli im
podać nil jako parametr, jeżeli potrzebują Ownera. Czasami też trzeba wcześniej użyć funkcji CoInitialize(nil);

program Project1;

{$APPTYPE cONSOLE}

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

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.ShowMainForm := False;
  Writeln(Form1.Edit1.Text);
  Write('Jestes w konsoli - napisz cos: ');
  Readln;
  repeat
    Writeln(Form1.JakasZmienna);
  until Form1.JakasZmienna > 100000;
end.

Można na przykład zrobić coś takiego. Kod projektu:

program Project1;

{$APPTYPE CONSOLE}

uses
  pingowanie;

begin
  if CzyJestPolaczenieInternetowe = True then
  begin
    Writeln('Masz polaczenie z Internetem.');
  end
  else
  begin
    Writeln('Nie wykryto polaczenia z internetem, pingujac po iP adres: ',
      AdresDoPingowania);
  end;
  Readln;
end.

Kod modułu pingowanie, który wykorzystuje moduł dping który można znaleźć w tym artykule pod adresem:
http://4programmers.net/Delphi/Gotowce/Dwa_w_jednym_czyli_jak_napisać_komponent_i_wysłać_pinga?sid=f9835f9d9f3c76d499fae3535d6229e8
Jak widzisz moduł pingowanie wykorzystuje niepubliczną klasę TPinger i obsługuje również zdarzenie, bo tego
wymaga w swej konstrukcji moduł dping. Zastosowałem to rozwiązanie wprawdzie w kilku swoich programach
okienkowych, ale jak sam możesz sprawdzić - działa to również pod aplikacją konsolową. Tylko exe "puchnie".

unit pingowanie;

interface

uses
  Classes, Forms, dping;

const
  AdresDoPingowania = 'www.wp.pl';

function CzyJestPolaczenieInternetowe : boolean;

implementation

type
  TPinger = class(TObject)
  private
    CzyJestInterNet : boolean;
    procedure PingerOdpowiedzi(Sender : TObject; ReplyStatus : TReplyStatus; ReplyTime : Integer);
  public
    constructor Create(var Rezultat : boolean);
  end;

procedure TPinger.PingerOdpowiedzi(Sender : TObject; ReplyStatus : TReplyStatus;
  ReplyTime : Integer);
begin
  CzyJestInterNet := ReplyStatus = rsLives;
end;

constructor TPinger.Create(var Rezultat : boolean);
const
  IleRazyMapingowac = 3;
  Ping_Limit_Czasu_MS = 500;
  Pinguj_Adres_IP = '212.77.100.101';
var
  I : Byte;
  Pinger : TDPing;
begin
  Rezultat := False;
  CzyJestInterNet := False;
  Pinger := TDPing.Create(Application);
  Pinger.TimeOut := Ping_Limit_Czasu_MS;
  Pinger.OnReply := PingerOdpowiedzi;
  Pinger.Host := Pinguj_Adres_IP;
  for I := 1 to IleRazyMapingowac do
  begin
    try
      Pinger.Ping;
    except
      CzyJestInterNet := False;
    end;
    if CzyJestInterNet = True then
    begin
      Break;
    end;
  end;
  Rezultat := CzyJestInterNet;
end;

function CzyJestPolaczenieInternetowe : boolean;
var
  Pinger : TPinger;
  JestInterNet : boolean;
begin
  JestInterNet := False;
  Pinger := TPinger.Create(JestInterNet);
  Result := JestInterNet;
  Pinger.Free;
end;

end.
0

jak chcesz to mozna odpalic konsole w czasie dzialania Twojego programu (niekonsolowego ;]), wiec mozesz probowac isc w tym kierunku:

procedure TForm1.Button1Click(Sender: TObject);
var
  s: string;
begin
  AllocConsole;
  try
    // Change color attributes
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
                                         FOREGROUND_BLUE OR FOREGROUND_GREEN or
                                         BACKGROUND_RED );
    Write('Type here your words and press ENTER: ');
    Readln(s);
    ShowMessage(Format('You typed: "%s"', [s]));
  finally
    FreeConsole;
  end;
end;

pytales tez o komponent udajacy konsole.
zwykle memo daje rade, trzeba tylko je upodobnic do konsoli:
zmieniasz kolory, czcionke i co wazne: kursor klawiatury

  CreateCaret(Memo1.Handle, Image1.Picture.Bitmap.Handle, 0, 0);
  ShowCaret(Memo1.Handle);

to zamienia domysla, mrugajaca pionowa kreske na bitmape zaladowana do image1.
musisz jeszcze tylko zabezpieczyc sie przez mozliwoscia zaznaczania tekstu w memo - nie pamietam jak ale na pewno sie da ;]

0

Dzięki za wyjaśnienia cimak - czegoś nowego się dowiedziałem. Nie byłem do końca przekonany czy tak się w
ogóle w Delphi da, ale skoro stara wersja WinUAE Kaillera bodajże, poza oknem tworzyła konsolę i to samo w
zasadzie robił i konsolowy DosBox pokazując swoje logi na osobnej konsoli, to pewnie i w Delphi też się da :)
No i teraz już wiem że można zrobić taki kod - jak poniżej i zadziała, a bez konsoli i tego sprawdzenia czy jej
uchwyt istnieje wywołanie Writeln czy Write bez konsoli oczywiście skutkowało błędem Wejścia/Wyjścia 105.

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if GetStdHandle(STD_OUTPUT_HANDLE) > 0 then
  begin
    Writeln(Random(100000));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AllocConsole;
end;
0

No panowie albo mamy aplikację konsolową, albo okienkową. Pisanie aplikacji konsolowej, żeby współgrała z okienkową ma sens w pewnych przypadkach, a autorowi chodzi o to, że woli se wyklikać niż napisać.

Co za problem użyć komponentów niewizualnych w aplikacji konsolowej? Nie wiem, jak jest z Timerem wspomnianym przez Olesia, natomiast czym są komponenty? Komponent to zwykła klasa. WIęc operujesz na nim jak na zwykłej klasie.

A co do CoInitialize, czy też COInitializeEx to wyjdzie dopiero po uruchomieniu programu. Jak w pewnym momencie dostaniesz dziwny błąd(prawdopodobnie "Program wykonał nieprawidłową operację"), umieść ten fragment w try..except i wywal sobie błąd do komunikatu. Jeśli dostaniesz coś związanego właśnie z CoInitialize(nie pamiętam dokładnie jak ten błąd brzmi, ale jest jednoznaczny), to musisz użyć funkcji COInitialize, lub COInitilizeEx. Pamiętaj, że przy zakończeniu aplikacji musisz wtedy użyć COUninitialize.

0

Żeby uzyskać efekt dosboksa wystarczy dodać do programu (project|view source) na początku linijkę

{$APPTYPE CONSOLE}

i już. Tylko że taki program będzie "sterowany z okienek", natomiast na konsolę można najwyżej od czasu do czasu coś wyświetlić za pomocą writeln.

0
olesio napisał(a)

Dzięki za wyjaśnienia cimak - czegoś nowego się dowiedziałem. Nie byłem do końca przekonany czy tak się w
ogóle w Delphi da, ale skoro stara wersja WinUAE Kaillera bodajże, poza oknem tworzyła konsolę i to samo w
zasadzie robił i konsolowy DosBox pokazując swoje logi na osobnej konsoli, to pewnie i w Delphi też się da :)
No i teraz już wiem że można zrobić taki kod - jak poniżej i zadziała, a bez konsoli i tego sprawdzenia czy jej
uchwyt istnieje wywołanie Writeln czy Write bez konsoli oczywiście skutkowało błędem Wejścia/Wyjścia 105.

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if GetStdHandle(STD_OUTPUT_HANDLE) > 0 then
  begin
    Writeln(Random(100000));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AllocConsole;
end;

Wszystko fajnie, lecz ja chciałem w tym programie móc pracować, czyli pisać i wpisany tekst pobierać do zmiennej tak jak to jest w zwykłej konsoli, a tutaj tylko wyświetla mi się tekst niestety.

A co do memo to próbowałem, lecz nawet czcionki nie można dobrać takiej samej, gdyż tej rastrowej nie mogę znaleźć w spisie, więc sztuczna konsola nie przypomina prawdziwej.

0
WielkiLol napisał(a)

Wszystko fajnie, lecz ja chciałem w tym programie móc pracować, czyli pisać i wpisany tekst pobierać do zmiennej tak jak to jest w zwykłej konsoli, a tutaj tylko wyświetla mi się tekst niestety.

a kto Ci broni? mozesz odczytywac i wpisywac text, to akurat nie problem, naprawde.

WielkiLol napisał(a)

A co do memo to próbowałem, lecz nawet czcionki nie można dobrać takiej samej, gdyż tej rastrowej nie mogę znaleźć w spisie, więc sztuczna konsola nie przypomina prawdziwej.

teraz sie zastanawiam nad jedna rzecza: czcionke konsoli da sie zmienic. pytanie tylko czy mozna zmienic globalnie, dla calego systemu, w sensie kazdej konsolowej aplikacji...
bo jesli tak, to ktos moze miec w systemie ustawiona cziocke inna niz domyslna i wtedy patenty z podrobkami na nic sie zdadza.

0
cimak napisał(a)
WielkiLol napisał(a)

Wszystko fajnie, lecz ja chciałem w tym programie móc pracować, czyli pisać i wpisany tekst pobierać do zmiennej tak jak to jest w zwykłej konsoli, a tutaj tylko wyświetla mi się tekst niestety.

a kto Ci broni? mozesz odczytywac i wpisywac text, to akurat nie problem, naprawde.

WielkiLol napisał(a)

A co do memo to próbowałem, lecz nawet czcionki nie można dobrać takiej samej, gdyż tej rastrowej nie mogę znaleźć w spisie, więc sztuczna konsola nie przypomina prawdziwej.

teraz sie zastanawiam nad jedna rzecza: czcionke konsoli da sie zmienic. pytanie tylko czy mozna zmienic globalnie, dla calego systemu, w sensie kazdej konsolowej aplikacji...
bo jesli tak, to ktos moze miec w systemie ustawiona cziocke inna niz domyslna i wtedy patenty z podrobkami na nic sie zdadza.

Chodzi o to że w tej wyświetlonej konsoli z " if GetStdHandle(STD_OUTPUT_HANDLE) > 0 then" nie mogę nic napisać, a jedynie wyświetlać tekst. Jak nacisnę jakiś klawisz na klawiaturze, to konsola tego nie wpisuje, nie reaguje.

0

caly czas nie lapie...:

cimak napisał(a)

jak chcesz to mozna odpalic konsole w czasie dzialania Twojego programu (niekonsolowego ;]), wiec mozesz probowac isc w tym kierunku:

procedure TForm1.Button1Click(Sender: TObject);
var
  s: string;
begin
  AllocConsole;
  try
    // Change color attributes
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
                                         FOREGROUND_BLUE OR FOREGROUND_GREEN or
                                         BACKGROUND_RED );
    Write('Type here your words and press ENTER: ');
    Readln(s);
    ShowMessage(Format('You typed: "%s"', [s]));
  finally
    FreeConsole;
  end;
end;

odczytuje, wypisuje....

0

Ok jak na razie wszystko działa wyśmienicie. Użyło poprawnie idhttp. Wielkie dzięki!

Zobaczę co z tego wyjdzie. Jak się nie uda to zastosuje czarne memo i tyle... Lepsze to niż nic.

Pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1