調(diào)用UpdateLayeredWindow實現(xiàn)半透明窗體_第1頁
調(diào)用UpdateLayeredWindow實現(xiàn)半透明窗體_第2頁
調(diào)用UpdateLayeredWindow實現(xiàn)半透明窗體_第3頁
調(diào)用UpdateLayeredWindow實現(xiàn)半透明窗體_第4頁
調(diào)用UpdateLayeredWindow實現(xiàn)半透明窗體_第5頁
全文預覽已結(jié)束

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、 最近看了桌面天氣秀這款小軟件,其界面精致漂亮,而且可以透明顯示,還有個特別有趣的功能就是能讓窗體固定在桌面上并且鼠標可以“穿透”而窗體不受任何影響,這就是帶著些許神秘的“有影無形”的功能。         事實上要實現(xiàn)這種“有影無形”的功能,很簡單,我相信聰明的您一定很快會想到怎么做。幾句代碼就可以搞定,給你點提示,只有在2000以上的Win操作系 統(tǒng)才支持(當然如果你有足夠的時間可以完全可以在98上實現(xiàn))。那么今天我們主要討論一下窗體的半透明顯示,其實,如果僅僅要實現(xiàn)窗體的半透明顯示,很簡 單,Upd

2、ateLayeredWindow調(diào)用就可以了,網(wǎng)上去搜一下幾乎都是貼的這個函數(shù)怎么怎么實現(xiàn)窗體的半透明,在往下就沒了,比如此函數(shù)有個缺 陷,就是經(jīng)過此函數(shù)處理過的窗體,其上面的控件都透明了。諸如此類的問題至少到現(xiàn)在我在網(wǎng)上沒找到一個讓人感覺滿意的解決方案。       記得在一個所謂專業(yè)的C#網(wǎng)站上看到一篇題為“XP下透明窗體的完美實現(xiàn)”,當時看了還真高興一陣子,可是把代碼下下來一看,又是被忽悠了,里面就調(diào)用了 UpdateLayeredWindow函數(shù)實現(xiàn)透明然后加個旋轉(zhuǎn)顯示,這樣子就算完美了,我暈!這個函數(shù)查查資料誰不會??磥磉€是

3、自己動手,不知道有心 的朋友注意到?jīng)]有,在桌面天氣秀里,打開設(shè)置,然后快速拖動,會看到上面的窗體明顯脫離,這就是多層窗口留下的尾巴。下面的透明窗體是背景,上面的窗體承 載控件。在拖動下層窗體的時候讓上層窗體跟著一起動。對于小軟件來說,效果還可以。事實上,今天我實現(xiàn)的也和這個思路差不多,不過我這個上下兩層窗體是父 子關(guān)系,它們各施其職,但是又沒有拖動時留下的尾巴(窗口移動的處理),我把這些功能都封裝在一起了,只需要簡單地把你要在透明窗體上顯示的窗體傳過去以 及透明處理的圖片就OK了。限于篇幅下面給繪制函數(shù)以及調(diào)用示例:bool DrawAlpha(Image* pBgImg, HWND hWnd

4、)   if (!:IsWindow(hWnd) return false;  CWndDecorate wndDecor(hWnd);  /wndDecor.SetAlpha(255 * 20) / 100);  /wndDecor.ShowOnDesk();  RECT rcWnd;  :GetWindowRect(hWnd, &rcWnd);  int nWid = rcWnd.right - rcWnd.left; &#

5、160;int nHei = rcWnd.bottom - rcWnd.top;  HDC hdcTemp = :GetWindowDC(hWnd);  HDC hdcMemory = :CreateCompatibleDC(hdcTemp);  HBITMAP hBitMap = CreateCompatibleBitmap(hdcTemp, nWid, nHei);  SelectObject(hdcMemory, hBitMap);  HDC hdcScreen = :GetWindowD

6、C(hWnd);  POINT ptWinPos = rcWnd.left, rcWnd.top;  Graphics graph(hdcMemory);  Point points = Point(0, 0),Point(nWid, 0),Point(0, nHei);  graph.DrawImage(pBgImg, points,3);  SIZE sizeWindow=nWid, nHei;  POINT ptSrc=0,0;  DWORD dwE

7、xStyle = :GetWindowLong(hWnd, GWL_EXSTYLE);  if (dwExStyle & 0x80000) != 0x80000)     :SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle 0x80000);    CString strTitle;  m_alWnd.GetWindowText(strTitle);  Gdiplus:Font  

