Comment faire pour afficher les propriétés de l'imprimante/boîte de dialogue préférences et enregistrer les modifications?
EDIT: Ma faute! J'ai attendu les modifications de paramètres d'imprimante par défaut alors qu'en fait, seule l'instance locale de la PrinterSettings sont modifiées. - Le code ci-dessous semble fonctionner comme prévu
Je suis en train d'essayer de montrer la coutume des propriétés de l'imprimante de l'imprimante. J'ai besoin de cela comme un élément d'une coutume PrintDialog qui je suis en train d'écrire.
La plupart des exemples que je peux trouver en ligne gérer pour afficher la boîte de dialogue, mais tous les changements que l'utilisateur sont perdues, ce qui le rend inutilisable.
Exemple:
http://www.codeproject.com/KB/system/PrinterPropertiesWindow.aspx
(concernant la page mentionnée ci-dessus: j'ai essayé de changer le code, tel que suggéré par BartJoy (sur la page), mais qui n'ont pas le fixer)
J'ai aussi essayé de l'échantillon et des suggestions sur la pinvoke.net la page mais cela ne fonctionne toujours pas:
http://www.pinvoke.net/default.aspx/winspool.documentproperties
De les sites ci-dessus, je suppose que le problème est peut-être seulement en 64 bits de Windows et/ou si un nom d'imprimante plus de 32 caractères.
Je ne sais pas ce que je devrais essayer la prochaine... j'apprécie tous les commentaires et suggestions!
EDIT: Voici ce que j'ai essayé:
[DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesW", SetLastError = true,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter,
[MarshalAs(UnmanagedType.LPWStr)] string pDeviceName,
IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode);
[DllImport("winspool.drv")]
private static extern int OpenPrinter(string pPrinterName, out IntPtr hPrinter, IntPtr pDefault);
[DllImport("winspool.drv")]
private static extern int ClosePrinter(IntPtr phPrinter);
[DllImport("kernel32.dll")]
static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern bool GlobalFree(IntPtr hMem);
private const int DM_PROMPT = 4;
private const int DM_OUT_BUFFER = 2;
private const int DM_IN_BUFFER = 8;
private void OpenPrinterPropertiesDialog()
{
var printerSettings = new System.Drawing.Printing.PrinterSettings();
var printerName = printerSettings.PrinterName;
IntPtr handle;
OpenPrinter(printerName, out handle, IntPtr.Zero);
IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings);
IntPtr pDevMode = GlobalLock(hDevMode);
int sizeNeeded = DocumentProperties(this.Handle, handle, printerName, pDevMode, pDevMode, 0);
IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);
DocumentProperties(this.Handle, handle, printerName, devModeData, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER);
ClosePrinter(handle);
GlobalUnlock(hDevMode);
printerSettings.SetHdevmode(devModeData);
printerSettings.DefaultPageSettings.SetHdevmode(devModeData);
GlobalFree(hDevMode);
Marshal.FreeHGlobal(devModeData);
}
J'ai essayé d'utiliser le OpenPrinter et ClosePrinter méthode et passer le devModeData tant que paramètre de sortie dans le deuxième appel que j'ai trouvé étrange que le code d'origine de l'pinvoke.net ne pas le faire. (mais j'avoue, que je ne sais pas ce que je fais - c'est juste essai et erreur).
Voici le code original du pinvoke site:
private void OpenPrinterPropertiesDialog(PrinterSettings printerSettings)
{
IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings);
IntPtr pDevMode = GlobalLock(hDevMode);
int sizeNeeded = DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, pDevMode, 0);
IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);
DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, pDevMode, 14);
GlobalUnlock(hDevMode);
printerSettings.SetHdevmode(devModeData);
printerSettings.DefaultPageSettings.SetHdevmode(devModeData);
GlobalFree(hDevMode);
Marshal.FreeHGlobal(devModeData);
}
OriginalL'auteur |
Vous devez vous connecter pour publier un commentaire.
DEVMODE
à la structure avant de l'allocation?DEVMODE
tampon avec les paramètres par défaut après que vous avez alloué?DM_IN_BUFFER
etDM_OUT_BUFFER
drapeaux (en plus deDM_IN_PROMPT
) dans lefMode
paramètreDocumentProperties
?pDevModeInput
etpDevModeOutput
à laDEVMODE
tampon vous avez initialisé au démarrage de l'application?dmFields
bits dans leDEVMODE
tampon correctement réglé avant votre appelDocumentProperties(... DM_IN_PROMPT ...)
DEVMODE
tampon entre les appels àDocumentProperties(... DM_IN_PROMPT ...)
?Voir:
de ma faute! J'ai attendu les modifications de paramètres d'imprimante par défaut de sorte que lorsque j'appelle la même méthode avec un nouveau PrinterSettings() il tient compte des dernières modifications. - Il semble qu'il est tout à travailler correctement, que la printerSettings sont mis à jour correctement.
OriginalL'auteur vladr
Même si la réponse a fini par travailler son chemin dans la question, je pense que le texte qui suit fournit une meilleure réponse à la question d'origine,
(1), Parce qu'il n'a clairement pas modifier le passé-PrinterSettings si l'utilisateur annule.
(2) Parce qu'elle renvoie un DialogResult, l'appelant sera probablement intéressé.
Alors qu'il est à un stade précoce, ce qui semble être la plus stable de code que j'ai trouvé jusqu'à présent afin de régler mon problème. La seule petite changé basé sur mon commentaire précédent est que, pour obtenir le sizeNeeded, vous avez besoin de changer l'appel API pour utiliser un IntPtr.Zéro au lieu d'un 0 c'est à dire Dim sizeNeeded as Integer = DocumentProperties(Me.Poignée, IntPtr.Zéro, printerSettings.PrinterName, IntPtr.Zéro, pDevMode, 0). Merci pour le partage!
OriginalL'auteur
Si vous cible x86 compilation et de l'exécuter à partir d'une machine x64, le code de Jeff Roe ne fonctionnera pas: lors de l'attribution de
devModeData
,DocumentPropreties
échouera toujours, et renvoie unesizeNeeded
de -1, avec unLastError
code 13.Pour résoudre le problème, assurez-vous de cibler AnyCPU ou tout simplement de changer l'appel à
DocumentPropreties
à la suivante:À l'aide de
IntPtr.Zero
au lieu d'un pointeur vers une structure DevMode semble mauvais, mais que le premier appel à DocumentProperties ne pas tenter de modifier la mémoire à cette position. Les seules données retourné par l'appel est la taille de la mémoire nécessaire pour stocker l'appareil en mode de données qui représente les paramètres internes du pilote d'impression.Référence:
OriginalL'auteur
Aussi, si vous voulez faire cela en utilisant des classes de WPF (file d'impression, PrintTicket) cette page vous oriente vers la bonne direction:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/0dc695c1-578d-4da5-8f68-b2a257846c02
OriginalL'auteur