现在的位置: 首页 > 综合 > 正文

Windows界面编程第四篇 异形窗体 高富帅版 .

2018年04月28日 ⁄ 综合 ⁄ 共 9835字 ⁄ 字号 评论关闭

上一篇《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界面编程第五篇
静态控件背景透明化
》将介绍如何为静态框设置透明背景。

 

转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8451638

欢迎关注微博:http://weibo.com/MoreWindows

抱歉!评论已关闭.