2009-07-08 59 views
2

按照以下頁面:C#自定義PrintDialog類的PInvoke DevMode的問題

http://msdn.microsoft.com/en-us/library/ms646964(VS.85).aspx

第一圖形的下面,「如果用戶點擊OK按鈕,PRINTDLG返回TRUE和PRINTDLG結構返回有關informmation用戶選擇「。

在這種情況下,我的自定義打印對話框幾乎可以正常工作,但我試圖提取有關打印機名稱,方向等信息......我的理解是,爲了檢索打印機名稱,我需要檢查PRINTDLG結構中的hDevMode值以查看打印機名稱。有沒有一個函數可以讓我提取這些信息?

我的代碼是這樣(其中PDLG是我定義的PRINTDLG結構的實例):

 bool f = false; 
     try 
     { 
      f = PrintDlg(ref pdlg); 
      DEVMODE dm = pdlg.hDevMode; 
      int k = 0; 
     } catch (Exception ex) 
     { 
      // hopefully it doesn't fail 
     } 

如果有人有任何pearlsof智慧在那裏,我將肯定得到任何提示。

回答

2

以下顯示如何提取打印機名稱和驅動程序。關鍵是在hDevNames上做一個GlobalLockMarshal.PtrToStructure把它變成CLR版本的struct,然後訪問它的內容。完成後請記住GlobalUnlock

您可以使用hDevMode做類似的事情,它會爲您提供有關打印機指標和設置的信息。您可以找到DEVMODE struct here的C#聲明。

using System; 
using System.Runtime.InteropServices; 

namespace ConsoleApplication3 { 
    class Program { 

     // Win32 struct declarations 
     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)] 
     [System.Runtime.InteropServices.ComVisible(false)] 
     internal class PRINTDLG { 
      public Int32 lStructSize; 
      public IntPtr hwndOwner; 
      public IntPtr hDevMode; 
      public IntPtr hDevNames; 
      public IntPtr hDC = IntPtr.Zero; 
      public Int32 Flags; 
      public Int16 FromPage = 0; 
      public Int16 ToPage = 0; 
      public Int16 MinPage = 0; 
      public Int16 MaxPage = 0; 
      public Int16 Copies = 0; 
      public IntPtr hInstance = IntPtr.Zero; 
      public IntPtr lCustData = IntPtr.Zero; 
      public IntPtr lpfnPrintHook; 
      public IntPtr lpfnSetupHook = IntPtr.Zero; 
      public IntPtr lpPrintTemplateName = IntPtr.Zero; 
      public IntPtr lpSetupTemplateName = IntPtr.Zero; 
      public IntPtr hPrintTemplate = IntPtr.Zero; 
      public IntPtr hSetupTemplate = IntPtr.Zero; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public class DEVNAMES { 
      public short wDriverOffset; 
      public short wDeviceOffset; 
      public short wOutputOffset; 
      public short wDefault; 
     } 

     // import PrintDlg, GlobalLock and GlobalUnlock 
     [DllImport("comdlg32.dll", CharSet = CharSet.Auto)] 
     private static extern bool PrintDlg([In, Out] PRINTDLG lppd); 

     [DllImport("kernel32.dll")] 
     private static extern IntPtr GlobalLock(IntPtr hMem); 

     [DllImport("kernel32.dll")] 
     private static extern bool GlobalUnlock(IntPtr hMem); 

     static void Main(string[] args) { 
      // show the printer dialog box 
      PRINTDLG pd = new PRINTDLG(); 
      pd.lStructSize = Marshal.SizeOf(pd); 
      PrintDlg(pd); 

      // here's the meat -- extract the printer information 
      // out of pd.hDevNames... 
      DEVNAMES devNames = new DEVNAMES(); 

      // lock hDevNames into memory and get a pointer to it 
      IntPtr pDevNames = GlobalLock(pd.hDevNames); 

      // marshal into a DEVNAME struct 
      Marshal.PtrToStructure(pDevNames, devNames); 

      // pull out the device and driver strings; hopefully not much of 
      // that in DEVMODE 
      string sDevice = Marshal.PtrToStringUni((IntPtr) (
       pDevNames.ToInt32() + 
        devNames.wDeviceOffset * Marshal.SystemDefaultCharSize)); 
      string sDriver = Marshal.PtrToStringUni((IntPtr) (
       pDevNames.ToInt32() + 
        devNames.wDriverOffset * Marshal.SystemDefaultCharSize)); 
      string sOutput = Marshal.PtrToStringUni((IntPtr) (
       pDevNames.ToInt32() + 
        devNames.wOutputOffset * Marshal.SystemDefaultCharSize)); 

      // done -- release the global memory handle 
      GlobalUnlock(pd.hDevNames); 
     } 
    } 
} 
+0

非常感謝。如果有問題的打印機長度超過32個字符,試圖打開DEVMODE.devName時會出現問題。我能夠獲得額外的信息,但該領域最終無法使用,所以我就這樣做了 – coson 2009-07-09 17:56:21