WPF换肤之三:WPF中的WndProc
在上篇文章中,我有提到过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);
}
上面的代码就是通过处理WM_GETMINMAXINFO消息来实现最大化时不遮蔽任务栏。 我们来看看效果:

需要补充一点的是,在WindowForm中,我们可以通过Point p = new Point(lParam.ToInt32())来确定我们的鼠标坐标在窗体的哪个位置上,但是在WPF中,Point没有带有单个参数的方法,这里只能通过
int x = lParam.ToInt32() & 0xffff;
int y = lParam.ToInt32() >> ;
来获取。
希望这篇文章对你有用。
WPF换肤之三:WPF中的WndProc的更多相关文章
- WPF换肤之四:界面设计和代码设计分离
原文:WPF换肤之四:界面设计和代码设计分离 说起WPF来,除了总所周知的图形处理核心的变化外,和Winform比起来,还有一个巨大的变革,那就是真正意义上做到了界面设计和代码设计的分离.这样可以让美 ...
- WPF换肤之二:可拉动的窗体
原文:WPF换肤之二:可拉动的窗体 让我们接着上一章: WPF换肤之一:创建圆角窗体 来继续. 在这一章,我主要是实现对圆角窗体的拖动,改变大小功能. 拖动自绘窗体的步骤 首先,通过上节的设计,我们知 ...
- WPF换肤之一:创建圆角窗体
原文:WPF换肤之一:创建圆角窗体 我们都期望自己的软件能够有一套看上去很吸引人眼球的外衣,使得别人看上去既专业又有美感.这个系列就带领着大家一步一步的讲解如何设计出一套自己的WPF的窗体皮肤,如果文 ...
- WPF换肤之八:创建3D浏览效果
原文:WPF换肤之八:创建3D浏览效果 上节中,我们展示了WPF中的异步以及界面线程交互的方式,使得应用程序的显示更加的流畅.这节我们主要讲解如何设计一个具有3D浏览效果的天气信息浏览器. 效果显示 ...
- WPF换肤之六:酷炫的时区浏览小精灵
原文:WPF换肤之六:酷炫的时区浏览小精灵 由于工作需要,经常要查看到不同地区的 当前时间,以前总是对照着时区表来进行加减运算,现在有了这个小工具以后,感觉省心了不少.下面是软件的截图: 效果图赏析 ...
- WPF换肤之七:异步
原文:WPF换肤之七:异步 在WinForm时代,相信大家都遇到过这种情形,如果在程序设计过程中遇到了耗时的操作,不使用异步会导致程序假死.当然,在WPF中,这种情况也是存在的,所以我们就需要寻找一种 ...
- WPF换肤之五:创建漂亮的窗体
原文:WPF换肤之五:创建漂亮的窗体 换肤效果 经过了前面四章的讲解,我们终于知道了如何拖拉窗体使之改变大小,也知道了如何处理鼠标事件,同时,也知道了如何利用更好的编写方式来编写一个方便实用和维护的换 ...
- 有点激动,WPF换肤搞定了!
一如既往没废话! wpf桌面应用开发都是window内引入很多个UserControl. 如果你有通过不同颜色来换肤的需求,那么下面我就将整个过程! 分2个步骤: 1.主窗体背景色替换: 2.同时界面 ...
- WPF:换肤
看了一篇博客,觉得样式很好看,就自己动手做了一下,做个总结. 效果: 选择不同的图片背景就会改变: 直接上代码: 每个Theme对应一张图,除了图的名称不同之外,Theme?.xaml中的内容相 ...
随机推荐
- ListView+CheckBox两种解决方式及原因分析
近期在用ListView+CheckBox搞一个item选中的项目,我将CheckBox的focus设置为false,另我大喜的是,CheckBox居然能够选中(窃喜中),这么简单就搞定了,由于数据量 ...
- XP下的进程静音技术(遍历进程,遍历输入模块,遍历输入函数,找到函数并HOOK) good
很多浏览器有这种功能,实现原理都是一样.发声源基本都来自Flash,比如Flash游戏啦,视频播放器啦等等 而Flash的发声都是通过winmm.dll::waveOutWrite函数来完成,所以,我 ...
- Delphi中WebBrowser自动填表模板
unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, ...
- 《转》Linux下的多线程编程
原地址:http://linux.chinaunix.net/doc/program/2001-08-11/642.shtml 1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程 ...
- 在HTML中如何隐藏某段文字具体该怎么实现
<p style="display:none;"> 需要隐藏的文字....... </p> <div style="display:none ...
- 数据结构《17》---- 自己主动补齐之《二》----Ternary Search Tree
一. 序言 上一篇文章中,给出了 trie 树的一个实现. 能够看到,trie 树有一个巨大的弊病,内存占用过大. 本文给出还有一种数据结构来解决上述问题---- Ternary Search Tre ...
- HDU 4704 Sum (费马定理+快速幂)
Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Subm ...
- Leetcode_num13_Climbing Stairs
称号: You are climbing a stair case. It takes n steps to reach to the top. Each time you can either cl ...
- 拿到阿里,网易游戏,腾讯,smartx的offer的过程 (转)
前言 从今年的3月14日阿里的电话面试开始,到现在4月16日在西安悦豪酒店进行的腾讯HR面到现在一个多月了,中间先后收到了阿里,网易游戏,腾讯和smartx的offer,今天早晨刚刚接到了腾讯HR的电 ...
- 关于windows系统影子账户的问题
在这之前,需要大家了解几个问题,一个是SID,一个是账号的F值. Windows账户的SID 在Windows系统中,系统会为每个用户账户建立一个唯一的安全标识符(Security Identifie ...