您的位置:首页 > 运维架构

(开源,GPLv3)EbookCopier 实现(2) – 具有半透明和鼠标穿透效果的“取景框”

2009-03-13 14:32 309 查看
设置剪辑区域后,程序会在屏幕上显示“取景框”标出剪辑区域,如下图所示,图中红色边框和和中间的“剪辑区域”字样即是。这个“取景框”像贴在屏幕上一样,不会影响你键盘和鼠标的操作。它事实上是由一个分层窗口(a layered window)实现的。



一、窗体的阿尔法混合透明(Per-Pixel-Alpha)效果

这一实现必须调用 Win32 API,这意味着我们的程序只能在 Windows 下运行,别指望随 Mono 去 Linux 兜风了。
很高兴的是,在我动手之前看到了 Rui Lopes 为此写的 Per Pixel Alpha Blend in C#,已经实现了这一效果的托管封装,我们的窗体从中派生就可以了。这些代码在项目的 /EbookCopier/Ref/PerPixelAlphaForm.cs 文件中。尽管如此,我们还是看一下实现的原理吧。

Windows 2000操作系统增加了 WS_EX_LAYERED 扩展窗口风格。如果使用了该属性,窗体将具备复合形状、动画、阿尔法混合等方面的视觉特效。为得到一个分层窗口(layered window),必须设置 WS_EX_LAYERED 标志位,这可以在窗体创建时设置,也可以在创建后通过以GWL_EXSTYLE标志调用 SetWindowLong() 来进行设置。在托管代码中可以这样实现:

protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
return cp;
}
}


接下来,可以通过 UpdateLayeredWindows() 函数来更新分层窗口。在具体使用时,需要在位图中绘制出可视区域,并将其与关键色、阿尔法混合参数等一起提供给 UpdateLayeredWindows() 函数。托管代码中需要 DllImport,封装如下:

public const Int32 ULW_COLORKEY = 0x00000001;
public const Int32 ULW_ALPHA = 0x00000002;
public const Int32 ULW_OPAQUE = 0x00000004;

///
/// The UpdateLayeredWindow function updates the position, size, shape, content,
/// and translucency of a layered window.
///
/// 窗体句柄
/// 窗体的 DC 句柄
/// 窗体左上角位置
/// 窗体大小
/// 要设置的图像源 DC 句柄
/// 图像源位置
/// 要透明的颜色
/// 窗体透明度
/// 标识位,ULW_COLORKEY 为指定颜色透明,ULW_ALPHA 为允许半透明的窗体,ULW_OPAQUE 为不透明
/// 成功=True; 失败=False;
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool UpdateLayeredWindow(
IntPtr hwnd,
IntPtr hdcDst,
ref Point pptDst,
ref Size psize,
IntPtr hdcSrc,
ref Point pprSrc,
Int32 crKey,
ref BLENDFUNCTION pblend,
Int32 dwFlags);


二、窗体的鼠标穿透(Click-Through)效果

具有WS_EX_LAYERED 标志的分层窗口,添加 WS_EX_TRANSPARENT 就可以使鼠标穿透。该实现位于 /EbookCopier/AlphaForm.cs 中。我添加了一个 ClickThroughEnable 属性,设置为True,则窗体具有鼠标穿透效果。

private bool clickThroughEnable = false;
///
/// 获取或设置一个值,指示窗体是否有鼠标穿透功能。
///
/// 如果该实例can penetrate,为true;否则为false。
public bool ClickThroughEnable
{
get { return clickThroughEnable; }
set
{
clickThroughEnable = value;

if (clickThroughEnable)
{//使窗口有鼠标穿透功能
uint intExTemp = GetWindowLong(this.Handle, GWL_EXSTYLE);
uint oldGWLEx = SetWindowLong(this.Handle, GWL_EXSTYLE, intExTemp | WS_EX_TRANSPARENT | WS_EX_LAYERED);
}
else
{//使窗体恢复正常
this.FormBorderStyle = FormBorderStyle.None;
}
}
}


三、GDI+ 绘图

在实现阿尔法混合透明和鼠标穿透功能后,设置窗体TopMost=true和ShowInTaskbar=false,就得到了我们想要的窗体。接下来GDI+绘制我们想要的图形就可以了。

“取景框”窗体类(class FocusRectForm)在 /EbookCopier/FocusRectForm.cs 中实现,它从 AlphaForm 类派生。根据捕捉状态的不同,它共有四种样子,正常模式如下:



连续捕捉时,显示当前页面:



截取屏幕图像时,需要剪辑区域空白:



截取屏幕后,显示半透明蒙层,以表示已经拷贝完毕:



具体代码比较繁琐,就不贴在文章中了,有兴趣的话请浏览 /EbookCopier/FocusRectForm.cs 文件。

至此,我们就实现了这个“取景框”窗体。

数字图书复印机(EbookCopier) 遵循 GPLv3 协议开源,如果你有更多的创意,欢迎请加入我们。
项目地址:http://code.google.com/p/ebookcopier/
源代码和可执行程序下载:http://code.google.com/p/ebookcopier/downloads/list

本文同时发布到以下位置,以便更多的朋友能够看到本文:
http://chuangen.name/ (我的主页)
http://blog.csdn.net/chuangen (IT 社区)
http://chuangen.cnblogs.com/ (.NET 技术社区)
http://chuangen-cn.spaces.live.com/ (live Spaces)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息