1.WM_CTLCOLORDLG消息
在对话框画出来之前,系统将该消息发给对话框窗口。通过WM_CTLCOLORDLG消息来设置对话框文本和背景。
当窗口处理函数处理这个消息时,wParam表示对话框设备上下文(HDC),lParam表示对话框句柄。
如果处理了这个消息,返回一个画刷,系统用这个画刷重绘对话框背景。
因此,在WM_CTLCOLORDLG消息中获得对话框的大小,通过StretchBlt函数将位图缩放后放到对话框中,就完成了背景设置。
并且,要返回一个空画刷给系统,系统才不会将位图背景覆盖。
在使用StretchBlt函数前,最好先用SetStretchBltMode函数来设置位图内容伸展模式,避免位图缩放后失真严重。
int SetStretchBltMode( HDC hdc, int iStretchMode);
伸展模式:
BLACKONWHITE / STRETCH_ANDSCANS
如果两个或多个像素得合成一个像素,那么StretchBlt会对像素执行一个逻辑and运算。只有全部的原始像素是白色时,该像素
才是白色,其实际意义是黑色像素控制了白色像素,适用于白色背景中是黑色的单色点阵图。
WHITEONBLACK / STRETCH_ORSCANS
如果两个或多个像素得合成一个像素,那么StretchBlt会对像素执行一个逻辑or运算。只有全部的原始像素是黑色时,该像素才
是黑色,也就是说白色像素决定颜色,适用于黑色背景中白色的单色点阵图。
COLORONCOLOR / STRETCH_DELETESCANS
简单地消除图素行或列,而没有任何逻辑组合。通常是处理彩色点阵图的最佳方法。
HALFONE / STRETCH_HALFONE
根据组合起来的源颜色计算目的的平均颜色。
代码:

1 #include "stdafx.h" 2 #include "01位图背景与位图画刷.h" 3 4 WCHAR dlgTitle[] = L"位图背景"; 5 6 BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 7 { 8 RECT rcDialog = { 0 }; 9 HBITMAP hBitmap = 0; 10 static BITMAP s_bm = { 0 }; 11 static HDC s_hdcMem = 0; 12 HDC hdc = 0; 13 switch (message) 14 { 15 case WM_INITDIALOG: 16 SetWindowText(hDlg, dlgTitle); //设置对话框标题 17 SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) | WS_SIZEBOX); //设置对话框大小可调节 18 19 //加载背景图片 20 hBitmap = (HBITMAP)LoadImage(NULL, L"005.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); 21 if (hBitmap == NULL) 22 { 23 MessageBox(hDlg, L"fail to load image!", L"Error", MB_ICONERROR); 24 exit(0); 25 } 26 27 //将背景图放入hdc 28 hdc = GetDC(hDlg); 29 s_hdcMem = CreateCompatibleDC(hdc); 30 SelectObject(s_hdcMem, hBitmap); 31 ReleaseDC(hDlg, hdc); 32 33 //得到位图信息 34 GetObject(hBitmap, sizeof(s_bm), &s_bm); 35 return FALSE; 36 37 case WM_SIZE: 38 InvalidateRect(hDlg, NULL, TRUE); 39 return FALSE; 40 41 case WM_CTLCOLORDLG: 42 //返回一个画刷,系统用该画刷重绘对话框背景,wParam为设备上下文HDC,lParam为窗口句柄 43 //然后返回一个空画刷给系统,这样系统就不会将位图背景给覆盖了 44 GetClientRect(hDlg, &rcDialog); 45 SetStretchBltMode((HDC)wParam, COLORONCOLOR); 46 StretchBlt((HDC)wParam, 0, 0, rcDialog.right, rcDialog.bottom, s_hdcMem, 0, 0, s_bm.bmWidth, s_bm.bmHeight, SRCCOPY); 47 return (BOOL)((HBRUSH)GetStockObject(NULL_BRUSH)); 48 49 case WM_COMMAND: 50 if (IDCANCEL == LOWORD(wParam)) 51 { 52 DeleteDC(s_hdcMem); 53 EndDialog(hDlg, LOWORD(wParam)); 54 return FALSE; 55 } 56 break; 57 } 58 return FALSE; 59 } 60 61 62 int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 63 { 64 DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc); 65 return 0; 66 }
运行结果:
也可以创建爱你一个位图画刷,然后再WM_CTLCOLORDLG消息中直接返回这个画刷,也能完成设置背景功能
HBRUSH CreatePatternBrush( HBITMAP hbmp);
代码:

1 #include "stdafx.h" 2 #include "01位图画刷.h" 3 4 WCHAR szDlgTitle[] = L"位图画刷"; 5 6 BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParams) 7 { 8 static HBRUSH s_hBitmapBrush; //位图画刷 9 switch (message) 10 { 11 case WM_INITDIALOG: 12 SetWindowText(hDlg, szDlgTitle); 13 SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) | WS_SIZEBOX); 14 15 // 加载背影图片 16 HBITMAP hBitmap; 17 hBitmap = (HBITMAP)LoadImage(NULL, L"005.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); 18 if (hBitmap == NULL) 19 { 20 MessageBox(hDlg, L"LoadImage failed", L"Error", MB_ICONERROR); 21 exit(0); 22 } 23 24 // 创建位图画刷 25 s_hBitmapBrush = CreatePatternBrush(hBitmap); 26 return FALSE; 27 28 case WM_COMMAND: 29 if (IDCANCEL == LOWORD(wParam)) 30 { 31 DeleteObject(s_hBitmapBrush); 32 EndDialog(hDlg, LOWORD(wParam)); 33 return TRUE; 34 } 35 break; 36 37 case WM_CTLCOLORDLG: 38 return (BOOL)s_hBitmapBrush; 39 } 40 return FALSE; 41 } 42 43 int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 44 { 45 DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc); 46 return 0; 47 }
运行结果:
注意,这两做法在窗口大小超过位图大小时会表现不同,前一种做法会拉伸位图以适应窗口大小,后一种做法是直接平铺。
类似的消息还有WM_CTLCOLORBTN、WM_CTLCOLOREDIT、WM_CTLCOLORLISTBOX、WM_CTLCOLORSCROLLBAR、WM_CTLCOLORSTATIC,分别用于设置按钮、编辑框、列表框、滚动条、静态框。