赞
踩
可以通过WM_CTLCOLORDLG消息来设置对话框的背景,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.
当窗口消息响应函数接收这个消息时,wParam表示对话框的设备上下方即HDC,lParam表示对话框的句柄。如果程序处理了这个消息,应返回一个画刷。系统将会用这个画刷来重绘对话框背景。
因此我们在这个WM_CTLCOLORDLG消息中得到对话框的大小,并通过StretchBlt函数将位图缩放后贴到对话框的HDC中就完成了对话框背景的设置,然后返回一个空画刷给系统,这样系统就不会将位图背景给覆盖了。
代码非常简单,要注意的是在使用StretchBlt函数缩放位图时,最好先使用
SetStretchBltMode函数来设置下位图内容伸展模式,这样可以避免缩放后位图失真严重。SetStretchBltMode函数原型如下:
int SetStretchBltMode(
HDChdc, // handle to DC
int iStretchMode // bitmap stretching mode
);
第一个参数就是设备上下方即HDC。
第二个参数有四种设置:
1. BLACKONWHITE or STRETCH_ANDSCANS
如果两个或多个像素得合并成一个像素,那么StretchBlt会对像素执行一个逻辑AND运算。这样的结果是只有全部的原始像素是白色时该像素才为白色,其实际意义是黑色像素控制了白色像素。这适用于白色背景中主要是黑色的单色点阵图。
2. WHITEONBLACK or STRETCH_ORSCANS
如果两个或多个像素得合并成一个像素,那么StretchBlt会对像素执行逻辑OR运算。这样的结果是只有全部的原始像素都是黑色时该像素才为黑色,也就是说由白色像素决定颜色。这适用于黑色背景中主要是白色的单色点阵图。
3. COLORONCOLOR or STRETCH_DELETESCANS
简单地消除图素行或列,而没有任何逻辑组合。这是通常是处理彩色点阵图的最佳方法。
4. HALFTONE or STRETCH_HALFTONE
根据组合起来的来源颜色来计算目的的平均颜色。
其它技术细节可以见代码中的注释,完整代码如下(也可以下载,下载地址为:http://download.csdn.net/download/morewindows/4947377):
- // 对话框位图背景 - WM_CTLCOLORDLG中使用StretchBlt贴图
- //By MoreWindows-(http://blog.csdn.net/MoreWindows)
- #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 - s_hdcMem
- 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的设置能使StretchBlt在缩放图像更加清晰
- 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;
- }
运行结果如下:
在上面这种方法中,我们是在WM_CTLCOLORDLG中贴图来完成背景设置了,也可以创建一个位图画刷,然后在WM_CTLCOLORDLG消息中直接返回这个画刷,这样系统将完成贴图功能。
位图画刷的创建函数为CreatePatternBrush,其函数原型如下:
HBRUSHCreatePatternBrush(
HBITMAPhbmp // handle to bitmap
);
只要给这个函数传入位图句柄即可,完整代码如下(下载地址为:http://download.csdn.net/download/morewindows/4947377):
- // 对话框位图背景 - 直接在WM_CTLCOLORDLG中使用位图画刷
- //By MoreWindows-(http://blog.csdn.net/MoreWindows)
- #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;
- }
运行结果如下:
注意,这两做法在窗口大小超过位图大小时会表现不同,前一种做法会拉伸位图以适应窗口大小,后一种做法是直接平铺。详见下图:
本篇《Windows界面编程第一篇位图背景与位图画刷》主要介绍了通过WM_CTLCOLORDLG消息来设置对话框的背景,在Windows系统中还有类似于WM_CTLCOLORDLG消息的还有WM_CTLCOLORBTN,WM_CTLCOLOREDIT,WM_CTLCOLORLISTBOX,WM_CTLCOLORSCROLLBAR,WM_CTLCOLORSTATIC这五种来分别管理按钮,编辑框,列表框,滚动条,静态框。有兴趣的读者可以试验下。
下一篇将介绍调节窗体透明度的方法,欢迎继续浏览《Windows界面编程第二篇 半透明窗体》
当窗口的背景用彩色图片来装饰时,其它控件如果还是用灰色的背景会显的比较不谐调,《Windows界面编程第五篇 静态控件背景透明化》将介绍如何为静态框设置透明背景。
Windows界面编程第二篇半透明窗体
上一篇《Windows界面编程第一篇 位图背景与位图画刷》介绍了通过WM_CTLCOLORDLG消息来来设置对话框的背景以及位图画刷的使用。本篇将介绍动态调节窗体透明度的方法。
调节窗体透明度可以先使用SetWindowLong为窗体加上WS_EX_LAYERED属性,再使用来SetLayeredWindowAttributes指定窗体的透明度。这样就可以在程序运行时动态的调节窗体的透明度了。
下面先介绍下SetWindowLong和SetLayeredWindowAttributes函数。
SetWindowLong可以用来设置窗口的一些属性,其函数原型如下:
LONGSetWindowLong(
HWNDhWnd,
int nIndex,
LONGdwNewLong
);
第一个参数表示窗口句柄。
第二个参数代表要设置的哪一种值,如GWL_STYLE表示将设置窗口的风格,这个参数还可以取GWL_EXSTYLE,GWL_WNDPROC,DWL_DLGPROC,GWL_HINSTANCE,GWL_USERDATA等等。
第三个参数表示要设置的值。
比如要设置对话框也能够可调节窗口大小,可以用:
// 设置对话框大小可调节
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.
其函数原型为:
BOOLSetLayeredWindowAttributes(
HWNDhwnd,
COLORREFcrKey,
BYTEbAlpha,
DWORDdwFlags
);
第一个参数表示窗口句柄。
第二个参数表示透明色。
第三个参数表示透明度。
第四个参数表示函数将完成什么样的功能,设置成LWA_COLORKEY表示为窗口指定了透明色,设置成LWA_ALPHA表示将调整窗口的透明度,可以同时设置这两种功能。
程序代码还将用到Slider控件,这种控件可以有如下操作:
1.通过SendMessage + TBM_SETRANGE来设置滑块变化的范围。
2.通过SendMessage + TBM_SETPOS来设置滑块当前位置。
3.通过SendMessage + TBM_GETPOS来获得滑块当前位置。
4.当滑块位置发生变化时,在其父窗口中通过WM_HSCROLL或WM_VSCROLL来响应消息。
下面给出完整的源代码(下载地址:http://download.csdn.net/download/morewindows/4947386)
- // 可变透明度窗体 先加上WS_EX_LAYERED属性再SetLayeredWindowAttributes设置透明度
- //By MoreWindows-(http://blog.csdn.net/MoreWindows)
- #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);
- // 设置透明度 0 - completely transparent 255 - opaque
- 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: // slider control 滑块位置有变化时的响应函数
- {
- // 获取当前滑块位置
- 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;
- }
运行结果如下:
在本篇文章中我们通过SetWindowLong为窗体加上WS_EX_LAYERED属性,再使用SetLayeredWindowAttributes完成窗体的透明度调节。下面两篇也将使用这两个函数来完成另一个功能——异形窗口(异形窗体)。异形窗口可以使得窗口更加美观,它能灵活的变动窗口的形状。欢迎继续浏览《Windows界面编程 第三篇异形窗体 普通版》和《Windows界面编程 第四篇异形窗体 高富帅版》
上一篇《Windows界面编程第二篇 半透明窗体》介绍了先使用SetWindowLong为窗体加上WS_EX_LAYERED属性,再使用SetLayeredWindowAttributes调整窗体的透明度。本篇将使用这二个函数来完成另一个实用的功能——异形窗口(异形窗体)。
异形窗口的原理很简单,首先加载一张位图画刷作窗口背景,然后设置透明色就可以使得窗口由矩形变成任意形状。这样使得窗口的显示更加美观。
下面先简单介绍下Win32 SDK方式创建窗口的流程(按《Windows程序设计》中的大体流程):
1.设置WNDCLASS类型的变量,这个变量将描述窗口的风格、窗口消息处理函数、程序图标、光标、窗口背景画刷等待。
2.使用RegisterClass将WNDCLASS类型的变量注册下。
3.使用CreateWindow或CreateWindowEx创建窗口,这里可以设置窗口的初始位置、初始大小、扩展属性等等。
4.通过ShowWindow和UpdateWindow将窗口显示出来。
5.窗口显示完成后,在WinMain()函数中添加消息处理:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
通过这五步就完成了一个窗口的创建了。
对于窗口消息函数,一般只要在WM_DESTROY消息中调用下PostQuitMessage(0);其它的消息都可以使用默认消息处理函数DefWindowProc。
对于异形窗口,可以在WM_CREATE即窗口初始化时设置好透明色就完成了窗口形状的改变,不过为了支持鼠标对窗口的拖曳,还要在WM_LBUTTONDOWN消息中加入:
PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
这样,异形窗口就可以在屏幕上像普通窗口一样的移动了。
完整的源代码如下所示(下载地址:http://download.csdn.net/download/morewindows/4966815):
- // 异形窗口1 窗口背景使用位图画刷再指定透明色
- //By MoreWindows-(http://blog.csdn.net/MoreWindows)
- #include <windows.h>
-
- const char szAppName[] = "异形窗口1 MoreWindows-(http://blog.csdn.net/MoreWindows)";
-
- /*
- * 函数名称: GetWindowSize
- * 函数功能: 得到窗口的宽高
- * hwnd 窗口句柄
- * pnWidth 窗口宽
- * pnHeight 窗口高
- */
- void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);
-
-
- /*
- * 函数名称: InitBitmapWindow
- * 函数功能: 位图窗口初始化
- * hinstance 进程实例
- * hBitmap 位图句柄
- * nCmdshow 显示方式-与ShowWindow函数的第二个参数相同
- */
- 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: //按下Esc键时退出
- 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;
- }
运行结果如下:
现在总结下异形窗口的创建,先通过创建位图画刷来做窗口的背景画刷,再通过SetWindowLong为窗体加上WS_EX_LAYERED属性,然后使用SetLayeredWindowAttributes指定窗口的透明色来完成窗口形状的调整。为了支持鼠标的拖曳,在WM_LBUTTONDOWN消息中作了特殊处理,使得异形窗口可以像普通窗口一样在屏幕上移动。
本篇程序中的异形窗口的大小是无法设置的,只能和位图一样。下一篇《Windows界面编程第四篇 异形窗体 高富帅版》将介绍窗口大小可以指定的异形窗口。欢迎继续浏览。
上一篇《Windows界面编程第三篇 异形窗体 普通版》介绍了异形窗口(异形窗体)的创建,其主要步骤为——先通过创建位图画刷来做窗口的背景画刷,再通过SetWindowLong为窗体加上WS_EX_LAYERED属性,然后使用SetLayeredWindowAttributes指定窗口的透明色来完成窗口形状的调整。并且为了使异形窗口支持鼠标的拖曳,在WM_LBUTTONDOWN消息中作了特殊处理。
然后在下图中有非常相似的两个异形窗体,只不过,左边的异形窗体小,右边的异形窗体大。这个可以怎么实现了?
先通过其它软件来缩放位图,然后再让程序加载这种方式来指定异形窗口的大小。这种方法虽然可以完成任务,但毕竟太OUT了。
由《Windows界面编程第一篇位图背景与位图画刷》可以想到不用位图画刷,而直接在窗口背景绘制时使用StretchBlt来缩放位图至窗口大小,这样就可以达到指定窗口大小的功能。
由于异形窗口运行后无法通过鼠标来动态调整窗口大小,因此可以窗口初始化时就可以先缩放位图并加载到一个缓冲HDC中,然后再在窗口背景绘制时使用BitBlt来贴图。这种做法只需要缩放位图一次,在每次背景绘制时只须拷贝位图,对程序的效率会有提高。下面给出完整源代码(下载地址:http://download.csdn.net/download/morewindows/4966819)
- // 异形窗口2 在WM_ERASEBKGND消息中自贴图
- //By MoreWindows-(http://blog.csdn.net/MoreWindows)
- #include <windows.h>
- const char szAppName[] = "异形窗口2 MoreWindows-(http://blog.csdn.net/MoreWindows)";
-
- /*
- * 函数名称: GetWindowSize
- * 函数功能: 得到窗口的宽高
- * hwnd 窗口句柄
- * pnWidth 窗口宽
- * pnHeight 窗口高
- */
- void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);
-
-
- /*
- * 函数名称: InitBitmapWindow
- * 函数功能: 位图窗口初始化
- * hinstance 进程实例
- * nWidth 窗口宽
- * nHeight 窗口高
- * nCmdshow 显示方式-与ShowWindow函数的第二个参数相同
- */
- 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)
- {
- //先创建一个无背影画刷窗口,
- //然后在WM_CREATE中并指定透明颜色, 缩放位图后加载至s_hdcMem中.
- //最后在WM_ERASEBKGND中用s_hdcMem贴图即可
- 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; //拉高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);
-
- // 缩放位图
- // 加载位图到hdcTemp中
- HDC hdc = GetDC(hwnd);
- HDC hdcTemp = CreateCompatibleDC(hdc);
- SelectObject(hdcTemp, g_hBitmap);
-
- // 得到窗口大小
- int nWidth, nHeight;
- GetWindowSize(hwnd, &nWidth, &nHeight);
-
- // 创建与窗口大小相等且能容纳位图的HDC - s_hdcMem
- 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: //按下Esc键时退出
- 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;
- }
运行程序将得到如文章中每一张图右边所示的异形窗口。
最后总结一下异形窗口的“三要素”:
1.WS_EX_LAYERED属性
2.以位图为窗口背景(自贴图或位图画刷)
3.指定透明色
本文配套程序下载地址为:http://download.csdn.net/download/morewindows/4966819
当窗口的背景用彩色图片来装饰时,其它控件如果还是用灰色的背景会显的比较不谐调,《Windows界面编程第五篇 静态控件背景透明化》将介绍如何为静态框设置透明背景。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。