2

根据以下页面:

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

在第一个图形下方,“如果用户单击确定按钮,PrintDlg 返回 TRUE,PRINTDLG 结构返回有关用户选择的信息”。

在这种情况下,我的自定义打印对话框几乎可以工作,但我正在尝试提取有关打印机名称、方向等的信息......我的理解是,为了检索打印机名称,我需要检查 hDevMode 值从 PRINTDLG 结构中查看打印机名称。是否有可以让我提取该信息的功能?

我的代码就像(其中 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
        } 

如果有人有任何智慧的珍珠,我肯定会很感激任何提示。

4

1 回答 1

3

下面显示如何提取打印机名称和驱动程序。关键是在hDevNames上做一个GlobalLock , Marshal.PtrToStructure把它变成CLR版本的struct,然后访问它的内容。完成后记得GlobalUnlock

您可以使用 hDevMode 执行类似的操作,这将为您提供有关打印机指标和设置的信息。您可以在此处找到DEVMODE结构的 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);
        }
    }
}
于 2009-07-09T01:15:26.873 回答