Модераторы: gambit, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Изменение режима окна: 'FullScreen' - 'WindowMode', свернуть и работать с другими окнамами 
:(
    Опции темы
MuForum
  Дата 27.10.2007, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



Доброе время суток!
Я начинаю программист, недавно перешел с 'C++' на 'C#', так что строго прошу не судить, а по возможности указать на ошибки.


# Задача:
  1.  Необходимо написать программу, которая будет перехватывать нажатия кнопок клавиатуры 'F11', 'F12' (Низкоуровневой) — Это осуществил.
  2.  При нажатие на кнопку 'F11', Необходимо менять статус чужого окна из 'FullScreen' в 'WindowMode' и наоборот — Это осуществил.
  3.  При нажатие на кнопку 'F12', необходимо скрывать(Hide)/показывть(Show) окно. — Тут проблема.


# Детально о проблеме:
  •  Если запустить изначально игру в режиме 'окно' (В дальнейшем 'WindowMode'), затем скрыть(В дальнейшем 'Hide') игру, то можно свободно работать с остальными приложениями. (То есть тут проблем не возникает), но если изначально запустить игру в режиме 'полный экран' (В дальнейшем 'FullScreen'), затем при помощи кнопки 'F11' поменять статус окна на 'WindowMode', затем скрыть(Hide), и попытаться нажать вне окна, то окно игры тутже разворачивается. (3 раза повторив — игра закрывается).

    P.S. -> Окно, над которым необходимо делать изменения(Не наше), то есть в коде той программы ничего не возможно изменять.
Код

        private static int hWnd, hWnd2;
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYUP = 0x0101;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;
......
......
......
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if ((nCode >= 0) && (wParam == (IntPtr)WM_KEYUP))
            {
                int vkCode = Marshal.ReadInt32(lParam);
                if (vkCode == 0x7A) // if have pressed button "F11"
                {
                    if (FindWindow("MU", null) != 0)
                    {
                        hWnd = FindWindow(null, "Game");
                        SetWindowText(hWnd, "new game");
                        hWnd2 = FindWindow(null, "new game");
                    }
                    if (IsWindowVisible(hWnd2) != 0)
                    {
                        if (fullmode1 == false)
                        {
                            SetWindowLong(hWnd2, GWL.GWL_STYLE, WS.WS_VISIBLE);
                            DEVMODE dm = new DEVMODE();
                            dm.dmBitsPerPel = Convert.ToSByte(CD);
                            dm.dmPelsWidth = CorX;
                            dm.dmPelsHeight = CorY;
                            dm.dmDisplayFrequency = RR;
                            if (CDS.ChangeDisplaySettings(ref dm, CDS.CDS_FULLSCREEN) != CDS.DISP_CHANGE_SUCCESSFUL) CDS.ChangeDisplaySettings(ref dm, CDS.CDS_FULLSCREEN);
                            MoveWindow(hWnd2, 0, 0, CorX, CorY, true);
                            SetForegroundWindow(hWnd2);
                            fullmode1 = true;
                            fullmode2 = false;
                        }
                        else
                        {
                            SetWindowLong(hWnd2, GWL.GWL_STYLE, WS.WS_OVERLAPPED | WS.WS_VISIBLE | WS.WS_CAPTION | WS.WS_THICKFRAME | WS.WS_SYSMENU);
                            MoveWindow(hWnd2, 0, 0, CorX + 5, CorY + 10, true);
                            SetWindowPos(hWnd2, HWND.HWND_TOPMOST, 0, 0, CorX + 5, CorY + 10, SWP.SWP_NOSIZE | SWP.SWP_SHOWWINDOW);
                            SetForegroundWindow(hWnd2);
                            fullmode1=false;
                            fullmode2=true;
                        }
                    }
                    return (IntPtr)1;
                }
                else if (vkCode == 0x7B) // if have pressed button "F12"
                {
                    if (fullmode2 == true)
                    {
                        if (IsWindowVisible(hWnd2) != 0)
                        {
                            SetWindowPos(hWnd2, HWND.HWND_BOTTOM, 0, 0, CorX + 5, CorY + 10, SWP.SWP_NOSIZE | SWP.SWP_NOMOVE | SWP.SWP_NOZORDER | SWP.SWP_NOACTIVATE | SWP.SWP_HIDEWINDOW | SWP.SWP_NOCOPYBITS | SWP.SWP_NOSENDCHANGING);
                        }
                        else
                        {
                            SetWindowPos(hWnd2, HWND.HWND_TOPMOST, 0, 0, CorX + 5, CorY + 10, SWP.SWP_NOSIZE | SWP.SWP_NOMOVE | SWP.SWP_SHOWWINDOW);
                            SetForegroundWindow(hWnd2);
                        }
                    }
                    return (IntPtr)1;
                }
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
......
......
......
        // ------------------------------------------------------------

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

        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
        private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, GWL nIndex, [MarshalAs(UnmanagedType.FunctionPtr)] WndProcDelegate windowCallback);
        
        public static IntPtr SetWindowLongPtr(IntPtr hWnd, GWL 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, GWL nIndex);

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

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

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

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

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

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

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

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SetWindowLong(IntPtr hWnd, GWL uFlags1, WS uFlags2);

        [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", ExactSpelling = true)]
        private static extern int SetWindowPos(IntPtr hWnd, HWND Flags, int X, int Y, int cx, int cy, SWP uFlags);

        // ---------- Start: Hook function. ----------

        [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);

        // ---------- End: Hook function. ----------

        [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 : int
        {
            GWL_WNDPROC = (-4),
            GWL_HINSTANCE = (-6),
            GWL_HWNDPARENT = (-8),
            GWL_STYLE = (-16),
            GWL_EXSTYLE = (-20),
            GWL_USERDATA = (-21),
            GWL_ID = (-12)
        }

        public enum SWP : uint
        {
            SWP_NOSIZE = 0x0001, // Сообщает, что нужно игнорировать параметры задания размеров окну.
            SWP_NOMOVE = 0x0002, // Сообщает, что нужно игнорировать параметры задания позиции окну.
            SWP_NOZORDER = 0x0004, // Сохраняет текущее положение в Z-последовательности (игнорирует сообщение hWndInsertAfter parameter).
            SWP_NOREDRAW = 0x0008, // Не перерисовывает окно.
            SWP_NOACTIVATE = 0x0010, // Не активизирует окно.
            SWP_FRAMECHANGED = 0x0020,
            SWP_SHOWWINDOW = 0x0040, // Отображает окно.
            SWP_HIDEWINDOW = 0x0080, // Скрывает окно.
            SWP_NOCOPYBITS = 0x0100, // Если этот спецификатор не будет установлен, тогда содержимое клиентской области окна будет скопировано и вставлено во вновь отобразившееся окно после его перемещения.
            SWP_NOOWNERZORDER = 0x0200, //Сообщает, что не следует изменять позицию окна владельца в Z-последовательности.
            SWP_NOSENDCHANGING = 0x0400, // Мешает окну получить сообщение WM_WINDOWPOSCHANGING.
            SWP_DRAWFRAME = SWP_FRAMECHANGED, // Прорисовка фрейма вокруг окна.
            SWP_NOREPOSITION = SWP_NOOWNERZORDER, // Такой же как и SWP_NOOWNERZORDER.
            SWP_DEFERERASE = 0x2000,
            SWP_ASYNCWINDOWPOS = 0x4000
        }
        
        public enum HWND : int
        {
            HWND_TOP = 0,
            HWND_BOTTOM = 1,
            HWND_TOPMOST = (-1),
            HWND_NOTOPMOST = (-2)
        }

        //Window Styles used when creating a window
        public enum WS : uint
        {
            WS_OVERLAPPED = 0x00000000,
            WS_POPUP = 0x80000000,
            WS_CHILD = 0x40000000,
            WS_MINIMIZE = 0x20000000,
            WS_VISIBLE = 0x10000000,
            WS_DISABLED = 0x08000000,
            WS_CLIPSIBLINGS = 0x04000000,
            WS_CLIPCHILDREN = 0x02000000,
            WS_MAXIMIZE = 0x01000000,
            WS_CAPTION = 0x00C00000,    /* WS_BORDER | WS_DLGFRAME  */
            WS_BORDER = 0x00800000,
            WS_DLGFRAME = 0x00400000,
            WS_VSCROLL = 0x00200000,
            WS_HSCROLL = 0x00100000,
            WS_SYSMENU = 0x00080000,
            WS_THICKFRAME = 0x00040000,
            WS_GROUP = 0x00020000,
            WS_TABSTOP = 0x00010000,
            WS_MINIMIZEBOX = 0x00020000,
            WS_MAXIMIZEBOX = 0x00010000,
            WS_TILED = WS_OVERLAPPED,
            WS_ICONIC = WS_MINIMIZE,
            WS_SIZEBOX = WS_THICKFRAME,
            WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW,
            WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
            WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
            WS_CHILDWINDOW = WS_CHILD
        }

        class CDS
        {
            [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 const int ENUM_CURRENT_SETTINGS = -1;
            public const int CDS_UPDATEREGISTRY = 0x00000001;
            public const int CDS_TEST = 0x00000002;
            public const int CDS_FULLSCREEN = 0x00000004;
            public const int CDS_GLOBAL = 0x00000008;
            public const int CDS_SET_PRIMARY = 0x00000010;
            public const int CDS_RESET = 0x40000000;
            public const int CDS_SETRECT = 0x20000000;
            public const int CDS_NORESET = 0x10000000;

            public const int DISP_CHANGE_SUCCESSFUL = 0;
            public const int DISP_CHANGE_RESTART = 1;
            public const int DISP_CHANGE_FAILED = (-1);
            public const int DISP_CHANGE_BADMODE = (-2);
            public const int DISP_CHANGE_NOTUPDATED = (-3);
            public const int DISP_CHANGE_BADFLAGS = (-4);
            public const int DISP_CHANGE_BADPARAM = (-5);
        }

        public enum DDSCL : int
        {
            DDSCL_ALLOWMODEX = 64,
            DDSCL_ALLOWREBOOT = 2,
            DDSCL_CREATEDEVICEWINDOW = 512,
            DDSCL_EXCLUSIVE = 16,
            DDSCL_FULLSCREEN = 1,
            DDSCL_MULTITHREADED = 1024,
            DDSCL_NORMAL = 8,
            DDSCL_NOWINDOWCHANGES = 4,
            DDSCL_SETDEVICEWINDOW = 256,
            DDSCL_SETFOCUSWINDOW = 128
        }
......
......
......



# Так же пробовал вот таким образом сворачивать:
Код

...
                    if (fullmode2 == true)
                    {
                        const int WM_SYSCOMMAND = 0x0112;
                        const int SC_MINIMIZE = 0xF020;
                        const int SC_RESTORE = 0xF120;
                        if (IsWindowVisible(hWnd2) != 0)
                        {
                            SendMessage(hWnd2, WM_SYSCOMMAND, SC_MINIMIZE, 0);
                        }
                        else
                        {
                            SendMessage(hWnd2, WM_SYSCOMMAND, SC_RESTORE, 0);
                            SetForegroundWindow(hWnd2);
                        }
...

- Но при нажатие на 'F12', окно сворачивается и тутже само разворачивается =( 



# Дополнительные ссылка на Интернет ресурсы:

Это сообщение отредактировал(а) MuForum - 11.11.2007, 20:32


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
MuForum
Дата 11.11.2007, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



Многие программисты пытались сделать программу 'WindowMode', при помощи которой можно было бы менять режим игры 'MuOnline' из 'FullScreen' в 'WindowMode' и наоборот, и также Сворачивать(Hide)/Разворачитвать(Show) игру.


# Но почему-то все сталкиваются с такой проблемой:
Цитата(S@nek)

Если запустить изначально игру в режиме 'окно' (В дальнейшем 'WindowMode'), затем скрыть(В дальнейшем 'Hide') игру, то можно свободно работать с остальными приложениями. (То есть тут проблем не возникает), но если изначально запустить игру в режиме 'полный экран' (В дальнейшем 'FullScreen'), затем при помощи кнопки 'F11' поменять статус окна на 'WindowMode', затем скрыть(Hide), и попытаться нажать вне окна, то окно игры тутже разворачивается. (3 раза повторив — игра закрывается).

P.S. -> Окно, над которым необходимо делать изменения(Не наше), то есть в коде той программы ничего не возможно изменять.



# Вопрос: А игра использует 'DirectDraw' или 'Direct3d'?
# Ответ: Если игры построена на 'спрайтах', т.е. никакого '3d', то это 'DirectDraw'. (То есть игра 'MuOnline' использует 'DirectDraw')
- И от сюда уже становиться понятно, почему игра 'так нагружает систему' и 'вылетает', и почему в 'полном экране' (FullScreen) работает быстрее.


# Вопрос: А почему когда запускаешь игру изначально в режиме 'FullScreen', то она потребляет меньше ресурсов чем в режиме 'WindowMode'?
# Ответ: Есть такая штука, зовется 'CooperativeLevel',
Цитата

device.SetCooperativeLevel(this, CooperativeLevelFlags.Normal);
- типа того...

Так вот, когда флаг установлен 'Normal', то работают медленные функции отрисовки, зато когда выставляете 'FullScreen', тогда включаются доп. функции, которые в других режимах просто 'блокируют' программы. Кстати, если запустить игру в режиме 'WindowMode'(Окне), а потом руками сменить на 'FullScreen', то прироста производительности, не будет(То есть производительность тогда заметно падает.).


# Вопрос: А из-за чего так получается, что при изначальном запуске игры в режиме 'FullScreen' нельзя работать с чужими окнами?
# Ответ: Это происходит из-за того, что установлены вот такие флаги:
Цитата

Цитата

...
hRet = pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
...



  •  'Эксклюзивный режим' говорит 'OS', что пока работает наше приложение, никакое другое не должно даже близко подходить к экрану, со своей информацией. Кстати, единожды установив кооперативный режим, второй раз сделать это не выйдет. Получим ответ в виде 'DDERR_HWNDALREADYSET' или «уже стоит» по-русски.
    -

  •  DSCL_EXCLUSIVE - Используется полноэкранными приложениями. Запрашивает эксклюзивный режим.

  •  DDSCL_FULLSCREEN - Устанавливает полноэкранный режим. При использовании этого флага обязателен флаг 'DDSCL_EXCLUSIVE'.

  •  DDSCL_NORMAL - Нормальный режим Windows, не доступны флаги 'DDSCL_ALLOWMODEX', 'DDSCL_EXCLUSIVE' и 'DDSCL_FULLSCREEN'. Иными словами, получаем простое оконное приложение.





Написал выше изложенное S@nek[BoR].
Благодарю за помощь 'Wisehorn' (Второй NickName: 'Baa')

Это сообщение отредактировал(а) MuForum - 11.11.2007, 20:03


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Разработка Windows Forms | Следующая тема »


 




[ Время генерации скрипта: 0.0795 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.