Suche Print-Routine für einen Texteditor

Wohl das A & O in der Windows-Programmierung

Moderatoren: crack, Krüsty, Marwin

Suche Print-Routine für einen Texteditor

Beitragvon Paulchen » Montag 10. Juli 2006, 10:22

Hallo,
ich suche einen Experten der mir helfen kann. Für einen Texteditor aus Masm32-Paket suche ich noch eine Druckroutine. Ich habe das Programm teilweise erweitert und nach meinem Verständnis umgeschrieben. Leider habe keine Ahnung wie man Texte ausdruckt. Ich habe einen Standard-Tintendrucker (Farbe + Schwarzweiß)von HP. Hinweise auf Druckroutinen in einer höheren Programmiersprache nutzen mir nichts. Leider kann ich mit diesen Sprachen nichts anfangen. Englisch kann ich auch nicht. Meine Schulzeit liegt schon 48 Jahre zurück.

Mit freundlichen Grüßen
Paulchen
Paulchen
Member
 
Beiträge: 11
Registriert: Samstag 6. Mai 2006, 13:02
Wohnort: 16727 Oberkrämer/Schwante

Beitragvon crack » Dienstag 11. Juli 2006, 15:43

Im Prinzip ist es nicht so kompliziert ... Windows behandelt die üblichen Ein- und Ausgabegeräte ja auch als 'Dateiobjekt', also könntest Du einfach das 'Fileobjekt' mit dem Namen 'LPT1' durch die API Prozedur 'CreateFile' als Writefile öffnen, und hineinschreiben, und zum Schluss wieder schliessen.... Ich werde mal einige Versuche in der Richtung anstellen, hier habe ich etwas ähnliches allerdings bezgl. der selben Problematik in C++ gefunden: drucken ...

mfg. Crack
mit freundlichen grüssen,
with best regards,

crack
Benutzeravatar
crack
Administrator
 
Beiträge: 280
Registriert: Dienstag 21. Dezember 2004, 15:02
Wohnort: 53783 Eitorf

Beitragvon crack » Dienstag 11. Juli 2006, 16:36

Ja, ich habe es getestet, man kann es exakt so machen:

Code: Alles auswählen
      PrintIt                 PROTO

.data
...
prn         db "LPT1",0
...
.data?
hDatei dd ?

.code
...

PrintIt proc

invoke CreateFile,addr prn,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
mov hDatei,eax
invoke SetFilePointer, hDatei, NULL, NULL, FILE_END
invoke WriteFile, hDatei,addr NBuffer, Klartextgroesse, addr GeschriebeneBytes, NULL
invoke CloseHandle, hDatei   
ret

PrintIt endp
...
...




Das kannst Du so als Prozedur benutzen (natürlich müssen 'NBuffer' (der zu druckende Text) und 'Klartextgroesse' (länge des Textes) dann an dein Programm angepasst werden.
mit freundlichen grüssen,
with best regards,

crack
Benutzeravatar
crack
Administrator
 
Beiträge: 280
Registriert: Dienstag 21. Dezember 2004, 15:02
Wohnort: 53783 Eitorf

Beitragvon CDW » Donnerstag 13. Juli 2006, 23:24

ich lege einfach mal paar Codeausschnitte bei .... Damals hatte ich das zuerst auch mit lpt &Co probiert, es musste aber auch für Netzwerkdrucker gehen, deswegen eine "allgemeinere" GDI-Basierende Lösung:

Code: Alles auswählen
 
Quellcode_drucken proc
    LOCAL pd:PRINTDLG
    LOCAL DocInfo:DOCINFO
    LOCAL LFont: TEXTMETRIC
    LOCAL hFont:HANDLE
 
    LOCAL buffer[129]:BYTE
    .data
      druckname db "ALI-Emulator ",169," by ***",0  ;das wird als Copyrightzeilge genutzt (gedruckt), kann eigentlich entfernt werden.
      FontName db "MS Sans Serif",0
      X DWORD X_MAX
      Y DWORD Y_MAX
      Numlines dd 0
    .code
    INVOKE PrintSetup, ADDR pd, hWin
    invoke PrintDlg,addr pd
    .if eax==0
       ret
    .endif 
     
     INVOKE  CreateFont,80,0,0,0,FW_LIGHT,FALSE,FALSE,FALSE,ANSI_CHARSET,0,0,DEFAULT_QUALITY,0,addr FontName
 
     mov hFont,eax
   
    mov eax, sizeof DOCINFO
    mov DocInfo.cbSize, eax
   
    mov eax, offset druckname
    mov DocInfo.lpszDocName, eax
    mov DocInfo.lpszOutput, NULL
    mov DocInfo.lpszDatatype, NULL
    mov DocInfo.fwType, 0
   
    INVOKE GetTextMetrics, pd.hDC, ADDR LFont
 
       
    ;druckstarten:
    invoke StartDoc,pd.hDC,addr DocInfo
    mov ecx,0 ;anzahl der Kopien
    PRINT_LOOP:
    push ecx
    invoke StartPage,pd.hDC; Inhalt ausgeben
    invoke SelectObject,pd.hDC,hFont
   
    invoke SendDlgItemMessage,hWin,ID_PROGRAM_INPUT,EM_GETLINECOUNT,0,0
    mov Numlines,eax
    xor ecx,ecx
   
    push ecx
    mov X,X_MAX
    mov Y,Y_MAX
    invoke TextOut,pd.hDC,X,Y,addr druckname,25  ;wie erwähnt, copyrightzeile
    mov eax, Y
    add eax, LFont.tmHeight
    add eax, LFont.tmExternalLeading
    add eax, LFont.tmHeight
    mov Y, eax
   
     lea esi,buffer
     mov WORD PTR [buffer],128
    TEXT_LOOP:
        pop ecx
        push ecx
        lea esi,buffer 
        invoke SendDlgItemMessage,hWin,ID_PROGRAM_INPUT,EM_GETLINE,ecx,esi
        mov edx,eax
        lea esi,buffer
        add esi,2 ;da wir ein Word für Größe des Textes haben
        invoke TextOut,pd.hDC,X,Y,addr buffer,edx
             mov eax, Y
             add eax, LFont.tmHeight
             add eax, LFont.tmExternalLeading
             mov Y, eax
        pop ecx
        inc ecx
        push ecx   
        cmp ecx,Numlines
        jng TEXT_LOOP
       
        pop ecx
    ;enden
    invoke EndPage,pd.hDC;
    pop ecx
    inc ecx
    cmp cx, pd.nCopies
    jg PRINT_LOOP
   
    invoke EndDoc,pd.hDC;
    invoke DeleteDC,pd.hDC
   
    .if pd.hDevMode != NULL
       invoke GlobalFree,pd.hDevMode
    .endif
    .if (pd.hDevNames != NULL)
        invoke GlobalFree,pd.hDevNames;
    .endif
    ret

 Quellcode_drucken endp

Code: Alles auswählen
 PrintSetup PROC PSprintdlg:DWORD, hWnd:DWORD

    push edi
    mov edi, PSprintdlg
   
    mov eax, sizeof PRINTDLG
    mov [edi].PRINTDLG.lStructSize, eax
    mov eax, hWnd
    mov [edi].PRINTDLG.hWndOwner, eax
    mov [edi].PRINTDLG.hDevMode, NULL
    mov [edi].PRINTDLG.hDevNames, NULL
    mov [edi].PRINTDLG.hDC, NULL
    mov [edi].PRINTDLG.Flags, PD_RETURNDC OR PD_NOSELECTION OR PD_NOPAGENUMS
    mov [edi].PRINTDLG.nFromPage, 0
    mov [edi].PRINTDLG.nToPage, 0
    mov [edi].PRINTDLG.nMinPage, 0
    mov [edi].PRINTDLG.nMaxPage, 0
    mov [edi].PRINTDLG.nCopies, 1
    mov [edi].PRINTDLG.hInstance, NULL
    mov [edi].PRINTDLG.lCustData, 0
    mov [edi].PRINTDLG.lpfnPrintHook, NULL
    mov [edi].PRINTDLG.lpfnSetupHook, NULL
    mov [edi].PRINTDLG.lpPrintTemplateName, NULL
    mov [edi].PRINTDLG.lpPrintSetupTemplateName, NULL
    mov [edi].PRINTDLG.hPrintTemplate, NULL
    mov [edi].PRINTDLG.hSetupTemplate, NULL

    pop edi
   
    ret
PrintSetup ENDP

Gedruckt wird aus einem EDIT-Control heraus, ich hoffe Du kannst es weitesgehend anpassen. Die Schriftart musst Du wahrschenilch wirklich anpassen, da sie auf großgeschriebenen Asm-Quellcodeausgelegt wurde.

Man kann da sogar noch einiges kürzen, da ich damals unbediengt einen Copyrightvermerk am Anfang haben wollte :rolleyes:
zusätzlich hat man im Gegensatzt zum LPT Output den Vorteil 1.keine Probeleme mit den USB/Netzwerkdruckern
2 die Schriftart und Größe sind anpassbar - und man kann auch Seitenränder usw. einhalten.
CDW
Alter Hase
 
Beiträge: 62
Registriert: Donnerstag 2. Oktober 2003, 17:17

Suche Print-Routine für einen Texteditor

Beitragvon Paulchen » Samstag 15. Juli 2006, 12:41

Hallo,
vielen Dank an alle Experten die mir bisher geantwortet haben. Ein besonderes Dankeschön geht an EBFE der sich viel Mühe gemacht hat.
Wenn ich wieder meht Zeit habe werde ich Ihre Vorschläge ausprobieren.
Z.ZT. ist viel Gartenarbeit angesagt und der Computer bleibt aus.

Mit freundlichen Grüßen
Paulchen
Paulchen
Member
 
Beiträge: 11
Registriert: Samstag 6. Mai 2006, 13:02
Wohnort: 16727 Oberkrämer/Schwante

Suche Print-Routine für einen Texteditor

Beitragvon Paulchen » Dienstag 18. Juli 2006, 08:49

Hallo EBFE,
habe mir Ihre Druckroutine angesehen und versucht sie zu verstehen.
Einige Dinge sind mir nicht klar.
1. Das Handle hWnd ist sicher das Handle des Elternfensters und nicht das des Richedit-Steuerelementes?
2. Welche Werte muß man für X-und Y_MAX angeben und was bedeuten sie?
3. Was bedeutet ID_PROGRAMM_INPUT und was muß dafür angeben?

Ich würde mich freuen wenn Sie mir nochmals helfen könnten.

Mit freundlichen Grüßen
Paulchen
Paulchen
Member
 
Beiträge: 11
Registriert: Samstag 6. Mai 2006, 13:02
Wohnort: 16727 Oberkrämer/Schwante

Beitragvon CDW » Dienstag 18. Juli 2006, 11:30

1. Das Handle hWnd ist sicher das Handle des Elternfensters und nicht das des Richedit-Steuerelementes?

korrekt. In meinem Fall ist es das Handle zum Hauptdialogfenster.

2. Welche Werte muß man für X-und Y_MAX angeben und was bedeuten sie?
Das sind die "Startwerte" für den Druckanfang der jeweiligen Seite: also an welcher logischer Koordinate der Text gezeichnet werden soll. "Logical" heißt eigentlich nicht pixelabhängig sondern "angepasst" an die Ausgabe. X_MAX ist bei mir 15 - damit hat man immer eine bestimmte Randbreite links. Für den Zeilenumbruch sollte der Editor sorgen und der Rand rechts ist undefiniert.

Wobei die Startwerte durch "Ausprobieren" ermittelt wurden (wie erwähnt,damals wollte ich unbediengt vorher ein Copyright vorher drucken).
Ansonsten wird mit Textmetric gearbetet:
mov eax, Y
add eax, LFont.tmHeight
add eax, LFont.tmExternalLeading
mov Y, eax

(Interessant ist dabei nur der code im Textloop), so dass man unabhängig von der gewählten Schrift immer einen bestimmten Zeilenabstand hat.
Hier bietet sich auch an, anstatt mit dem festen Wert 15 für X tmWeight
zu verwenden.
3. Was bedeutet ID_PROGRAMM_INPUT und was muß dafür angeben?

das ist die ID meines EDIT-Controls. Da wird der Text zeilenweise "ausgelesen".richEdit sollte analog funktionieren.
CDW
Alter Hase
 
Beiträge: 62
Registriert: Donnerstag 2. Oktober 2003, 17:17

Suche Print-Routine für Texteditor

Beitragvon Paulchen » Montag 24. Juli 2006, 14:03

Hallo EBFE,
habe Ihre Druckroutine für ein Richedit1-Steuerelement umgegeschrieben. Funktioniert gut. Schicke sie Ihnen mit. Bekomme sie aber nur sehr unübersichtlich in das Fenster.

Mit freundlichen Grüßen
Paulchen


name Drucken
title "Text ausdrucken"

Drucken PROTO
PrintSetup PROTO :DWORD,:DWORD

X_MAX equ 120 ;Breite linker Seitenrand
Y_MAX equ 20

.data
FontName db "MS Sans Serif",0
X DWORD X_MAX
Y DWORD Y_MAX

.code

align 4

Drucken proc

LOCAL pd:PRINTDLG ;Struktur für Printdialog
LOCAL DocInfo:DOCINFO ;Struktur für StartDoc
LOCAL LFont: TEXTMETRIC
LOCAL hFont:HANDLE ;Handle Schriftart
LOCAL buffer[130]:BYTE ;I/O für Zeile
LOCAL AnzZeilen:DWORD ;Anzahl Zeilen
LOCAL ZeilenIndex:DWORD ;Zeilennummer im Control
LOCAL LgPfad:DWORD ;L'Pfad der Datei
LOCAL AnzKopien:DWORD ;Anzahl Kopien
LOCAL ZProSeite:DWORD ;Zeilen pro Seite

mov AnzZeilen,0 ;Anzzahl Zeilen im Control löschen
mov ZeilenIndex,0 ;Zeilennummer im Control löschen
mov ZProSeite,0 ;Zeilen pro Seite löschen


invoke SendMessage,hWnd,WM_GETTEXTLENGTH,0,0 ;L'Fenstername holen
mov LgPfad,eax ;Länge sichern

invoke PrintSetup, ADDR pd,hWnd ;Struktur für Printdialog füllen
invoke PrintDlg,addr pd ;Printdialog aufrufen
cmp eax,0 ;Abbruch?
je druckende ;ja
;
;*** Schriftart 'MS Sans Serif' erzeugen
;
invoke Font,50,0,0,0,FW_LIGHT,FALSE,FALSE,FALSE,ANSI_CHARSET,0,0,\
DEFAULT_QUALITY,0,addr FontName ;Schriftart MS Sans Serif erzeugen
mov hFont,eax ;Handle Schriftart

;
;*** Struktur DOCINFO versorgen
;

mov DocInfo.cbSize, sizeof DOCINFO ;L' der Struktur DOCINFO
mov eax, offset szFileName ;Pfadname
mov DocInfo.lpszDocName, eax
mov DocInfo.lpszOutput, NULL
mov DocInfo.lpszDatatype, NULL
mov DocInfo.fwType, 0

invoke GetTextMetrics, pd.hDC, ADDR LFont ;Metrische Eigenschaften der Schriftart bestimmen

invoke SendMessage,hRichEd,EM_GETLINECOUNT,0,0 ;Anz. Zeilen im Steuerelement holen
mov AnzZeilen,eax ;Anzahl Zeilen sichern

;
;*** Druckauftrag starten
;
invoke StartDoc,pd.hDC,addr DocInfo
mov AnzKopien,0 ;Anzahl der Kopien

print_loop:
invoke StartPage,pd.hDC ;neue Seite
invoke SelectObject,pd.hDC,hFont ;selektiere Gerätekontext

mov X,X_MAX
mov Y,Y_MAX
mov eax,LgPfad
invoke TextOut,pd.hDC,X,Y,addr szFileName,eax ;Pfad der Datei
mov eax, Y
add eax, LFont.tmHeight
add eax, LFont.tmExternalLeading
add eax, LFont.tmHeight
mov Y, eax

text_loop:
mov WORD PTR [buffer],128 ;max. Zeilenlänge
invoke SendMessage,hRichEd,EM_LINELENGTH,ZeilenIndex,0 ;Zeilenlänge holen
invoke SendMessage,hRichEd,EM_GETLINE,ZeilenIndex,ADDR buffer ;Zeile lesen

sub eax,2 ;wahrscheinlich am Ende der Zeile X'OD0A'
invoke TextOut,pd.hDC,X,Y,ADDR buffer,eax ;Zeile ausgeben
mov eax, Y
add eax, LFont.tmHeight
add eax, LFont.tmExternalLeading
mov Y, eax
inc ZeilenIndex ;Index Zeilennummer + 1

inc ZProSeite ;Zeile pro Seite + 1
cmp ZProSeite,62 ;62 Zeilen pro Seite?
jne text_loop10 ;nein

invoke EndPage,pd.hDC ;Ende der Seite
mov ZProSeite,0 ;Zähler pro Seite auf 0
jmp print_loop ;neue Seite

text_loop10:
mov eax,ZeilenIndex ;ZeilenIndex
cmp eax,AnzZeilen ;alle Zeilen gedruckt?
jng text_loop ;nein

invoke EndPage,pd.hDC ;Ende der Seite
invoke EndDoc,pd.hDC ;Ende Druckauftrag
invoke DeleteDC,pd.hDC ;lösche Gerätekontext

.if pd.hDevMode != NULL
invoke GlobalFree,pd.hDevMode
.endif

.if (pd.hDevNames != NULL)
invoke GlobalFree,pd.hDevNames
.endif

druckende:
ret
Drucken endp
Paulchen
Member
 
Beiträge: 11
Registriert: Samstag 6. Mai 2006, 13:02
Wohnort: 16727 Oberkrämer/Schwante

Suche Print-Routine für Texteditor

Beitragvon Paulchen » Freitag 28. Juli 2006, 14:15

Hallo EBFE,
habe Ihre Druckroutine jetzt voll an meine Bedürfnisse angepaßt. Funktioniert auch mit einem Netzwerkdrucker. Ich möchte gerne noch wissen, wie man Fehlermeldungen vom Drucker abfangen kann.
Z.B. 'Drucker nicht eingeschaltet' oder 'Kein Papier im Druker' usw.
Wäre schön wenn Sie mir noch einmal helfen könnten.

Mit freundlichen Grüßen
Paulchen
Paulchen
Member
 
Beiträge: 11
Registriert: Samstag 6. Mai 2006, 13:02
Wohnort: 16727 Oberkrämer/Schwante


Zurück zu Windows-API

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder

cron