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

API, COM et SDKs Delphi Discussion :

PrintDlg dans une Unit - trouver le nom ?


Sujet :

API, COM et SDKs Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 364
    Billets dans le blog
    1
    Par défaut PrintDlg dans une Unit - trouver le nom ?
    Bonsoir,

    Je suis nouveau sous Delphi. Je cherche à ouvrir la boite de dialogue de sélection d'imprimante par programmation, sans utiliser l'objet PrintDialog, car je dois le faire dans une Unit sans form, pour pouvoir placer mes fonctions dans une DLL plus tard.

    J'ai d'abord tout fait dans une form avec PrintDialog: tout marche bien, je peux mémoriser l'imprimante par défaut actuelle, choisir mon imprimante, mémoriser l'imprimante choisie comme imprimante par défaut, restaurer l'imprimante par défaut initiale, ...

    Je veux tout faire maintenant dans une unit en vue de la fabrication de ma DLL. Toutes les fonctions citées ci-dessus marchent, en utilisant certains API, sans problème. Sauf un point précis: pour choisir la nouvelle imprimante, j'utilise l'API PrintDlg comme ceci:

    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
    function SelectDefaultPrinter(): integer;
     
    var
       Pd: TPrintDlg;
       PrinterName: Pchar;
     
    begin
        FillChar(Pd, sizeof(Pd), #0);
        Pd.lStructSize := sizeof(Pd);
        pd.hDevNames := 0;
        Pd.Flags := PD_RETURNDC;
     
      if PrintDlg(Pd) then begin
        result := 1;
        showmessage('Validé');
    {  C'est dans la ligne suivante que se trouve mon problème : }
        printername := globallock(pd.hDevNames);
    {  l'instruction suivante affiche n'importe quoi: }
        showmessage('device=['+PrinterName+']');    
     
        globalunlock(pd.hDevNames);
    {  l'instruction suivante ne marche évidemment pas:}
        SetDefaultPrinter(PrinterName);
      end
    else
      begin
        result := 0;
        showmessage('Abandonné')
      end;
    end;
     
    procedure SetDefaultPrinter(PrinterName: String);
     
    var
       I: Integer;
       Device : PChar;
       Driver : Pchar;
       Port : Pchar;
       HdeviceMode: Thandle;
       aPrinter : TPrinter;
       bFoundPrinter : Boolean;
       strPrinterName : string;
     
    begin
      bFoundPrinter := False;
      Printer.PrinterIndex := -1;
      GetMem( device, 255);
      GetMem( Driver, 255);
      GetMem( Port, 255);
      aPrinter := TPrinter.create;
      for I := 0 to Printer.printers.Count-1 do
      begin
        strPrinterName := Printer.Printers[i];
        if strPrinterName = PrinterName then
        begin
          bFoundPrinter := True;
          aprinter.printerindex := i;
          aPrinter.getprinter( device, driver, port, HdeviceMode);
          StrCat(Device, ',');
          StrCat(Device, Driver );
          StrCat(Device, Port );
          WriteProfileString('windows', 'device', Device );
          StrCopy( Device, 'windows' );
          SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, Longint(@Device));
       end;
      end;
      FreeMem( Port, 255);
      FreeMem( Driver, 255);
      FreeMem( Devite, 255);
      aPrinter.free;
      if bFoundPrinter = False then
        MessageDlg('Unable to change default printer to ' + PrinterName, mtWarning, [mbOK], 0);
    end ;
    N.B. La fonction SetDefaultPrinter fonctionne parfaitement - elle est testée avec la version "form" de mon programme.

    Je sais que hDeviceNames pointe sur une structure de 4 mots dont les 3 premiers contiennent des offsets dans une zone "extra" de 255 caractères suivant ces 4 mots, et le second offset doit pointer vers le début du nom long de l'imprimante sous forme d'un string terminé par un byte zéro.

    Je veux récupérer ce nom sous forme de pchar dans PrinterName pour pouvoir l'utiliser après, mais je n'ai pas trouvé le moyen de le faire.

    Je parcours les documentations, les forums et les sites d'info depuis des jours et je n'arrive pas à trouver comment faire. En fait, je ne sais pas comment suivre la chaine de pointeurs pd.hDevNames --> (wDeviceOffset) --> wExtra pour récupérer le nom en clair de l'imprimante.

    Toute aide d'une âme indugente envers un débutant sera la bienvenue !

    Merci à Evarisnea pour l'ajout des balises "code" - c'est évidemment beaucoup plus lisible ainsi et je tiendrai compte de votre conseil.

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    119
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2003
    Messages : 119
    Par défaut
    Salut,
    Tu fais F1 sur le nom du composant ou l'objet, en l'occurence TPrintDlg et tu tombes dans l'aide et là, tu trouveras le nom de l'unité.

  3. #3
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 236
    Par défaut
    Pour le composant PrintDialog tu as deux possibilité assez simple :

    - Avoir un Datamodule dasn ton programme et poser le composants dedans
    - Créer dynamiquement le PrintDialog (qui ne nécessite pas obligatoirement une form pour l'utiliser)
    Modérateur Delphi

    Le guide du bon forumeur :
    __________
    Rayek World : Youtube Facebook

  4. #4
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 364
    Billets dans le blog
    1
    Par défaut
    Bonsoir,

    Je vous remercie tous les deux pour vos réponses. Mais malgré mon post assez long, ma question n'a peut-être pas été assez précise. Je ne souhaite pas connaître le nom au niveau du développement. Ce que je cherche, c'est en cours d'exécution, le nom long de l'imprimante que l'utilisateur a chosi par l'API PrintDlg qui ouvre la boite de dialogue de configuration d'imprimante, tel que je le fais dans mon programme ci-dessus.

    Je ne peux pas non plus utiliser ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          printer.GetPrinter(FDevice,FDriver,FPort,FHandle);
    car je n'ai pas de context "application" à l'intérieur d'une unit destinée à aller dans une DLL. Mon problème est simplement une question de technique de programmation pour laquelle ne ne suis pas assez solide en Delphi: récupérer le string adressé par un pointeur vers un pointeur avec decalage - voir le code source de mon post initial. Ce que je cherche, c'est une ligne permettant de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    PrinterName := .......... ;
    en utilisant la structure Pd retourné par l'appel PrintDlg.

  5. #5
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Par défaut
    Citation Envoyé par KlausGunther
    Je parcours les documentations, les forums et les sites d'info depuis des jours et je n'arrive pas à trouver comment faire. En fait, je ne sais pas comment suivre la chaine de pointeurs pd.hDevNames --> (wDeviceOffset) --> wExtra pour récupérer le nom en clair de l'imprimante.
    pd.hDevNames pointe effectivement vers une structure de type DevNames
    et non vers un pchar. On ne peut donc pas faire directement
    PrinterName := globallock(pd.hDevNames);

    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
     
    Function SelectDefaultPrinter(): integer;
    Var
      Pd: TPrintDlg;
      PrinterName: Pchar;
      DevNameStruct: PDevNames; //Ajout ici
    Begin
      FillChar(Pd, sizeof(Pd), #0);
      Pd.lStructSize := sizeof(Pd);
      pd.hDevNames := 0;
      Pd.Flags := PD_RETURNDC;
     
      If PrintDlg(Pd) Then Begin
        result := 1;
        showmessage('Validé');
    {  C'est dans la ligne suivante que se trouve mon problème : }
        DevNameStruct := GlobalLock(pd.hDevNames);
        PrinterName := PChar(integer(DevNameStruct) + DevNameStruct.wDeviceOffset);
     
    {  l'instruction suivante affiche n'importe quoi: }
        showmessage('device=[' + PrinterName + ']');
     
    {  l'instruction suivante ne marche évidemment pas:}
        SetDefaultPrinter(PrinterName);
     
        GlobalUnlock(pd.hDevNames); //<-Attention puisque PrinterName pointe
                                    // pd.hDevNames, on set le Default Printer
                                    // avant de faire le GlobalUnlock
      End
      Else
      Begin
        result := 0;
        showmessage('Abandonné')
      End;
    End;
    NOTE:
    Attention de faire le GlobalUnlock seulement lorsqu'on a terminé avec le nom
    du printer....
    Comment dupliquer un disque...ça vous intéresse?
    Tutoriel et code source delphi ici

  6. #6
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 364
    Billets dans le blog
    1
    Par défaut
    OK, tu confirmes mon diagnostic. Alors, la vraie question: comment faire pour récupérer string représentant le nom de l'imprimante dans ma variable PrinterName: pchar; ? Car j'avais bien diagnistiqué tout cela, j'ai trouvé les structures, mais je ne sais pas comment récupérer ce string.

    D'accord, je veillerai à l'emplacement du GlobalUnlock - j'en étais pas là...

    Merci de ton aide !

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

Discussions similaires

  1. [XL-2007] comment trouver une colonne dans une BD par son nom via VBA
    Par chikitin dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 30/06/2010, 08h52
  2. uses dans une unité simple
    Par izguit dans le forum Delphi
    Réponses: 7
    Dernier message: 01/06/2006, 15h28
  3. Réponses: 9
    Dernier message: 09/11/2005, 11h53
  4. Réponses: 1
    Dernier message: 23/09/2005, 18h30
  5. Comment empêcher le debuger d'entrer dans une unité ?
    Par Alex Laforest dans le forum EDI
    Réponses: 5
    Dernier message: 22/07/2005, 21h14

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