Avatar billede kim_bille Nybegynder
15. januar 2000 - 15:39 Der er 24 kommentarer og
1 løsning

Udskriv ren tekst

Jeg skal skrive tekst ud på en gammel matrix-printer (IBM Proprinter XL24)
Jeg prøvede først printer.canvas.textout, det virker også fint, men det går meget langsomt, da printeren jo tror at det er grafik den skriver.
Hvis skriver
AssignPrn(F);
Rewrite(F);
Writeln(F,'Linje 1');
CloseFile(F);
skriver den fint ud, men hvis jeg vil skrive flere linjer, fx.
AssignPrn(F);
Rewrite(F);
Writeln(F,'Linje 1');
Writeln(F,'Linje 2');
CloseFile(F);
går prn helt amok efter første linje!!
Hvad gør jeg forkert
(printeren virker normalt fint, wp51 har intet problem og skriver hurtigt ud)
Avatar billede koonz Nybegynder
15. januar 2000 - 16:16 #1
Hvis det kører gennem widows - hvad delphi jo gør, så "plejer" jeg at lave en hvid form, med de tekster jeg vil udskrive, det giver brugeren mulighed for at få en "preview" samtidig er det så bare at kode en frmPreview.Print (hvis du kalder formen det), og så klarer winddows resten ;)
Avatar billede kim_bille Nybegynder
16. januar 2000 - 00:51 #2
Lad mig lige forstå det rigtigt.
Du laver en (evt skjult) form, lader som om formen er papiret. dvs skriver til form.canvas og til sidst skriver form.print. Har du også gjort det med er matrix printer?

Kim
Avatar billede sjensen Nybegynder
16. januar 2000 - 09:12 #3
Her er et eks på hvordan jeg gjorde før i tiden. I dag bruger jeg ReportPrinter Pro:

procedure Tudskform.skriv_print;
var antal_udskrevet : integer;
    skru            : integer;
    zt              : integer;
