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;就可以解決最大化避免覆蓋任務欄的問題了。