天天看點

(開源,GPLv3)EbookCopier 實作(2) – 具有半透明和滑鼠穿透效果的“取景框”

設定剪輯區域後,程式會在螢幕上顯示“取景框”标出剪輯區域,如下圖所示,圖中紅色邊框和和中間的“剪輯區域”字樣即是。這個“取景框”像貼在螢幕上一樣,不會影響你鍵盤和滑鼠的操作。它事實上是由一個分層視窗(a layered window)實作的。

(開源,GPLv3)EbookCopier 實作(2) – 具有半透明和滑鼠穿透效果的“取景框”

一、窗體的阿爾法混合透明(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 類派生。根據捕捉狀态的不同,它共有四種樣子,正常模式如下:

(開源,GPLv3)EbookCopier 實作(2) – 具有半透明和滑鼠穿透效果的“取景框”

連續捕捉時,顯示目前頁面:

(開源,GPLv3)EbookCopier 實作(2) – 具有半透明和滑鼠穿透效果的“取景框”

截取螢幕圖像時,需要剪輯區域空白:

(開源,GPLv3)EbookCopier 實作(2) – 具有半透明和滑鼠穿透效果的“取景框”

截取螢幕後,顯示半透明蒙層,以表示已經拷貝完畢:

(開源,GPLv3)EbookCopier 實作(2) – 具有半透明和滑鼠穿透效果的“取景框”

具體代碼比較繁瑣,就不貼在文章中了,有興趣的話請浏覽 /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)

繼續閱讀