By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,649 Members | 696 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,649 IT Pros & Developers. It's quick & easy.

SetHdevmode and printer configuration

P: n/a
Hello,
I need to implement a custom print dialog, and I'm trying to show a printers
configuration box, like when you click Properties on the windows forms
PrintDialog. I've gotten as far as showing the dialog. Now what do I do with
the devmode pointer? I've tried using SetHdevmode on the printer setting,
and it's default page setting, but I'm getting a System.EngineExecution
error.

Here's the declarations,
[DllImport("winspool.drv", EntryPoint="DocumentProperties",
SetLastError=true,
CallingConvention=CallingConvention.StdCall)]
private static extern int DocumentProperties(IntPtr hwnd, int hPrinter,
string pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode);

[DllImport("winspool.drv", EntryPoint="OpenPrinter", SetLastError=true,
CallingConvention=CallingConvention.StdCall)]
private static extern int OpenPrinter(string pPrinterName, ref int
phPrinter, PRINTER_DEFAULTS pDefault);

[DllImport("winspool.drv", EntryPoint="ClosePrinter", SetLastError=true,
CallingConvention=CallingConvention.StdCall)]
private static extern int ClosePrinter(int hPrinter);

Here's the code to show the dialog:

string printerName = cboPrinter.PrinterName; // user selected printer
PRINTER_DEFAULTS pd = new PRINTER_DEFAULTS();
int handle = 0;
int ret = OpenPrinter(printerName, ref handle, pd);

IntPtr devOut = cboPrinter.Printer.GetHdevmode();
IntPtr devIn = cboPrinter.Printer.GetHdevmode();

int propSetRet = DocumentProperties(this.Handle, handle, printerName,
devOut, devIn, DM_IN_PROMPT | DM_OUT_BUFFER);
int closeRet = ClosePrinter(handle);

cboPrinter.Printer.DefaultPageSettings.SetHdevmode (devOut); //<-- Error here
cboPrinter.Printer.SetHdevmode(devOut);

All the API calls return 1 so that part seems to be working. So how do I
make use of the changes the user made in the printer's dialog? And is there
any way I can use the IntPtr to devOut and get a structure that I can look
at the values? I don't think I really need that for my program, but it might
help me debug.

TIA,
Eric Eggermann
Nov 15 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Eric,
IntPtr devOut = cboPrinter.Printer.GetHdevmode();
IntPtr devIn = cboPrinter.Printer.GetHdevmode();
GetHdevmode returns a memory object *handle*. You should use
GlobalLock to get a pointer to the DEVMODE.

I also believe you have to set CharSet=CharSet.Auto in your DllImport
attributes to get this to work.

And is there
any way I can use the IntPtr to devOut and get a structure that I can look
at the values?


Yes, you can dereference the pointer with Marshal.PtrToStructure().

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 15 '05 #2

P: n/a

"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:e%****************@TK2MSFTNGP09.phx.gbl...
Eric,
IntPtr devOut = cboPrinter.Printer.GetHdevmode();
IntPtr devIn = cboPrinter.Printer.GetHdevmode();


GetHdevmode returns a memory object *handle*. You should use
GlobalLock to get a pointer to the DEVMODE.

I also believe you have to set CharSet=CharSet.Auto in your DllImport
attributes to get this to work.


Thanks Matthias,
I'm going to try that right now. But, what is the difference between the
handle and the address to the memory? What is in the handle?

And I'm sort of guessing here, but do you mean that, I should use
GetHdevmode to get handles to two devmode structures for the printer, then
use GlobalLock on them, then on success pass the returns from that to the
DocumentProperties call? Anyway, that's what I'm going to do for starters.

Thanks again,
Eric
Nov 15 '05 #3

P: n/a
Eric,
I'm going to try that right now. But, what is the difference between the
handle and the address to the memory? What is in the handle?
The address is just that, an address to a place in the process'
virtual memory.

The handle represents a "memory object", which is created when you
allocate movable memory with the Global or Local memory APIs. Here are
some quotes from the docs about this that may help

"GMEM_MOVEABLE
Allocates movable memory. Memory blocks are never moved in physical
memory, but they can be moved within the default heap.
The return value is a handle to the memory object. To translate the
handle into a pointer, use the GlobalLock function."

"When you allocate fixed memory, GlobalAlloc and LocalAlloc return a
pointer that the calling process can immediately use to access the
memory. When you allocate moveable memory, the return value is a
handle. To get a pointer to a movable memory object, use the
GlobalLock and LocalLock functions."

And I'm sort of guessing here, but do you mean that, I should use
GetHdevmode to get handles to two devmode structures for the printer, then
use GlobalLock on them, then on success pass the returns from that to the
DocumentProperties call? Anyway, that's what I'm going to do for starters.


Exactly. Also make sure you free (GlobalFree) devIn and devOut when
you're done, since each call to GetHdevnode returns newly allocated
memory.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 15 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.