2009-04-07 26 views
5

Tôi đang sử dụng WPF và cần cho phép người dùng đặt một số tùy chọn liên quan đến in như máy in và thuộc tính máy in (ví dụ: papertray, landscape/portrait, duplex, v.v ...). Tôi biết về lớp PrintDialog để lấy đối tượng PrintQueue và PrintTicket. Tuy nhiên tôi cần phải tạo giải pháp tùy chỉnh và không thể hiển thị PrintDialog. Tôi quản lý để nhận các đối tượng PrintQueue có sẵn và cho phép người dùng chọn máy in. Tôi đang đấu tranh với các thuộc tính máy in. Câu hỏi của tôi là: làm cách nào tôi có thể hiển thị hộp thoại trong đó người dùng có thể đặt thuộc tính máy in cho PrintQueue đã chọn (hộp thoại được hiển thị khi người dùng nhấp vào nút Thuộc tính trong WPF PrintDialog).Làm cách nào để tôi có thể gọi hộp thoại để đặt tùy chọn máy in theo cách thủ công?

+0

Xem câu hỏi này: http://stackoverflow.com/questions/2437337/how-to-show-printer-properties-preferences-dialog-and -lưu thay đổi –

Trả lời

4

Mã sau được tìm thấy here (trừ sự kiện Window_Loaded). Tôi đã thử nghiệm nó và nó có vẻ hoạt động như một sự quyến rũ. Rõ ràng bạn sẽ phải đặt tên máy in trong đối tượng PrinterSettings trước khi hiển thị hộp thoại.

Hy vọng điều này làm việc cho bạn:

[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); 

[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); 

private const Int32 DM_OUT_BUFFER = 14; 

public void OpenPrinterPropertiesDialog(PrinterSettings printerSettings, System.IntPtr pHandle) { 
    IntPtr hDevMode = printerSettings.GetHdevmode(); 
    IntPtr pDevMode = GlobalLock(hDevMode); 
    Int32 fMode = 0; 
    int sizeNeeded = DocumentProperties(pHandle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, pDevMode, fMode); 
    IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded); 

    fMode = DM_OUT_BUFFER; 

    DocumentProperties(pHandle, IntPtr.Zero, printerSettings.PrinterName, devModeData, pDevMode, fMode); 
    GlobalUnlock(hDevMode); 
    printerSettings.SetHdevmode(devModeData); 
    printerSettings.DefaultPageSettings.SetHdevmode(devModeData); 
    GlobalFree(hDevMode); 
    Marshal.FreeHGlobal(devModeData); 
} 

private void Window_Loaded(object sender, RoutedEventArgs e) { 
    OpenPrinterPropertiesDialog(new PrinterSettings(), new WindowInteropHelper(this).Handle); 
} 
3

Nếu bạn nhắm mục tiêu x86 biên soạn và chạy từ một máy x64, mã từ Pwninstein sẽ không hoạt động: khi phân bổ devModeData, DocumentPropreties sẽ luôn luôn thất bại và trả về một sizeNeeded của -1, với một mã LastError 13.

để giải quyết vấn đề, hoặc đảm bảo bạn nhắm mục tiêu AnyCPU hoặc chỉ cần thay đổi các cuộc gọi đến DocumentPropreties như sau:

int sizeNeeded = DocumentProperties(pHandle, 
            IntPtr.Zero, 
            printerSettings.PrinterName, 
            IntPtr.Zero, // This solves it 
            pDevMode, 
            fMode); 

Sử dụng IntPtr.Zero thay vì một con trỏ thích hợp để một cấu trúc devmode trông sai, nhưng mà cuộc gọi đầu tiên để DocumentProperties không cố gắng để thay đổi bộ nhớ tại vị trí đó. Dữ liệu duy nhất được trả về bởi cuộc gọi là kích thước bộ nhớ cần thiết để lưu trữ dữ liệu chế độ thiết bị đại diện cho các tham số bên trong của trình điều khiển in.

tham khảo:

Các vấn đề liên quan