9loong / 用户界面 / windows编程——背景图片和透明特效的使用2

分享

   

windows编程——背景图片和透明特效的使用2

2013-08-26  9loong

Windows界面编程第二篇半透明窗体

    上一篇《Windows界面编程第一篇 位图背景与位图画刷》介绍了通过WM_CTLCOLORDLG消息来来设置对话框的背景以及位图画刷的使用。本篇将介绍动态调节窗体透明度的方法。

    调节窗体透明度可以先使用SetWindowLong为窗体加上WS_EX_LAYERED属性,再使用来SetLayeredWindowAttributes指定窗体的透明度。这样就可以在程序运行时动态的调节窗体的透明度了。

    下面先介绍下SetWindowLongSetLayeredWindowAttributes函数。

SetWindowLong可以用来设置窗口的一些属性,其函数原型如下:

LONGSetWindowLong(

    HWNDhWnd,

    int nIndex,

    LONGdwNewLong

);

第一个参数表示窗口句柄。

第二个参数代表要设置的哪一种值,如GWL_STYLE表示将设置窗口的风格,这个参数还可以取GWL_EXSTYLEGWL_WNDPROCDWL_DLGPROCGWL_HINSTANCEGWL_USERDATA等等。

第三个参数表示要设置的值。

比如要设置对话框也能够可调节窗口大小,可以用:

 // 设置对话框大小可调节

SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) | WS_SIZEBOX);

 

SetLayeredWindowAttributesMSDN上解释如下:

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_HSCROLLWM_VSCROLL来响应消息。

 

