在wnidows C++ 用戶端開發中,使用GDI+和png透明或者異形圖片,結合UpdateLayeredWindow 雙層視窗,可以實現透明,陰影,異形的效果。 其原理便是背景視窗使用UpdateLayeredWindow,重新整理png圖片,前景視窗作為實際視窗放一些空間,但前景視窗實際上是透明的,這樣可以點擊移動背景視窗,然後當背景視窗移動時,移動前景視窗。
1.當時候產品馬上要發布的時候,在XP系統上,出現了當視窗最小化到工作列,無法點擊回來。各種使用ModifyStyle(0, WS_MINIMIZEBOX, 0);
使用OnACtive(),各種難受就是談不出來,無奈只好繞過了這個問題。後來才發現了原因。
void CBackDlg::OnMove(int x, int y) {CDialog::OnMove(x, y);CRect rect;GetWindowRect(rect); //在XP和win7行都正常。 m_pChildWnd->MoveWindow(rect.left, rect.top, rect.Width(), rect.Height()); //在XP系統上,當視窗回到工作列時候,點擊工作列視窗就出不來了。但在win7上正常。 //m_pChildWnd->SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW);}
2.第一次啟動視窗位置設定,UpdateLayeredWindow的第二個參數,當然你也可以在OnInitDialog中設定,但有時候效果
似乎不是很好。
BOOL CBackDlg::OnEraseBkgnd(CDC *pDC){ CRect rect; this->GetClientRect(rect); if(!m_pBkImage) { m_pBkImage = new Image(_T("main_frame.png")); }int wndW = rect.Width();int wndH = rect.Height(); CDC memDC; CBitmap memBmp; memDC.CreateCompatibleDC(pDC); memBmp.CreateCompatibleBitmap(pDC, wndW, wndH); CBitmap *pOldBmp = memDC.SelectObject(&memBmp); ModifyStyleEx(0, WS_EX_LAYERED); Graphics bmpGraphics(memDC.m_hDC); bmpGraphics.SetSmoothingMode(SmoothingModeAntiAlias); bmpGraphics.DrawImage(m_pBkImage, 0, 0, wndW, wndH); BLENDFUNCTION _Blend; _Blend.BlendOp = 0; _Blend.BlendFlags = 0; _Blend.AlphaFormat =1; _Blend.SourceConstantAlpha = 255; int posX = (GetSystemMetrics ( SM_CXSCREEN ) - wndW)/2; int posY = (GetSystemMetrics ( SM_CYSCREEN ) - wndH)/2; //此時,滑鼠會穿透表單中Alpha值為0的地區。 並且計算了在螢幕的位置 UpdateLayeredWindow(pDC, &CPoint(posX, posY), &CSize(wndW, wndH), &memDC, &CPoint(0, 0), 0, &_Blend, ULW_ALPHA); bmpGraphics.ReleaseHDC(memDC.m_hDC); memDC.SelectObject(pOldBmp); memDC.DeleteDC(); return TRUE;}
3.托盤菜單遮蓋對話方塊不能移動的問題,不要動態建立托盤和菜單就行。
4.單層視窗能否實現png陰影和透明效果?
當然可以實現的,可惜的你視窗上所有控制項將不再顯示,使用UpdateLayeredWindow後,視窗將不再響應OnPaint, OnEraseBkgnd訊息,這點就是微軟的噁心,意思是你要使用UpdateLayeredWindow,那麼就全部重畫吧,我不管了。使用spy++時查看疼訊QQ,金山殺毒的陰影製作效果的視窗,也有WS_EX_LAYERED擴充狀態,似乎也會用到UpdateLayeredWindow,就不知道他們是不是單層能實現了。 知識太有限,待以後研究學習。