Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > [VC#] Функция 'DefWindowProc'


Автор: MuForum 29.10.2007, 14:42
Доброе время суток!
- Так как мне никто не смог помочь в моей приведущей теме, то я уже пишу новую с новой проблемой.

Задача: Необходимо перехватывать системные сообщения указанному окну.

На C++ это выглядело так:
Код

LRESULT m_OrigWndProc;
bool m_Subclassed = false;
bool SubClassWindowProc(HWND);
LRESULT CALLBACK SCWinProc( HWND, UINT, WPARAM, LPARAM);
//---------------------------------------------------------------------------

bool SubClassWindowProc(HWND hWnd)
{
 m_OrigWndProc = GetWindowLongPtr(hWnd,GWL_WNDPROC);
 if(SetWindowLongPtr(hWnd,GWL_WNDPROC,(LONG)SCWinProc) == m_OrigWndProc)
 {
  m_Subclassed = true;
 }
 else
 {
  m_Subclassed = false;
 }
 ChangeDisplaySettings(NULL,0);
 return m_Subclassed;
}
//---------------------------------------------------------------------------

LRESULT CALLBACK SCWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 switch(uMsg)
 {
  case WM_ACTIVATE:
  case WM_KILLFOCUS: return DefWindowProc(hWnd,uMsg,wParam,lParam); break;
  default: break;
 }
 return CallWindowProc((FARPROC)m_OrigWndProc,hWnd,uMsg,wParam,lParam);
}
//---------------------------------------------------------------------------


Перевести данный код в полном объёме на C# у меня не выходит =(


# Вот то, что у меня приблизительно выходит:
Код

IntPtr m_OrigWndProc;
bool m_Subclassed = false;
delegate bool SubClassWindowProc(IntPtr hWnd);
IntPtr SCWinProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
//---------------------------------------------------------------------------

bool SubClassWindowProc(IntPtr hWnd)
{
 public const GWL_WNDPROC = (-4);
 m_OrigWndProc = GetWindowLongPtr(hWnd,GWL_WNDPROC);
 if(SetWindowLongPtr(hWnd,GWL_WNDPROC,(long)SCWinProc) == m_OrigWndProc)
 {
  m_Subclassed = true;
 }
 else
 {
  m_Subclassed = false;
 }
 ChangeDisplaySettings(null,0);
 return m_Subclassed;
}
//---------------------------------------------------------------------------

        public static IntPtr SCWinProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam)
        {
            const uint WM_ACTIVATE = 0x0006;
            const uint WM_KILLFOCUS = 0x0008;
            switch(uMsg)
            {
                case WM_ACTIVATE:
                case WM_KILLFOCUS: return DefWindowProc(hWnd, uMsg, wParam, lParam);
                default: break;
            }
            return CallWindowProc((FARPROC)m_OrigWndProc, hWnd, uMsg, wParam, lParam);
        }

Автор: VisualProgrammerNET 29.10.2007, 14:59
А нужно ли вообще переводить? Напиши дллку на плюсах, а потом из программы на C# просто вызывай из неё нужный метод - и будет тебе щастье  smile 

Автор: MuForum 29.10.2007, 15:02
#2, VisualProgrammerNET - Тут дело принципа, хоче разобраться и сделать именно на C#.

P.S. -> Если можешь помочь, буду благодарен.

Автор: Walker 29.10.2007, 15:17
Доброго времени суток!
В .NET концепция сообщений завуалирована концепцией событий. Аналогии сможете позднее провести самостоятельно. Вы "подписываете" контрол на системное событие (Загрузка окна, щелчок кнопки мыши, нажатие на кнопку клавиатуры). Делается это путём объявления делегата.
Код

f.Load += new System.EventHandler(f.Form_Load);

Как только событие происходит, вызывается функция его обработки, которой в числе аргументов передаются ещё и дополнительные полезные сведения, полученные от системы - например, какая кнопка мыши именно была нажата и где находлся в это время курсор
Код

private void Form_Load(object sender, EventArgs e)
{
 // Ваш код. Что должно быть выполнено, если произошла загрузка окна.
}

Список событий, на которые может быть подписан контрол, приведён в документации (msdn - для встроенных MS-контролов). Если работаете в студии, то в дизайнере в свойствах контрола есть перечень событий - находите нужное, щёлкаете два раза мышкой и пишите код функции обработки события. Т.е. то, что бы Вы написали после, например, case WM_ACTIVATE:
P.S. Примеры приведены на собтыие загрузки окна.

Автор: MuForum 29.10.2007, 15:36
#4, Walker - Проблема в том, что я работаю с чужим окном, а не своим!

