a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 學院 > 開發設計 > 正文

在windows上創建完美的不規則窗口

2019-11-14 09:48:08
字體:
來源:轉載
供稿:網友

在windows上創建完美的不規則窗口

不規則窗口方法簡介

windows上的窗口絕大多數是方形的,但是偶爾也會有一些其他形狀的窗口,如圓形甚至不規則形狀。這些不常見的窗口是如何做出來的呢? 有兩種方法可以創建不規則窗口 1、windows在很早的時代就支持不規則形狀的窗口了。windows提供了SetWindowRgn 函數來設置窗口的區域,還提供了一些函數來創建橢圓、圓角矩形區域,還可以自己繪制區域,但是這種方法有個缺陷,曲線的邊緣有嚴重的鋸齒。 2、使用windows2000以后提供的透明窗口方法來創建不規則形狀的窗口。當透明窗口的透明部分的透明度為0的時候次部分就會完全透明,鼠標也可以穿透。所以只要制造出有不規則的完全透明區域的窗口后,就可以形成不規則窗口。 而且可以通過邊緣抗鋸齒來實現平滑的窗口邊緣,消除鋸齒。 本文主要講的就是第二種方法。

透明窗口API詳解

之前已經有一篇文章介紹了簡單的透明窗口使用vc++創建windows透明窗口,一些基礎內容就不在贅述,請自行閱讀。 此次主要用到上一篇文章中沒有詳細說明的UpdateLayeredWindow函數,UpdateLayeredWindow函數的透明和其他的透明方式不太一樣,一旦使用UpdateLayeredWindow函數就不能再使用其他的透明函數, 而且窗口的繪制也完全被UpdateLayeredWindow接管,此時正常的繪圖都不再生效,必須通過UpdateLayeredWindow來刷新窗口的界面。 要使用UpdateLayeredWindow刷新窗口,首先要建立一個內存dc,然后在dc上畫圖,在通過UpdateLayeredWindowdc上的內容根據參數做透明處理然后刷新界面。

BOOL WINAPI UpdateLayeredWindow( _In_ HWND hwnd, _In_opt_ HDC hdcDst, _In_opt_ POINT *PPTDst, _In_opt_ SIZE *psize, _In_opt_ HDC hdcSrc, _In_opt_ POINT *pptSrc, _In_ COLORREF crKey, _In_opt_ BLENDFUNCTION *pblend, _In_ DWord dwFlags);

UpdateLayeredWindow有9個參數。 第一個參數是要刷新的窗口句柄,第二個是要刷新的窗口的 dc,這個參數通常可以傳NULL,會自動從第一個參數的窗口句柄代表的窗口中去獲取。 第三個參數是你要刷新的區域的左上坐標點,如果是全屏也可以傳NULL,第四個參數是刷新區域的長寬,不能傳NULL。 第五個參數就是畫好圖的內存dc了,第六個參數是內存dc上刷新過去的區域的左上坐標點。 第七個參數和第八個參數就是控制透明處理的參數,第七個參數設置透明色,也就是這種顏色的區域全部透明,第八個參數是設置整體透明度。 第九個參數控制是第七個參數還是第八個參數生效或者都生效。 此處要說明一下第八個參數設置的整體透明度,他只是在原有的顏色上按照參數里的比例做透明處理,如果內存dc里的一塊區域顏色本身就是全透明的,那么無論怎么設置參數這里依然是全透明的。

制造透明區域

使用透明窗口來制造不規則窗口的關鍵就在于怎樣制造出包含透明區域的內存dc來。

外部作圖

眾所周知,png是支持透明通道的一種圖片格式,所以只要提前做好png透明圖片,然后運行時加載到內存dc上就行了,是不是簡單爆了。

實時繪圖

如果能用圖片那是最好啦,但是有時候如果窗口的形狀要經常變化而且形態非常多的話,就不能通過外部圖片了。只能在內存中畫出dc的圖來。 gdi+中的顏色支持了透明色,但是這種透明色指的是畫刷畫圖的時候和背景色做透明,最終畫在dc上還是不透明的,并不能達到我們要的效果。那么怎么辦呢?只能使出終極辦法: 直接修改內存中的顏色數據。也就是將要透明的區域先用一種特別的顏色填充好,然后遍歷內存中的顏色數據,將這個顏色的內存數據強行修改為完全透明-——將ARGB的代表A通道的字節置零。 由于內存dc并不支持遍歷內存數據,所以一般是建立一個位圖,然后在這個位圖上畫圖標記處需要透明的位置,最后遍歷位圖內存,將需要透明的位置全部摳掉。托cpu進步的福,我摳一副1080p的圖瞬間就可以完成。然后把位圖畫到dc上去。 這里有一個小問題,因為位圖中有透明顏色,上次在dc畫圖的時候這部分會遺留下來干擾到下次繪圖,所以要每次重畫之前把dc內容用其他顏色給填掉。 最后就是鋸齒的問題了。如果要抗鋸齒的話就要再做一個特殊處理,首先得明白抗鋸齒的原理,可以Jan之前我寫過的gdi+的畫圖抗鋸齒原理。 用gdi+畫出抗鋸齒的圖后,然后在遍歷的時候尋找那些由兩種顏色混合成的顏色,然后根據混合的比例相應的轉換成半透明度設置到這個像素點。通常我用白色和黑色做前景色和背景色,這樣混合變成灰色,灰色的rgb值除以白色rgb值的比例就是半透明度。 最后將這樣一幅位圖畫到dc上,用UpdateLayeredWindow函數刷新到窗口上就會形成不規則的窗口了。

