C # Custom PrintDialog PInvoke DevMode Вопрос - PullRequest
2 голосов
/ 09 июля 2009

Согласно следующей странице:

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

под первым рисунком: «Если пользователь нажимает кнопку ОК, PrintDlg возвращает значение ИСТИНА и структуру 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
        } 

Если у кого-то есть жемчужины мудрости, я буду признателен за любые советы.

1 Ответ

2 голосов
/ 09 июля 2009

Ниже показано, как извлечь имя принтера и драйвер. Ключ должен сделать GlobalLock для hDevNames, Marshal.PtrToStructure в CLR-версию struct , а затем получить доступ к ее содержимому. Не забудьте GlobalUnlock когда закончите.

Вы можете сделать что-то подобное с hDevMode, который даст вам информацию о параметрах и настройках принтера. Вы можете найти объявление C # DEVMODE struct здесь .

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