WPF中的WndProc
其实,在WPF中,要想利用WndProc来处理所有的事件,需要利用到SourceInitialized Event,首先需要创建一个HwndSource对象,然后利用其AddHook方法来将所有的windows消息附加到一个现有的事件中,这个就是WndProc。
void WSInitialized(object sender, EventArgs e)
{
hs = PresentationSource.FromVisual(this) as HwndSource;
hs.AddHook(new HwndSourceHook(WndProc));
}
这样,我们就成功地添加了一个可以接收所有windows消息的函数,那么有了它,就让我们用它来做一些有意义的事情吧。
在WPF设计过程中,我是利用一个无边框窗体进行了重绘。所以当我设置其最大化时,肯定是要遮蔽任务栏的:
this.WindowState = (this.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal);
下面就让我们来实现不遮蔽任务栏(参考文章:Maximizing window (with WindowStyle=None) considering Taskbar)。
#region 这一部分用于最大化时不遮蔽任务栏
private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
{ MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); // Adjust the maximized size and position to fit the work area of the correct monitor
int MONITOR_DEFAULTTONEAREST = 0x00000002;
System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); if (monitor != System.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);
} /// <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> Win32 </summary>
[StructLayout(LayoutKind.Sequential, Pack = )]
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);
}
} [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 = ;
} [DllImport("user32")]
internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi); [DllImport("User32")]
internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
#endregion
上面这部分主要就是通过显示器信息来确定窗体显示的WorkArea和MonitorArea。
上面的函数准备好以后,下面就开始处理最大化按钮事件:
首先,让我们来看一个常量:
|
WM_GETMINMAXINFO |
0x24 |
The WM_GETMINMAXINFO message is sent to a window when the size or position of the window is about to change. An application can use this message to override the window's default maximized size and position, or its default minimum or maximum tracking size. |
从字面意思看来就是这个消息是用来处理窗体大小或者是位置变化的。程序可以使用这个消息来重载原本存在的最大化信息,位置信息等等。
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case 0x0024:/* WM_GETMINMAXINFO */
WmGetMinMaxInfo(hwnd, lParam);
handled = true;
break;
default: break;
}
return (System.IntPtr);
}
需要补充一点的是,在WindowForm中,我们可以通过Point p = new Point(lParam.ToInt32())来确定我们的鼠标坐标在窗体的哪个位置上,但是在WPF中,Point没有带有单个参数的方法,这里只能通过
int x = lParam.ToInt32() & 0xffff;
int y = lParam.ToInt32() >> 16;
来获取。
http://www.cnblogs.com/scy251147/archive/2012/07/28/2612670.html
WPF中的WndProc的更多相关文章
- WPF换肤之三:WPF中的WndProc
原文:WPF换肤之三:WPF中的WndProc 在上篇文章中,我有提到过WndProc中可以处理所有经过窗体的事件,但是没有具体的来说怎么可以处理的. 其实,在WPF中,要想利用WndProc来处理所 ...
- 在WPF中处理Windows消息
在Winform中 处理Windows消息通过重写WndProc方法 在WPF中 使用的是System.Windows. Sytem.Windows.Controls等名字空间,没有WndProc函数 ...
- Windows 消息循环(2) - WPF中的消息循环
接上文: Windows 消息循环(1) - 概览 win32/MFC/WinForm/WPF 都依靠消息循环驱动,让程序跑起来. 本文介绍 WPF 中是如何使用消息循环来驱动程序的. 4 消息循环在 ...
- wpf 中AxShockwaveFlash重写以及屏蔽鼠标右键
在wpf中需要用到flash播放swf或者图片,需要使用 AxShockwaveFlashObjects.dll和ShockwaveFlashObjects.dll 在项目中使用的时候遇到 问题1.使 ...
- WinForm和WPF中注册热键
由于.Net没有提供专门的类库处理热键,所以需要直接调用windows API来解决. HotKey为.NET调用Windows API的封装代码,主要是RegisterHotKey和Unregist ...
- 在WPF中使用依赖注入的方式创建视图
在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...
- MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信
MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...
- MVVM设计模式和WPF中的实现(四)事件绑定
MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
随机推荐
- JS计算两个经纬度的距离
var mapNumberUtil = {}; /** * 计算两个经纬度的距离(千米) */mapNumberUtil.getDistance = function(lat1, lng1, lat2 ...
- div悬浮在屏幕的中间及点击按钮关闭弹出框
#fd { position: fixed; z-index: 999; width: 109px; height: 323px; top: 71%; right: 1%; margin: -50px ...
- java线程中的同步锁和互斥锁有什么区别?
两者都包括对资源的独占. 区别是 1:互斥是通过竞争对资源的独占使用,彼此没有什么关系,也没有固定的执行顺序. 2:同步是线程通过一定的逻辑顺序占有资源,有一定的合作关系去完成任务.
- Qualcomm_Mobile_OpenCL.pdf 翻译-7 内存性能优化
内存优化是最重要也是最有效的OpenCL性能优化技术.大量的应用程序是内存限制而不是计算限制.所以,掌握内存优化的方法是OpenCL优化的基础.在这章中,将会回顾OpenCL的内存模型,然后是最优的实 ...
- zabbix 内存溢出
tail -f /var/log/zabbix/zabbix_server_log ::165110.914 ================================ ::165110.914 ...
- Python核心技术与实战——十三|Python中参数传递机制
我们在前面的章节里学习了Python的函数基础以及应用,那么现在想一想:传参,也就是把一些参数从一个函数传递到另一个函数,从而使其执行相应的任务,这个过程的底层是如何工作的,原理又是怎样的呢? 在实际 ...
- iOS的UILabel设置多行显示
label.lineBreakMode = NSLineBreakByWordWrapping; label.numberOfLines = ;
- (转载)自然语言处理中的Attention Model:是什么及为什么
转载说明来源:http://blog.csdn.net/malefactor/article/details/50550211 author: 张俊林 原文写得非常好! 原文: 要是关注深度学习在自然 ...
- Spring Boot 的各种start
新建一个springBoot项目时,你会选择很多依赖,在项目中的build.gradle中你会看见各种start,例如下边的代码: 今天就在这里列举一下各种start: 1.spring-boot-s ...
- docker小知识
1,docker 使用普通用户 添加用户组: sudo groupadd docker 加入docker 组 sudo gpasswd -a ${USER} docker 或 usermod -aG ...