2010-03-12 19 views
8

Me gustaría ser capaz de cambiar las propiedades de la impresora sin tener que acceder la ventana de propiedades de la impresora ...Does PrinterSettings.GetHdevmode() tiene un error?

Usando los DocumentProperties (importado de winspool.drv) función ha fracasado hasta ahora, porque si bien es fácil suprimir Al aparecer el cuadro de diálogo, parece que el valor devuelto por PrinterSettings.GetHdevmode() no refleja el PrinterSettings que lo está llamando, sino que el valor de las propiedades de la impresora anterior vuelve a ser correcto. Por ejemplo, esto me da los valores anteriores (equivocadas) desde la última llamada a las propiedades, en lugar de los valores que debe tener de los PrinterSettings objetar:

IntPtr hdevmode = PrinterSettings.GetHdevmode(PrinterSettings.DefaultPageSettings); 
PrinterSettings.SetHdevmode(hdevmode); 
PrinterSettings.DefaultPageSettings.SetHdevmode(hdevmode); 

Entonces, ¿GetHdevmode tienen un fallo, o es esto lo que su ¿supone que debe hacer? ¿Existe un C# que funcione para esto o incluso alguien tiene información al respecto? Me ha costado mucho incluso encontrar información sobre el tema.

Gracias de antemano por cualquier idea.

EDIT: No quiero que esto sea demasiado personal de un problema, pero con suerte tener toda la información en este caso puede proporcionar una respuesta que es una solución útil para otros también.

Aquí es una DLL de C++ que he escrito con el fin de tener una solución para este problema. Actualmente no funciona: cambia otras memorias, como copias, y no logra cambiar el tamaño de papel "subyacente". Pensé que todo lo que tenía que hacer era especificar la bandera del búfer de salida para hacer los cambios.

extern "C" __declspec(dllexport) DEVMODE* __stdcall GetRealHDevMode(int width, int height, char *printerName, DEVMODE* inDevMode) 
    { 
//declare handles and variables 
HANDLE printerHandle; 
LPHANDLE printerHandlePointer(&printerHandle); 

//get printer handle pointer 
OpenPrinter((LPWSTR)printerName, printerHandlePointer, NULL); 

//Get size needed for public and private devmode data and declare devmode structure 
size_t devmodeSize = DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, NULL, NULL, 0); 
DEVMODE* devmode = reinterpret_cast<DEVMODE*>(new char[devmodeSize + sizeof(DEVMODE) + sizeof(inDevMode->dmDriverExtra)]); 

//lock memory 
GlobalLock(devmode); 

//fill the out buffer 
DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, devmode, NULL, DM_OUT_BUFFER); 

//change the values as required 
devmode->dmPaperWidth = width; 
devmode->dmPaperLength = height; 
devmode->dmPaperSize = DMPAPER_USER; 

devmode->dmFields &= ~DM_PAPERSIZE; 
devmode->dmFields &= ~DM_PAPERLENGTH; 
devmode->dmFields &= ~DM_PAPERWIDTH; 
devmode->dmFields |= (DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH); 

//input flag on now to put the changes back in 
DocumentProperties(NULL, printerHandle, (LPWSTR)printerName, devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER); 

//unlock memory 
GlobalUnlock(devmode); 

//return the devmode that was used to alter the settings 
return devmode; 
    } 

que pensé el código C++ fue suficiente para cambiar la configuración, por lo que todo lo que hago en C# es la siguiente:

public PrinterSettings ChangePrinterProperties(PrinterSettings inPrinterSettings) 
    { 
     IntPtr TemphDevMode = inPrinterSettings.GetHdevmode(inPrinterSettings.DefaultPageSettings); 
     IntPtr hDevMode = GetRealHDevMode((int)(inPrinterSettings.DefaultPageSettings.PaperSize.Width * 2.54F), 
      (int)(inPrinterSettings.DefaultPageSettings.PaperSize.Height * 2.54F), 
      inPrinterSettings.PrinterName, TemphDevMode); 
     GlobalFree(hDevMode); 
     return inPrinterSettings; 
    } 

ACTUALIZACIÓN: Se ha cambiado el orden un poco con dmPaperSize y dmFields. Resultados mejorados; todavía no está allí.

ACTUALIZACIÓN 2: Bien, encontré una página de Microsoft que dice que la documentación es incorrecta. MSDN dice que establezca dmPaperSize en 0 cuando desee especificar el ancho y el alto, mientras que la corrección de soporte técnico de Microsoft indica que se establezca en DMPAPER_USER. http://support.microsoft.com/kb/108924

+0

Uso C++. La mayoría de los problemas relacionados con la estructura 'DEVMODE' con los que me he encontrado están relacionados ya sea con 1) Problemas de lectura: no bloquear la memoria antes de acceder a la estructura o 2) Escribir problemas: no crear una nueva estructura al configurar' DEVMODE'. HTH. – dirkgently

+0

Su fragmento de código no tiene ningún sentido, devuelve lo que ya estaba allí.Huele como un problema de selección de impresora predeterminado, pero no tiene ninguna pista de la información dada. Publique más código o solicite a otra persona que lo ayude a explicar mejor el problema. –

+0

@nobugz: Exactamente el punto ... simplemente debería volver a colocarlo allí, pero en cambio le da un valor diferente, que no refleja el objeto de configuración de la impresora utilizado para crearlo, sino la última llamada a las propiedades de la impresora. No es un problema de impresora predeterminado (esto es general). @dirkgently: Intenté escribir una DLL C++, pero terminó cambiando otra memoria además de la que estaba intentando cambiar. No estaba seguro de lo que estaba haciendo mal, pero parece que debería buscar en la solución de bloqueo de memoria. Gracias por la sugerencia. :) – Brandi

Respuesta

2

Hay 2 problemas con la forma en que está especificando el tamaño del papel en el DEVMODE:

(1) Si se especifica DM_PAPERWIDTH o DM_PAPERLENGTH o ambos, no debe también establecer el bit DM_PAPERSIZE. Depende del controlador de la impresora, pero muchos controladores ignorarán DM_PAPERLENGTH/WIDTH en el código anterior.

(2) Muchos conductores no son compatibles con DM_PAPERLENGTH/ANCHO en absoluto. Con estos controladores, simplemente no puede establecer el tamaño del papel como lo intenta hacer arriba. Solo puede seleccionar uno de los dmPaperSizes predefinidos.

Puede utilizar DeviceCapabilities (DC_FIELDS) para determinar si su controlador es compatible con DM_PAPERLENGTH/ANCHO.

Puede utilizar DeviceCapabilities (DC_PAPERS) para enumerar los dmPaperSizes permisibles.

+0

Creo que esto me ha puesto en el camino correcto ... aunque MSDN dice que establezca dmPaperSize en cero: http://msdn.microsoft.com/en-us/library/ms896928.aspx – Brandi

+0

Actualización: Encontré esto: http://support.microsoft.com/kb/108924 que dice 0 no es el valor correcto. – Brandi

Cuestiones relacionadas