下面给出完整的源代码(下载地址:http://download.csdn.net/download/morewindows/4947386

  1. // 可变透明度窗体 先加上WS_EX_LAYERED属性再SetLayeredWindowAttributes设置透明度   
  2. //By MoreWindows-(http://blog.csdn.net/MoreWindows)   
  3. #include <windows.h>   
  4. #include <commctrl.h>   
  5. #include "resource.h"   
  6. const char szDlgTitle[] = "可变透明度窗体 MoreWindows-(http://blog.csdn.net/MoreWindows)";  
  7. // 对话框消息处理函数   
  8. BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);  
  9.   
  10. int APIENTRY WinMain(HINSTANCE hInstance,  
  11.                      HINSTANCE hPrevInstance,  
  12.                      LPSTR     lpCmdLine,  
  13.                      int       nCmdShow)  
  14. {  
  15.     DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);  
  16.     return 0;  
  17. }  
  18.   
  19.   
  20. BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)  
  21. {  
  22.     const int INIT_TRANSPARENT = 200; //窗体初始透明度   
  23.     static HBRUSH    s_hBitmapBrush; //位图画刷   
  24.   
  25.     switch (message)  
  26.     {  
  27.     case WM_INITDIALOG:  
  28.         // 设置对话框标题   
  29.         SetWindowText(hDlg, szDlgTitle);  
  30.   
  31.         // 加载背影图片   
  32.         HBITMAP hBitmap;  
  33.         hBitmap = (HBITMAP)LoadImage(NULL, "005.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);  
  34.         if (hBitmap == NULL)  
  35.         {  
  36.             MessageBox(hDlg, "LoadImage failed""Error", MB_ICONERROR);  
  37.             exit(0);  
  38.         }         
  39.   
  40.         // 创建位图画刷   
  41.         s_hBitmapBrush = CreatePatternBrush(hBitmap);  
  42.   
  43.         // 设置分层属性   
  44.         SetWindowLong(hDlg, GWL_EXSTYLE, GetWindowLong(hDlg, GWL_EXSTYLE) | WS_EX_LAYERED);  
  45.         // 设置透明度 0 - completely transparent   255 - opaque   
  46.         SetLayeredWindowAttributes(hDlg, 0, INIT_TRANSPARENT, LWA_ALPHA);  
  47.   
  48.         // 设置滑动条变化范围   
  49.         SendMessage(GetDlgItem(hDlg, IDC_SLIDER_TRANSPARENT), TBM_SETRANGE, (WPARAM)FALSE, MAKELONG(0, 255));  
  50.         // 设置滑块初始位置   
  51.         SendMessage(GetDlgItem(hDlg, IDC_SLIDER_TRANSPARENT), TBM_SETPOS, (WPARAM)TRUE, INIT_TRANSPARENT);  
  52.         return 0;  
  53.   
  54.   
  55.     case WM_COMMAND:  
  56.         switch (LOWORD(wParam))  
  57.         {  
  58.         case IDCANCEL:  
  59.             DeleteObject(s_hBitmapBrush);  
  60.             EndDialog(hDlg, LOWORD(wParam));  
  61.             return TRUE;  
  62.         }  
  63.         break;  
  64.   
  65.   
  66.     case WM_HSCROLL: // slider control 滑块位置有变化时的响应函数   
  67.         {  
  68.             // 获取当前滑块位置   
  69.             int nTransparent = SendMessage(GetDlgItem(hDlg, IDC_SLIDER_TRANSPARENT), TBM_GETPOS, 0, 0);   
  70.             // 设置新透明度   
  71.             SetLayeredWindowAttributes(hDlg, 0, nTransparent, LWA_ALPHA);  
  72.         }  
  73.         break;  
  74.   
  75.   
  76.     case WM_CTLCOLORDLG:  //对话框背影   
  77.         return (BOOL)s_hBitmapBrush;  
  78.     }  
  79.     return FALSE;  
  80. }  

运行结果如下:

 

在本篇文章中我们通过SetWindowLong为窗体加上WS_EX_LAYERED属性,再使用SetLayeredWindowAttributes完成窗体的透明度调节。下面两篇也将使用这两个函数来完成另一个功能——异形窗口(异形窗体)。异形窗口可以使得窗口更加美观,它能灵活的变动窗口的形状。欢迎继续浏览《Windows界面编程 第三篇异形窗体 普通版》和《Windows界面编程 第四篇异形窗体 高富帅版

    上一篇《Windows界面编程第二篇 半透明窗体》介绍了先使用SetWindowLong为窗体加上WS_EX_LAYERED属性,再使用SetLayeredWindowAttributes调整窗体的透明度。本篇将使用这二个函数来完成另一个实用的功能——异形窗口(异形窗体)。

异形窗口的原理很简单,首先加载一张位图画刷作窗口背景,然后设置透明色就可以使得窗口由矩形变成任意形状。这样使得窗口的显示更加美观。

 

    下面先简单介绍下Win32 SDK方式创建窗口的流程(按《Windows程序设计》中的大体流程):

1.设置WNDCLASS类型的变量,这个变量将描述窗口的风格、窗口消息处理函数、程序图标、光标、窗口背景画刷等待。

2.使用RegisterClassWNDCLASS类型的变量注册下。

3.使用CreateWindowCreateWindowEx创建窗口,这里可以设置窗口的初始位置、初始大小、扩展属性等等。

4.通过ShowWindowUpdateWindow将窗口显示出来。

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. //   异形窗口1  窗口背景使用位图画刷再指定透明色   
  2. //By MoreWindows-(http://blog.csdn.net/MoreWindows)   
  3. #include <windows.h>   
  4.   
  5. const char szAppName[] = "异形窗口1 MoreWindows-(http://blog.csdn.net/MoreWindows)";  
  6.   
  7. /* 
  8.  * 函数名称: GetWindowSize 
  9.  * 函数功能: 得到窗口的宽高 
  10.  * hwnd      窗口句柄 
  11.  * pnWidth   窗口宽 
  12.  * pnHeight  窗口高 
  13. */  
  14. void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);  
  15.   
  16.   
  17. /* 
  18.  * 函数名称: InitBitmapWindow 
  19.  * 函数功能: 位图窗口初始化 
  20.  * hinstance 进程实例 
  21.  * hBitmap   位图句柄 
  22.  * nCmdshow  显示方式-与ShowWindow函数的第二个参数相同 
  23. */  
  24. BOOL InitBitmapWindow(HINSTANCE hinstance, HBITMAP hBitmap, int nCmdshow);  
  25.   
  26. // 位图窗口消息处理函数   
  27. LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm);  
  28.   
  29.   
  30. int APIENTRY WinMain(HINSTANCE hInstance,  
  31.                      HINSTANCE hPrevInstance,  
  32.                      LPSTR     lpCmdLine,  
  33.                      int       nCmdShow)  
  34. {  
  35.     //设置窗口背景画刷为图片画刷,再指定透明颜色即可以创建透明区域。   
  36.     HBITMAP  hBitmap;  
  37.     hBitmap = (HBITMAP)LoadImage(NULL, "Kitty.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);  
  38.     if (hBitmap == NULL)  
  39.     {  
  40.         MessageBox(NULL, "位图加载失败""Error", MB_ICONERROR);  
  41.         return 0;  
  42.     }  
  43.     if (!InitBitmapWindow(hInstance, hBitmap, nCmdShow))  
  44.         return 0;  
  45.   
  46.     MSG msg;  
  47.     while (GetMessage(&msg, NULL, 0, 0))  
  48.     {  
  49.         TranslateMessage(&msg);  
  50.         DispatchMessage(&msg);  
  51.     }  
  52.     DeleteObject(hBitmap);  
  53.   
  54.     return msg.wParam;  
  55. }  
  56.   
  57.   
  58. BOOL InitBitmapWindow(HINSTANCE hinstance, HBITMAP hBitmap, int nCmdshow)  
  59. {  
  60.     HWND hwnd;  
  61.     WNDCLASS wndclass;  
  62.       
  63.     wndclass.style       = CS_VREDRAW | CS_HREDRAW;  
  64.     wndclass.lpfnWndProc = BitmapWindowWndPrco;   
  65.     wndclass.cbClsExtra  = 0;  
  66.     wndclass.cbWndExtra  = 0;  
  67.     wndclass.hInstance   = hinstance;     
  68.     wndclass.hIcon       = LoadIcon(NULL, IDI_APPLICATION);  
  69.     wndclass.hCursor     = LoadCursor(NULL, IDC_ARROW);  
  70.     wndclass.hbrBackground = CreatePatternBrush(hBitmap);//位图画刷   
  71.     wndclass.lpszMenuName  = NULL;  
  72.     wndclass.lpszClassName = szAppName;  
  73.       
  74.     if (!RegisterClass(&wndclass))  
  75.     {  
  76.         MessageBox(NULL, "Program Need Windows NT!""Error", MB_ICONERROR);  
  77.         return FALSE;  
  78.     }  
  79.   
  80.     BITMAP bm;  
  81.     GetObject(hBitmap, sizeof(bm), &bm);  
  82.     hwnd = CreateWindowEx(WS_EX_TOPMOST,  
  83.                         szAppName,  
  84.                         szAppName,   
  85.                         WS_POPUP,  
  86.                         CW_USEDEFAULT,   
  87.                         CW_USEDEFAULT,   
  88.                         bm.bmWidth,   
  89.                         bm.bmHeight,  
  90.                         NULL,  
  91.                         NULL,  
  92.                         hinstance,  
  93.                         NULL);  
  94.     if (hwnd == NULL)  
  95.         return FALSE;  
  96.       
  97.     ShowWindow(hwnd, nCmdshow);  
  98.     UpdateWindow(hwnd);  
  99.       
  100.     return TRUE;  
  101. }  
  102.   
  103. LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm)  
  104. {  
  105.     static HDC s_hdcMem;  
  106.     static HBRUSH s_hBackBrush;  
  107.       
  108.     switch (message)  
  109.     {  
  110.     case WM_CREATE:  
  111.         {  
  112.             // 设置分层属性   
  113.             SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);  
  114.             // 设置透明色   
  115.             COLORREF clTransparent = RGB(0, 0, 0);  
  116.             SetLayeredWindowAttributes(hwnd, clTransparent, 0, LWA_COLORKEY);  
  117.         }  
  118.         return 0;  
  119.   
  120.           
  121.     case WM_KEYDOWN:   
  122.         switch (wParam)  
  123.         {  
  124.         case VK_ESCAPE: //按下Esc键时退出   
  125.             SendMessage(hwnd, WM_DESTROY, 0, 0);  
  126.             return 0;  
  127.         }  
  128.         break;  
  129.       
  130.   
  131.     case WM_LBUTTONDOWN: //当鼠标左键点击时可以拖曳窗口   
  132.         PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);   
  133.         return 0;  
  134.   
  135.   
  136.     case WM_DESTROY:  
  137.         PostQuitMessage(0);  
  138.         return 0;  
  139.     }  
  140.     return DefWindowProc(hwnd, message, wParam, lParm);  
  141. }  
  142.   
  143. void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight)  
  144. {  
  145.     RECT rc;  
  146.     GetWindowRect(hwnd, &rc);  
  147.     *pnWidth = rc.right - rc.left;  
  148.     *pnHeight = rc.bottom - rc.top;  
  149. }  

