Window 에 아래 코드 입력
private void Window_Loaded(object sender, RoutedEventArgs e)
{
IntPtr handle = (new WindowInteropHelper(this)).Handle;
HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(WindowProc));
}
private static IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case 0x10:
//Console.WriteLine("Close reason: Clicking X");
break;
case 0x11:
case 0x16:
//Console.WriteLine("Close reason: WindowsShutDown");
break;
case 0x0024:
WmGetMinMaxInfo(hwnd, lParam);
handled = true;
break;
case 0x0046:
NativeMethods.WINDOWPOS pos = (NativeMethods.WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS));
if ((pos.flags & (int)(NativeMethods.SWP.NOMOVE)) != 0)
{
return IntPtr.Zero;
}
Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual;
if (wnd == null)
{
return IntPtr.Zero;
}
bool changedPos = false;
if (pos.cx < wnd.MinWidth) { pos.cx = (int)wnd.MinWidth; changedPos = true; }
if (pos.cy < wnd.MinHeight) { pos.cy = (int)wnd.MinHeight; changedPos = true; }
if (!changedPos)
{
return IntPtr.Zero;
}
Marshal.StructureToPtr(pos, lParam, true);
handled = true;
break;
case 0x112:
if (((ushort)wParam & 0xfff0) == 0xf060)
{
// close (alt + F4)
handled = true;
}
break;
default:
break;
}
return IntPtr.Zero;
}
private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
{
NativeMethods.MINMAXINFO mmi = (NativeMethods.MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(NativeMethods.MINMAXINFO));
// Adjust the maximized size and position to fit the work area of the correct monitor
int MONITOR_DEFAULTTONEAREST = 0x00000002;
IntPtr monitor = NativeMethods.MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor != System.IntPtr.Zero)
{
NativeMethods.MONITORINFO monitorInfo = new NativeMethods.MONITORINFO();
NativeMethods.GetMonitorInfo(monitor, monitorInfo);
NativeMethods.RECT rcWorkArea = monitorInfo.rcWork;
NativeMethods.RECT rcMonitorArea = monitorInfo.rcMonitor;
mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left);
mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top);
mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left);
mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);
}
Marshal.StructureToPtr(mmi, lParam, true);
}
public class NativeMethods
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
// Define the Win32 API methods we are going to use
[DllImport("user32.dll")]
internal static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern bool InsertMenu(IntPtr hMenu, uint wPosition, uint wFlags, UIntPtr wIDNewItem, string lpNewItem);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern int ModifyMenu(IntPtr hMenu, uint uPosition, uint wFlags, UIntPtr wIDNewItem, string text);
[DllImport("user32.dll")]
internal static extern bool DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);
[DllImport("user32")]
public static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[DllImport("User32")]
public static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
#region Win32 Imports
internal const UInt32 MF_BYCOMMAND = 0x00000000;
internal const UInt32 SC_SIZE = 0xF000;
internal const UInt32 SC_MOVE = 0xF010;
internal const UInt32 SC_MINIMIZE = 0xF020;
internal const UInt32 SC_MAXIMIZE = 0xF030;
internal const UInt32 SC_NEXTWINDOW = 0xF040;
internal const UInt32 SC_PREVWINDOW = 0xF050;
internal const UInt32 SC_CLOSE = 0xF060;
internal const UInt32 SC_VSCROLL = 0xF070;
internal const UInt32 SC_HSCROLL = 0xF080;
internal const UInt32 SC_MOUSEMENU = 0xF090;
internal const UInt32 SC_KEYMENU = 0xF100;
internal const UInt32 SC_ARRANGE = 0xF110;
internal const UInt32 SC_RESTORE = 0xF120;
internal const UInt32 SC_TASKLIST = 0xF130;
internal const UInt32 SC_SCREENSAVE = 0xF140;
internal const UInt32 SC_HOTKEY = 0xF150;
internal const UInt32 SC_DEFAULT = 0xF160;
internal const UInt32 SC_MONITORPOWER = 0xF170;
internal const UInt32 SC_CONTEXTHELP = 0xF180;
internal const UInt32 SC_SEPARATOR = 0xF00F;
/// Define our Constants we will use
public const Int32 WM_SYSCOMMAND = 0x112;
public const Int32 MF_SEPARATOR = 0x800;
public const Int32 MF_BYPOSITION = 0x400;
public const Int32 MF_STRING = 0x0;
public enum SWP : uint
{
NOSIZE = 0x0001,
NOMOVE = 0x0002,
NOZORDER = 0x0004,
NOREDRAW = 0x0008,
NOACTIVATE = 0x0010,
FRAMECHANGED = 0x0020,
SHOWWINDOW = 0x0040,
HIDEWINDOW = 0x0080,
NOCOPYBITS = 0x0100,
NOOWNERZORDER = 0x0200,
NOSENDCHANGING = 0x0400,
}
/// <summary>
/// POINT aka POINTAPI
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
/// <summary>
/// x coordinate of point.
/// </summary>
public int x;
/// <summary>
/// y coordinate of point.
/// </summary>
public int y;
/// <summary>
/// Construct a point of coordinates (x,y).
/// </summary>
public POINT(int x, int y)
{
this.x = x;
this.y = y;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MINMAXINFO
{
public POINT ptReserved;
public POINT ptMaxSize;
public POINT ptMaxPosition;
public POINT ptMinTrackSize;
public POINT ptMaxTrackSize;
};
/// <summary>
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MONITORINFO
{
/// <summary>
/// </summary>
public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
/// <summary>
/// </summary>
public RECT rcMonitor = new RECT();
/// <summary>
/// </summary>
public RECT rcWork = new RECT();
/// <summary>
/// </summary>
public int dwFlags = 0;
}
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x;
public int y;
public int cx;
public int cy;
public int flags;
}
/// <summary> Win32 </summary>
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct RECT
{
/// <summary> Win32 </summary>
public int left;
/// <summary> Win32 </summary>
public int top;
/// <summary> Win32 </summary>
public int right;
/// <summary> Win32 </summary>
public int bottom;
/// <summary> Win32 </summary>
public static readonly RECT Empty = new RECT();
/// <summary> Win32 </summary>
public int Width
{
get { return Math.Abs(right - left); } // Abs needed for BIDI OS
}
/// <summary> Win32 </summary>
public int Height
{
get { return bottom - top; }
}
/// <summary> Win32 </summary>
public RECT(int left, int top, int right, int bottom)
{
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
/// <summary> Win32 </summary>
public RECT(RECT rcSrc)
{
this.left = rcSrc.left;
this.top = rcSrc.top;
this.right = rcSrc.right;
this.bottom = rcSrc.bottom;
}
/// <summary> Win32 </summary>
public bool IsEmpty
{
get
{
// BUGBUG : On Bidi OS (hebrew arabic) left > right
return left >= right || top >= bottom;
}
}
/// <summary> Return a user friendly representation of this struct </summary>
public override string ToString()
{
if (this == RECT.Empty) { return "RECT {Empty}"; }
return "RECT { left : " + left + " / top : " + top + " / right : " + right + " / bottom : " + bottom + " }";
}
/// <summary> Determine if 2 RECT are equal (deep compare) </summary>
public override bool Equals(object obj)
{
if (!(obj is Rect)) { return false; }
return (this == (RECT)obj);
}
/// <summary>Return the HashCode for this struct (not garanteed to be unique)</summary>
public override int GetHashCode()
{
return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode();
}
/// <summary> Determine if 2 RECT are equal (deep compare)</summary>
public static bool operator ==(RECT rect1, RECT rect2)
{
return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom);
}
/// <summary> Determine if 2 RECT are different(deep compare)</summary>
public static bool operator !=(RECT rect1, RECT rect2)
{
return !(rect1 == rect2);
}
}
#endregion
}