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 :

Comment obtenir la liste des imprimantes disponibles


Sujet :

Composants FMX Delphi

  1. #1
    Membre confirmé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    522
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 522
    Points : 544
    Points
    544
    Par défaut Comment obtenir la liste des imprimantes disponibles
    Bonjour tout le monde,
    Je crois que j'ai (encore) trouvé une régression dans XE3.
    Avant, Printer.Printers permettait d'obtenir la liste des imprimantes disponibles sur l'ordinateur.
    Maintenant, les éléments de la la liste printers ne sont accessible que par la méthode GetPrinters (index) qui retourne UN TPrinterDevice de la liste FPrinters.
    Je pourrais parcourir la liste pour récupérer les devices un par un mais la liste elle-même est déclarée protected et je n'ai donc pas accès à la propriété FPrinters.count

    Existe-t-il un moyen détourné d'accéder à la liste qui contient l'élément(par exemple Printer.Printers[0].owner ou Printer.Printers[0].parent)

    J'ai essayé de dupliquer le code de FMX.Printer.win.RefreshPrinterDevices; mais le code fait référence à des types déclarés uniquement dans la partie implementation de FMX.Printer (qu'il faudrait modifier aussi du coup) et en plus je perdrais le côté multi-plateforme.
    Avez-vous rencontré ce problème? avez-vous des pistes?

  2. #2
    Membre confirmé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    522
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 522
    Points : 544
    Points
    544
    Par défaut
    Je me suis débrouillé pour dupliquer les unités et par contre je cale sur un autre point.
    J'avais l'habitude de mémoriser les réglages de l'imprimante pour les restituer en fonction du contexte (edition de tel document sur bac1, tel autre sur bac2, etc..)
    J'utilisait pour ça la fonction Printer.GetPrinter(Device, Driver, Port, DevMode);
    Elle semble ne plus exister sur Firemonkey et je ne trouve pas d'équivalent dans la classe TPrinterDevice

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 670
    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 670
    Points : 25 477
    Points
    25 477
    Par défaut
    Une régression ?
    FMX XE3 par rapport à FMX XE2 ?
    ou juste que FMX est moins complet que la VCL parce qu'il doit respecter les contraintes du multiplateforme en trouvant un facteur commun entre Windows et MacOS

    En VCL, GetPrinter utilise la propriété Printers
    En FMX, GetPrinter a été supprimé car la propriété Printers[] la remplace
    TPrinterDevice contient les propriétés Port, Driver et Device

    Comme DevMode est une structure DEVMODE de Windows, cela se complique !
    Pour le multi-plateforme, il te faut écrire les codes pour chaque OS

    Il te faudrait faire une classe abstraite pour gérer les donnnés associés à d'un TPrinterDevice comme par exemple THigginsPrinterContext
    Tu codes la version THigginsPrinterContextWindows et THigginsPrinterContextMacOS

    Il te faut gérer les uses de FMX.Printer.Mac et FMX.Printer.Win selon directive de compilation comme dans les uses de FMX.Printer

    Ainsi ton THigginsPrinterContextWindows utilisera en interne un TPrinterWin
    et ton THigginsPrinterContextMacOS un TPrinterMac

    TPrinterWin et TPrinterMac sont les classes réelles du TPrinter qui est lui totalement abstrait
    Dommage que TWinPrinterDevice et TMacPrinterDevice soit des types privés
    Ils auraient pu les mettre en publique avec un code en directive ou en jouant sur is\as on aurait pu avoir accès à DevMode ou PMPrinter

    les THigginsPrinterContext* seront chargés de sérialiser leur TPrinter* interne

    Tu conserves ainsi le multi-plateforme

    Tu peux d'ailleurs commencer par THigginsPrinterContextWindows qui utilise sont TPrinterWin pour encpasuler le DEVMODE, DocumentProperties et EnumDisplaySettings


    Cette technique d'implémentation via classe abstraite ou via interface est présente partout dans le code de FMX pour gérer les variantes selon OS des libs graphiques par exemple ou dans FMX.Printer
    le code du JPG est très instructifs sur cette manière de procéder très OO

    En m'inspirant de la documentation, j'aurais tenté ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    with Printer() do
    begin
      for i := 0 to Count - 1 do
      begin
        PrinterDevice := Printers[i]; 
        ComboBox.Items.Add(PrinterDevice.Device + ' : ' + PrinterDevice.Title, PrinterDevice);
      end;
    end;

  4. #4
    Membre confirmé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    522
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 522
    Points : 544
    Points
    544
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message

    En m'inspirant de la documentation, j'aurais tenté ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    with Printer() do
    begin
      for i := 0 to Count - 1 do
      begin
        PrinterDevice := Printers[i]; 
        ComboBox.Items.Add(PrinterDevice.Device + ' : ' + PrinterDevice.Title, PrinterDevice);
      end;
    end;
    C'est exactement ce que j'ai fait.
    Le mot régression est effectivement mal choisi, puisque je compare à la VCL mais je découvre au fur et à mesure que les éléments basiques n'existent pas (voir mon post sur les messageDlg).

    J'ai également réécrit une fonction GetPrinter pour accéder au paramétrage de l'imprimante, qui à priori me retourne bien les infos.
    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
     
    procedure GetPrinter(APrinter:TPrinterDevice;ADevice, ADriver, APort: PChar; var ADeviceMode: THandle);
    var FPrinterHandle:Thandle;
      DevMode:PDeviceMode;
    begin
      with APrinter do
      begin
        StrCopy(ADevice, PChar(Device));
        StrCopy(ADriver, PChar(Driver));
        StrCopy(APort, PChar(Port));
      end;
      OpenPrinter(ADevice, FPrinterHandle, nil);
      ADeviceMode := GlobalAlloc(GHND,
            DocumentProperties(0, FPrinterHandle, ADevice, nil, nil, 0));
      if ADeviceMode <> 0 then
      begin
        DevMode := GlobalLock(ADeviceMode);
        if DocumentProperties(0, FPrinterHandle, ADevice, DevMode^,
          DevMode^, DM_OUT_BUFFER) < 0 then
        begin
          GlobalUnlock(ADeviceMode);
          GlobalFree(ADeviceMode);
          ADeviceMode := 0;
          DevMode := nil;
        end
      end;
    end;
    Par contre, les paramétrages modifiées dans TPrinterSetupDialog semblent rester "locaux" à l'application. Je ne les vois pas lorsque j'ouvre "périphérique et imprimantes" or j'ai l'impression que c'est à ceux-là qu'accède mon GetPrinter.
    Je n'ai pas trouvé de propriété dans la classe TPrinterDevice qui stocke ces infos. Sais-tu où elles sont enregistrées?

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 670
    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 670
    Points : 25 477
    Points
    25 477
    Par défaut
    Passe à la phase 2 : le polymorphisme

    En lisant le code source de FMX, on doit pouvoir suivre la même logique OO
    Je ne connais pas FMX, c'est purement théorique !

    Pour l'écran d'imprimante, c'est surement Windows qui gère cela, FMX ne fait que consulter via DocumentProperties
    D'ailleurs TPrinterSetupDialog n'est pas implémentée pour MAC.
    DocumentProperties utilisent un hWnd, cela a peut-être un lien avec le Dialog ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    with Printer() do
    begin
      for i := 0 to Count - 1 do
      begin
        PrinterDevice := Printers[i]; 
        ComboBox.Items.Add(PrinterDevice.Device + ' - ' + PrinterDevice.Title + ' : ' + HigginsPrinterContext().GetStringInfo(PrinterDevice), PrinterDevice);
      end;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //class THigginsPrinterContext
      function GetStringInfo(PrinterDevice: TPrinterDevice); string; virtual; abstract;
     
    // voir code de Printer()
    function HigginsPrinterContext();
    begin
      if not Assigned(GContext)
        GContext := HigginsPrinterContextClass.Create(); // class of THigginsPrinterContext;
     
      Result := GContext ;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    uses
    {$IFDEF MSWINDOWS}
      HigginsPrinterContextWindows;
    {$ENDIF}
     
    {$IFDEF MACOS}
      HigginsPrinterContextMacOS;
    {$ENDIF MACOS}
    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
     
    uses FMX.Printer.Win;
     
    function THigginsPrinterContextWindows.GetStringInfo(PrinterDevice: TPrinterDevice); string; // override;
    var
      lDevice, lDriver, lPort: PChar;
      lDeviceMode: THandle;
    begin
      if Printer() is TPrinterWin then
      begin
        with TPrinterWin(Printer()) do
        begin
          ActivePrinter := PrinterDevice;
          GetPrinter(lDevice, lDriver, lPort, lDeviceMode);
          with PDeviceMode(lDeviceMode) do
          begin
            Result := PaperSizeToPaperName(dmPaperSize); 
            ...
          end;
        end;
      end;
    end;
    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
     
    uses FMX.Printer.Mac;
     
    function THigginsPrinterContextMacOs.GetStringInfo(PrinterDevice: TPrinterDevice); string; // override;
    begin
      if Printer() is TPrinterMac then
      begin
        with TPrinterMac(Printer()) do
        begin
          ActivePrinter := PrinterDevice;
          with PrintInfo do
          begin
            Result := paperName ; 
            ...
          end;
        end;
      end;
    end;
    PrintInfo

  6. #6
    Membre confirmé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    522
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 522
    Points : 544
    Points
    544
    Par défaut
    Merci pour ton aide, j'ai bien compris le principe
    Mais pour l'instant, mon problème est plus "basique"
    Je configure l'imprimante par défaut pour une orientation de page portrait (dmOrientation=1)
    J'utilise TPrinterSetupDialog pour modifier l'orientation en paysage (dmOrientation=2)
    Lorsque je ferme la boite de dialogue et que je rappelle ma fonction GetPrinter, j'ai dmOrientation=1 pourtant si je rouvre la boite de dialogue, c'est bien paysage qui est sélectionné.
    Si je quitte l'application et que je vais vérifier le paramétrage de l'imprimante, elle est restée sur portrait.
    Ce qui me laisse penser que le TPrinterSetupDialog n'écrit pas les modifs là ou getprinter va lire mais dans un "endroit" temporaire, liée à l'application. J'ai supposé que cet endroit était une propriété de TPrinterdevice, mais elles sont peu nombreuses et ça n'a pas l'air d'être le cas. Le problème est que je ne trouve aucune documentation précise sur TPrinterSetupDialog et TprintrDevice

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 670
    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 670
    Points : 25 477
    Points
    25 477
    Par défaut
    En fait TPrinterSetupDialog utilise une autre technique de OO, ce n'est plus des classes abstraites mais des Interfaces GUID
    Ainsi via Supports, il peut savoir si le code existe pour la plate-forme en cours !
    Tu te rappelles du IFMXMouseService : Connaitre la position de la souris

    Donc même délire avec IFMXDialogService.DialogPageSetup et IFMXDialogService.DialogPrinterSetup !

    Dans FMX.Platform.Win, l'objet TPlatformWin implémente IFMXDialogService, le code de DialogPrinterSetup utilise justement GetPrinter\SetPrinter du TPrinterWin
    Le DialogPrinterSetup du TPlatformCocoa renvoie juste False !

    Je pense qu'il vaut mieux que tu utilises les valeurs contenus dans le TPrinterWin comme je l'ai proposé dans mon message précédent avec mon GetStringInfo
    Je te laisse recopier la Factory et les sections Initialization\Finalization de Printer pour gèrer le GContext\HigginsPrinterContextClass comme est géré le GPrinter\ActualPrinterClass

    Voir aussi TPageSetupDialog et ses propriétés Margin*, PageHeight, PageWidth

    J'ai utilisé ce même principe d'interface\supports en C++Builder 2007 pour gérer un système de driver et dois faire la doc de mes 200 classes,
    j'espérais utiliser des fragments de la Doc d'Embarcadero pour expliquer mon choix technique !
    Après tout, en FMX, ils ont suivi une méthodologie précise !
    Pourquoi n'aide-t-il pas les développeurs à faire les bons choix pour un développement multi-plateforme ?

    Car ma doc ressemble pour le moment à
    Embarcadero TechnologiesShaiLeTroll ne possède pas d'informations supplémentaires pour le moment. Veuillez nous aider à documenter cette rubrique en utilisant la page Discussion !

  8. #8
    Membre confirmé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    522
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 522
    Points : 544
    Points
    544
    Par défaut
    Effectivement, en utilisant TPrinterWin(Printer), je retrouve la fonction GetPrinter que j'avais l'habitude d'utiliser. Pour l'instant, tant pis pour le multi-plateforme
    Merci beaucoup pour ton aide

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

Discussions similaires

  1. Comment obtenir la liste des noms des ordinateurs du réseau ?
    Par da_latifa dans le forum Web & réseau
    Réponses: 2
    Dernier message: 17/08/2005, 11h58
  2. Réponses: 3
    Dernier message: 25/07/2005, 14h58
  3. Réponses: 1
    Dernier message: 25/06/2005, 09h40
  4. Comment obtenir la liste des paramètres d'une SP ?
    Par Le Gritche dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 14/03/2003, 16h54

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