运行结果如下:

 

 

现在总结下异形窗口的创建,先通过创建位图画刷来做窗口的背景画刷,再通过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

  1. //   异形窗口2  在WM_ERASEBKGND消息中自贴图   
  2. //By MoreWindows-(http://blog.csdn.net/MoreWindows)   
  3. #include <windows.h>   
  4. const char szAppName[] = "异形窗口2 MoreWindows-(http://blog.csdn.net/MoreWindows)";  
  5.   
  6. /* 
  7.  * 函数名称: GetWindowSize 
  8.  * 函数功能: 得到窗口的宽高 
  9.  * hwnd      窗口句柄 
  10.  * pnWidth   窗口宽 
  11.  * pnHeight  窗口高 
  12. */  
  13. void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);  
  14.   
  15.   
  16. /* 
  17.  * 函数名称: InitBitmapWindow 
  18.  * 函数功能: 位图窗口初始化 
  19.  * hinstance 进程实例 
  20.  * nWidth    窗口宽 
  21.  * nHeight   窗口高 
  22.  * nCmdshow  显示方式-与ShowWindow函数的第二个参数相同 
  23. */  
  24. BOOL InitBitmapWindow(HINSTANCE hinstance, int nWidth, int nHeight, int nCmdshow);  
  25.   
  26. // 位图窗口消息处理函数   
  27. LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm);  
  28.   
  29.             
  30. HBITMAP  g_hBitmap;  
  31. int APIENTRY WinMain(HINSTANCE hInstance,  
  32.                      HINSTANCE hPrevInstance,  
  33.                      LPSTR     lpCmdLine,  
  34.                      int       nCmdShow)  
  35. {  
  36.     //先创建一个无背影画刷窗口,   
  37.     //然后在WM_CREATE中并指定透明颜色, 缩放位图后加载至s_hdcMem中.   
  38.     //最后在WM_ERASEBKGND中用s_hdcMem贴图即可   
  39.     g_hBitmap = (HBITMAP)LoadImage(NULL, "Kitty.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);  
  40.     if (g_hBitmap == NULL)  
  41.     {  
  42.         MessageBox(NULL, "位图加载失败""Error", MB_ICONERROR);  
  43.         return 0;  
  44.     }  
  45.   
  46.     // 设置异形窗口大小   
  47.     BITMAP bm;  
  48.     GetObject(g_hBitmap, sizeof(bm), &bm);  
  49.     int nWindowWidth = bm.bmWidth;  
  50.     int nWindowHeight = bm.bmHeight + 100; //拉高100高度   
  51.   
  52.     if (!InitBitmapWindow(hInstance, nWindowWidth, nWindowHeight, nCmdShow))  
  53.         return 0;  
  54.   
  55.     MSG msg;  
  56.     while (GetMessage(&msg, NULL, 0, 0))  
  57.     {  
  58.         TranslateMessage(&msg);  
  59.         DispatchMessage(&msg);  
  60.     }  
  61.     DeleteObject(g_hBitmap);  
  62.   
  63.     return msg.wParam;  
  64. }  
  65.   
  66.   
  67. BOOL InitBitmapWindow(HINSTANCE hinstance, int nWidth, int nHeight, int nCmdshow)  
  68. {  
  69.     HWND hwnd;  
  70.     WNDCLASS wndclass;  
  71.       
  72.     wndclass.style       = CS_VREDRAW | CS_HREDRAW;  
  73.     wndclass.lpfnWndProc = BitmapWindowWndPrco;   
  74.     wndclass.cbClsExtra  = 0;  
  75.     wndclass.cbWndExtra  = 0;  
  76.     wndclass.hInstance   = hinstance;     
  77.     wndclass.hIcon       = LoadIcon(NULL, IDI_APPLICATION);  
  78.     wndclass.hCursor     = LoadCursor(NULL, IDC_ARROW);  
  79.     wndclass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);//窗口背影画刷为空   
  80.     wndclass.lpszMenuName  = NULL;  
  81.     wndclass.lpszClassName = szAppName;  
  82.       
  83.     if (!RegisterClass(&wndclass))  
  84.     {  
  85.         MessageBox(NULL, "Program Need Windows NT!""Error", MB_ICONERROR);  
  86.         return FALSE;  
  87.     }  
  88.       
  89.     hwnd = CreateWindowEx(WS_EX_TOPMOST,  
  90.                         szAppName,  
  91.                         szAppName,   
  92.                         WS_POPUP,  
  93.                         CW_USEDEFAULT,   
  94.                         CW_USEDEFAULT,   
  95.                         nWidth,   
  96.                         nHeight,  
  97.                         NULL,  
  98.                         NULL,  
  99.                         hinstance,  
  100.                         NULL);  
  101.     if (hwnd == NULL)  
  102.         return FALSE;  
  103.       
  104.     ShowWindow(hwnd, nCmdshow);  
  105.     UpdateWindow(hwnd);  
  106.       
  107.     return TRUE;  
  108. }  
  109.   
  110. LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm)  
  111. {  
  112.     static HDC s_hdcMem; //放置缩放后的位图   
  113.       
  114.     switch (message)  
  115.     {  
  116.     case WM_CREATE:  
  117.         {  
  118.             // 设置分层属性   
  119.             SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);  
  120.             // 设置透明色   
  121.             COLORREF clTransparent = RGB(0, 0, 0);  
  122.             SetLayeredWindowAttributes(hwnd, clTransparent, 0, LWA_COLORKEY);  
  123.               
  124.             //   缩放位图   
  125.             // 加载位图到hdcTemp中   
  126.             HDC hdc = GetDC(hwnd);  
  127.             HDC hdcTemp = CreateCompatibleDC(hdc);  
  128.             SelectObject(hdcTemp, g_hBitmap);  
  129.   
  130.             // 得到窗口大小   
  131.             int nWidth, nHeight;  
  132.             GetWindowSize(hwnd, &nWidth, &nHeight);  
  133.   
  134.             // 创建与窗口大小相等且能容纳位图的HDC - s_hdcMem   
  135.             s_hdcMem = CreateCompatibleDC(hdc);  
  136.             HBITMAP hbmp = CreateCompatibleBitmap(hdc, nWidth, nHeight);  
  137.             SelectObject(s_hdcMem, hbmp);  
  138.   
  139.             // 将原位图缩放到窗口大小   
  140.             BITMAP bm;  
  141.             GetObject(g_hBitmap, sizeof(bm), &bm);  
  142.             StretchBlt(s_hdcMem, 0, 0, nWidth, nHeight, hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);  
  143.               
  144.             // 释放资源   
  145.             DeleteDC(hdcTemp);  
  146.             ReleaseDC(hwnd, hdc);  
  147.         }  
  148.         return 0;  
  149.   
  150.           
  151.     case WM_KEYDOWN:   
  152.         switch (wParam)  
  153.         {  
  154.         case VK_ESCAPE: //按下Esc键时退出   
  155.             SendMessage(hwnd, WM_DESTROY, 0, 0);  
  156.             return TRUE;  
  157.         }  
  158.         break;  
  159.       
  160.   
  161.     case WM_LBUTTONDOWN: //当鼠标左键点击时可以拖曳窗口   
  162.         PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);   
  163.         return TRUE;  
  164.                   
  165.     case WM_ERASEBKGND: //在窗口背景中直接贴图   
  166.         {  
  167.             HDC hdc = (HDC)wParam;  
  168.             int nWidth, nHeight;  
  169.             GetWindowSize(hwnd, &nWidth, &nHeight);  
  170.             BitBlt(hdc, 0, 0, nWidth, nHeight, s_hdcMem, 0, 0, SRCCOPY);  
  171.             return TRUE;  
  172.         }  
  173.   
  174.     case WM_DESTROY:  
  175.         DeleteDC(s_hdcMem);  
  176.         PostQuitMessage(0);  
  177.         return 0;  
  178.     }  
  179.     return DefWindowProc(hwnd, message, wParam, lParm);  
  180. }  
  181.   
  182.   
  183. void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight)  
  184. {  
  185.     RECT rc;  
  186.     GetWindowRect(hwnd, &rc);  
  187.     *pnWidth = rc.right - rc.left;  
  188.     *pnHeight = rc.bottom - rc.top;  
  189. }  

