Доброе время суток!
Я начинаю программист, недавно перешел с 'C++' на 'C#', так что строго прошу не судить, а по возможности указать на ошибки.
# Задача:
Необходимо написать программу, которая будет перехватывать нажатия кнопок клавиатуры 'F11', 'F12' (Низкоуровневой) — Это осуществил.
При нажатие на кнопку 'F11', Необходимо менять статус окна из 'FullScreen' в 'WindowMode' и наоборот — Это осуществил.
При нажатие на кнопку 'F12', необходимо скрывать(Hide)/показывть(Show) окно. — Тут проблема.
# Детально о проблеме:
Если запустить изначально игру в режиме 'WindowMode', затем скрыть(hide) игру, то можно свободно работать с остальными приложениями. (То есть тут проблем не возникает), но если изначально запустить игру в режиме 'FullScreen', затем при помощи кнопки 'F11' поменять статус окна на 'WindowMode', затем скрыть(hide), и попытаться нажать вне окна, то окно игры тутже разворачивается. (3 раза повторив — игра закрывается).
P.S. -> Я уже пытаюсь решить эту проблему около недели(чуть больше). Читал достаточно много информации по поводу 'SetWindowPos', перехвата глобальных сообщений и т.д. Через 'SetWindowPos' к сажалению решить проблему не удалось =(
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((IntPtr)hWnd2, (int)GWL.GWL_STYLE, 0x10000000); // WS_VISIBLE = '0x10000000'
DEVMODE dm = new DEVMODE();
dm.dmBitsPerPel = Convert.ToSByte(CD);
dm.dmPelsWidth = CorX;
dm.dmPelsHeight = CorY;
dm.dmDisplayFrequency = RR;
if (ChangeDisplaySettings(ref dm, 0x02 | 0x04) != 0) ChangeDisplaySettings(ref dm, 0x04);
MoveWindow((IntPtr)hWnd2, 0, 0, CorX, CorY, true);
SetForegroundWindow(hWnd2);
fullmode1 = true;
fullmode2 = false;
}
else
{
SetWindowLong((IntPtr)hWnd2, (int)GWL.GWL_STYLE, 0x00000000 | 0x10000000 | 0x00C00000 | 0x00040000 | 0x00080000);
MoveWindow((IntPtr)hWnd2, 0, (-13), CorX + 5, CorY + 10, true);
SetWindowPos((IntPtr)hWnd2, (IntPtr)(-1), 0, (-13), CorX + 5, CorY + 10, 0x0001 | 0x0040);
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((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;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
......
......
......
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", 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);
// ---------- 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
{
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. -> Появляется только сообщение "Step1", а "Step2" и "Step3" не появляются=(