WPF当窗体WindowStyle=”None”时,最大化会覆盖掉任务栏。如何解决这个问题呢?
我在Google里面搜到一篇文章,要用到Win32 API,通过让WPF窗体WM_GETMINMAXINFO消息挂接一个钩子来处理。
public
static
void
RepairWindowBehavior(Window wpfWindow)
{
if
(wpfWindow ==
null
)
return
;
wpfWindow.SourceInitialized +=
delegate
{
IntPtr handle = (
new
WindowInteropHelper(wpfWindow)).Handle;
HwndSource source = HwndSource.FromHwnd(handle);
if
(source !=
null
)
{
source.AddHook(WindowProc);
}
};
}
private
static
IntPtr WindowProc(IntPtr hwnd,
int
msg, IntPtr wParam, IntPtr lParam,
ref
bool
handled)
{
switch
(msg)
{
case
0x0024:
WmGetMinMaxInfo(hwnd, lParam);
handled =
true
;
break
;
}
return
(IntPtr)0;
}
private
static
void
WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
{
MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam,
typeof
(MINMAXINFO));
int
MONITOR_DEFAULTTONEAREST = 0x00000002;
IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if
(monitor != IntPtr.Zero)
{
MONITORINFO monitorInfo =
new
MONITORINFO();
GetMonitorInfo(monitor, monitorInfo);
RECT rcWorkArea = monitorInfo.rcWork;
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
);
}
[DllImport(
"user32"
)]
internal
static
extern
bool
GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[DllImport(
"User32"
)]
internal
static
extern
IntPtr MonitorFromWindow(IntPtr handle,
int
flags);
#region Nested type: MINMAXINFO
[StructLayout(LayoutKind.Sequential)]
internal
struct
MINMAXINFO
{
public
POINT ptReserved;
public
POINT ptMaxSize;
public
POINT ptMaxPosition;
public
POINT ptMinTrackSize;
public
POINT ptMaxTrackSize;
}
#endregion
#region Nested type: MONITORINFO
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal
class
MONITORINFO
{
public
int
cbSize = Marshal.SizeOf(
typeof
(MONITORINFO));
public
RECT rcMonitor;
public
RECT rcWork;
public
int
dwFlags;
}
#endregion
#region Nested type: POINT
[StructLayout(LayoutKind.Sequential)]
internal
struct
POINT
{
public
int
x;
public
int
y;
public
POINT(
int
x,
int
y)
{
this
.x = x;
this
.y = y;
}
}
#endregion
#region Nested type: RECT
[StructLayout(LayoutKind.Sequential, Pack = 0)]
internal
struct
RECT
{
public
int
left;
public
int
top;
public
int
right;
public
int
bottom;
public
static
readonly
RECT Empty;
public
int
Width
{
get
{
return
Math.Abs(right - left); }
}
public
int
Height
{
get
{
return
bottom - top; }
}
public
RECT(
int
left,
int
top,
int
right,
int
bottom)
{
this
.left = left;
this
.top = top;
this
.right = right;
this
.bottom = bottom;
}
public
RECT(RECT rcSrc)
{
left = rcSrc.left;
top = rcSrc.top;
right = rcSrc.right;
bottom = rcSrc.bottom;
}
public
bool
IsEmpty
{
get
{
return
left >= right || top >= bottom;
}
}
public
override
string
ToString()
{
if
(
this
== Empty)
{
return
"RECT {Empty}"
;
}
return
"RECT { left : "
+ left +
" / top : "
+ top +
" / right : "
+ right +
" / bottom : "
+ bottom +
" }"
;
}
public
override
bool
Equals(
object
obj)
{
if
(!(obj
is
Rect))
{
return
false
;
}
return
(
this
== (RECT)obj);
}
public
override
int
GetHashCode()
{
return
left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode();
}
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);
}
public
static
bool
operator
!=(RECT rect1, RECT rect2)
{
return
!(rect1 == rect2);
}
}
#endregion
}
通过调用WindowHelper.RepairWindowBehavior(Window)方法注册Win32消息事件,以后调用this.WindowState = WindowState.Maximized;就可以解决最大化避免覆盖任务栏的问题了。