运行程序将得到如文章中每一张图右边所示的异形窗口。

 

最后总结一下异形窗口的“三要素”:

1.WS_EX_LAYERED属性

2.以位图为窗口背景(自贴图或位图画刷)

3.指定透明色

 

本文配套程序下载地址为:http://download.csdn.net/download/morewindows/4966819

 

当窗口的背景用彩色图片来装饰时,其它控件如果还是用灰色的背景会显的比较不谐调,《Windows界面编程第五篇 静态控件背景透明化》将介绍如何为静态框设置透明背景。

分类: Windows编程 2013-01-07 10:25 767人阅读 评论(0) 收藏 举报

    上一篇《Windows界面编程第三篇 异形窗体 普通版》和《Windows界面编程第四篇异形窗体 高富帅版》介绍了异形窗口(异形窗体)的创建,并总结出了异形窗口的“三要素”:

1.WS_EX_LAYERED属性

2.指定透明色

3.以位图为窗口背景

 

    本篇文章将主要介绍Windows编程中如何实现静态控件背景的透明化,这将进一步的美化界面。下面先看一张没有做静态控件背景透明化的对话框程序的运行画面,对话框的彩色图片背景可以参考《Windows界面编程第一篇位图背景与位图画刷》。

    可以看出静态控件的灰度背景在对话框的彩色图片背景中显得很不谐调,因此有必要对其美化一下。

    在第一篇《Windows界面编程第一篇位图背景与位图画刷》中介绍了通过WM_CTLCOLORDLG消息来设置对话框的背景,而在Windows系统中还有类似于WM_CTLCOLORDLG消息的还有WM_CTLCOLORBTNWM_CTLCOLOREDITWM_CTLCOLORLISTBOXWM_CTLCOLORSCROLLBARWM_CTLCOLORSTATIC这五种来分别管理按钮,编辑框,列表框,滚动条,静态框。因此我们首先在WM_CTLCOLORSTATIC消息中返回一个空画刷看看能不能达到背景透明化的要求。另外对于文字区域的背景透明可以通过SetBkMode来设置。其函数原型如下:

