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:
N.B. La fonction SetDefaultPrinter fonctionne parfaitement - elle est testée avec la version "form" de mon programme.
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 ;
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.
Partager