代碼示例

畫出要被扣掉的關鍵色區域位圖的代碼:

void SpotlightWindow::DrawMaskImage(Bitmap * pImage){ Graphics graphics(pImage); graphics.FillRectangle(m_pBlackBrush, 0, 0, m_windowRect.Width(), m_windowRect.Height()); graphics.SetSmoothingMode(Gdiplus::SmoothingMode::SmoothingModeAntiAlias); graphics.FillEllipse(m_pKeyBrush, m_ellipseRect.left, m_ellipseRect.top, m_ellipseRect.Width(), m_ellipseRect.Height()); graphics.Flush(Gdiplus::FlushIntentionSync);}

遍歷摳掉透明區域并對邊緣做半透明處理的代碼:

void SpotlightWindow::MakeTransparentImage(Bitmap * pImage){ Gdiplus::Rect rect(0, 0, pImage->GetWidth(), pImage->GetHeight()); Gdiplus::BitmapData bmpData; pImage->LockBits(&rect, Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bmpData); int width = pImage->GetWidth(); int height = pImage->GetHeight(); int stride = bmpData.Stride; unsigned int *pData = reinterPRet_cast<unsigned int *>(bmpData.Scan0); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { unsigned int color = *pData; if (color == WHITE_COLOR) { *pData = TRANSPARENCY_WHITE_COLOR;//設為透明色 } else if (color != BLACK_COLOR) { *pData = TransportTransparentColor(color);//根據計算結果設為把半透明顏色 } ++pData; } } pImage->UnlockBits(&bmpData);}

計算半透明的代碼:

unsigned int SpotlightWindow::TransportTransparentColor(unsigned int color){ //像素顏色數據 unsigned char * pArgb = reinterpret_cast<unsigned char *>(&color); //換算出的透明度 unsigned char transparency = MAX_COLOR-*pArgb; //新的像素顏色 unsigned int transparencyColor = BLACK_COLOR; pArgb = reinterpret_cast<unsigned char *>(&transparencyColor); //設置新的像素顏色的透明度 pArgb[TRANSPARENCY_INDEX] = transparency; return transparencyColor;}

將透明圖片畫到dc上并刷新到窗口上的代碼:

void SpotlightWindow::Paint(Gdiplus::Bitmap * pImage){ HBITMAP old = SelectBitmap(m_memoryDC, m_memoryBitmap); FillRect(m_memoryDC, m_windowRect, m_backgroundBrush); Graphics graphics(m_memoryDC); graphics.DrawImage(pImage, 0, 0, m_windowRect.Width(), m_windowRect.Height()); CSize size(m_windowRect.Width(), m_windowRect.Height()); CPoint point(0, 0); UpdateLayeredWindow(m_mainWindow, NULL, NULL,&size, m_memoryDC, &point, 0, &m_blendFunc32bpp, ULW_ALPHA); SelectBitmap(m_memoryDC, old);}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 国产免费小视频 | 亚洲欧美v国产一区二区 | 国产精品自产拍在线观看桃花 | 免费观看一级特黄欧美大片 | 欧美大片在线免费观看 | av资源中文在线天堂 | 一级片观看| 欧美色图 | 亚洲精品v| 成人在线中文字幕 | 日韩另类 | 国产剧情一区二区 | 91麻豆精品国产91久久久更新时间 | 国产午夜久久久久 | 亚洲黄色网址 | 成人免费视频观看视频 | 久久一区 | 日韩一区二区在线观看视频 | 国产区在线| 黄色网址免费在线观看 | 在线 丝袜 欧美 日韩 制服 | 国产精品粉嫩白浆在线观看 | 亚洲天堂成人 | 国产一区二区三区精品久久久 | 99精品国产一区二区三区 | 偷拍亚洲色图 | 国外成人免费视频 | 欧美日韩国产综合视频 | 免费看的黄色网 | 超碰中文字幕 | 日本激情网 | 在线日韩 | 欧美一区二区三区电影 | 色噜噜视频在线观看 | 日韩电影一区二区三区 | 全黄大全大色全免费大片 | 久久国产精品影视 | 欧美一区二区三区在线 | 久久毛片 | 黄色网址网站在线观看 | 色欧美日韩 |