設定剪輯區域後,程式會在螢幕上顯示“取景框”标出剪輯區域,如下圖所示,圖中紅色邊框和和中間的“剪輯區域”字樣即是。這個“取景框”像貼在螢幕上一樣,不會影響你鍵盤和滑鼠的操作。它事實上是由一個分層視窗(a layered window)實作的。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLlNjYxETMjBDMiVDNtcjZ1EWLhJTY00SM5AjNtYWN0YzN1IjYfV2Zh1Waf92LcNzMzgTM18CXuV2ZuFWdoN2LcRXZu9lbkN3Yfd2bsJ2Xw9CXzV2Zh1WavwFdl5mLuR2cj5yZvxmYtA3Lc9CX6MHc0RHaiojIsJye.png)
一、窗體的阿爾法混合透明(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)