8、font(L"宋體",12,FontStyleBold,UnitPixel);  StringFormat   strFormat;  SolidBrush   brush(Color(0xff,0,0,0);  graph.DrawString(strTitle, -1, &font, PointF(32,30),&strFormat, &brush);   :UpdateLayeredWindow(hWnd, hdcScreen

9、, &ptWinPos, &sizeWindow, hdcMemory, &ptSrc, 0, &m_alBlend, ULW_ALPHA);  graph.ReleaseHDC(hdcMemory);  :ReleaseDC(hWnd,hdcScreen);  hdcScreen = NULL;  :ReleaseDC(hWnd,hdcTemp);  hdcTemp = NULL;  DeleteObject(hBitMap); &

10、#160;DeleteDC(hdcMemory);  hdcMemory = NULL;  return true; 調(diào)用示例:CWndAlpha<CMainDlg> wndAl;wndAl.InitAlpha(L"C:bg.png", NULL, rcMargin, true);m_pMainWnd = wndAl.GetMainWnd();wndAl.DoModal();本篇演示實現(xiàn)仿QQ界面的中間客戶區(qū)。QQ是可以調(diào)整界面透明度的,但是調(diào)整了透明度卻連中間客戶區(qū)也變得半透明了??蛻魠^(qū)畢竟是軟件最重要的部分,

11、是要 與用戶交互的,透明了就影響操作了,因此這里的客戶區(qū)不學QQ,始終不透明。要實現(xiàn)不透明控件,只能創(chuàng)建一個彈出窗口,遮住主界面的客戶區(qū)域,然后設(shè)定與 主界面連動,即始終跟著主窗口移動及調(diào)整尺寸。這個方法并不是很好,但卻幾乎是唯一的方法。為什么說幾乎是唯一的方法呢?的確存在著另外的解決方案,但是 這個方法太麻煩了,在此討論一下這個方法。 fV>d_6Lf  ph5i2U0  實 現(xiàn)半透明窗體,不透明控件,應該有不少朋友碰到過這個問題:為什么設(shè)定了窗口透明,窗口上的子窗口及控件也變得透明了?這個是受系統(tǒng)限制的,創(chuàng)建一個窗 口,這個窗口區(qū)域就相當于一塊畫布,最終系統(tǒng)要在這

12、塊畫布上繪制出窗口標題,客戶區(qū),控件等等,而窗口和控件繪制時的GetDC,BeginPaint等 不過是獲取到了跟自己相關(guān)的這塊畫布的一部分,在限定的區(qū)域內(nèi)繪制,最終是畫到這塊畫布上,系統(tǒng)最后顯示窗口就是在桌面上顯示這塊畫布,透明度也是認這塊 畫布,因此上面的子窗口及控件也一起變得透明了。另建一個彈出式窗口,相當于創(chuàng)建了另一塊畫布,就不受主窗口的透明度限制。 dX/7n=  <!> nA  知 道了原因,現(xiàn)在來討論如何不創(chuàng)建彈出式窗口,實現(xiàn)不透明控件。透明窗口有兩種實現(xiàn)方法,一種是調(diào)用 SetLayeredWindowAttributes,設(shè)定統(tǒng)一的窗口透明度,

13、既整個窗口采用同樣的透明度,QQ2009和這里的演示程序采用的就是這 個方法,這個方法不創(chuàng)建彈出窗口是無法實現(xiàn)不透明控件的,因為想要控件不透明,就必須在控件區(qū)域采用不同的透明 度,SetLayeredWindowAttributes無法做到,只能通過調(diào)用另一個函數(shù)UpdateLayeredWindow來實現(xiàn)可指定不同區(qū) 域不同透明度的窗口,API代碼大致如下: 37kFbRx  Ny7*MZ-  C/C+ code HDC hdc,hMemDC;   TSewq4K  RECT rc;   0ex.S_Oj4  &

14、#160;    IXtG 36O  GetWindowRect(hWnd,&rc);   M;<!C%K>       uFSU|SDd.  POINT ptSrc = 0,0;   _x(hlHFk  POINT ptWinPos = rc.left,rc.top;   GgY8>u  SIZE szWin = rc.right-rc.left,rc.bottom-rc.top;

15、0;  !0?o3,of-  BLENDFUNCTION stBlend = AC_SRC_OVER, 0,255,AC_SRC_ALPHA;   U=yvi8         !gWxVGv  hdc = GetWindowDC(m_hWnd);   &Iy58  hMemDC = CreateCompatibleDC(hdc);   OQP;5 #K  SelectObject(hMemDC,hbmp);

16、       /hbmp為整個窗口貼圖   aXj UDu7  UpdateLayeredWindow(hWnd,hdc,&ptWinPos,&szWin,hMemDC,&ptSrc,0,&stBlend,ULW_ALPHA);   gNP1UH4m  8%B_nVc  ,zxRDI  最 關(guān)鍵的部分就是SelectObject(hMemDC,hbmp);實現(xiàn)不同區(qū)域不同透明度,全在這個選入設(shè)備的hbmp的圖象數(shù)據(jù),Wind

17、ows的 32位色圖像的像素數(shù)據(jù)是COLORREF類型,0x00bbggrr格式,關(guān)鍵就在最高位的字節(jié)0x00,UpdateLayeredWindow是認 這個字節(jié)來設(shè)定透明度,0x00為全透明,0xFF為不透明,這個字節(jié)的集合有個專門名稱叫ALPHA通道。設(shè)定hbmp圖象每一個像素的這個最高位字節(jié) 數(shù)據(jù),就可以實現(xiàn)像素級別的透明度。網(wǎng)上應該能搜到大把利用PNG圖片實現(xiàn)半透明窗口的例子,因為PNG圖片是可以帶ALPHA通道的,解碼PNG圖片, 自然就有了ALPHA通道,即設(shè)定了這個最高位字節(jié),就不需要用代碼來一個個像素指定透明度了。實現(xiàn)這樣的半透明窗口是這樣一個過程:首先要用雙緩沖,創(chuàng) 建與窗

18、口相同大小的內(nèi)存圖象,然后在這個內(nèi)存圖象上繪制窗口的各個部分,標題欄,背景等等,一般是用PNG圖片實現(xiàn),這樣就不用逐個像素指定透明度了,最 后把這個內(nèi)存圖象繪制到窗口。想實現(xiàn)不透明控件,就要把控件區(qū)域的ALPHA通道值設(shè)為0xFF,然而不幸的是,幾乎所有的GDI操作,除了 TransparentBlt,那些最常用的BitBlt,TextOut,FillRect等等都是忽略ALPHA通道的,繪制過后這些區(qū)域的 ALPHA值都變成了0,即全透明。因此想要實現(xiàn)不透明控件,就要實現(xiàn)所有控件的自繪,使控件繪制到內(nèi)存圖象上,常規(guī)GDI操作過后再設(shè)定這些區(qū)域的 ALPHA值為0xFF。是不是頭大了?這個方法

19、太麻煩了,而且僅僅是為了在半透明窗口上實現(xiàn)不透明控件這樣一個效果,代價太大,因此并不實用。 QQ2009所用的DirectUI應該能很容易實現(xiàn)這個效果,但是并沒實現(xiàn),估計跟執(zhí)行效率有關(guān),因為這種像素級透明的程序在繪制時很耗時,調(diào)整窗口大 小時可能會有延遲現(xiàn)象,在速度慢一點的機器上更是明顯。 C8|Ls(4Ck  *1>)P8#  現(xiàn) 在來講模仿QQ的客戶區(qū),有很多種方法,這里選用相對比較簡單的方法,有更好的解決方案歡迎留言討論。首先是上部的搜索欄,當然是子類化EDIT控件進行 自繪,處理WM_NCCALCSIZE消息加大其非客戶區(qū),畫個外方內(nèi)圓的邊框。在編輯框輸入內(nèi)容

20、后會有個自繪的下拉列表出來,這個其實跟點了“更改外 觀”按鈕后出現(xiàn)的界面調(diào)色對話框是一樣的,不過是把那對話框改一下表現(xiàn)形式,然后搬到編輯框下面,就不演示了,還有右邊會出現(xiàn)清除和執(zhí)行按鈕,又是貼圖, 屬于非典型編輯框功能,也不演示了,有興趣的可以自己完成。 VI4mEq,V  Jkj7ty.J  然 后是側(cè)邊欄,看起來是TAB控件的功能,其實用工具欄更簡單一些,添加TBSTYLE_BUTTON|TBSTYLE_CHECKGROUP類型的按鈕就 跟TAB控件的效果差不多。怎么繪制前面一篇已經(jīng)講過了,收起和展開只是隱藏和顯示而已。最重要的好友列表部分,這個要用到TAB控件了,調(diào)整

21、窗口尺寸時 3個標簽的寬度是跟著變的,這個需要創(chuàng)建TAB控件時指定TCS_FIXEDWIDTH窗口類型,子類化后在WM_SIZE消息里發(fā)送 TCM_SETITEMSIZE消息調(diào)整標簽的寬度。標簽需要自繪,鼠標點擊上面的下拉箭頭會彈出菜單,這個需要在WM_LBUTTONDOWN消息里判 斷一下,子類化后其實想干什么都行,只是麻煩一點罷了:)點擊標簽后下面列表子窗口的滑動效果切換也很簡單,把兩個窗口并排然后連續(xù)移動就可以,不過因為 刷新的關(guān)系,可能會有重影,如果想要更好的效果,應該是把子窗口截圖,然后用雙緩沖繪制出滑動效果,這里就簡單一點,不用這個方法了。 nyHt/T  *| hd/j  好 友列表,群列表和最近聯(lián)系人列表是用ListBox

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論