2009-07-08 2 views
2

다음 페이지에 따르면 : 첫 번째 그래픽 아래C# 사용자 정의 PrintDialog PInvoke를 DevMode를 질문

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

, "사용자가 확인 버튼을 클릭하면, PRINTDLG TRUE를 반환하고 PRINTDLG 구조가에 대해 informmation를 반환 사용자 선택 ".

이 경우 내 사용자 정의 인쇄 대화 상자가 거의 작동하지만 프린터 이름, 방향 등에 대한 정보를 추출하려고합니다. 프린터 이름을 검색하기 위해서는 다음과 같이해야합니다. PRINTDLG 구조체에서 hDevMode 값을 검사하여 프린터 이름을 확인하십시오. 그 정보를 추출 할 수있는 함수가 있습니까? (pdlg는 PRINTDLG 구조의 내 정의 된 인스턴스 인 경우에)

내 코드가 같다 : 누군가가 그곳에 pearlsof 지혜가있는 경우

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

, 나는 확실히 어떤 조언을 부탁드립니다.

답변

2

다음은 프린터 이름과 드라이버를 추출하는 방법입니다. 열쇠는 hDevNames에서 GlobalLock을 수행하고 Marshal.PtrToStructurestruct의 CLR 버전에 넣은 다음 내용에 액세스하는 것입니다. 완료되면 GlobalUnlock을 기억하십시오.

hDevMode와 비슷한 기능을 수행하면 프린터 메트릭 및 설정에 대한 정보를 얻을 수 있습니다. DEVMODE 구조체 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