Автор: Walker 29.10.2007, 16:00
Хук, что ли, поставить? Тогда, ИМХО, боюсь, C# действительно неэффективен для таких задач. Я не знаю классов, "занимающихся этим вопросом". Попробуйте поискать в направлении "C# для диагностических задач", может есть методы цепляния к чужим процессам, но и они не могут быть реализованы в безопасном коде... Кстати, нужное вам окно тоже спроектировано в .NET? Если нет, то нельзя однозначно, ведь приходится вылезать за границы среды исполнения. Тогда пишите класс управления "хуками", засунутыми в dll.

Автор: stab 29.10.2007, 16:21
MuForum, .NET не самая подходящая среда для таких хитростей. Лучше наверное оставить этот низкоуровневый код в исходном виде, видимо, в DLL, иначе он с чужими окнами работать никак не мог. И посылать из него уведомления управляющему .NET процессу с помощью SendMessage или другого механизма.

Добавлено через 7 минут и 33 секунды
.. или под чужими окнами подразумеваются чужие, но в том же процессе?

Автор: Stepan_Lameroff 29.10.2007, 16:51
Набросал по-быстрому (не тестировал!)
Думаю, что после доработки напильником должно работать smile

Код

    [StructLayout(LayoutKind.Sequential)]
    public struct DEVMODE
    {
        public const int CCHDEVICENAME = 32;
        public const int CCHFORMNAME = 32;
        public short dmBitsPerPel;
        public short dmCollate;
        public short dmColor;

        public short dmCopies;
        public short dmDefaultSource;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
        public string dmDeviceName;

        public int dmDisplayFlags;
        public int dmDisplayFrequency;
        public int dmDitherType;
        public short dmDriverExtra;
        public short dmDriverVersion;
        public short dmDuplex;
        public int dmFields;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
        public string dmFormName;

        public int dmICMIntent;
        public int dmICMMethod;
        public short dmLogPixels;
        public int dmMediaType;
        public short dmOrientation;
        public int dmPanningHeight;
        public int dmPanningWidth;
        public short dmPaperLength;
        public short dmPaperSize;
        public short dmPaperWidth;
        public int dmPelsHeight;
        public int dmPelsWidth;

        public int dmPositionX;
        public int dmPositionY;
        public short dmPrintQuality;
        public int dmReserved1;
        public int dmReserved2;
        public short dmScale;
        public short dmSize;
        public short dmSpecVersion;
        public short dmTTOption;
        public short dmYResolution;
    }

    public enum GWL
    {
        GWL_WNDPROC = (-4),
        GWL_HINSTANCE = (-6),
        GWL_HWNDPARENT = (-8),
        GWL_STYLE = (-16),
        GWL_EXSTYLE = (-20),
        GWL_USERDATA = (-21),
        GWL_ID = (-12)
    }

    public delegate IntPtr WndProcDelegate(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    internal class HookWindowsMessages
    {
        private static IntPtr m_OrigWndProc;
        private static bool m_Subclassed = false;

        [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
        private static extern int SetWindowLong32(HandleRef hWnd,
                                                  int nIndex,
                                                  [MarshalAs(UnmanagedType.FunctionPtr)] WndProcDelegate windowCallback);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
        private static extern IntPtr SetWindowLongPtr64(HandleRef hWnd,
                                                        int nIndex,
                                                        [MarshalAs(UnmanagedType.FunctionPtr)] WndProcDelegate
                                                            windowCallback);

        public static IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, WndProcDelegate windowCallback)
        {
            if (IntPtr.Size == 8)
                return SetWindowLongPtr64(hWnd, nIndex, windowCallback);
            else
                return new IntPtr(SetWindowLong32(hWnd, nIndex, windowCallback));
        }

        [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
        private static extern int GetWindowLong32(HandleRef hWnd, int nIndex);

        [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
        private static extern IntPtr GetWindowLongPtr64(HandleRef hWnd, int nIndex);

        public static IntPtr GetWindowLongPtr(HandleRef hWnd, int nIndex)
        {
            if (IntPtr.Size == 8)
                return GetWindowLongPtr64(hWnd, nIndex);
            else
                return new IntPtr(GetWindowLong32(hWnd, nIndex));
        }

        [DllImport("user32.dll")]
        private static extern IntPtr DefWindowProc(IntPtr hWnd,
                                                   uint uMsg,
                                                   IntPtr wParam,
                                                   IntPtr lParam);

        [DllImport("User32.dll")]
        private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc,
                                                    IntPtr hWnd,
                                                    uint iMsg,
                                                    IntPtr wParam,
                                                    IntPtr lParam);

        public static IntPtr HookWindowMessage(HandleRef window, WndProcDelegate callback)
        {
            return SetWindowLongPtr(window, (int)GWL.GWL_WNDPROC, callback);
        }

        [DllImport("user32.dll")]
        public static extern int EnumDisplaySettings(string deviceName,
                                                     int modeNum,
                                                     ref DEVMODE devMode);

        [DllImport("user32.dll")]
        public static extern int ChangeDisplaySettings(ref DEVMODE devMode,
                                                       int flags);

        public static bool SubClassWindowProc(HandleRef hWnd)
        {
            m_OrigWndProc = GetWindowLongPtr(hWnd, (int)GWL.GWL_WNDPROC);
            if (HookWindowMessage(hWnd, SCWinProc) == m_OrigWndProc)
            {
                m_Subclassed = true;
            }
            else
            {
                m_Subclassed = false;
            }

            DEVMODE d = new DEVMODE();
            ChangeDisplaySettings(ref d, 0);
            return m_Subclassed;
        }

        public static IntPtr SCWinProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam)
        {
            const uint WM_ACTIVATE = 0x0006;
            const uint WM_KILLFOCUS = 0x0008;
            switch (uMsg)
            {
                case WM_ACTIVATE:
                case WM_KILLFOCUS:
                    return DefWindowProc(hWnd, uMsg, wParam, lParam);
                default:
                    break;
            }
            return CallWindowProc(m_OrigWndProc, hWnd, uMsg, wParam, lParam);
        }
    }

Автор: MuForum 29.10.2007, 17:25
#8, Stepan_Lameroff - Благодарю за помощь, сейчас буду разбираться.

P.S. -> Может кому понадобиться...

Код

public enum SWP
        {
            SWP_NOSIZE = 0x0001,
            SWP_NOMOVE = 0x0002,
            SWP_NOZORDER = 0x0004,
            SWP_NOREDRAW = 0x0008,
            SWP_NOACTIVATE = 0x0010,
            SWP_FRAMECHANGED = 0x0020,
            SWP_SHOWWINDOW = 0x0040,
            SWP_HIDEWINDOW = 0x0080,
            SWP_NOCOPYBITS = 0x0100,
            SWP_NOOWNERZORDER = 0x0200,
            SWP_NOSENDCHANGING = 0x0400,
            SWP_DRAWFRAME = SWP_FRAMECHANGED,
            SWP_NOREPOSITION = SWP_NOOWNERZORDER,
            SWP_DEFERERASE = 0x2000,
            SWP_ASYNCWINDOWPOS = 0x4000
        }

Автор: MuForum 29.10.2007, 18:10
#8, Stepan_Lameroff - Сделал, но к сажалению почему-то функция вообще не вызывается по время работы =(

P.S. -> Появляется только сообщение "Step1", а "Step2" и "Step3" не появляются=(


Код

                else if (vkCode == 0x7B) // if have pressed button "F12"
                {
                    if (fullmode2 == true)
                    {
                        if (IsWindowVisible(hWnd2) != 0)
                        {
                            SetWindowPos((IntPtr)hWnd2, (IntPtr)1, 0, (-13), CorX + 5, CorY + 10, 0x0001 | 0x0002 | 0x0004 | 0x0010 | 0x0080 | 0x0400);
                            m_OrigWndProc = GetWindowLongPtr((IntPtr)hWnd2, (int)GWL.GWL_WNDPROC);
                            HookWindowMessage((IntPtr)hWnd2, SCWinProc);
                            DEVMODE d = new DEVMODE();
                            ChangeDisplaySettings(ref d, 0);
                            MessageBox.Show("Spet1");
                        }
                        else
                        {
                            SetWindowPos((IntPtr)hWnd2, (IntPtr)(-1), 0, (-13), CorX + 5, CorY + 10, 0x0001 | 0x0002 | 0x0040);
                            SetForegroundWindow(hWnd2);
                        }
                    }
                    return (IntPtr)1;
                }

...

        public static IntPtr SCWinProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam)
        {
            MessageBox.Show("Spet2");
            const uint WM_ACTIVATE = 0x0006;
            const uint WM_KILLFOCUS = 0x0008;
            switch (uMsg)
            {
                case WM_ACTIVATE:
                case WM_KILLFOCUS:
                    MessageBox.Show("Spet3");
                    return DefWindowProc(hWnd, uMsg, wParam, lParam);
                default:
                    break;
            }
            return CallWindowProc(m_OrigWndProc, hWnd, uMsg, wParam, lParam);
        }

...

private static IntPtr m_OrigWndProc;

        public delegate IntPtr WndProcDelegate(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
        private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, [MarshalAs(UnmanagedType.FunctionPtr)] WndProcDelegate windowCallback);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
        private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, [MarshalAs(UnmanagedType.FunctionPtr)] WndProcDelegate windowCallback);
        public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, WndProcDelegate windowCallback)
        {
            if (IntPtr.Size == 8)
                return SetWindowLongPtr64(hWnd, nIndex, windowCallback);
            else
                return new IntPtr(SetWindowLong32(hWnd, nIndex, windowCallback));
        }

        [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
        private static extern int GetWindowLong32(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
        private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);

        public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
        {
            if (IntPtr.Size == 8)
                return GetWindowLongPtr64(hWnd, nIndex);
            else
                return new IntPtr(GetWindowLong32(hWnd, nIndex));
        }

        [DllImport("user32.dll")]
        private static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
        [DllImport("User32.dll")]
        private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint iMsg, IntPtr wParam, IntPtr lParam);

        public static IntPtr HookWindowMessage(IntPtr window, WndProcDelegate callback)
        {
            return SetWindowLongPtr(window, (int)GWL.GWL_WNDPROC, callback);
        }

        [DllImport("user32.dll")]
        public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);
        [DllImport("user32.dll")]
        public static extern int ChangeDisplaySettings(ref DEVMODE devMode, int flags);


        [DllImport("user32.dll")]
        public static extern int FindWindow(string strclassName, string strWindowName);

        [DllImport("user32.dll")]
        public static extern void SetWindowText(int h, String s);

        [DllImport("user32.dll")]
        private static extern int IsWindowVisible(int hwnd);

        [DllImport("user32.dll")]
        private static extern int SetForegroundWindow(int hwnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SetWindowLong(IntPtr hWnd, int Index, uint Value);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);


        [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
        public static extern int GetSystemMetrics(int abc);

        [DllImport("user32.dll", ExactSpelling = true)]
        private static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        [StructLayout(LayoutKind.Sequential)]
        public struct DEVMODE
        {
            public const int CCHDEVICENAME = 32;
            public const int CCHFORMNAME = 32;
            public short dmBitsPerPel;
            public short dmCollate;
            public short dmColor;
            public short dmCopies;
            public short dmDefaultSource;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
            public string dmDeviceName;
            public int dmDisplayFlags;
            public int dmDisplayFrequency;
            public int dmDitherType;
            public short dmDriverExtra;
            public short dmDriverVersion;
            public short dmDuplex;
            public int dmFields;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
            public string dmFormName;
            public int dmICMIntent;
            public int dmICMMethod;
            public short dmLogPixels;
            public int dmMediaType;
            public short dmOrientation;
            public int dmPanningHeight;
            public int dmPanningWidth;
            public short dmPaperLength;
            public short dmPaperSize;
            public short dmPaperWidth;
            public int dmPelsHeight;
            public int dmPelsWidth;
            public int dmPositionX;
            public int dmPositionY;
            public short dmPrintQuality;
            public int dmReserved1;
            public int dmReserved2;
            public short dmScale;
            public short dmSize;
            public short dmSpecVersion;
            public short dmTTOption;
            public short dmYResolution;
        }

        public enum GWL
        {
            GWL_WNDPROC = (-4),
            GWL_HINSTANCE = (-6),
            GWL_HWNDPARENT = (-8),
            GWL_STYLE = (-16),
            GWL_EXSTYLE = (-20),
            GWL_USERDATA = (-21),
            GWL_ID = (-12)
        }

        public enum SWP
        {
            SWP_NOSIZE = 0x0001,
            SWP_NOMOVE = 0x0002,
            SWP_NOZORDER = 0x0004,
            SWP_NOREDRAW = 0x0008,
            SWP_NOACTIVATE = 0x0010,
            SWP_FRAMECHANGED = 0x0020,
            SWP_SHOWWINDOW = 0x0040,
            SWP_HIDEWINDOW = 0x0080,
            SWP_NOCOPYBITS = 0x0100,
            SWP_NOOWNERZORDER = 0x0200,
            SWP_NOSENDCHANGING = 0x0400,
            SWP_DRAWFRAME = SWP_FRAMECHANGED,
            SWP_NOREPOSITION = SWP_NOOWNERZORDER,
            SWP_DEFERERASE = 0x2000,
            SWP_ASYNCWINDOWPOS = 0x4000
        }



P.S. -> Странно то, что функция по сути должны обрабатываться(Но как видно из примера, то шаги 2 и 3 не выводится сис.сообщениями) =(

Автор: Stepan_Lameroff 29.10.2007, 20:37
Посмотрите http://sourceforge.net/project/showfiles.php?group_id=175606
Цитата

A collection of .NET components that wrap PInvoke calls to access native API by managed code

Там есть ответы на все ваши вопросы. (начинайте с ...\mwinapi\ManagedWinapi\SystemWindow.cs)
Исходники берите лучше в SVN - "svn co https://mwinapi.svn.sourceforge.net/svnroot/mwinapi/trunk mwinapi"

http://forum.vingrad.ru/index.php?showtopic=170164&view=findpost&p=1244439 я выкладывал пример работы с этой библиотекой

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)