2010-03-12 2 views
8

Tôi muốn có thể thay đổi các thuộc tính của máy in mà không cần bật lên cửa sổ thuộc tính máy in ...Liệu PrinterSettings.GetHdevmode() có lỗi không?

Sử dụng chức năng DocumentProperties (nhập từ winspool.drv) cho đến nay không thành công, bởi vì trong khi nó rất dễ dàng để ngăn chặn hộp thoại hiển thị, có vẻ như giá trị trả về bởi PrinterSettings.GetHdevmode() không phản ánh PrinterSettings đang gọi nó, nhưng thay vào đó giá trị từ các thuộc tính máy in trước đó trả về OK. Ví dụ, điều này mang lại cho tôi những giá trị (sai) trước từ cuộc gọi cuối cùng để các thuộc tính, thay vì các giá trị cần có từ PrinterSettings đối tượng:

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

Vì vậy, không GetHdevmode có một lỗi hay là những gì của nó phải làm gì? Có một C# làm việc xung quanh cho điều này hay không ai thậm chí có bất kỳ thông tin về nó? Tôi đã bị ép ngay cả khi tìm thông tin về chủ đề này.

Cảm ơn trước vì mọi thông tin chi tiết.

EDIT: Tôi không muốn điều này quá cá nhân, nhưng hy vọng rằng tất cả thông tin trong trường hợp này có thể cung cấp câu trả lời cũng là giải pháp hữu ích cho người khác.

Dưới đây là một DLL C++ tôi đã viết để có giải pháp cho vấn đề này. Nó hiện không hoạt động - nó thay đổi bộ nhớ khác như bản sao, và không thành công trong việc thay đổi các giấy tờ "cơ bản". Tôi nghĩ tất cả những gì tôi cần làm là chỉ định cờ đệm ra để thực hiện thay đổi?

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; 
    } 

Tôi nhận thấy ++ mã C là đủ để thay đổi các thiết lập, vì vậy tất cả tôi làm trong C# là thế này:

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; 
    } 

UPDATE: Đã thay đổi lên thứ tự một chút với dmPaperSize và dmFields. Cải thiện kết quả; chưa hoàn toàn ở đó.

CẬP NHẬT 2: OK, tôi đã tìm thấy trang microsoft cho biết tài liệu sai. MSDN nói để đặt dmPaperSize thành 0 khi bạn muốn chỉ định chiều rộng và chiều cao trong khi sửa chữa Hỗ trợ của Microsoft nói để đặt nó thành DMPAPER_USER. http://support.microsoft.com/kb/108924

+0

Tôi sử dụng C++. Hầu hết các vấn đề liên quan đến cấu trúc 'DEVMODE' mà tôi gặp phải liên quan đến 1) Đọc vấn đề - không khóa bộ nhớ trước khi truy cập cấu trúc hoặc 2) Viết vấn đề - không tạo cấu trúc mới khi cài đặt' DEVMODE'. HTH. – dirkgently

+0

Đoạn mã của bạn không có ý nghĩa gì, nó đặt lại những gì đã có ở đó.Mùi giống như một vấn đề lựa chọn máy in mặc định, nhưng không có đầu mối từ các thông tin nhất định. Đăng thêm mã hoặc yêu cầu người khác giúp bạn giải thích vấn đề tốt hơn. –

+0

@nobugz: Chính xác là ... chỉ cần đặt nó vào trong đó, nhưng thay vào đó nó đưa ra một giá trị khác, không phản ánh đối tượng cài đặt máy in được sử dụng để tạo nó, mà là cuộc gọi cuối cùng đến thuộc tính máy in. Nó không phải là một vấn đề máy in mặc định (đây là trên bảng). @dirkgently: Tôi đã thử viết một C + + DLL, nhưng nó đã kết thúc thay đổi bộ nhớ khác bên cạnh đó mà tôi đã cố gắng để thay đổi. Không chắc tôi đang làm gì sai, nhưng có vẻ như tôi nên nhìn vào giải pháp khóa bộ nhớ. Cám ơn vì sự gợi ý. :) – Brandi

Trả lời

2

Có 2 vấn đề với cách bạn đang xác định kích thước giấy trong devmode:

(1) Nếu bạn chỉ định DM_PAPERWIDTH hoặc DM_PAPERLENGTH hoặc cả hai, bạn PHẢI KHÔNG cũng thiết lập các bit DM_PAPERSIZE. Nó phụ thuộc vào trình điều khiển máy in, nhưng nhiều trình điều khiển sẽ bỏ qua DM_PAPERLENGTH/WIDTH trong đoạn mã trên.

(2) Nhiều trình điều khiển không hỗ trợ DM_PAPERLENGTH/WIDTH. Với trình điều khiển như vậy, bạn chỉ đơn giản là không thể thiết lập kích thước giấy như bạn đang cố gắng làm ở trên. Bạn chỉ có thể chọn một trong các dmPaperSizes được xác định trước.

Bạn có thể sử dụng DeviceCapabilities (DC_FIELDS) để xác định xem trình điều khiển của bạn có hỗ trợ DM_PAPERLENGTH/WIDTH không.

Bạn có thể sử dụng DeviceCapabilities (DC_PAPERS) để liệt kê các dmPaperSizes cho phép.

+0

Tôi nghĩ rằng điều này đã đặt tôi vào đúng hướng ... mặc dù MSDN không nói để đặt dmPaperSize thành số không: http://msdn.microsoft.com/en-us/library/ms896928.aspx – Brandi

+0

Cập nhật: Tôi thấy điều này: http://support.microsoft.com/kb/108924 cho biết 0 không phải là giá trị chính xác. – Brandi