Windows界面編程第一篇 位圖背景與位圖畫刷 ??? 可以通過WM_CTLCOLORDLG消息來設(shè)置對話框的背景,MSDN上對這個消息的說明如下:
The?WM_CTLCOLORDLG ?message is sent to a dialog box before the system draws the dialog box. By responding to this message, the dialog box can set its text and background colors using the specified display device context handle.
當(dāng)窗口消息響應(yīng)函數(shù)接收這個消息時,wParam表示對話框的設(shè)備上下方即HDC,lParam表示對話框的句柄。如果程序處理了這個消息,應(yīng)返回一個畫刷。系統(tǒng)將會用這個畫刷來重繪對話框背景。
因此我們在這個WM_CTLCOLORDLG消息中得到對話框的大小,并通過StretchBlt函數(shù)將位圖縮放后貼到對話框的HDC中就完成了對話框背景的設(shè)置,然后返回一個空畫刷給系統(tǒng),這樣系統(tǒng)就不會將位圖背景給覆蓋了。
代碼非常簡單,要注意的是在使用StretchBlt函數(shù)縮放位圖時,最好先使用
SetStretchBltMode函數(shù)來設(shè)置下位圖內(nèi)容伸展模式,這樣可以避免縮放后位圖失真嚴(yán)重。SetStretchBltMode函數(shù)原型如下:
int?SetStretchBltMode(
????HDChdc,???????????// handle to DC
??? int?iStretchMode???// bitmap stretching mode
);
第一個參數(shù)就是設(shè)備上下方即HDC。
第二個參數(shù)有四種設(shè)置:
1.? BLACKONWHITE?or?STRETCH_ANDSCANS
?如果兩個或多個像素得合并成一個像素,那么StretchBlt會對像素執(zhí)行一個邏輯AND運(yùn)算。這樣的結(jié)果是只有全部的原始像素是白色時該像素才為白色,其實(shí)際意義是黑色像素控制了白色像素。這適用于白色背景中主要是黑色的單色點(diǎn)陣圖。
2.? WHITEONBLACK?or?STRETCH_ORSCANS
?如果兩個或多個像素得合并成一個像素,那么StretchBlt會對像素執(zhí)行邏輯OR運(yùn)算。這樣的結(jié)果是只有全部的原始像素都是黑色時該像素才為黑色,也就是說由白色像素決定顏色。這適用于黑色背景中主要是白色的單色點(diǎn)陣圖。
3.? COLORONCOLOR?or?STRETCH_DELETESCANS
?簡單地消除圖素行或列,而沒有任何邏輯組合。這是通常是處理彩色點(diǎn)陣圖的最佳方法。
4.? HALFTONE?or?STRETCH_HALFTONE
根據(jù)組合起來的來源顏色來計算目的的平均顏色。
?
其它技術(shù)細(xì)節(jié)可以見代碼中的注釋,完整代碼如下(也可以下載,下載地址為:http://download.csdn.net/download/morewindows/4947377):
[cpp] ?view plaincopyprint?
?? ?? #include?<windows.h>? ??#include?"resource.h"? ???? const ?char ?szDlgTitle[]?=?"位圖背景?使用StretchBlt貼圖?MoreWindows-(http://blog.csdn.net/MoreWindows)" ;???? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam);?????????????? int ?APIENTRY?WinMain(HINSTANCE ?hInstance,???????????????????????HINSTANCE ?hPrevInstance,?? ?????????????????????LPSTR ?????lpCmdLine,?? ?????????????????????int ???????nCmdShow)?? {?? ????DialogBox(hInstance,?MAKEINTRESOURCE(IDD_DIALOG1),?NULL,?DlgProc);?? ????return ?0;?? }?? ?? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam)??{?? ????RECT???????rcDialog;?? ????HBITMAP ????hBitmap;?? ????static ?BITMAP?s_bm;?? ????static ?HDC ????s_hdcMem;?? ?? ????switch ?(message)?? ????{?? ????case ?WM_INITDIALOG:?? ?????????? ????????SetWindowText(hDlg,?szDlgTitle);?? ?????????? ????????SetWindowLong(hDlg,?GWL_STYLE,?GetWindowLong(hDlg,?GWL_STYLE)?|?WS_SIZEBOX);?? ?? ?????????? ????????hBitmap?=?(HBITMAP )LoadImage(NULL,?"005.bmp" ,?IMAGE_BITMAP,?0,?0,?LR_LOADFROMFILE?|?LR_CREATEDIBSECTION);?? ????????if ?(hBitmap?==?NULL)?? ????????{?? ????????????MessageBox(hDlg,?"LoadImage?failed" ,?"Error" ,?MB_ICONERROR);?? ????????????exit(0);?? ????????}????????? ????????else ?? ????????{?? ?????????????? ????????????HDC ????????hdc;?? ????????????hdc?=?GetDC(hDlg);?? ????????????s_hdcMem?=?CreateCompatibleDC(hdc);?? ????????????SelectObject(s_hdcMem,?hBitmap);?????? ????????????ReleaseDC(hDlg,?hdc);?? ?? ?????????????? ????????????GetObject(hBitmap,?sizeof (s_bm),?&s_bm);?? ????????}?? ?? ????????return ?0;?? ?? ????case ?WM_COMMAND:?? ????????switch ?(LOWORD(wParam))?? ????????{?? ????????case ?IDCANCEL:?? ????????????DeleteDC(s_hdcMem);?? ????????????EndDialog(hDlg,?LOWORD(wParam));?? ????????????return ?TRUE;?? ????????}?? ????????break ;?? ?? ?? ????case ?WM_SIZE:?? ????????InvalidateRect(hDlg,?NULL,?TRUE);?? ????????return ?TRUE;?? ?? ????case ?WM_CTLCOLORDLG:?? ????????GetClientRect(hDlg,?&rcDialog);?? ?????????? ????????SetStretchBltMode((HDC )wParam,?COLORONCOLOR);?? ????????StretchBlt((HDC )wParam,?0,?0,?rcDialog.right,?rcDialog.bottom,?s_hdcMem,?0,?0,?s_bm.bmWidth,?s_bm.bmHeight,?SRCCOPY);????? ????????return ?(BOOL )((HBRUSH )GetStockObject(NULL_BRUSH));?? ????}?? ????return ?FALSE;?? }?? 運(yùn)行結(jié)果如下:
?
?
在上面這種方法中,我們是在WM_CTLCOLORDLG中貼圖來完成背景設(shè)置了,也可以創(chuàng)建一個位圖畫刷,然后在WM_CTLCOLORDLG消息中直接返回這個畫刷,這樣系統(tǒng)將完成貼圖功能。
???????位圖畫刷的創(chuàng)建函數(shù)為CreatePatternBrush,其函數(shù)原型如下:
HBRUSHCreatePatternBrush(
????HBITMAPhbmp???// handle to bitmap
);
只要給這個函數(shù)傳入位圖句柄即可,完整代碼如下(下載地址為:http://download.csdn.net/download/morewindows/4947377):
[cpp] ?view plaincopyprint?
?? ?? #include?<windows.h>? ??#include?"resource.h"? ???? const ?char ?szDlgTitle[]?=?"位圖畫刷?MoreWindows-(http://blog.csdn.net/MoreWindows)" ;???? ?? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam);???? int ?APIENTRY?WinMain(HINSTANCE ?hInstance,???????????????????????HINSTANCE ?hPrevInstance,?? ?????????????????????LPSTR ?????lpCmdLine,?? ?????????????????????int ???????nCmdShow)?? {?? ????DialogBox(hInstance,?MAKEINTRESOURCE(IDD_DIALOG1),?NULL,?DlgProc);?? ????return ?0;?? }?? ?? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam)??{?? ????static ?HBRUSH ????s_hBitmapBrush;??? ?? ????switch ?(message)?? ????{?? ????case ?WM_INITDIALOG:?? ?????????? ????????SetWindowText(hDlg,?szDlgTitle);?? ?????????? ????????SetWindowLong(hDlg,?GWL_STYLE,?GetWindowLong(hDlg,?GWL_STYLE)?|?WS_SIZEBOX);?? ?? ?????????? ????????HBITMAP ?hBitmap;?? ????????hBitmap?=?(HBITMAP )LoadImage(NULL,?"005.bmp" ,?IMAGE_BITMAP,?0,?0,?LR_LOADFROMFILE?|?LR_CREATEDIBSECTION);?? ????????if ?(hBitmap?==?NULL)?? ????????{?? ????????????MessageBox(hDlg,?"LoadImage?failed" ,?"Error" ,?MB_ICONERROR);?? ????????????exit(0);?? ????????}????????? ?? ?????????? ????????s_hBitmapBrush?=?CreatePatternBrush(hBitmap);?? ????????return ?0;?? ?? ?? ????case ?WM_COMMAND:?? ????????switch ?(LOWORD(wParam))?? ????????{?? ????????case ?IDCANCEL:?? ????????????DeleteObject(s_hBitmapBrush);?? ????????????EndDialog(hDlg,?LOWORD(wParam));?? ????????????return ?TRUE;?? ????????}?? ????????break ;?? ?? ????case ?WM_CTLCOLORDLG:?? ????????return ?(BOOL )s_hBitmapBrush;?? ????}?? ????return ?FALSE;?? }?? 運(yùn)行結(jié)果如下:
?
?
注意,這兩做法在窗口大小超過位圖大小時會表現(xiàn)不同,前一種做法會拉伸位圖以適應(yīng)窗口大小,后一種做法是直接平鋪。詳見下圖:
?
?
本篇《Windows界面編程第一篇位圖背景與位圖畫刷》主要介紹了通過WM_CTLCOLORDLG消息來設(shè)置對話框的背景,在Windows系統(tǒng)中還有類似于WM_CTLCOLORDLG消息的還有WM_CTLCOLORBTN,WM_CTLCOLOREDIT,WM_CTLCOLORLISTBOX,WM_CTLCOLORSCROLLBAR,WM_CTLCOLORSTATIC這五種來分別管理按鈕,編輯框,列表框,滾動條,靜態(tài)框。有興趣的讀者可以試驗(yàn)下。
?
下一篇將介紹調(diào)節(jié)窗體透明度的方法,歡迎繼續(xù)瀏覽《Windows界面編程第二篇 半透明窗體》
?
?當(dāng)窗口的背景用彩色圖片來裝飾時,其它控件如果還是用灰色的背景會顯的比較不諧調(diào),《Windows界面編程第五篇 靜態(tài)控件背景透明化》將介紹如何為靜態(tài)框設(shè)置透明背景。
?
?
Windows界面編程第二篇半透明窗體
??? 上一篇《Windows界面編程第一篇 位圖背景與位圖畫刷》介紹了通過WM_CTLCOLORDLG消息來來設(shè)置對話框的背景以及位圖畫刷的使用。本篇將介紹動態(tài)調(diào)節(jié)窗體透明度的方法。
??? 調(diào)節(jié)窗體透明度可以先使用SetWindowLong為窗體加上WS_EX_LAYERED屬性,再使用來SetLayeredWindowAttributes指定窗體的透明度。這樣就可以在程序運(yùn)行時動態(tài)的調(diào)節(jié)窗體的透明度了。
??? 下面先介紹下SetWindowLong和SetLayeredWindowAttributes函數(shù)。
SetWindowLong可以用來設(shè)置窗口的一些屬性,其函數(shù)原型如下:
LONGSetWindowLong(
??? HWNDhWnd,
??? int?nIndex,
??? LONGdwNewLong
);
第一個參數(shù)表示窗口句柄。
第二個參數(shù)代表要設(shè)置的哪一種值,如GWL_STYLE表示將設(shè)置窗口的風(fēng)格,這個參數(shù)還可以取GWL_EXSTYLE,GWL_WNDPROC,DWL_DLGPROC,GWL_HINSTANCE,GWL_USERDATA等等。
第三個參數(shù)表示要設(shè)置的值。
比如要設(shè)置對話框也能夠可調(diào)節(jié)窗口大小,可以用:
?//?設(shè)置對話框大小可調(diào)節(jié)
SetWindowLong(hDlg,?GWL_STYLE,?GetWindowLong(hDlg,?GWL_STYLE) |?WS_SIZEBOX);
?
SetLayeredWindowAttributes在MSDN上解釋如下:
The?SetLayeredWindowAttributes ?function sets the opacity and transparency color key of a layered window.
其函數(shù)原型為:
BOOLSetLayeredWindowAttributes(
??? HWNDhwnd,
??? COLORREFcrKey,
??? BYTEbAlpha,
??? DWORDdwFlags
);
第一個參數(shù)表示窗口句柄。
第二個參數(shù)表示透明色。
第三個參數(shù)表示透明度。
第四個參數(shù)表示函數(shù)將完成什么樣的功能,設(shè)置成LWA_COLORKEY表示為窗口指定了透明色,設(shè)置成LWA_ALPHA表示將調(diào)整窗口的透明度,可以同時設(shè)置這兩種功能。
?
程序代碼還將用到Slider控件,這種控件可以有如下操作:
1.通過SendMessage?+?TBM_SETRANGE來設(shè)置滑塊變化的范圍。
2.通過SendMessage?+?TBM_SETPOS來設(shè)置滑塊當(dāng)前位置。
3.通過SendMessage?+?TBM_GETPOS來獲得滑塊當(dāng)前位置。
4.當(dāng)滑塊位置發(fā)生變化時,在其父窗口中通過WM_HSCROLL或WM_VSCROLL來響應(yīng)消息。
?
下面給出完整的源代碼(下載地址:http://download.csdn.net/download/morewindows/4947386)
[cpp] ?view plaincopyprint?
?? ?? #include?<windows.h>? ??#include?<commctrl.h>? ??#include?"resource.h"? ??const ?char ?szDlgTitle[]?=?"可變透明度窗體?MoreWindows-(http://blog.csdn.net/MoreWindows)" ;???? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam);???? int ?APIENTRY?WinMain(HINSTANCE ?hInstance,???????????????????????HINSTANCE ?hPrevInstance,?? ?????????????????????LPSTR ?????lpCmdLine,?? ?????????????????????int ???????nCmdShow)?? {?? ????DialogBox(hInstance,?MAKEINTRESOURCE(IDD_DIALOG1),?NULL,?DlgProc);?? ????return ?0;?? }?? ?? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam)??{?? ????const ?int ?INIT_TRANSPARENT?=?200;??? ????static ?HBRUSH ????s_hBitmapBrush;??? ?? ????switch ?(message)?? ????{?? ????case ?WM_INITDIALOG:?? ?????????? ????????SetWindowText(hDlg,?szDlgTitle);?? ?? ?????????? ????????HBITMAP ?hBitmap;?? ????????hBitmap?=?(HBITMAP )LoadImage(NULL,?"005.bmp" ,?IMAGE_BITMAP,?0,?0,?LR_LOADFROMFILE?|?LR_CREATEDIBSECTION);?? ????????if ?(hBitmap?==?NULL)?? ????????{?? ????????????MessageBox(hDlg,?"LoadImage?failed" ,?"Error" ,?MB_ICONERROR);?? ????????????exit(0);?? ????????}????????? ?? ?????????? ????????s_hBitmapBrush?=?CreatePatternBrush(hBitmap);?? ?? ?????????? ????????SetWindowLong(hDlg,?GWL_EXSTYLE,?GetWindowLong(hDlg,?GWL_EXSTYLE)?|?WS_EX_LAYERED);?? ?????????? ????????SetLayeredWindowAttributes(hDlg,?0,?INIT_TRANSPARENT,?LWA_ALPHA);?? ?? ?????????? ????????SendMessage(GetDlgItem(hDlg,?IDC_SLIDER_TRANSPARENT),?TBM_SETRANGE,?(WPARAM )FALSE,?MAKELONG(0,?255));?? ?????????? ????????SendMessage(GetDlgItem(hDlg,?IDC_SLIDER_TRANSPARENT),?TBM_SETPOS,?(WPARAM )TRUE,?INIT_TRANSPARENT);?? ????????return ?0;?? ?? ?? ????case ?WM_COMMAND:?? ????????switch ?(LOWORD(wParam))?? ????????{?? ????????case ?IDCANCEL:?? ????????????DeleteObject(s_hBitmapBrush);?? ????????????EndDialog(hDlg,?LOWORD(wParam));?? ????????????return ?TRUE;?? ????????}?? ????????break ;?? ?? ?? ????case ?WM_HSCROLL:??? ????????{?? ?????????????? ????????????int ?nTransparent?=?SendMessage(GetDlgItem(hDlg,?IDC_SLIDER_TRANSPARENT),?TBM_GETPOS,?0,?0);??? ?????????????? ????????????SetLayeredWindowAttributes(hDlg,?0,?nTransparent,?LWA_ALPHA);?? ????????}?? ????????break ;?? ?? ?? ????case ?WM_CTLCOLORDLG:???? ????????return ?(BOOL )s_hBitmapBrush;?? ????}?? ????return ?FALSE;?? }?? 運(yùn)行結(jié)果如下:
?
在本篇文章中我們通過SetWindowLong為窗體加上WS_EX_LAYERED屬性,再使用SetLayeredWindowAttributes完成窗體的透明度調(diào)節(jié)。下面兩篇也將使用這兩個函數(shù)來完成另一個功能——異形窗口(異形窗體)。異形窗口可以使得窗口更加美觀,它能靈活的變動窗口的形狀。歡迎繼續(xù)瀏覽《Windows界面編程 第三篇異形窗體 普通版》和《Windows界面編程 第四篇異形窗體 高富帥版》
Windows界面編程第三篇 異形窗體 普通版 ??? 上一篇《Windows界面編程第二篇 半透明窗體》介紹了先使用SetWindowLong為窗體加上WS_EX_LAYERED屬性,再使用SetLayeredWindowAttributes調(diào)整窗體的透明度。本篇將使用這二個函數(shù)來完成另一個實(shí)用的功能——異形窗口(異形窗體)。
異形窗口的原理很簡單,首先加載一張位圖畫刷作窗口背景,然后設(shè)置透明色就可以使得窗口由矩形變成任意形狀。這樣使得窗口的顯示更加美觀。
?
??? 下面先簡單介紹下Win32 SDK方式創(chuàng)建窗口的流程(按《Windows程序設(shè)計》中的大體流程):
1.設(shè)置WNDCLASS類型的變量,這個變量將描述窗口的風(fēng)格、窗口消息處理函數(shù)、程序圖標(biāo)、光標(biāo)、窗口背景畫刷等待。
2.使用RegisterClass將WNDCLASS類型的變量注冊下。
3.使用CreateWindow或CreateWindowEx創(chuàng)建窗口,這里可以設(shè)置窗口的初始位置、初始大小、擴(kuò)展屬性等等。
4.通過ShowWindow和UpdateWindow將窗口顯示出來。
5.窗口顯示完成后,在WinMain()函數(shù)中添加消息處理:???
?????? MSG?msg;
?????? while (GetMessage(&msg,?NULL, 0, 0))
???????{
??????????????TranslateMessage(&msg);
??????????????DispatchMessage(&msg);
???????}
通過這五步就完成了一個窗口的創(chuàng)建了。
對于窗口消息函數(shù),一般只要在WM_DESTROY消息中調(diào)用下PostQuitMessage(0);其它的消息都可以使用默認(rèn)消息處理函數(shù)DefWindowProc。
?
對于異形窗口,可以在WM_CREATE即窗口初始化時設(shè)置好透明色就完成了窗口形狀的改變,不過為了支持鼠標(biāo)對窗口的拖曳,還要在WM_LBUTTONDOWN消息中加入:
PostMessage(hwnd,?WM_SYSCOMMAND,?SC_MOVE?|?HTCAPTION, 0);
這樣,異形窗口就可以在屏幕上像普通窗口一樣的移動了。
?
完整的源代碼如下所示(下載地址:http://download.csdn.net/download/morewindows/4966815):
[cpp] ?view plaincopyprint?
?? ?? #include?<windows.h>? ???? const ?char ?szAppName[]?=?"異形窗口1?MoreWindows-(http://blog.csdn.net/MoreWindows)" ;???? ? ? ? ? ? ? ?? void ?GetWindowSize(HWND ?hwnd,?int ?*pnWidth,?int ?*pnHeight);???? ?? ? ? ? ? ? ? ?? BOOL ?InitBitmapWindow(HINSTANCE ?hinstance,?HBITMAP ?hBitmap,?int ?nCmdshow);???? ?? LRESULT ?CALLBACK?BitmapWindowWndPrco(HWND ?hwnd,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParm);???? ?? int ?APIENTRY?WinMain(HINSTANCE ?hInstance,???????????????????????HINSTANCE ?hPrevInstance,?? ?????????????????????LPSTR ?????lpCmdLine,?? ?????????????????????int ???????nCmdShow)?? {?? ?????? ????HBITMAP ??hBitmap;?? ????hBitmap?=?(HBITMAP )LoadImage(NULL,?"Kitty.bmp" ,?IMAGE_BITMAP,?0,?0,?LR_LOADFROMFILE);?? ????if ?(hBitmap?==?NULL)?? ????{?? ????????MessageBox(NULL,?"位圖加載失敗" ,?"Error" ,?MB_ICONERROR);?? ????????return ?0;?? ????}?? ????if ?(!InitBitmapWindow(hInstance,?hBitmap,?nCmdShow))?? ????????return ?0;?? ?? ????MSG?msg;?? ????while ?(GetMessage(&msg,?NULL,?0,?0))?? ????{?? ????????TranslateMessage(&msg);?? ????????DispatchMessage(&msg);?? ????}?? ????DeleteObject(hBitmap);?? ?? ????return ?msg.wParam;?? }?? ?? ?? BOOL ?InitBitmapWindow(HINSTANCE ?hinstance,?HBITMAP ?hBitmap,?int ?nCmdshow)??{?? ????HWND ?hwnd;?? ????WNDCLASS?wndclass;?? ?????? ????wndclass.style???????=?CS_VREDRAW?|?CS_HREDRAW;?? ????wndclass.lpfnWndProc?=?BitmapWindowWndPrco;??? ????wndclass.cbClsExtra??=?0;?? ????wndclass.cbWndExtra??=?0;?? ????wndclass.hInstance???=?hinstance;????? ????wndclass.hIcon???????=?LoadIcon(NULL,?IDI_APPLICATION);?? ????wndclass.hCursor?????=?LoadCursor(NULL,?IDC_ARROW);?? ????wndclass.hbrBackground?=?CreatePatternBrush(hBitmap);?? ????wndclass.lpszMenuName??=?NULL;?? ????wndclass.lpszClassName?=?szAppName;?? ?????? ????if ?(!RegisterClass(&wndclass))?? ????{?? ????????MessageBox(NULL,?"Program?Need?Windows?NT!" ,?"Error" ,?MB_ICONERROR);?? ????????return ?FALSE;?? ????}?? ?? ????BITMAP?bm;?? ????GetObject(hBitmap,?sizeof (bm),?&bm);?? ????hwnd?=?CreateWindowEx(WS_EX_TOPMOST,?? ????????????????????????szAppName,?? ????????????????????????szAppName,??? ????????????????????????WS_POPUP,?? ????????????????????????CW_USEDEFAULT,??? ????????????????????????CW_USEDEFAULT,??? ????????????????????????bm.bmWidth,??? ????????????????????????bm.bmHeight,?? ????????????????????????NULL,?? ????????????????????????NULL,?? ????????????????????????hinstance,?? ????????????????????????NULL);?? ????if ?(hwnd?==?NULL)?? ????????return ?FALSE;?? ?????? ????ShowWindow(hwnd,?nCmdshow);?? ????UpdateWindow(hwnd);?? ?????? ????return ?TRUE;?? }?? ?? LRESULT ?CALLBACK?BitmapWindowWndPrco(HWND ?hwnd,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParm)??{?? ????static ?HDC ?s_hdcMem;?? ????static ?HBRUSH ?s_hBackBrush;?? ?????? ????switch ?(message)?? ????{?? ????case ?WM_CREATE:?? ????????{?? ?????????????? ????????????SetWindowLong(hwnd,?GWL_EXSTYLE,?GetWindowLong(hwnd,?GWL_EXSTYLE)?|?WS_EX_LAYERED);?? ?????????????? ????????????COLORREF ?clTransparent?=?RGB(0,?0,?0);?? ????????????SetLayeredWindowAttributes(hwnd,?clTransparent,?0,?LWA_COLORKEY);?? ????????}?? ????????return ?0;?? ?? ?????????? ????case ?WM_KEYDOWN:??? ????????switch ?(wParam)?? ????????{?? ????????case ?VK_ESCAPE:??? ????????????SendMessage(hwnd,?WM_DESTROY,?0,?0);?? ????????????return ?0;?? ????????}?? ????????break ;?? ?????? ?? ????case ?WM_LBUTTONDOWN:??? ????????PostMessage(hwnd,?WM_SYSCOMMAND,?SC_MOVE?|?HTCAPTION,?0);??? ????????return ?0;?? ?? ?? ????case ?WM_DESTROY:?? ????????PostQuitMessage(0);?? ????????return ?0;?? ????}?? ????return ?DefWindowProc(hwnd,?message,?wParam,?lParm);?? }?? ?? void ?GetWindowSize(HWND ?hwnd,?int ?*pnWidth,?int ?*pnHeight)??{?? ????RECT?rc;?? ????GetWindowRect(hwnd,?&rc);?? ????*pnWidth?=?rc.right?-?rc.left;?? ????*pnHeight?=?rc.bottom?-?rc.top;?? }?? 運(yùn)行結(jié)果如下:
?
?
現(xiàn)在總結(jié)下異形窗口的創(chuàng)建,先通過創(chuàng)建位圖畫刷來做窗口的背景畫刷,再通過SetWindowLong為窗體加上WS_EX_LAYERED屬性,然后使用SetLayeredWindowAttributes指定窗口的透明色來完成窗口形狀的調(diào)整。為了支持鼠標(biāo)的拖曳,在WM_LBUTTONDOWN消息中作了特殊處理,使得異形窗口可以像普通窗口一樣在屏幕上移動。
?
本篇程序中的異形窗口的大小是無法設(shè)置的,只能和位圖一樣。下一篇《Windows界面編程第四篇 異形窗體 高富帥版》將介紹窗口大小可以指定的異形窗口。歡迎繼續(xù)瀏覽。
Windows界面編程第四篇 異形窗體 高富帥版 ??? 上一篇《Windows界面編程第三篇 異形窗體 普通版》介紹了異形窗口(異形窗體)的創(chuàng)建,其主要步驟為——先通過創(chuàng)建位圖畫刷來做窗口的背景畫刷,再通過SetWindowLong為窗體加上WS_EX_LAYERED屬性,然后使用SetLayeredWindowAttributes指定窗口的透明色來完成窗口形狀的調(diào)整。并且為了使異形窗口支持鼠標(biāo)的拖曳,在WM_LBUTTONDOWN消息中作了特殊處理。
然后在下圖中有非常相似的兩個異形窗體,只不過,左邊的異形窗體小,右邊的異形窗體大。這個可以怎么實(shí)現(xiàn)了?
?
先通過其它軟件來縮放位圖,然后再讓程序加載這種方式來指定異形窗口的大小。這種方法雖然可以完成任務(wù),但畢竟太OUT了。
由《Windows界面編程第一篇位圖背景與位圖畫刷》可以想到不用位圖畫刷,而直接在窗口背景繪制時使用StretchBlt來縮放位圖至窗口大小,這樣就可以達(dá)到指定窗口大小的功能。
由于異形窗口運(yùn)行后無法通過鼠標(biāo)來動態(tài)調(diào)整窗口大小,因此可以窗口初始化時就可以先縮放位圖并加載到一個緩沖HDC中,然后再在窗口背景繪制時使用BitBlt來貼圖。這種做法只需要縮放位圖一次,在每次背景繪制時只須拷貝位圖,對程序的效率會有提高。下面給出完整源代碼(下載地址:http://download.csdn.net/download/morewindows/4966819)
[cpp] ?view plaincopyprint?
?? ?? #include?<windows.h>? ??const ?char ?szAppName[]?=?"異形窗口2?MoreWindows-(http://blog.csdn.net/MoreWindows)" ;???? ? ? ? ? ? ? ?? void ?GetWindowSize(HWND ?hwnd,?int ?*pnWidth,?int ?*pnHeight);???? ?? ? ? ? ? ? ? ? ?? BOOL ?InitBitmapWindow(HINSTANCE ?hinstance,?int ?nWidth,?int ?nHeight,?int ?nCmdshow);???? ?? LRESULT ?CALLBACK?BitmapWindowWndPrco(HWND ?hwnd,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParm);???? ???????????? HBITMAP ??g_hBitmap;??int ?APIENTRY?WinMain(HINSTANCE ?hInstance,???????????????????????HINSTANCE ?hPrevInstance,?? ?????????????????????LPSTR ?????lpCmdLine,?? ?????????????????????int ???????nCmdShow)?? {?? ?????? ?????? ?????? ????g_hBitmap?=?(HBITMAP )LoadImage(NULL,?"Kitty.bmp" ,?IMAGE_BITMAP,?0,?0,?LR_LOADFROMFILE);?? ????if ?(g_hBitmap?==?NULL)?? ????{?? ????????MessageBox(NULL,?"位圖加載失敗" ,?"Error" ,?MB_ICONERROR);?? ????????return ?0;?? ????}?? ?? ?????? ????BITMAP?bm;?? ????GetObject(g_hBitmap,?sizeof (bm),?&bm);?? ????int ?nWindowWidth?=?bm.bmWidth;?? ????int ?nWindowHeight?=?bm.bmHeight?+?100;??? ?? ????if ?(!InitBitmapWindow(hInstance,?nWindowWidth,?nWindowHeight,?nCmdShow))?? ????????return ?0;?? ?? ????MSG?msg;?? ????while ?(GetMessage(&msg,?NULL,?0,?0))?? ????{?? ????????TranslateMessage(&msg);?? ????????DispatchMessage(&msg);?? ????}?? ????DeleteObject(g_hBitmap);?? ?? ????return ?msg.wParam;?? }?? ?? ?? BOOL ?InitBitmapWindow(HINSTANCE ?hinstance,?int ?nWidth,?int ?nHeight,?int ?nCmdshow)??{?? ????HWND ?hwnd;?? ????WNDCLASS?wndclass;?? ?????? ????wndclass.style???????=?CS_VREDRAW?|?CS_HREDRAW;?? ????wndclass.lpfnWndProc?=?BitmapWindowWndPrco;??? ????wndclass.cbClsExtra??=?0;?? ????wndclass.cbWndExtra??=?0;?? ????wndclass.hInstance???=?hinstance;????? ????wndclass.hIcon???????=?LoadIcon(NULL,?IDI_APPLICATION);?? ????wndclass.hCursor?????=?LoadCursor(NULL,?IDC_ARROW);?? ????wndclass.hbrBackground?=?(HBRUSH )GetStockObject(NULL_BRUSH);?? ????wndclass.lpszMenuName??=?NULL;?? ????wndclass.lpszClassName?=?szAppName;?? ?????? ????if ?(!RegisterClass(&wndclass))?? ????{?? ????????MessageBox(NULL,?"Program?Need?Windows?NT!" ,?"Error" ,?MB_ICONERROR);?? ????????return ?FALSE;?? ????}?? ?????? ????hwnd?=?CreateWindowEx(WS_EX_TOPMOST,?? ????????????????????????szAppName,?? ????????????????????????szAppName,??? ????????????????????????WS_POPUP,?? ????????????????????????CW_USEDEFAULT,??? ????????????????????????CW_USEDEFAULT,??? ????????????????????????nWidth,??? ????????????????????????nHeight,?? ????????????????????????NULL,?? ????????????????????????NULL,?? ????????????????????????hinstance,?? ????????????????????????NULL);?? ????if ?(hwnd?==?NULL)?? ????????return ?FALSE;?? ?????? ????ShowWindow(hwnd,?nCmdshow);?? ????UpdateWindow(hwnd);?? ?????? ????return ?TRUE;?? }?? ?? LRESULT ?CALLBACK?BitmapWindowWndPrco(HWND ?hwnd,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParm)??{?? ????static ?HDC ?s_hdcMem;??? ?????? ????switch ?(message)?? ????{?? ????case ?WM_CREATE:?? ????????{?? ?????????????? ????????????SetWindowLong(hwnd,?GWL_EXSTYLE,?GetWindowLong(hwnd,?GWL_EXSTYLE)?|?WS_EX_LAYERED);?? ?????????????? ????????????COLORREF ?clTransparent?=?RGB(0,?0,?0);?? ????????????SetLayeredWindowAttributes(hwnd,?clTransparent,?0,?LWA_COLORKEY);?? ?????????????? ?????????????? ?????????????? ????????????HDC ?hdc?=?GetDC(hwnd);?? ????????????HDC ?hdcTemp?=?CreateCompatibleDC(hdc);?? ????????????SelectObject(hdcTemp,?g_hBitmap);?? ?? ?????????????? ????????????int ?nWidth,?nHeight;?? ????????????GetWindowSize(hwnd,?&nWidth,?&nHeight);?? ?? ?????????????? ????????????s_hdcMem?=?CreateCompatibleDC(hdc);?? ????????????HBITMAP ?hbmp?=?CreateCompatibleBitmap(hdc,?nWidth,?nHeight);?? ????????????SelectObject(s_hdcMem,?hbmp);?? ?? ?????????????? ????????????BITMAP?bm;?? ????????????GetObject(g_hBitmap,?sizeof (bm),?&bm);?? ????????????StretchBlt(s_hdcMem,?0,?0,?nWidth,?nHeight,?hdcTemp,?0,?0,?bm.bmWidth,?bm.bmHeight,?SRCCOPY);?? ?????????????? ?????????????? ????????????DeleteDC(hdcTemp);?? ????????????ReleaseDC(hwnd,?hdc);?? ????????}?? ????????return ?0;?? ?? ?????????? ????case ?WM_KEYDOWN:??? ????????switch ?(wParam)?? ????????{?? ????????case ?VK_ESCAPE:??? ????????????SendMessage(hwnd,?WM_DESTROY,?0,?0);?? ????????????return ?TRUE;?? ????????}?? ????????break ;?? ?????? ?? ????case ?WM_LBUTTONDOWN:??? ????????PostMessage(hwnd,?WM_SYSCOMMAND,?SC_MOVE?|?HTCAPTION,?0);??? ????????return ?TRUE;?? ?????????????????? ????case ?WM_ERASEBKGND:??? ????????{?? ????????????HDC ?hdc?=?(HDC )wParam;?? ????????????int ?nWidth,?nHeight;?? ????????????GetWindowSize(hwnd,?&nWidth,?&nHeight);?? ????????????BitBlt(hdc,?0,?0,?nWidth,?nHeight,?s_hdcMem,?0,?0,?SRCCOPY);?? ????????????return ?TRUE;?? ????????}?? ?? ????case ?WM_DESTROY:?? ????????DeleteDC(s_hdcMem);?? ????????PostQuitMessage(0);?? ????????return ?0;?? ????}?? ????return ?DefWindowProc(hwnd,?message,?wParam,?lParm);?? }?? ?? ?? void ?GetWindowSize(HWND ?hwnd,?int ?*pnWidth,?int ?*pnHeight)??{?? ????RECT?rc;?? ????GetWindowRect(hwnd,?&rc);?? ????*pnWidth?=?rc.right?-?rc.left;?? ????*pnHeight?=?rc.bottom?-?rc.top;?? }?? 運(yùn)行程序?qū)⒌玫饺缥恼轮忻恳粡垐D右邊所示的異形窗口。
?
最后總結(jié)一下異形窗口的“三要素”:
1.WS_EX_LAYERED屬性
2.以位圖為窗口背景(自貼圖或位圖畫刷)
3.指定透明色
?
本文配套程序下載地址為:http://download.csdn.net/download/morewindows/4966819
?
當(dāng)窗口的背景用彩色圖片來裝飾時,其它控件如果還是用灰色的背景會顯的比較不諧調(diào),《Windows界面編程第五篇 靜態(tài)控件背景透明化》將介紹如何為靜態(tài)框設(shè)置透明背景。
Windows界面編程第五篇 靜態(tài)控件背景透明化 分類:?Windows編程? 2013-01-07 10:25 ?
767人閱讀 ??
收藏 ?
舉報 Windows界面編程靜態(tài)控件透明背景文字區(qū)域透明背景SetBkModeWM_CTLCOLORSTATIC
??? 上一篇《Windows界面編程第三篇 異形窗體 普通版》和《Windows界面編程第四篇異形窗體 高富帥版》介紹了異形窗口(異形窗體)的創(chuàng)建,并總結(jié)出了異形窗口的“三要素”:
1.WS_EX_LAYERED屬性
2.指定透明色
3.以位圖為窗口背景
?
??? 本篇文章將主要介紹Windows編程中如何實(shí)現(xiàn)靜態(tài)控件背景的透明化,這將進(jìn)一步的美化界面。下面先看一張沒有做靜態(tài)控件背景透明化的對話框程序的運(yùn)行畫面,對話框的彩色圖片背景可以參考《Windows界面編程第一篇位圖背景與位圖畫刷》。
??? 可以看出靜態(tài)控件的灰度背景在對話框的彩色圖片背景中顯得很不諧調(diào),因此有必要對其美化一下。
??? 在第一篇《Windows界面編程第一篇位圖背景與位圖畫刷》中介紹了通過WM_CTLCOLORDLG消息來設(shè)置對話框的背景,而在Windows系統(tǒng)中還有類似于WM_CTLCOLORDLG消息的還有WM_CTLCOLORBTN,WM_CTLCOLOREDIT,WM_CTLCOLORLISTBOX,WM_CTLCOLORSCROLLBAR,WM_CTLCOLORSTATIC這五種來分別管理按鈕,編輯框,列表框,滾動條,靜態(tài)框。因此我們首先在WM_CTLCOLORSTATIC消息中返回一個空畫刷看看能不能達(dá)到背景透明化的要求。另外對于文字區(qū)域的背景透明可以通過SetBkMode來設(shè)置。其函數(shù)原型如下:
int?SetBkMode(
????HDC?hdc,??????// handle to DC
????int?iBkMode???// background mode
);
這個函數(shù)的第二個參數(shù)設(shè)置為TRANSPARENT時就可以將文字區(qū)域的前景設(shè)置成透明。
?
下面給出完整的源代碼(下載地址:http://download.csdn.net/download/morewindows/4966826):
[cpp] ?view plaincopyprint?
?? ?? #include?<windows.h>? ??#include?"resource.h"? ???? const ?char ?szDlgTitle[]?=?"靜態(tài)控件背景透明化MoreWindows-(http://blog.csdn.net/MoreWindows)" ;???? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam);?????????????? int ?APIENTRY?WinMain(HINSTANCE ?hInstance,???????????????????????HINSTANCE ?hPrevInstance,?? ?????????????????????LPSTR ?????lpCmdLine,?? ?????????????????????int ???????nCmdShow)?? {?? ????DialogBox(hInstance,?MAKEINTRESOURCE(IDD_DIALOG1),?NULL,?DlgProc);?? ????return ?0;?? }?? ?? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam)??{?? ????RECT???????rcDialog;?? ????HBITMAP ????hBitmap;?? ????static ?BITMAP?s_bm;?? ????static ?HDC ????s_hdcMem;?? ?? ????switch ?(message)?? ????{?? ????case ?WM_INITDIALOG:?? ?????????? ????????SetWindowText(hDlg,?szDlgTitle);?? ?????????? ????????SetWindowLong(hDlg,?GWL_STYLE,?GetWindowLong(hDlg,?GWL_STYLE)?|?WS_SIZEBOX);?? ?? ?????????? ????????hBitmap?=?(HBITMAP )LoadImage(NULL,?"006.bmp" ,?IMAGE_BITMAP,?0,?0,?LR_LOADFROMFILE?|?LR_CREATEDIBSECTION);?? ????????if ?(hBitmap?==?NULL)?? ????????{?? ????????????MessageBox(hDlg,?"LoadImage?failed" ,?"Error" ,?MB_ICONERROR);?? ????????????exit(0);?? ????????}????????? ????????else ?? ????????{?? ?????????????? ????????????HDC ????????hdc;?? ????????????hdc?=?GetDC(hDlg);?? ????????????s_hdcMem?=?CreateCompatibleDC(hdc);?? ????????????SelectObject(s_hdcMem,?hBitmap);?????? ????????????ReleaseDC(hDlg,?hdc);?? ?? ?????????????? ????????????GetObject(hBitmap,?sizeof (s_bm),?&s_bm);?? ????????}?? ?? ????????return ?0;?? ?? ????case ?WM_COMMAND:?? ????????switch ?(LOWORD(wParam))?? ????????{?? ????????case ?IDCANCEL:?? ????????????DeleteDC(s_hdcMem);?? ????????????EndDialog(hDlg,?LOWORD(wParam));?? ????????????return ?TRUE;?? ????????}?? ????????break ;?? ?? ?? ????case ?WM_SIZE:?? ????????InvalidateRect(hDlg,?NULL,?TRUE);?? ????????return ?TRUE;?? ?? ????case ?WM_CTLCOLORSTATIC:?? ????????SetBkMode((HDC )wParam,?TRANSPARENT);?? ????????return ?(BOOL )((HBRUSH )GetStockObject(NULL_BRUSH));?? ?? ????case ?WM_CTLCOLORDLG:?? ????????GetClientRect(hDlg,?&rcDialog);?? ?????????? ????????SetStretchBltMode((HDC )wParam,?COLORONCOLOR);?? ????????StretchBlt((HDC )wParam,?0,?0,?rcDialog.right,?rcDialog.bottom,?s_hdcMem,?0,?0,?s_bm.bmWidth,?s_bm.bmHeight,?SRCCOPY);????? ????????return ?(BOOL )((HBRUSH )GetStockObject(NULL_BRUSH));?? ????}?? ????return ?FALSE;?? }?? 這份代碼也是在《Windows界面編程第一篇位圖背景與位圖畫刷》文章的代碼上增加了
????case?WM_CTLCOLORSTATIC:
?????????????SetBkMode((HDC)wParam,?TRANSPARENT);
?????????????return?(BOOL)((HBRUSH)GetStockObject(NULL_BRUSH));
來達(dá)到靜態(tài)控件背景透明化的效果的,程序運(yùn)行效果如下:
?
由圖可以看出,雖然Static Text控件的是達(dá)到了背景透明化的要求,但是Group Box控件的描述文字的顯示卻顯得很不美觀。
?
要解決這一問題,可以試下位圖畫刷,我們在WM_CTLCOLORSTATIC消息中像WM_CTLCOLORDLG消息一樣也返回一個位圖畫刷來試試。
[cpp] ?view plaincopyprint?
?? ?? #include?<windows.h>? ??#include?"resource.h"? ???? const ?char ?szDlgTitle[]?=?"靜態(tài)控件背景透明化MoreWindows-(http://blog.csdn.net/MoreWindows)" ;???? ?? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam);???? int ?APIENTRY?WinMain(HINSTANCE ?hInstance,???????????????????????HINSTANCE ?hPrevInstance,?? ?????????????????????LPSTR ?????lpCmdLine,?? ?????????????????????int ???????nCmdShow)?? {?? ????DialogBox(hInstance,?MAKEINTRESOURCE(IDD_DIALOG1),?NULL,?DlgProc);?? ????return ?0;?? }?? ?? ?? BOOL ?CALLBACK?DlgProc(HWND ?hDlg,?UINT ?message,?WPARAM ?wParam,?LPARAM ?lParam)??{?? ????static ?HBRUSH ????s_hBitmapBrush;??? ?? ????switch ?(message)?? ????{?? ????case ?WM_INITDIALOG:?? ?????????? ????????SetWindowText(hDlg,?szDlgTitle);?? ?????????? ????????SetWindowLong(hDlg,?GWL_STYLE,?GetWindowLong(hDlg,?GWL_STYLE)?|?WS_SIZEBOX);?? ?? ?????????? ????????HBITMAP ?hBitmap;?? ????????hBitmap?=?(HBITMAP )LoadImage(NULL,?"006.bmp" ,?IMAGE_BITMAP,?0,?0,?LR_LOADFROMFILE?|?LR_CREATEDIBSECTION);?? ????????if ?(hBitmap?==?NULL)?? ????????{?? ????????????MessageBox(hDlg,?"LoadImage?failed" ,?"Error" ,?MB_ICONERROR);?? ????????????exit(0);?? ????????}????????? ?? ?????????? ????????s_hBitmapBrush?=?CreatePatternBrush(hBitmap);?? ????????return ?0;?? ?? ?? ????case ?WM_COMMAND:?? ????????switch ?(LOWORD(wParam))?? ????????{?? ????????case ?IDCANCEL:?? ????????????DeleteObject(s_hBitmapBrush);?? ????????????EndDialog(hDlg,?LOWORD(wParam));?? ????????????return ?TRUE;?? ????????}?? ????????break ;?? ?? ????case ?WM_CTLCOLORSTATIC:?? ????????SetBkMode((HDC )wParam,?TRANSPARENT);?? ?? ????case ?WM_CTLCOLORDLG:?? ????????return ?(BOOL )s_hBitmapBrush;?? ????}?? ????return ?FALSE;?? }?? 與上一個程序一樣,這個程序也只是在在《Windows界面編程第一篇位圖背景與位圖畫刷》文章的代碼上增加了
???????case?WM_CTLCOLORSTATIC:
??????????????SetBkMode((HDC)wParam,?TRANSPARENT);
來設(shè)置靜態(tài)控件背景透明化,程序運(yùn)行效果如下:
?
由圖可以看出,靜態(tài)控件的透明化還是非常方便的,只要在WM_CTLCOLORSTATIC消息中完成二個步驟即可:
1.通過SetBkMode((HDC)wParam,?TRANSPARENT);來設(shè)置文字區(qū)域背景透明。
2.返回空畫刷或與父窗口相同的畫刷。
?
自繪實(shí)現(xiàn)半透明水晶按鈕 運(yùn)行效果 實(shí)現(xiàn)方法 1.給按鈕加上BS_OWNERDRAW樣式 2.重載DrawItem函數(shù),在這里繪制按鈕 3.關(guān)鍵之處就是把父窗口的背景復(fù)制到按鈕上,實(shí)現(xiàn)視覺上的透明 4.最后通過AlphaBlend實(shí)現(xiàn)半透明.源碼下載: http://blog.csdn.net/cometnet/article/details/8464693 實(shí)現(xiàn)源碼
C/C++ code
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 //?MyButton.h #pragma?once //?CMyButton class?CMyButton?:?public?CButton { ????DECLARE_DYNAMIC(CMyButton) public: ????CMyButton(); ????virtual?~CMyButton(); public: ????void?SetBkColor(COLORREF?color); ????void?SetTextColor(COLORREF?color); private: ????bool?m_bOver; ????bool?m_bDown; ????bool?m_bDisable; ????bool?m_bTracking; ????COLORREF?m_bkColor; ????COLORREF?m_textColor; protected: ????DECLARE_MESSAGE_MAP() ????virtual?BOOL?PreCreateWindow(CREATESTRUCT&?cs); ????virtual?void?PreSubclassWindow(); public: ????virtual?void?DrawItem(LPDRAWITEMSTRUCT?/*lpDrawItemStruct*/); ????afx_msg?void?OnMouseMove(UINT?nFlags,?CPoint?point); ????afx_msg?void?OnLButtonDown(UINT?nFlags,?CPoint?point); ????afx_msg?void?OnLButtonUp(UINT?nFlags,?CPoint?point); ????afx_msg?LRESULT?OnMouseLeave(WPARAM?wParam,?LPARAM?lParam); ????afx_msg?LRESULT?OnMouseHover(WPARAM?wParam,?LPARAM?lParam); ????afx_msg?void?OnEnable(BOOL?bEnable); private: ????void?ButtonInit(); ????void?DrawButton(); ????void?DrawButton(HDC?hDestDC); };
?
C/C++ code
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 //?MyButton.cpp?:?實(shí)現(xiàn)文件 // #include?"stdafx.h" #include?"AlphaButton.h" #include?"MyButton.h" #include?"MainDlg.h" //?CMyButton IMPLEMENT_DYNAMIC(CMyButton,?CButton) CMyButton::CMyButton() { ????m_bkColor=0xFFFFFF; ????m_textColor=0x000000; } CMyButton::~CMyButton() { } BEGIN_MESSAGE_MAP(CMyButton,?CButton) ????ON_WM_MOUSEMOVE() ????ON_WM_LBUTTONDOWN() ????ON_WM_LBUTTONUP() ????ON_MESSAGE(WM_MOUSELEAVE,?OnMouseLeave) ????ON_MESSAGE(WM_MOUSEHOVER,?OnMouseHover) ????ON_WM_ENABLE() END_MESSAGE_MAP() //?CMyButton?消息處理程序 void?CMyButton::SetBkColor(COLORREF?color) { ????m_bkColor=color; } void?CMyButton::SetTextColor(COLORREF?color) { ????m_textColor=color; } BOOL?CMyButton::PreCreateWindow(CREATESTRUCT&?cs) { ????BOOL?bRet=CButton::PreCreateWindow(cs); ????ButtonInit(); ????return?bRet; } void?CMyButton::PreSubclassWindow() { ????CButton::PreSubclassWindow(); ????ButtonInit(); } void?CMyButton::ButtonInit() { ????m_bTracking=false; ????m_bOver=m_bDown=m_bDisable=false; ????m_bDisable=IsWindowEnabled()?FALSE:TRUE; ????ModifyStyle(NULL,BS_OWNERDRAW); } void?CMyButton::DrawItem(LPDRAWITEMSTRUCT?lpDrawItemStruct) { ????DrawButton(lpDrawItemStruct->hDC); } void?CMyButton::OnMouseMove(UINT?nFlags,?CPoint?point) { ????if?(!m_bTracking) ????{ ????????m_bOver?=?TRUE; ????????TRACKMOUSEEVENT?tme; ????????tme.cbSize?=?sizeof(tme); ????????tme.hwndTrack?=?m_hWnd; ????????tme.dwFlags?=?TME_LEAVE?|?TME_HOVER; ????????tme.dwHoverTime?=?50; ????????m_bTracking?=?(bool)_TrackMouseEvent(&tme); ????} ????CButton::OnMouseMove(nFlags,?point); } void?CMyButton::OnLButtonDown(UINT?nFlags,?CPoint?point) { ????m_bDown=TRUE; ????CButton::OnLButtonDown(nFlags,?point); } void?CMyButton::OnLButtonUp(UINT?nFlags,?CPoint?point) { ????m_bDown=FALSE; ????CButton::OnLButtonUp(nFlags,?point); } LRESULT?CMyButton::OnMouseLeave(WPARAM?wParam,?LPARAM?lParam) { ????m_bOver?=?FALSE; ????m_bTracking?=?FALSE; ????m_bDown=FALSE; ????InvalidateRect(NULL,?FALSE); ????return?0; } LRESULT?CMyButton::OnMouseHover(WPARAM?wParam,?LPARAM?lParam) { ????m_bOver?=?TRUE; ????InvalidateRect(NULL); ????return?0; } void?CMyButton::DrawButton() { ????HDC?hDC=::GetDC(m_hWnd); ????DrawButton(hDC); ????::ReleaseDC(m_hWnd,hDC); } void?CMyButton::DrawButton(HDC?hDestDC) { ????CRect?rc; ????GetClientRect(rc); ????int?nWindth=rc.Width(); ????int?nHeight=rc.Height(); ????HDC?hDC=CreateCompatibleDC(hDestDC);//創(chuàng)建兼容DC,采用雙緩沖畫出 ????HDC?hMaskDC=CreateCompatibleDC(hDestDC); ????HBITMAP?hBitmap=CreateCompatibleBitmap(hDestDC,nWindth,nHeight); ????HBITMAP?hMaskBitmap=CreateCompatibleBitmap(hDestDC,nWindth,nHeight); ????HBITMAP?hOldBitmap=(HBITMAP)SelectObject(hDC,hBitmap); ????HBITMAP?hOldMaskBitmap=(HBITMAP)SelectObject(hMaskDC,hMaskBitmap); ????SetBkMode(hDC,TRANSPARENT); ????//把父窗口的背景圖復(fù)制到按鈕的DC上,實(shí)現(xiàn)視覺透明---------------- ????CMainDlg*?pParent=(CMainDlg*)GetParent(); ????CPoint?pt(0,0); ????MapWindowPoints(pParent,&pt,1); ????pParent->m_bkImage.BitBlt(hDC,rc,pt,SRCCOPY); ????//------------------------------------------------------------- ????int?nAlpha=100;//0--255 ????int?nOffset=0; ????HBRUSH?hbr=CreateSolidBrush(m_bkColor); ????FillRect(hMaskDC,&rc,hbr); ????DeleteObject(hbr); ????if(m_bDisable){ ????????nAlpha=100; ????}else?if(m_bDown){ ????????nAlpha=180; ????????nOffset=1; ????}else?if(m_bOver){ ????????nAlpha=150; ????}else{ ????????nAlpha=100; ????} ????BLENDFUNCTION?blend; ????memset(?&blend,?0,?sizeof(?blend)?); ????blend.BlendOp=?AC_SRC_OVER; ????blend.SourceConstantAlpha=?nAlpha;?//?透明度?最大255 ????HRGN?hRgn=CreateRoundRectRgn(0,0,nWindth,nHeight,3,3); ????SelectClipRgn?(hDC,hRgn); ????AlphaBlend?(hDC,0,0,nWindth,nHeight,hMaskDC,?0,0,nWindth,nHeight,blend); ????CString?strText; ????GetWindowText(strText); ????if(strText!=_T("")){ ????????rc.InflateRect(-2,-2); ????????rc.OffsetRect(nOffset,nOffset); ????????HFONT?hFont=(HFONT)SendMessage(WM_GETFONT); ????????if(!hFont)hFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT); ????????HFONT?hOldFont=(HFONT)SelectObject(hDC,hFont); ????????::SetTextColor(hDC,m_textColor); ????????::DrawText(hDC,strText,-1,&rc,DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_WORD_ELLIPSIS); ????????::SelectObject(hDC,hOldFont); ????} ????SelectClipRgn?(hDC,NULL); ????DeleteObject(hRgn); ????//復(fù)制到控件的DC上------------------------ ????BitBlt(hDestDC,0,0,nWindth,nHeight,hDC,0,0,SRCCOPY); ????//刪除資源,釋放內(nèi)存----------------------- ????SelectObject(hDC,hOldBitmap); ????DeleteObject(hBitmap); ????DeleteDC(hDC); ????SelectObject(hMaskDC,hOldMaskBitmap); ????DeleteObject(hMaskBitmap); ????DeleteDC(hMaskDC); } void?CMyButton::OnEnable(BOOL?bEnable) { ????CButton::OnEnable(bEnable); ????m_bDisable=IsWindowEnabled()?FALSE:TRUE; ????DrawButton(); }
轉(zhuǎn)載于:https://www.cnblogs.com/qq292873711/p/3721474.html
總結(jié)
以上是生活随笔 為你收集整理的Windows界面编程-背景图片、透明特效使用 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。