int SetBkMode(

    HDC hdc,      // handle to DC

    int iBkMode   // background mode

);

这个函数的第二个参数设置为TRANSPARENT时就可以将文字区域的前景设置成透明。

 

下面给出完整的源代码(下载地址:http://download.csdn.net/download/morewindows/4966826):

  1. // 静态控件背景透明化WM_CTLCOLORSTATIC中返回空画刷   
  2. //By MoreWindows-(http://blog.csdn.net/MoreWindows)   
  3. #include <windows.h>   
  4. #include "resource.h"   
  5.   
  6. const char szDlgTitle[] = "静态控件背景透明化MoreWindows-(http://blog.csdn.net/MoreWindows)";  
  7.   
  8. // 对话框消息处理函数   
  9. BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);  
  10.             
  11. int APIENTRY WinMain(HINSTANCE hInstance,  
  12.                      HINSTANCE hPrevInstance,  
  13.                      LPSTR     lpCmdLine,  
  14.                      int       nCmdShow)  
  15. {  
  16.     DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);  
  17.     return 0;  
  18. }  
  19.   
  20.   
  21. BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)  
  22. {  
  23.     RECT       rcDialog;  
  24.     HBITMAP    hBitmap;  
  25.     static BITMAP s_bm;  
  26.     static HDC    s_hdcMem;  
  27.   
  28.     switch (message)  
  29.     {  
  30.     case WM_INITDIALOG:  
  31.         // 设置对话框标题   
  32.         SetWindowText(hDlg, szDlgTitle);  
  33.         // 设置对话框大小可调节   
  34.         SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) | WS_SIZEBOX);  
  35.   
  36.         // 加载背影图片   
  37.         hBitmap = (HBITMAP)LoadImage(NULL, "006.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);  
  38.         if (hBitmap == NULL)  
  39.         {  
  40.             MessageBox(hDlg, "LoadImage failed""Error", MB_ICONERROR);  
  41.             exit(0);  
  42.         }         
  43.         else  
  44.         {  
  45.             // 将背影图片放入HDC - s_hdcMem   
  46.             HDC        hdc;  
  47.             hdc = GetDC(hDlg);  
  48.             s_hdcMem = CreateCompatibleDC(hdc);  
  49.             SelectObject(s_hdcMem, hBitmap);      
  50.             ReleaseDC(hDlg, hdc);  
  51.   
  52.             // 得到位图信息   
  53.             GetObject(hBitmap, sizeof(s_bm), &s_bm);  
  54.         }  
  55.   
  56.         return 0;  
  57.   
  58.     case WM_COMMAND:  
  59.         switch (LOWORD(wParam))  
  60.         {  
  61.         case IDCANCEL:  
  62.             DeleteDC(s_hdcMem);  
  63.             EndDialog(hDlg, LOWORD(wParam));  
  64.             return TRUE;  
  65.         }  
  66.         break;  
  67.   
  68.   
  69.     case WM_SIZE:  
  70.         InvalidateRect(hDlg, NULL, TRUE);  
  71.         return TRUE;  
  72.   
  73.     case WM_CTLCOLORSTATIC:  
  74.         SetBkMode((HDC)wParam, TRANSPARENT);  
  75.         return (BOOL)((HBRUSH)GetStockObject(NULL_BRUSH));  
  76.   
  77.     case WM_CTLCOLORDLG:  
  78.         GetClientRect(hDlg, &rcDialog);  
  79.         //通过SetStretchBltMode的设置能使StretchBlt在缩放图像更加清晰   
  80.         SetStretchBltMode((HDC)wParam, COLORONCOLOR);  
  81.         StretchBlt((HDC)wParam, 0, 0, rcDialog.right, rcDialog.bottom, s_hdcMem, 0, 0, s_bm.bmWidth, s_bm.bmHeight, SRCCOPY);     
  82.         return (BOOL)((HBRUSH)GetStockObject(NULL_BRUSH));  
  83.     }  
  84.     return FALSE;  
  85. }  

