WPF当窗体WindowStyle=”None”时,最大化会覆盖掉任务栏。如何解决这个问题呢?要用到Win32 API,通过让WPF窗体WM_GETMINMAXINFO消息挂接一个钩子来处理。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
public
static
class
WindowHelper
{
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;就可以解决最大化避免覆盖任务栏的问题了。