• 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. constchar 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.     //然后在WM_CREATE中并指定透明颜色, 缩放位图后加载至s_hdcMem中. 
    37.     //最后在WM_ERASEBKGND中用s_hdcMem贴图即可 
    38.     g_hBitmap = (HBITMAP)LoadImage(NULL,"Kitty.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); 
    39.     if (g_hBitmap == NULL) 
    40.     { 
    41.         MessageBox(NULL, "位图加载失败", "Error", MB_ICONERROR); 
    42.         return 0; 
    43.     } 
    44.  
    45.     // 设置异形窗口大小 
    46.     BITMAP bm; 
    47.     GetObject(g_hBitmap, sizeof(bm), &bm); 
    48.     int nWindowWidth = bm.bmWidth; 
    49.     int nWindowHeight = bm.bmHeight + 100;//拉高100高度 
    50.  
    51.     if (!InitBitmapWindow(hInstance, nWindowWidth, nWindowHeight, nCmdShow)) 
    52.         return 0; 
    53.  
    54.     MSG msg; 
    55.     while (GetMessage(&msg, NULL, 0, 0)) 
    56.     { 
    57.         TranslateMessage(&msg); 
    58.         DispatchMessage(&msg); 
    59.     } 
    60.     DeleteObject(g_hBitmap); 
    61.  
    62.     return msg.wParam; 
    63.  
    64.  
    65. BOOL InitBitmapWindow(HINSTANCE hinstance,int nWidth,int nHeight,int nCmdshow) 
    66.     HWND hwnd; 
    67.     WNDCLASS wndclass; 
    68.      
    69.     wndclass.style       = CS_VREDRAW | CS_HREDRAW; 
    70.     wndclass.lpfnWndProc = BitmapWindowWndPrco;  
    71.     wndclass.cbClsExtra  = 0; 
    72.     wndclass.cbWndExtra  = 0; 
    73.     wndclass.hInstance   = hinstance;    
    74.     wndclass.hIcon       = LoadIcon(NULL, IDI_APPLICATION); 
    75.     wndclass.hCursor     = LoadCursor(NULL, IDC_ARROW); 
    76.     wndclass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);//窗口背影画刷为空 
    77.     wndclass.lpszMenuName  = NULL; 
    78.     wndclass.lpszClassName = szAppName; 
    79.      
    80.     if (!RegisterClass(&wndclass)) 
    81.     { 
    82.         MessageBox(NULL,"Program Need Windows NT!","Error", MB_ICONERROR); 
    83.         return FALSE; 
    84.     } 
    85.      
    86.     hwnd = CreateWindowEx(WS_EX_TOPMOST, 
    87.                         szAppName, 
    88.                         szAppName,  
    89.                         WS_POPUP, 
    90.                         CW_USEDEFAULT,  
    91.                         CW_USEDEFAULT,  
    92.                         nWidth,  
    93.                         nHeight, 
    94.                         NULL, 
    95.                         NULL, 
    96.                         hinstance, 
    97.                         NULL); 
    98.     if (hwnd == NULL) 
    99.         return FALSE; 
    100.      
    101.     ShowWindow(hwnd, nCmdshow); 
    102.     UpdateWindow(hwnd); 
    103.      
    104.     return TRUE; 
    105.  
    106. LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParm) 
    107.     staticHDC s_hdcMem;//放置缩放后的位图 
    108.      
    109.     switch (message) 
    110.     { 
    111.     case WM_CREATE: 
    112.         { 
    113.             // 设置分层属性 
    114.             SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); 
    115.             // 设置透明色 
    116.             COLORREF clTransparent = RGB(0, 0, 0); 
    117.             SetLayeredWindowAttributes(hwnd, clTransparent, 0, LWA_COLORKEY); 
    118.              
    119.             //   缩放位图 
    120.             // 加载位图到hdcTemp中 
    121.             HDC hdc = GetDC(hwnd); 
    122.             HDC hdcTemp = CreateCompatibleDC(hdc); 
    123.             SelectObject(hdcTemp, g_hBitmap); 
    124.  
    125.             // 得到窗口大小 
    126.             int nWidth, nHeight; 
    127.             GetWindowSize(hwnd, &nWidth, &nHeight); 
    128.  
    129.             // 创建与窗口大小相等且能容纳位图的HDC - s_hdcMem 
    130.             s_hdcMem = CreateCompatibleDC(hdc); 
    131.             HBITMAP hbmp = CreateCompatibleBitmap(hdc, nWidth, nHeight); 
    132.             SelectObject(s_hdcMem, hbmp); 
    133.  
    134.             // 将原位图缩放到窗口大小 
    135.             BITMAP bm; 
    136.             GetObject(g_hBitmap,sizeof(bm), &bm); 
    137.             StretchBlt(s_hdcMem, 0, 0, nWidth, nHeight, hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); 
    138.              
    139.             // 释放资源 
    140.             DeleteDC(hdcTemp); 
    141.             ReleaseDC(hwnd, hdc); 
    142.         } 
    143.         return 0; 
    144.  
    145.          
    146.     case WM_KEYDOWN:  
    147.         switch (wParam) 
    148.         { 
    149.         case VK_ESCAPE: //按下Esc键时退出 
    150.             SendMessage(hwnd, WM_DESTROY, 0, 0); 
    151.             return TRUE; 
    152.         } 
    153.         break
    154.      
    155.  
    156.     case WM_LBUTTONDOWN: //当鼠标左键点击时可以拖曳窗口 
    157.         PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);  
    158.         return TRUE; 
    159.                  
    160.     case WM_ERASEBKGND: //在窗口背景中直接贴图 
    161.         { 
    162.             HDC hdc = (HDC)wParam; 
    163.             int nWidth, nHeight; 
    164.             GetWindowSize(hwnd, &nWidth, &nHeight); 
    165.             BitBlt(hdc, 0, 0, nWidth, nHeight, s_hdcMem, 0, 0, SRCCOPY); 
    166.             return TRUE; 
    167.         } 
    168.  
    169.     case WM_DESTROY: 
    170.         DeleteDC(s_hdcMem); 
    171.         PostQuitMessage(0); 
    172.         return 0; 
    173.     } 
    174.     return DefWindowProc(hwnd, message, wParam, lParm); 
    175.  
    176.  
    177. void GetWindowSize(HWND hwnd,int *pnWidth,int *pnHeight) 
    178.     RECT rc; 
    179.     GetWindowRect(hwnd, &rc); 
    180.     *pnWidth = rc.right - rc.left; 
    181.     *pnHeight = rc.bottom - rc.top; 

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

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

    1.WS_EX_LAYERED属性

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

    3.指定透明色

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

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

  • 相关阅读:
    NOIP200801 ISBN号码
    NOIP200902分数线划定
    NOIP200901多项式输出
    NOIP200603 Jam的计数法
    HDNOIP201102读数
    Modular Inverse(扩展欧几里得)
    青蛙的约会(扩展欧几里得)
    A Famous City(单调栈)
    Triangles
    2971: 魔族密码 (trie树)
  • 原文地址:https://www.cnblogs.com/jinsedemaitian/p/5589195.html
Copyright © 2020-2023  润新知