在Win32API窗體下實現透明背景

2021-06-08 09:53:12 字數 2869 閱讀 1652

前面拜讀過本站無數高手的許多好文章,受益非淺,首先向各位大俠致敬!今天程式設計偶有小得,不敢獨享,特拿出來與各位共享,希望對某些朋友有些許幫助。

如果我的窗體支援resize,那麼我調整大小的過程中,要不停的計算裁切框(要逐點掃瞄象素,並對裁切框進行操作),計算量相當大,特別當窗體比較大的時候更是如此,會造成窗體的閃爍。

首先介紹一下這個函式: 

bool setlayeredwindowattributes(

hwnd hwnd,     // 應用目標視窗的控制代碼

colorref crkey, // 掩碼的顏色,可以用rgb(r,g,b)來指定

byte balpha,     // 掩碼顏色部分的alpha值,0是全透明,255是完全不透明

dword dwflags     // 透明方式

);  

要說名的是這個函式只在windows2000及以上版本才支援。msdn對要求的描述如下 

windows nt/2000/xp: included in windows 2000 and later.

windows 95/98/me: unsupported.

header: declared in winuser.h; include windows.h.

library: use user32.lib.

還有就是這個函式對於有標題框的窗體支援不好,就是它裁切的只是客戶區域,好在我們要製作透明窗體的場合一般用不到標題框下面就說名例程的製作過程。(我旨在說明這種透明窗體的思路及函式的用法,所以**非常簡單,並且沒有必要的錯誤驗證機制,希望大家諒解) 

建立一張用於在窗體上繪製的背景,把要裁切的部分用一種顏色標記出來,我們叫它maskcolor,我的如下:

我的maskcolor = 0xff00,也就是 rgb(0,255,0). 

建立乙個基於對話方塊的工程,修改對話方塊資源的屬性,主要修改兩個地方。一是指定沒有titlebar,二是指定borderstyle為none.這樣才能保證出來的窗體符合你的要求 

把加入資源,付id = idb_background 

下面就開始寫**了,呵呵,看下面的**這麼長。是不是頭有點大呀,別急,這些多半都是工程嚮導自動生成的,我加的都已經註解上了,並用黃色表示沒有幾行的。要不然我怎麼敢向各位吹噓這個實現方法簡單呢。 

a.首先我們給窗體新增兩個成員變數: 

cbitmap * m_oldbitmap; //指向記憶體dc原來的 bitmap

cdc m_dc;              //用於存放背景的記憶體dc

b.在窗體的oninitdialog()函式中做一番初始化: 

bool ctranswindowdlg::oninitdialog()

就像注釋的那樣,我們首先把load進來,然後把m_dc建立乙個與視窗dc相容的dc,並把剛才load進來的繫結到該記憶體dc上,並用m_oldbitmap 記錄下原有bitmap,使用者最後釋放。 

c.向onpaint中新增**,用於把背景繪製到視窗上: 

void ctranswindowdlg::onpaint() 

else

}d.到這裡我們要的功能就已經能夠實現了,但是好的程式設計師絕對不應該忘記釋放資源,你也一樣,一定沒有忘記在程式結束時釋放資源,呵呵,我們可以寫到析構函式中,我們也可放到onclose()函式中,都一樣,我採用了後一種:新增函式並新增釋放資源的** 

void ctranswindowdlg::onclose()

e.現在好了,執行一下吧,真爽,就這麼幾行**搞定了乙個漂亮的視窗。是不是很有成就感?呵呵。又看了幾次真的美滋滋的。不好發現問題了,怎麼程式執行的時候開始有一下閃爍呢?哦,是清空背景的時候畫了一下,沒關係,讓我們乾掉它。新增wm_erasebkgnd事件的響應函式,把原來的注釋掉直接返回true,再執行一下看看吧?怎麼樣,滿意了嗎? 

bool ctranswindowdlg::onerasebkgnd(cdc* pdc)

f.好了,我已經非常滿意了,要休息一下了,但我怎麼關閉這個視窗呢?糟糕,非要我用alt+f4不成?算了再多用一下功,寫個雙擊事件好了: 

void ctranswindowdlg::onlbuttondblclk(uint nflags, cpoint point)

呵呵,本文旨在說明透明窗體的思路及函式用法,拋磚引玉,相信大家一定有好多更好的創意通過這個思路實現,比如,可以新增resize功能呀,使掩碼不完全透明甚至是漸隱呀等等,總之創意無限,等待著大家的發掘!

對話方塊上的控制項如edit control屬於子視窗

ws_ex_transparent不支援

( sheismylife 發表於 2004-11-23 10:40:00)

請問,如果要透明和不透明的內容是動態的,那又應該如何實現,例如,如果我要在乙個透明窗體上畫圖,窗體是透明的,但畫的東西不透明。 ( cyvk 發表於 2004-7-5 15:42:00)

你這個程式不能執行呀,,怎麼回事啊 ( bapldc 發表於 2004-6-13 21:16:00)

此法可以將對話方塊上的edit box透明嗎?我試了不行,不知何故!另:我已安裝了最新的sdk,也在vc6的tools-option中新增了include、library目錄,但編譯時還是提示未定義? ( xmxjh 發表於 2004-6-13 0:58:00)

在onpaint裡面至少要執行一次beginpaint和endpaint,否則視窗會不斷地收到wm_paint訊息,出現死迴圈 ( duxiuxing 發表於 2004-6-10 10:39:00)

我這裡執行只能看到背景,但所有控制都不可見,如winterain所說加上cdialog::onpaint()後,確實可見控制,但效果很差! ( xander 發表於 2004-6-9 15:05:00)

很好,但是  onpaint  裡的cdialog::onpaint();不應該被注釋掉,不然程式無法正常執行!

通過 WIN32 API 實現嵌入程式窗體

寫了乙個不使用 com,而是通過 win32 api 實現的示例,它把寫字板程式嵌在了自己的乙個面板中.這麼做可能沒有實際意義,因為兩個程式之前沒有進行有價值的互動,這裡僅僅是為了演示這麼做到,以下是詳細注釋過的主要源 我把它封裝到乙個類中 csharp copy using system usin...

通過 WIN32 API 實現嵌入程式窗體

寫了乙個不使用 com,而是通過 win32 api 實現的示例,它把寫字板程式嵌在了自己的乙個面板中.這麼做可能沒有實際意義,因為兩個程式之前沒有進行有價值的互動,這裡僅僅是為了演示這麼做到,以下是詳細注釋過的主要源 我把它封裝到乙個類中 csharp copy using system usin...

win32彙編使用win32 api實現字串拷貝

字串拷貝,呼叫win32的lstrcpy函式 拷貝了以後用訊息框顯示一下 386 model flat,stdcall option casemap none include s masm32 include windows.inc include s masm32 include user32.i...