这份代码也是在《Windows界面编程第一篇位图背景与位图画刷》文章的代码上增加了

    case WM_CTLCOLORSTATIC:

             SetBkMode((HDC)wParamTRANSPARENT);

             return (BOOL)((HBRUSH)GetStockObject(NULL_BRUSH));

来达到静态控件背景透明化的效果的,程序运行效果如下:

 

由图可以看出,虽然Static Text控件的是达到了背景透明化的要求,但是Group Box控件的描述文字的显示却显得很不美观。

 

要解决这一问题,可以试下位图画刷,我们在WM_CTLCOLORSTATIC消息中像WM_CTLCOLORDLG消息一样也返回一个位图画刷来试试。

  1. // 静态控件背景透明化- 在WM_CTLCOLORDLG返回窗口背景的位图画刷   
  2. //By MoreWindows-(http://blog.csdn.net/MoreWindows)   
  3. #include <windows.h>   
  4. #include "resource.h"   
  5.   
  6. const char szDlgTitle[] = "静态控件背景透明化MoreWindows-(http://blog.csdn.net/MoreWindows)";  
  7.   
  8.   
  9. // 对话框消息处理函数   
  10. BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);  
  11.   
  12. int APIENTRY WinMain(HINSTANCE hInstance,  
  13.                      HINSTANCE hPrevInstance,  
  14.                      LPSTR     lpCmdLine,  
  15.                      int       nCmdShow)  
  16. {  
  17.     DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);  
  18.     return 0;  
  19. }  
  20.   
  21.   
  22. BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)  
  23. {  
  24.     static HBRUSH    s_hBitmapBrush; //位图画刷   
  25.   
  26.     switch (message)  
  27.     {  
  28.     case WM_INITDIALOG:  
  29.         // 设置对话框标题   
  30.         SetWindowText(hDlg, szDlgTitle);  
  31.         // 设置对话框大小可调节   
  32.         SetWindowLong(hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) | WS_SIZEBOX);  
  33.   
  34.         // 加载背影图片   
  35.         HBITMAP hBitmap;  
  36.         hBitmap = (HBITMAP)LoadImage(NULL, "006.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);  
  37.         if (hBitmap == NULL)  
  38.         {  
  39.             MessageBox(hDlg, "LoadImage failed""Error", MB_ICONERROR);  
  40.             exit(0);  
  41.         }         
  42.   
  43.         // 创建位图画刷   
  44.         s_hBitmapBrush = CreatePatternBrush(hBitmap);  
  45.         return 0;  
  46.   
  47.   
  48.     case WM_COMMAND:  
  49.         switch (LOWORD(wParam))  
  50.         {  
  51.         case IDCANCEL:  
  52.             DeleteObject(s_hBitmapBrush);  
  53.             EndDialog(hDlg, LOWORD(wParam));  
  54.             return TRUE;  
  55.         }  
  56.         break;  
  57.   
  58.     case WM_CTLCOLORSTATIC:  
  59.         SetBkMode((HDC)wParam, TRANSPARENT);  
  60.   
  61.     case WM_CTLCOLORDLG:  
  62.         return (BOOL)s_hBitmapBrush;  
  63.     }  
  64.     return FALSE;  
  65. }  

与上一个程序一样,这个程序也只是在在《Windows界面编程第一篇位图背景与位图画刷》文章的代码上增加了

       case WM_CTLCOLORSTATIC:

              SetBkMode((HDC)wParamTRANSPARENT);

来设置静态控件背景透明化,程序运行效果如下:

 

由图可以看出,静态控件的透明化还是非常方便的,只要在WM_CTLCOLORSTATIC消息中完成二个步骤即可:

1.通过SetBkMode((HDC)wParamTRANSPARENT);来设置文字区域背景透明。

2.返回空画刷或与父窗口相同的画刷。


(###)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多
    喜欢该文的人也喜欢 更多

    ×
    ×

    ¥.00

    微信或支付宝扫码支付:

    开通即同意《个图VIP服务协议》

    全部>>