begin
  antal_udskrevet := 0;
  printer.printerindex := find_printer(udsk_dev); // Udsk_Dev indeholder navnet på den printer jeg vil skrive på
  repeat
    skru := 0;
    try
      assignprn(filu);  // filu er def. som textfile og 'printers' er tilføjet usesclause
      rewrite(filu);
      printer.title := 'W-MINI '+listtype+' liste.';
      printer.canvas.font.name := font_navn;
      printer.canvas.font.size := 12;
      try
        for zt := 0 to sortrec.items.count -1 do
        begin
          if sortrec.items[zt] = '[SIDE SKIFT]' then
          begin
            writeln(filu,#12); {printer.newpage;}
          end else
          begin
            writeln(filu,sortrec.items[zt]);
          end;
          skru := skru + 1;
          label1.caption := 'Skriver liste nr: '+inttostr(antal_udskrevet+1)+' -linie nr: '+inttostr(skru);
          application.processmessages;
          if afbrudt then
          begin
            printer.abort;
            break;
          end;
        end;
      finally
        closefile(filu);
        antal_udskrevet := antal_udskrevet + 1;
      end;
    except
      on EInOutError do
      begin
        showmessage('Fejl: Kan ikke åbne til printeren !');
        afbrudt := true;
        break;
      end;
    end;
  until (antal_udskrevet = udsk_ant) or afbrudt;
  if afbrudt then
  begin
    liste_ok := false;
  end else
  begin
    liste_ok := true;
  end;
end;

Dette skriver fint på alle matrixprintere. Mon ikke at det er fordi du ikke vælger font og størrelse. Tænk på at printeren måske ikke kan skrive den fonttype der er valgt (times new roman ?) fordi den er proportional. Vælg en 10-12 cpi font a la Currier New og se om ikke det hjælper.

sjensen
Avatar billede koonz Nybegynder
16. januar 2000 - 11:51 #4
Kim
Ja lidt i den stil, jeg laver dog ikke formen skjult, men giver brugeren mulighed for at se den - en slags preview.
På siden har jeg et string array, som jeg putter de varible ind i som jeg skal have skrevet ud.

Nej jeg har ikke prøvet til en matrix printer, men hvis den er i widows printer liste - så vil jeg tro det fungerer.
Avatar billede sjensen Nybegynder
16. januar 2000 - 13:03 #5
Koonz>Nej, ikke når man bruger en form. Den bliver udskrivet grafisk på en matrixprinter.

Kim>Jeg laver udskriften som linier i en listbox som brugeren så kan se som preview. Derefter udskriver hver enkelt linie fra den med writeln, som du kan se i mit eks. Det virker som sagt fint hos mig.

sjensen
Avatar billede koonz Nybegynder
16. januar 2000 - 13:07 #6
Ja - den havde jeg ikke lige tænkt på
Avatar billede kim_bille Nybegynder
17. januar 2000 - 01:12 #7
SJensen> Jeg har
Avatar billede kim_bille Nybegynder
17. januar 2000 - 01:23 #8
Hov
SJensen>
Jeg har prøvet din code, (selvfølgelig efter jeg tilføjede diverse vars og printers i uses) men det virkede ikke. Jeg kunne ikke regne ud hvad "listtype" var, så jeg fjernede den, var den vigtig?
Det er stadigt det samme: Printeren skriver fint den første linje ud, kommer med et error-bip (det tror jeg det er) og skriver derefter volapyk ud.
Jeg har ingen andelse om hvor det går galt, og det irritere mig.
Jeg har prøvet at skrive en lille txt fil ud fra dos via cmd:
"type lille.txt > prn"
og det virker fint. Kan man kalde dos cmd. fra Delphi?

Kim
Avatar billede sjensen Nybegynder
18. januar 2000 - 15:15 #9
Det lille bip efter første linie kunne tyde på at den linie du vil skrive er for lang. Prøv engang med mindre tekst pr. linie og se om det er det samme.

Nej, listtype var ikke vigtig. Det er blot en streng der indeholdt info om hvilken af de mulige udskrifter der var valgt, og som man kunne se sammen med navnet W-Mini i printerens dokumentliste, mens udskriften foregår.

Dos Cmd fra Delphi: Ja, brug CreateProcess med "filnavn.cmd" som programnavn.

Du kan bruge både CreateProcess der blot igangsætter et program, og eller går videre med det samme, og CreateProcessAndWait, der igangsætter et program og venter på at det bliver færdigt inden det bliver færdigt.

Hvis du ikke har koden til disse så sig til, så smider jeg dem op.

sjensen
Avatar billede kim_bille Nybegynder
18. januar 2000 - 16:15 #10
Lad os forestille os at jeg skrev det der skal printes ud ned i en txt-fil (som var formateret udelukkende med "space" og "return")
og kaldte denne fil "print.txt" (liggende i prg. dir) hvordan skal jeg så få windows til at udføre cmd. "type print.txt > prn"

med andre ord: ja, du må gerne lægge lidt (mere) kode op

Kim
Avatar billede kim_bille Nybegynder
18. januar 2000 - 16:18 #11
Foresten 1. linje inderholder kun: "Linje 1".
Avatar billede sjensen Nybegynder
18. januar 2000 - 16:44 #12
Ok, her kommer det:

function CreateProcessAndWait(const AppPath, AppParams: String;
                              Visibility: word): DWord;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
  Proc: THandle;
begin
  FillChar(SI, SizeOf(SI), 0);
  SI.cb := SizeOf(SI);
  SI.wShowWindow := Visibility;
  if not CreateProcess(PChar(AppPath), PChar(AppParams), Nil, Nil, False,
                  Normal_Priority_Class, Nil, Nil, SI, PI) then
    raise EExecuteError.CreateFmt('Kunne ikke starte program.  Fejl kode: %d',
                                  [GetLastError]);
  Proc := PI.hProcess;
  CloseHandle(PI.hThread);
  if WaitForSingleObject(Proc, Infinite) <> Wait_Failed then
    GetExitCodeProcess(Proc, Result);
  CloseHandle(Proc);
end;

function CreateProcessNoWait(const AppPath, AppParams: String;
                              Visibility: word): DWord;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
  Proc: THandle;
begin
  FillChar(SI, SizeOf(SI), 0);
  SI.cb := SizeOf(SI);
  SI.wShowWindow := Visibility;
  if not CreateProcess(PChar(AppPath), PChar(AppParams), Nil, Nil, False,
                  Normal_Priority_Class, Nil, Nil, SI, PI) then
    raise EExecuteError.CreateFmt('Kunne ikke starte program.  Fejl kode: %d',
                                  [GetLastError]);
  Proc := PI.hProcess;
  CloseHandle(PI.hThread);
  GetExitCodeProcess(Proc, Result);
  CloseHandle(Proc);
end;

Og for at lette kaldeet til disse funktioner bruger jeg disse:

function WinExecAndWait(Path, Params: String): Word;
begin
  Result := CreateProcessAndWait(Path, Params, sw_show);
end;

function WinExecNoWait(Path, Params: String): Word;
begin
  Result := CreateProcessNoWait(Path, Params, sw_show);
end;

Jeg mener i øvrigt du skal kopiere det til printernavnet:

Jeg håber at du kan få det til at virke.

sjensen
Avatar billede kim_bille Nybegynder
18. januar 2000 - 19:21 #13
Filen print.txt ligger i dir. "sjensen udskriv"

skal jeg så gøre sådan;

unit UdskUnit;

interface

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

type
  TUdskForm = class(TForm)
    Button1: TButton;
    sortrec: TListBox;
    Label1: TLabel;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  UdskForm: TUdskForm;

implementation

{$R *.DFM}

function CreateProcessAndWait(const AppPath, AppParams: String;
                              Visibility: word): DWord;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
  Proc: THandle;
begin
  FillChar(SI, SizeOf(SI), 0);
  SI.cb := SizeOf(SI);
  SI.wShowWindow := Visibility;
  if not CreateProcess(PChar(AppPath), PChar(AppParams), Nil, Nil, False,
                  Normal_Priority_Class, Nil, Nil, SI, PI) then
    raise EExecuteError.CreateFmt('Kunne ikke starte program.  Fejl kode: %d', [GetLastError]);
  Proc := PI.hProcess;
  CloseHandle(PI.hThread);
  if WaitForSingleObject(Proc, Infinite) <> Wait_Failed then
    GetExitCodeProcess(Proc, Result);
  CloseHandle(Proc);
end;

function CreateProcessNoWait(const AppPath, AppParams: String;
                              Visibility: word): DWord;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
  Proc: THandle;
begin
  FillChar(SI, SizeOf(SI), 0);
  SI.cb := SizeOf(SI);
  SI.wShowWindow := Visibility;
  if not CreateProcess(PChar(AppPath), PChar(AppParams), Nil, Nil, False,
                  Normal_Priority_Class, Nil, Nil, SI, PI) then
    raise EExecuteError.CreateFmt('Kunne ikke starte program.  Fejl kode: %d', [GetLastError]);
  Proc := PI.hProcess;
  CloseHandle(PI.hThread);
  GetExitCodeProcess(Proc, Result);
  CloseHandle(Proc);
end;

//Og for at lette kaldeet til disse funktioner bruger jeg disse:

function WinExecAndWait(Path, Params: String): Word;
begin
  Result := CreateProcessAndWait(Path, Params, sw_show);
end;

function WinExecNoWait(Path, Params: String): Word;
begin
  Result := CreateProcessNoWait(Path, Params, sw_show);
end;

procedure TUdskForm.Button2Click(Sender: TObject);
begin
WinExecNoWait('e:\kim\borland\Delphi5\Projects\sjensen udskriv\','type print.txt > prn');
end;

end.

Undeclared identifier: EExecuteError!!!!
Avatar billede kim_bille Nybegynder
20. januar 2000 - 01:12 #14
sjensen> Du har hjulpet mig meget, men lige det sidste tak.
Hvad skal jeg erklære EExecuteError som?
og kalder jeg WinExecNoWait rigtigt?

Kim
Avatar billede sjensen Nybegynder
20. januar 2000 - 09:57 #15
Kim> Eexecuteerror erklæres som følgende

type
  EExecuteError = class(Exception);

Med hensyn til den rigtige syntax vender jeg lige tilbage. Jeg har lige prøvet det på min NT og det virker ikke helt som jeg ønskede. Du hører fra mig

sjensen
Avatar billede sjensen Nybegynder
20. januar 2000 - 11:16 #16
Syntaxen for WinExecNoWait (eller ..AndWait)er:

WinExecNoWait(Path, Param);

Path er sti og programnavn til det program du vil igangsætte. For at bruge kommandoer (doskommandoer!) skal path pege enten på Command.com eller cmd.exe
Dette vil skabe et DOS vindue

Param er så den kommando du vil have udført i vinduet, på samme måde som du ville skrive den ud for promptet:

Type xxx > prn

MEN...

Type en-eller-anden-tekstfil til prn virker ikke (under NT i hvertfald, men måske under Win95/98).

Syntaxen for dette tilfælde (hvor xxx er filnavnet på den fil du vil udskrive) er:

WinExecAndWait('c:\winnt\system32\cmd.exe','/C type xxx > prn');

/C betyder at vinduet skal lukke efter udførelsen.

NB! Som kommando kan du også bruge 'copy xxx prn' eller 'copy xxx LTP1:'

Under NT er det lidt mere tricky. Der skal man type eller copy til den pågældende printer. For at dette kan virke SKAL printeren være delt ud, og man skal sende udskriften til "\\maskinnavn\printernavn". Min maskine hedder DG5LSI14 og min printer hedder HP1100, så for mig vil det være:

WinExecAndWait('c:\winnt\system32\cmd.exe','/C type xxx > \\DG5LSI14\HP1100');

og når du så har filnavnet i en var ser linierne således ud:

Win95/98:

WinExecAndWait('c:\winnt\system32\cmd.exe','/C type '+filnavn+' > prn');


NT:
WinExecAndWait('c:\winnt\system32\cmd.exe','/C type '+filnavn+' > \\DG5LSI14\HP1100');

NB1! Jeg er ikke sikker på hvordan systemet reagerer hvis der er mellemrum i printernavnet, ligesom jeg ikke er sikker på at en kommando vil blive udført rigtigt hvis der er mellemrum i et af dirnavnene i enten Path eller Param værdierne. Du skal formentligt i dette tilfælde sætte anførselstegn rundt om.

NB2! Fordi min printer er en laserprinter, laver hhv. 'Type >' og 'copy ' ikke en formfeed når filen er overført, og det problem har du også på en matrixprinter, men hvor den sidste side bliver inde i laserprinteren indtil man manuelt trykker formfeed (eller sender næste fil) vil den på matrixprinteren blive udskrevet til og med sidste linie. Printhovedet vil så bare stå på næste linie, så du skal selv trykke en formfeed.

Du kan selvfølgeligt også proppe tegnet for ascii 12 (formfeed) ned i en lille fil du kalder ff.dat og så type den til printeren bagefter. Så laver den en formfeed.

NB3! Du laver filen på denne måde:

Åben en dosboks og skift til det dir hvor du vil have filen.
skriv copy con ff.dat og tryk enter
tryk på ALT og 12 på det numeriske tastatur. (du burde også kunne trykke Ctrl+L) Skærmen viser nu ^L. Tryk på enter. Tryk på Ctrl+Z og enter. Filen er nu skabt og ligger i det dir du valgte. Lad os sige det er C:\. Så vil du lave følgende for at få printeren til at udføre en formfeed:

Win95/98:

WinExecAndWait('c:\winnt\system32\cmd.exe','/C type c:\ff.dat > prn');

NT:
WinExecAndWait('c:\winnt\system32\cmd.exe','/C type c:\ff.dat > \\DG5LSI14\HP1100');

Jeg håber at det lykkes dig at få det til at virke ordentligt.

sjensen
Avatar billede kim_bille Nybegynder
21. januar 2000 - 02:25 #17
desværre det virker ikke efter hensigten. Hvis jeg skriver:

WinExecNoWait('c:\Windows\Notepad.exe','');

er der ikke noget i vejen, notepad starter og alt er i den skøneste orden, men skriver jeg:

WinExecNoWait('c:\Windows\Command.com','');

for jeg fejlmeddelsen: "Project sjensen.exe reised exception class EExecuteError with message 'Kunne ikke starte program. Fejl kode: 2'. Process stopped Use Step or Run to continue."

nb: jeg har win98

Kan det tænkes at CreateProcess kun kan køre windows programmer, for command.com er vel et dos prg.

nb: jeg har prøvet flere andre win og dos prg, alle win prg starter mens alle dos prg ikke gør.

Kim

ps: jeg har accepteret dit/dine svar, fordi
1: det jo delvist virker og burde virke (det virker jo hos dig)
2: du har gjort dei fortjent til de 100 point. Jeg vil selvfølgelig gerne have hvis du kan hjælpe mig ydreliger, så kan vi senere tale om hvormange flere point du skal have.
Avatar billede kim_bille Nybegynder
21. januar 2000 - 02:28 #18
ups: dei = dig!
Avatar billede sjensen Nybegynder
21. januar 2000 - 08:02 #19
Kim, prøv at sætte /c som parameter til linien:

WinExecNoWait('c:\Windows\Command.com',');

således

WinExecNoWait('c:\Windows\Command.com','/c');

Det betyder i win98 at command.com skal etablere en dos miljø. I øvrigt tror jeg ikke at command.com ligger i c:\windows, men bare i C:\ (eller måske c:\command)

En anden ting jeg vil råde dig til mens du tester er at udskifte NoWait med AndWait således at du kan se hvad der foregår. En ande  mulighed er at lave en batfil der tager et argument og sender dette til printeren:

prnt.bat:
type %1 > prn

og i linie skrive:

WinExecNoWait('{drive-sti}\prnt.bat','{drive-sti}\filnavn-der-skal-printes.txt'); hvis du forstår hvad jeg mener.

Hvis det er helt galt skal jeg prøve at lave et lille program på min W95 maskine (delphi2) og se hvordan det ter sig. Det kan jeg evt. gøre i løbet af eftermiddagen.

sjensen


Avatar billede sjensen Nybegynder
21. januar 2000 - 08:03 #20
NB! Lige en ekstra ting: Fejl 2: kunne ikke starte program er ensbetydende med at 1. den kunne ikke finde programmet eller 2. programmet er ikke en exe, com eller bat fil.

sjensen
Avatar billede kim_bille Nybegynder
21. januar 2000 - 12:29 #21
/c virker ikke

command.com ligger begge steder

udskriv? Jeg har kørt step-run mange gange og hver gang opstår fejl 2 i CreateProcess, hvis det er et dos-prg, mens det ikke er nogen fejl hvis det er et win prg.

prnt.bat: (som test)
type c:\print.txt > prn;
denne bat virker fint, hvis jeg dobbelt-klikker, men igen en fejl2 i D5.

Jeg venter spænt på at høre hvordan din W95 opføre sig

Kim
Avatar billede sjensen Nybegynder
21. januar 2000 - 18:45 #22
Hej Kim,

Jeg har nu testet det på win95 og du har ret. Det virker ikke. Det er fordi CreateProcess er skabt til 32bit prorammer (som windows) og en dosboks er 16bit

Men løsningen er så følgende:

1. Glem createprocess og brug winexec i stedet. Selvom MS siger den er "fased out" så gælder det jo kun for nyere versioner af windows, ikke Win95.

2. Brug en batfil der udfører selve kopieringen. (type xxx > lpt1:)

Sådan:

i programmet skriver du:

winexec(pchar('c:\prnt.bat '+edit1.text),sw_show);  // edit1.text indeholder filnavn på fil der skal udskrives

og du opretter en batfil (i dette tilfælde i c-root) der hedder prnt.bat med følgende indhold:

type %1 > lpt1:

Det virker på min Win95. Testprogrammet er lavet i D2, men er gældende både for D3, og D4. D5 har jeg ikke prøvet med.

NB! %1 i batfilen betyder "første parameter" og det er filnavnet.

Jeg håber at du får det til at virke. God fornøjelse,

sjensen
Avatar billede sjensen Nybegynder
21. januar 2000 - 18:49 #23
Og så lige en ting til: Hvis dosboksen ikke lukker af sig selv, så tilføj en linie efter "Type" linie der kun
indeholder ordet Exit. Altså

Type %1 > lpt1:
exit

sjensen
Avatar billede kim_bille Nybegynder
22. januar 2000 - 02:25 #24
Det virker!!!!

Mange, mange tak

mvh
Kim Bille
Avatar billede sjensen Nybegynder
22. januar 2000 - 14:18 #25
Kim,

Du fik på et tidspunkt en mail fra mig med SQL søgning.

Hvis du ikke selv har set det har jeg haft en længere dialog igang med madshenrik om nogle tilsvarende problemer.

Du kan læse mere om det i fælgende spm. hvis du er interesseret:

http://www.eksperten.dk/spm.asp?id=10200
http://www.eksperten.dk/spm.asp?id=9775

sjensen
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester