IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants FMX Delphi Discussion :

Changer d'imprimante par code (sans dialogue) - Imprimer un ticket de caisse [Windows]


Sujet :

Composants FMX Delphi

  1. #1
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut Changer d'imprimante par code (sans dialogue) - Imprimer un ticket de caisse
    Bonjour,

    décidemment la reprise est difficile. Cela fait bien 3 jours que je galère sur ce sujet tout bête

    Je dois imprimer un ticket de caisse (imprimante sur un port com, driver ok) , j'ai d'abord essayer avec FastReport mais le ticket ne s'imprime que lorsqu'il le veut bien (autrement dit rarement)
    Du coup je me suis lancé dans du begindoc/enddoc mais, cela commence bien, je n'arrive même pas à initialiser le TPrinter

    Evidement la doc de l'imprimante (Epson TM H6000 III) ne m'aide pas beaucoup dans le sens où les quelques programmes de démo sont soit en VB soit en C mais surtout sont plus pour des trucs particuliers (cutter, logo etc..) que pour du texte tout bête.

    De plus comme il s'agit de FMX là où un TextOut VCL existe seul un printer.canvas.FillText (un canvas donc) est possible du coup, je me pose pas mal de questions sur la possibilité d'utiliser le Printer.Canvas et je ne vois pas trop comment utiliser les ESC/POS à la place.

    Quelqu'un peut-il me sortir du brouillard FMX ?
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Les dimensions du FastReport sont bien adaptées à la taille du ticket ?
    je me suis arrêté au format libre 25mm x 31mm avec Zebra pour ReportBuilder VCL, je ne sais pas en FastReport FMX jusqu'où il peut aller pour gérer la petite taille.
    Le calibrage n'a pas été facile, pour que rien de dépasse, que cela imprime juste ce qu'il faut, étiquette décollable en rouleau que l'opérateur doit prélever pour la poser sur l'objet en cours de traitement.
    Avant, le plus petit que l'on avait c'était du A6, bien plus simple, comme toi au début, ça imprimait pas, ou alors ça sortait des étiquettes vides.



    Après en VCL, Canvas pour des étiquettes genre 20mm x 20mcm, en fait c'est des planches genre 60 mm x 40 mm avec deux étiquettes principales + deux étiquettes secondaires dedans, imprimante SATO, texte et code-barre généré manuellement en pixel.
    le plus petit c'était genre 15mm sur 70mm

    FMX est-ce une solution unique ?
    Ton Epson TM H6000 III pourra-t-elle est connecté sur autre chose que du Windows ?
    Si oui, fin de ma réponse
    Si non, DLL en VCL invoqué par programme FMX


    Ou je travaillais avant, abandon de l'ERP en Delphi au profite de SAP et d'autres logiciels pour la Logistique, la Compta ...
    Finalement, personne n'a voulu gérer l'impression des millions d'étiquettes annuelles, dont une partie imprimées en Chine, Inde, Italie, Allemagne en plus de la France.

    Solution, un Serveur Web JSON qui peut être invoqué par n'importe quel client, aussi bien SAP, le(s) logiciel(s) logistique, l'ERP Delphi lui même.
    Sur les postes Windows équipés d'imprimante, un petit programme lancé en CITRIX qui s'abonne au Serveur TCP (contenu dans le Server Web évoqué précédemment), ce programme est caché, il est visible que dans la zone de notification.

    Ainsi, le client envoie une demande JSON, le contenu souhaité et le poste de sortie, le serveur HTTP lui joue son rôle de proxy vers le poste de sortie qui fait l'impression, sachant que tout ça fait des allers retours entre plusieurs logiciels.
    Le logiciel logistique qui identifie un LOT
    SAP qui calcule les numéros de série pour ce LOT et envoie la demande d'étiquette
    Le Server Delphi et ses clients d'impression


    Amusant, historiquement le premier programme il y a 20ans était l'impression d'étiquette, puis tout un ERP Maison a existé 15 ans, et la seule chose qui restera après c'est une nouvelle mouture du programme d'impression d'étiquette !


    Conclusion dans un environnement où Delphi n'existe plus, où tous les autres logiciels sont des boites noires gérées par des prestataires, il reste caché un serveur et des clients discrets pour assurer un service que personne ne pouvait assurer.
    Donc dans un environnement FMX, ne pas profiter d'un bout de VCL, n'est-ce pas se compliquer la vie ?

    Et rien n'empêche un jour de faire une version 100% FMX mais à temps perdu.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    je pensais bien que tu serais dans les premiers à répondre

    Citation Envoyé par ShaiLeTroll Voir le message
    Les dimensions du FastReport sont bien adaptées à la taille du ticket ?
    oui, parce qu'il en sort de temps en temps (et correctement)
    Ton Epson TM H6000 III pourra-t-elle est connecté sur autre chose que du Windows ?
    pour l'instant non, mais je me méfie et je ne voudrais pas avoir à recoder toute l'application

    Si non, DLL en VCL invoqué par programme FMX
    Je n'avais pas pensé à la DLL ni même à un programme VCL spécifique d'édition.
    Il y a une dizaine d'années j'avais réalisé un programme (D2010+ravereport) quasi identique

    Où je travaillais avant, abandon de l'ERP en Delphi au profite de SAP et d'autres logiciels pour la Logistique, la Compta ...
    c'est certainement ce qu'il arrivera dans 2 ans quand je ne serai plus qu'un retraité à moins que je ne trouve un reprenneur de source

    Finalement, personne n'a voulu gérer l'impression des millions d'étiquettes annuelles, dont une partie imprimées en Chine, Inde, Italie, Allemagne en plus de la France.
    l'inconvénient de solution "prêt à porter" qui répond à tout sauf à quelques essentiels contenu dans le "sur mesure"

    En attendant, j'ai fait ceci pour "retrouver" l'imprimante par code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    idxPrinter:=-1;
     
    for idxPrinter:=0 to Printer.Count-1
      do begin
        memo1.Lines.Add(Printer.Printers[idxPrinter].Device);
        if sameText(Printer.Printers[idxPrinter].Device,'EPSON TM-H6000III Receipt')
          then break;
      end;
    J'eusse préféré passer par un indexof mais je n'ai pas trouvé comment.

    Maintenant je me bat avec la fonction SetPrinter qui pour l'instant gagne SetPrinter attend un TPrinter alors que moi j'ai un TPrinterDevice
    cela dit, je me souviens d'avoir posté sur ce sujet
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    SetPrinter c'est pour remplacer tout le système d'impression par tes propres classes d'implémentations
    Rien a voir avec le SetPrinter VCL, un faux ami total !

    Printer.Printers[idxPrinter] est un TPrinterDevice,
    Printer.Printers[idxPrinter].Device est un string.
    C'est logique tout ça en terme de nommage

    Tu ne devrais pas l'affecter plutôt via ActivePrinter ?
    IndexOf(TPrinterDevice) est utilisé par SetActivePrinter mais c'est celui TObjectList<TPrinterDevice> et non un IndexOf(String)
    Semble que ta boucle soit la seule méthode

    Au fait que donne FMX.Printer.Win.TPrinterWin avant de tenter la DLL ?
    Accéder aux API Windows presque directement avec moins d'abstraction que celle tu TPrinter FMX ?



    J'ai une fonction similaire car le IndexOf(string) du TStrings ne permet pas de résoudre la problématique de l'époque
    Tient on en parlait déjà ailleurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    //------------------------------------------------------------------------------
    class function TXXXXModuleTool.FindPrinter(var APrinterName: string): Boolean;
     
      function GetExtendedPrinterName(const ALocalPrinterName: string; const AComputerName: string): string;
      var
        I: Integer;
        ExtendedPrinterName: string;
      begin
        // le Nom de l'imprimante est décoré sur le Serveur CITRIX :
        // - "Nom de l'imprimante (de Nom Poste) dans la session n"
        // - "Nom Imprimante/Nom Poste/Session N°"
        // - "Client/Nom Poste/Nom Imprimante"
        Result := EmptyStr;
        for I := 0 to Printer.Printers.Count - 1 do
        begin
          ExtendedPrinterName := Printer.Printers.Strings[I];
          if (StartsText(ALocalPrinterName, ExtendedPrinterName) or EndsText(ALocalPrinterName, ExtendedPrinterName)) and ((AComputerName = '') or ContainsText(ExtendedPrinterName, AComputerName)) then
            Exit(ExtendedPrinterName);
        end;
      end;
     
    var
      ComputerName: string;
    begin
      // En CITRIX, le nom de l'imprimante mappé est décorée par les informations de session
      // Exemple en nouvelle ferme "Nom de l'imprimante (de NOM_POSTE) dans la session n"
      // En local, le nom de l'imprimante doit être EXACT ( sauf la casse ) !
      if TXXXXModuleTool.IsCitrix() then
      begin
        if APrinterName = 'Microsoft XPS Document Writer' then
          Exit(True);
     
        TXXXXModuleTool.GetClientComputerOfRemoteSession(ComputerName);
        APrinterName := GetExtendedPrinterName(APrinterName, ComputerName);
        Result := APrinterName <> EmptyStr;
      end
      else
        Result := Printer.Printers.IndexOf(APrinterName) >= 0;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    pour ma part, j'imprime sur des TM-T88V et TM-T20II

    pour ce faire je produire mon ticket dans un Bitmap noir et blanc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function GeBbitmap: TBitmap;
    begin
      Result := TBitmap.Create;
      Result.PixelFormat := pf1Bit;
      Result.Canvas.Font.PixelsPerInch := Dpi; // 180 dpi
      Result.SetSize(Width, PrintCanvas(Result.Canvas, 0, Width));
    PrintCanvas et la fonction d'impression de mon ticket, quand on lui donne une hauteur de 0 (comme ici) la fonction n'imprime rien et calcule la hauteur nécessaire pour tout imprimer...du coup Getbitmap me crée un bitmap de la bonne taille pour pouvoir appeler PrintCanvas(Bitmap.Canvas, Bitmap.Width, Bitmap.Height); qui cette fois va le remplir.

    ensuite j'ai une fonction qui me converti le bitmap en séquence d'impression compatible EPSON, soit je l'envoie directement sur le périphérique USB
    (pas besoin de driver, j'écris directement sur un "fichier" du type "\\?\usb#vid_04b8&pid_0202#513650463573330000#{5dd901c0-bcf4-11d1-9738-008029e6a5b3}\TM"), soit je l'envoie en impression réseau si c'est une imprimante en réseau...en dernier recours je passe par le mode escape du driver d'imprimante.

    et comme j'avais réalisé tout cela sous VCL et que ça marchait super bien, je n'avais pas envie de tout recommencer dans une version FMX que j'ai du faire ensuite...du coup je me suis créé un unité qui reprend en gros le code de VCL.Printers et j'ai déclaré tout ce dont j'avais besoin pour avoir un TBitmap, un TPrinter et un TCanvas (et un TFont) compatible VCL...c'est pas tant de boulot que ça, je tape directement dans l'API Windows en prenant quelques raccourci vu que je sais que je serais toujours dans le cadre d'un bitmap monochrome

    mon unité FMX.Canvas fait 1000 lignes pour déclarer TBitmap, TPrinter TCanvas TFont et TPNGImage (dont j'avais besoin pour insérer un logo), le tout en version light qui ne reprend que ce dont j'avais besoin dans mes fonctions d'impression
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Tu ne devrais pas l'affecter plutôt via ActivePrinter ?
    Oui, je l'ai fait ainsi après mon dernier message.
    Semble que ta boucle soit la seule méthode
    Hélas oui, dommage
    L'inconvénient : c'est un peu lent sur windows et cela change l'imprimante pour le programme, il faut donc mémoriser l'imprimante par défaut avant et ne pas oublier de la réactiver ensuite


    Citation Envoyé par ShaiLeTroll Voir le message
    Tient on en parlait déjà ailleurs
    Oui, et dans ce cas il s'agissait d'un pdf à imprimer, je récupérai le canvas d'une page pour l'imprimer donc, un peu la méthode de Paul.

    Faire un canvas dans un bitmap est aussi une solution que j'envisage.

    J'ai aussi lu un code tout simple qu'il me reste à tester (je vous rapelle qu'il n'y a que du texte, du moins pour l'instant) : l'envoi direct sur le port COM
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    procedure TForm130.Button2Click(Sender: TObject);
    var port : System.Text;
      I: Integer;
    begin
     assignFile(port,'COM1');
     try
     Rewrite(port);
     for I := 0 to 10 do
       Writeln(port, 'Ligne '+i.ToString);
     writeln(port,Chr(29)+'V'+Chr(66)+Chr(0));  // cut
     finally
      closefile(port);
     end;
    end;
    l'auteur de ce bout de code indiquait aussi qu'il serait plus judicieux de passer par TComport (que je n'ai pas encore installé) pour gérer les diverses erreurs
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  7. #7
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    J'ai aussi lu un code tout simple qu'il me reste à tester (je vous rapelle qu'il n'y a que du texte, du moins pour l'instant) : l'envoi direct sur le port COM
    Alors, après tests, cela va bien vers l'imprimante, c'est bien dans le spool (comme d'ailleurs quand j'utilisais FastReport) mais ça n'en décolle pas
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    J'ai changé les réglages : la vitesse à 19200 bauds (hard et port)
    utilisé l'unité winspool et du ESC/POS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
     
    const
         escNewLine      = AnsiChar(10);  // New line (LF line feed)
         escUnerlineOn   = AnsiChar(27) + AnsiChar(45) + AnsiChar(1);  // Unerline On
         escUnerlineOnx2 = AnsiChar(27) + AnsiChar(45) + AnsiChar(2);  // Unerline On x 2
         escUnerlineOff  = AnsiChar(27) + AnsiChar(45) + AnsiChar(0);  // Unerline Off
         escBoldOn       = AnsiChar(27) + AnsiChar(69) + AnsiChar(1);  // Bold On
         escBoldOff      = AnsiChar(27) + AnsiChar(69) + AnsiChar(0);  // Bold Off
         escNegativeOn   = AnsiChar(29) + AnsiChar(66) + AnsiChar(1);  // White On Black On'
         escNegativeOff  = AnsiChar(29) + AnsiChar(66) + AnsiChar(0);  // White On Black Off
         esc8CpiOn       = AnsiChar(29) + AnsiChar(33) + AnsiChar(16); // Font Size x2 On
         esc8CpiOff      = AnsiChar(29) + AnsiChar(33) + AnsiChar(0);  // Font Size x2 Off
         esc16Cpi        = AnsiChar(27) + AnsiChar(77) + AnsiChar(48); // Font A  -  Normal Font
         esc20Cpi        = AnsiChar(27) + AnsiChar(77) + AnsiChar(49); // Font B - Small Font
         escReset        = AnsiChar(27) + AnsiChar(64); //AnsiChar(27) + AnsiChar(77) + AnsiChar(48); // Reset Printer
         escFeedAndCut   = AnsiChar(29) + AnsiChar(86) + AnsiChar(65)+ AnsiChar(20); // Partial Cut and feed
         escFormFeed     = AnsiChar(12);
         escAlignLeft    = AnsiChar(27) + AnsiChar(97) + AnsiChar(48); // Align Text to the Left
         escAlignCenter  = AnsiChar(27) + AnsiChar(97) + AnsiChar(49); // Align Text to the Center
         escAlignRight   = AnsiChar(27) + AnsiChar(97) + AnsiChar(50); // Align Text to the Right
         gsFeedandCut    = AnsiChar(29) + AnsiChar(86) + AnsiChar(48) ;
    ...
     
     
    procedure TDatas.imprimerticket(const numero : integer=0);
    var i : integer;
        hPrinter: THandle;
        DocInfo: TDocInfo1;
        dwBytesWritten: DWord;
        DocumentDataAnsi,s: AnsiString;
        d : tdateTime;
        total,tva : currency;
    begin
       OpenPrinter(PChar(parametres.Imprimante), hPrinter, nil);
       DocInfo.pOutputFile:= nil;
       DocInfo.pDatatype:= 'RAW';
       DocInfo.pDocName:= PChar('Ticket '+Numero.ToString);
       StartDocPrinter(hPrinter, 1, @DocInfo);
       StartPagePrinter(hPrinter);
       fdlignesTicket.Open('',[numero]);
       if fdLignesTicketDATE_VENTE.IsNull
         then d:=now
         else d:=fdLignesTicket.FieldByName('DATE_VENTE').AsDateTime;
       EnteteTicket(hprinter,d,numero.ToString);
    { imprimer lignes}
     
       total:=0;
       tva:=0;
       while not fdLignesTicket.eof do
        begin
          if FDLignesTicketSOLDE.AsString='N' then s:=' ' else s:=AnsiChar(169);
     
          s:=s+fdLignesTicketMODELE.asString+'-'+fdLignesTicketASSORTIMENT.AsString+' '+fdLignesTicketPOINTURE.AsString;
          s:=s+esc20Cpi+escAlignRight+format('%3.2f',[fdlignesTicketPRIX_TTC.asCurrency])+escAlignLeft;
          DocumentDataAnsi := esc20Cpi+s+escNewLine;
          WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
          DocumentDataAnsi := esc20Cpi+fdlignesTicketDESCRIPTION.asString+escNewLine;
          WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
          if FDLignesTicketREMISE.AsCurrency>0 then
            begin
              DocumentDataAnsi := esc20Cpi+escAlignRight+Format('Remise -%3.2f',[FDLignesTicketREMISE.ascurrency])+escNewLine;
              WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
            end;
          DocumentDataAnsi :=escNewLine;
          WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
          total:=total+fdlignesTicketPRIX_TTC.asCurrency-fdlignesTicketRemise.asCurrency;
          tva:=tva+((fdlignesTicketPRIX_TTC.asCurrency-fdlignesTicketRemise.asCurrency)*FDLignesTicketTAUX_TVA.AsCurrency/100);
          fdlignesTicket.Next;
        end;
     
       DocumentDataAnsi := esc20Cpi+escAlignRight+StringofChar('-',20)+escNewLine+escAlignLeft;
       WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
     
       documentDataAnsi := esc16Cpi+escBoldOn+escAlignCenter+'TOTAL'+escAlignRight+format('%3.2f',[total])+escboldoff+escNewLine;
       WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
       documentDataAnsi := esc16Cpi+escAlignCenter+'Dont T.V.A.'+escAlignRight+format('%3.2f',[tva])+escNewLine;
       WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
       documentDataAnsi := escNewLine+escNewLine;
       WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
       DocumentDataAnsi := escFeedAndCut;
       WritePrinter(hPrinter,@DocumentDataAnsi[1],length(DocumentDataAnsi),dwBytesWritten);
     
       DocumentDataAnsi :=chr(13);
       WritePrinter(hPrinter,@DocumentDataAnsi[1],1,dwBytesWritten);
     
       EndPagePrinter(hPrinter);
       EndDocPrinter(hPrinter);
       ClosePrinter(hPrinter);
    end;
    et enfin j'ai quelque chose qui sort. ça merde encore aux entournures sur les montants (il y a un '2' supplémentaire i.e : 215,00 au lieu de 15,00) un pb dans ma constante escsalignright ou autre chose.
    Nom : 20210831_170230.png
Affichages : 370
Taille : 69,8 Ko

    Je vais faire des essais en découpant la ligne ou en réalisant des chaines de caractères de taille fixe (cpi16 42c, cpi20 52c)

    En tout cas, ça avance. du moins pour windows, je n'ai pas encore fait de test avec comport
    Le changement du baud rate fait aussi l'affaire de fastreport mais la vitesse de réponse n'est pas à la hauteur (trop lent, dommage)
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Cela semble la bonne piste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
         escAlignLeft    = AnsiChar(27) + AnsiChar(97) + AnsiChar(0); // Align Text to the Left
         escAlignCenter  = AnsiChar(27) + AnsiChar(97) + AnsiChar(1); // Align Text to the Center
         escAlignRight   = AnsiChar(27) + AnsiChar(97) + AnsiChar(2); // Align Text to the Right
    et curieusement pour la font, 0 et 1 sont utilisables comme 48 et 49, un peu comme si ça acceptait au choix la valeur binaire ou l'expression textuelle de la valeur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
         esc16Cpi        = AnsiChar(27) + AnsiChar(77) + AnsiChar(0); // Font A  -  Normal Font
         esc20Cpi        = AnsiChar(27) + AnsiChar(77) + AnsiChar(1); // Font B - Small Font
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  10. #10
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    @ShaiLeTroll merci de ta réponse.Entre-temps j'ai ajouté l'image du résultat. Comme tu le remarqueras la partie 'trait' était correctement aligné à droite malgré tout

    Donc je vais modifier le programme avec ceinture et bretelles, c'est à dire, prendre en compte tes constantes et scinder l'envoi dès qu'il y a alignement à droite.
    Envoyer ça au poste à distance et croiser les doigts

    Petite question subsidiaire
    comment je débarrasse de cet avertissement [dcc32 Avertissement] DataModule.pas(549): W1058 Transtypage de chaîne implicite avec perte de données potentielle de 'string' en 'AnsiString' ?
    Je sais que c'est possible mais je ne m'en souviens plus (la faute aux vacances )
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Pour l'avertissement, plusieurs techniques, utiliser les fonctions tel que System.AnsiStrings.Format pour travailler le plus possible avec des AnsiString

    Sinon des séquences types + AnsiString(StringofChar('-',20)) + quand tu n'as pas la fonction d'équivalence (ou que le compilateur ne choisit pas la bonne version à cause d'ambiguïté)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  12. #12
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    les fonctions tel que System.AnsiStrings.Format
    je ne connaissais pas par contre le transtypage en AnsiString m'est revenu entre temps

    Résultat : si la ceinture (remplacer les constantes) fonctionne
    les bretelles ( scinder l'envoi) non
    - plus de code article
    - le pied (total et tva) toujours collé (sans le '2' toutefois)

    Nom : 20210901_091105.jpg
Affichages : 371
Taille : 47,2 Ko

    je vais passer au plan B : une chaine de caractères complète dans laquelle je mettrai les montants en fin comme ça, fini le mélange d'alignements
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  13. #13
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    franchement, je pense que tu t'embêtes pour pas grand chose

    voici les tickets que je sors
    Nom : ticket.png
Affichages : 387
Taille : 15,7 Ko

    c'est fait comme indiqué plus haut sur un bitmap noir et blanc à travers le canvas

    ensuite j'utilise cette fonction pour la convertir en ordre d'impression EPSON

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    const
      EPSON_RESET  : AnsiString = #27'@';
      EPSON_DRAWER : AnsiString = #27'p07y';
      EPSON_CUT    : AnsiString = #29'VB'#5;  // Partical Cut after 5 LF
     
    function EpsonBitmap(Bitmap: TBitmap; Pad: Integer; OpenDrawer: Boolean): TBytes;
    var
      Chars : Integer;
      y, x  : Integer;
      Index : Integer;
    begin
      Assert(Bitmap.PixelFormat = pf1Bit);
      with Bitmap do
      begin
        Chars := (Width + 7) div 8;
     
        Index := Pad + Length(EPSON_RESET) + 8 + Chars * Height + Length(EPSON_CUT);
     
        if OpenDrawer then
          Inc(Index, Length(EPSON_DRAWER));
     
        SetLength(Result, Index);
     
        Index := Pad;
        Move(EPSON_RESET[1], Result[Index], Length(EPSON_RESET));
        Inc(Index, Length(EPSON_RESET));
     
        Result[Index] := $1D; Inc(Index);
        Result[Index] := Ord('v'); Inc(Index);
        Result[Index] := Ord('0'); Inc(Index);
        Result[Index] := 0; Inc(Index);
        Result[Index] := Byte(Chars); Inc(Index);
        Result[Index] := Byte(Chars shr 8); Inc(Index);
        Result[Index] := Byte(Height); Inc(Index);
        Result[Index] := Byte(Height shr 8); Inc(Index);
     
        for y := 0 to Height - 1 do
        begin
          Move(ScanLine[y]^, Result[Index], Chars);
          for x := 0 to Chars - 1 do
          begin
            Result[Index] := 255 - Result[Index];
            Inc(Index);
          end;
        end;
      end;
     
      if OpenDrawer then
      begin
        Move(EPSON_DRAWER[1], Result[Index], Length(EPSON_DRAWER));
        Inc(Index, Length(EPSON_DRAWER));
      end;
     
      Move(EPSON_CUT[1], Result[Index], Length(EPSON_CUT));
    end;
    et il suffit d'envoyer le résultat à l'imprimante en mode RAW ou directement en USB/Réseau

    le paramètre Pad est là pour ça justement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
            Printer.Title := ATitle;
            Printer.BeginDoc;
            Data := EpsonBitmap(Bitmap, 2, False);
            Len := Length(Data) - 2;
            Move(Len, Data[0] , 2);
            Escape(Printer.Handle, PASSTHROUGH, 0, PAnsiChar(@Data[1]), nil);
            Printer.EndDoc;
    et comme c'est un Bitmap ça me permet facilement de l'afficher à l'écran au besoin, de le sauvegarder pour archivage ou de mettre un logo ou quoi que ce soit d'autre...c'est d'ailleurs la demande de logo qui m'a amené à cette solution car je devais de toute façon produire un bitmap

    autre intérêt de la méthode j'ai aussi un mode "compatible" qui utilise la fonction d'impression sur le canvas du bitmap directement sur le canvas de l'imprimante sans passer par la conversion Espson...mais c'est généralement 2 à 3 fois plus lent
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  14. #14
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    tient...je viens de voir un bug dans mon code

    heureusement je n'utilise jamais l'impression via Windows...mon code devais sans doute utiliser des AnsiString que j'ai ensuite remplacé par TBytes, car @Data[1] n'est pas bon dans la fonction Escape() il faudrait juste prendre PAnsiChar(Data)

    j'envoie toujours mes impressions directement en USB/Réseau sans installer le driver d'imprimante.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  15. #15
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    franchement, je pense que tu t'embêtes pour pas grand chose
    oui c'est possible, le truc c'est l'urgence et je me sens plus à l'aise dans l'envoi de texte que d'un bitmap (pour l'instant)
    je n'ai pas laissé tomber la version bitmap mais vu que le pc et l'imprimante sont à côté de Limoges et moi à Nantes, je vais botter en touche si mon truc fonctionne

    Citation Envoyé par Paul TOTH Voir le message
    tient...je viens de voir un bug dans mon code
    Comme quoi c'est utile de se relire
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  16. #16
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    oui c'est possible, le truc c'est l'urgence et je me sens plus à l'aise dans l'envoi de texte que d'un bitmap (pour l'instant)
    je n'ai pas laissé tomber la version bitmap mais vu que le pc et l'imprimante sont à côté de Limoges et moi à Nantes, je vais botter en touche si mon truc fonctionne


    Comme quoi c'est utile de se relire
    oui ça m'arrive régulièrement de trouver un petit bug en postant ici

    ceci dit, l'autre gros avantage du bitmap, c'est que si tu t'assures de savoir imprimer un bitmap...tu peux faire toutes les modifications que tu veux sur ce bitmap, l'impression n'en sera pas affectée car ça reste un tableau de bits, alors que quand tu joues avec les codes EPSON dans ton impression, la moindre erreur de code peut faire partir l'imprimante en vrille
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 17/06/2010, 11h39
  2. changer l'imprimante par défaut
    Par LeXo dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 26/01/2007, 15h39
  3. [NotifyIcon]Comment changer l'icone par code ?
    Par exclusif dans le forum Windows Forms
    Réponses: 2
    Dernier message: 20/01/2007, 18h25
  4. changer l'imprimante par défaut
    Par SegmentationFault dans le forum Delphi
    Réponses: 2
    Dernier message: 17/08/2006, 17h36
  5. Réponses: 2
    Dernier message: 10/05/2006, 09h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo