The SetWindowLong function changes an attribute of the specified window. The function also sets the 32-bit (long) value at the specified offset into the extra window memory. Note This function has been superseded by the SetWindowLongPtr function. To write code that is compatible with both 32-bit and 64-bit versions of Microsoft Windows, use the SetWindowLongPtr function.
这两个函数中的其它参数就不多说了,这里简单说明一下 nIndex 的意义:Specifies the zero-based offset to the value to be retrieved. Valid values are in the range zero through the number of bytes of extra window memory, minus four; for example, if you specified 12 or more bytes of extra memory, a value of 8 would be an index to the third 32-bit integer. To retrieve any other value, specify one of the following values.(MSDN)
这个参数值列在下面(后三个值对于对话框有效),具体的意义请参看 MSDN。
#define GWL_WNDPROC (-4)
#define GWL_HINSTANCE (-6)
#define GWL_HWNDPARENT (-8)
#define GWL_STYLE (-16)
#define GWL_EXSTYLE (-20)
#define GWL_USERDATA (-21)
#define GWL_ID (-12)
#define DWL_MSGRESULT 0
#define DWL_DLGPROC 4
#define DWL_USER 8
好了,可以开始更改窗体的属性了。不过在更改之前,还有一个工作要做:获取窗体的句柄。C#(或VC++)中,获取指定窗体的句柄简直就是易如反掌,不过在 WPF 下,就不那么容易了,需要一个过渡:
IntPtr hWnd = new WindowInteropHelper(this).Handle;
可以获取窗体的显示样式了:
int nStyle = GetWindowLong(hWnd, GWL_STYLE);
根据我们的需求,禁止最大化按钮可以被点击,做如下操作即可:
nStyle &= ~WS_MAXIMIZEBOX;
重新将更改后的显示样式设置回窗体即可:
SetWindowLong(hWnd, GWL_STYLE, nStyle);
好了,似乎工作已经结束了。可惜,运行之后会发现,功能已经实现了,不过窗体上显示的最大化按钮的状态却没有更新。实际上,还需要调用另一个 API —— SetWindowPos 来实现这个功能。
The SetWindowPos function changes the size, position, and Z order of a child, pop-up, or top-level window. Child, pop-up, and top-level windows are ordered according to their appearance on the screen. The topmost window receives the highest rank and is the first window in the Z order.(MSDN)
这个函数的语法为:
Syntax
BOOL SetWindowPos(
HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags );
前几个参数的意义请参看 MSDN。最后一个参数指定了窗体大小和位置的标志。这些标志可以联合使用,进行或操作,具体的意义请参看 MSDN。
#define SWP_NOSIZE 0x0001
#define SWP_NOMOVE 0x0002
#define SWP_NOZORDER 0x0004
#define SWP_NOREDRAW 0x0008
#define SWP_NOACTIVATE 0x0010
#define SWP_FRAMECHANGED 0x0020 /* The frame changed: send WM_NCCALCSIZE */
#define SWP_SHOWWINDOW 0x0040
#define SWP_HIDEWINDOW 0x0080
#define SWP_NOCOPYBITS 0x0100
#define SWP_NOOWNERZORDER 0x0200 /* Don't do owner Z ordering */
#define SWP_NOSENDCHANGING 0x0400 /* Don't send WM_WINDOWPOSCHANGING */
#define SWP_DRAWFRAME SWP_FRAMECHANGED
#define SWP_NOREPOSITION SWP_NOOWNERZORDER
#if(WINVER >= 0x0400)
#define SWP_DEFERERASE 0x2000
#define SWP_ASYNCWINDOWPOS 0x4000
#endif /* WINVER >= 0x0400 */
好了,可以刷新窗体显示样式了:
SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
OK,一切大功告成!
从这个例子可以看出,WPF 的功能还很不完善。虽然 WPF 的界面做的可以说的美轮美奂,不过未来发展的路还很漫长。同时从另一个侧面反应出,Windows 的 API 还是解决问题的根本方法。看来无论什么时候,对 Windows API 的掌握还是很重要的。