1.新建一个MFC项目,如图所示

 

 

 

2.在设计视图右键对话框,选择属性选项并设置窗口属性,如下图所示

 

 

3.CTRL+S保存(养成良好的保存数据的习惯,能有效避免错误的发生机率)

 

4.将资源图片导入,素材图片要准备两张,一张为背景图"Background.bmp",另一张"Border.bmp"是"Background.bmp"的边框图.如下图所示

 

 

 

找到刚刚复制进去的res文件夹打开

 

 

选中第一副图,点打开按钮

 

 继续按照上述方法添加另外一张图

两张图片都导入后可以展开节点看到如下效果!

 

CTRL+S 保存,好习惯啊

 

 

5.切换到"解决方案资源管理器"选项卡,双击展开"头文件"节点,双击TestBorder.Dlg.h打开,如下图

6.在"public:"与" CTestBorderDlg(CWnd* pParent = NULL); "中间插入一行,添加如下代码:

 
    
  1. HRGN BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance=NULL); 

添加后效果如图所示,记得CTRL+S保存

7.找到"类视图"选项卡,双击打开"OnInitDialog()",在指定位置处添加如下代码并保存.

 
    
  1. CBitmap bmp;      
  2. if(bmp.LoadBitmap(IDB_BITMAP2))  
  3. {  
  4.     HRGN rgn;  
  5.     rgn = BitmapToRegion((HBITMAP)bmp, RGB(0,0,0));  
  6.     SetWindowRgn(rgn, TRUE);  
  7.     bmp.DeleteObject();  

.如图所示

8.双击打开"OnPaint()"在指定位置处增加如下代码,并保存

 

 
    
  1. CClientDC dc(this);  
  2. CDC memDC;  
  3. memDC.CreateCompatibleDC(&dc);  
  4.  
  5. CBitmap bmp;  
  6. bmp.LoadBitmap(IDB_BITMAP1);  
  7. CBitmap *pOldBmp;  
  8. pOldBmp = memDC.SelectObject(&bmp);  
  9.  
  10. BITMAP bm;  
  11. bmp.GetBitmap(&bm);  
  12.  
  13. dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);  
  14.  
  15. memDC.SelectObject(pOldBmp);  
  16. bmp.DeleteObject(); 

 9.拖动滚动条到代码最底部,添加如下代码,并保存

 
    
  1. HRGN CTestBorderDlg::BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance)  
  2. {  
  3.     HRGN hRgn = NULL;  
  4.       
  5.     if (hBmp)  
  6.     {  
  7.         HDC hMemDC = CreateCompatibleDC(NULL);  
  8.         if (hMemDC)  
  9.         {  
  10.             BITMAP bm;  
  11.             GetObject(hBmp, sizeof(bm), &bm);  
  12.               
  13.             //创建一个32位色的位图,并选进内存设备环境  
  14.             BITMAPINFOHEADER RGB32BITSBITMAPINFO = {  
  15.                         sizeof(BITMAPINFOHEADER),       // biSize   
  16.                             bm.bmWidth,                 // biWidth;   
  17.                             bm.bmHeight,                // biHeight;   
  18.                             1,                          // biPlanes;   
  19.                             32,                         // biBitCount   
  20.                             BI_RGB,                     // biCompression;   
  21.                             0,                          // biSizeImage;   
  22.                             0,                          // biXPelsPerMeter;   
  23.                             0,                          // biYPelsPerMeter;   
  24.                             0,                          // biClrUsed;   
  25.                             0                           // biClrImportant;   
  26.                                                     };  
  27.             VOID * pbits32;   
  28.             HBITMAP hbm32 = CreateDIBSection(hMemDC,(BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);  
  29.             if (hbm32)  
  30.             {  
  31.                 HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);  
  32.                   
  33.                 // Create a DC just to copy the bitmap into the memory DC  
  34.                 HDC hDC = CreateCompatibleDC(hMemDC);  
  35.                 if (hDC)  
  36.                 {  
  37.                     // Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits)  
  38.                     BITMAP bm32;  
  39.                     GetObject(hbm32, sizeof(bm32), &bm32);  
  40.                     while (bm32.bmWidthBytes % 4)  
  41.                         bm32.bmWidthBytes++;  
  42.                       
  43.                     // Copy the bitmap into the memory DC  
  44.                     HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);  
  45.                     BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);  
  46.                       
  47.                     // For better performances, we will use the ExtCreateRegion() function to create the  
  48.                     // region. This function take a RGNDATA structure on entry. We will add rectangles by  
  49.                     // amount of ALLOC_UNIT number in this structure.  
  50. #define ALLOC_UNIT  100  
  51.                     DWORD maxRects = ALLOC_UNIT;  
  52.                     HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));  
  53.                     RGNDATA *pData = (RGNDATA *)GlobalLock(hData);  
  54.                     pData->rdh.dwSize = sizeof(RGNDATAHEADER);  
  55.                     pData->rdh.iType = RDH_RECTANGLES;  
  56.                     pData->rdh.nCount = pData->rdh.nRgnSize = 0;  
  57.                     SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);  
  58.                       
  59.                     // Keep on hand highest and lowest values for the "transparent" pixels  
  60.                     BYTE lr = GetRValue(cTransparentColor);  
  61.                     BYTE lg = GetGValue(cTransparentColor);  
  62.                     BYTE lb = GetBValue(cTransparentColor);  
  63.                     BYTE hr = min(0xff, lr + GetRValue(cTolerance));  
  64.                     BYTE hg = min(0xff, lg + GetGValue(cTolerance));  
  65.                     BYTE hb = min(0xff, lb + GetBValue(cTolerance));  
  66.                       
  67.                     // Scan each bitmap row from bottom to top (the bitmap is inverted vertically)  
  68.                     BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;  
  69.                     for (int y = 0; y < bm.bmHeight; y++)  
  70.                     {  
  71.                         // Scan each bitmap pixel from left to right  
  72.                         for (int x = 0; x < bm.bmWidth; x++)  
  73.                         {  
  74.                             // Search for a continuous range of "non transparent pixels"  
  75.                             int x0 = x;  
  76.                             LONG *p = (LONG *)p32 + x;  
  77.                             while (x < bm.bmWidth)  
  78.                             {  
  79.                                 BYTE b = GetRValue(*p);  
  80.                                 if (b >= lr && b <= hr)  
  81.                                 {  
  82.                                     b = GetGValue(*p);  
  83.                                     if (b >= lg && b <= hg)  
  84.                                     {  
  85.                                         b = GetBValue(*p);  
  86.                                         if (b >= lb && b <= hb)  
  87.                                             // This pixel is "transparent"  
  88.                                             break;  
  89.                                     }  
  90.                                 }  
  91.                                 p++;  
  92.                                 x++;  
  93.                             }  
  94.                               
  95.                             if (x > x0)  
  96.                             {  
  97.                                 // Add the pixels (x0, y) to (x, y+1) as a new rectangle in the region  
  98.                                 if (pData->rdh.nCount >= maxRects)  
  99.                                 {  
  100.                                     GlobalUnlock(hData);  
  101.                                     maxRects += ALLOC_UNIT;  
  102.                                     hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);  
  103.                                     pData = (RGNDATA *)GlobalLock(hData);  
  104.                                 }  
  105.                                 RECT *pr = (RECT *)&pData->Buffer;  
  106.                                 SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);  
  107.                                 if (x0 < pData->rdh.rcBound.left)  
  108.                                     pData->rdh.rcBound.left = x0;  
  109.                                 if (y < pData->rdh.rcBound.top)  
  110.                                     pData->rdh.rcBound.top = y;  
  111.                                 if (x > pData->rdh.rcBound.right)  
  112.                                     pData->rdh.rcBound.right = x;  
  113.                                 if (y+1 > pData->rdh.rcBound.bottom)  
  114.                                     pData->rdh.rcBound.bottom = y+1;  
  115.                                 pData->rdh.nCount++;  
  116.                                   
  117.                                 // On Windows98, ExtCreateRegion() may fail if the number of rectangles is too  
  118.                                 // large (ie: > 4000). Therefore, we have to create the region by multiple steps.  
  119.                                 if (pData->rdh.nCount == 2000)  
  120.                                 {  
  121.                                     HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);  
  122.                                     if (hRgn)  
  123.                                     {  
  124.                                         CombineRgn(hRgn, hRgn, h, RGN_OR);  
  125.                                         DeleteObject(h);  
  126.                                     }  
  127.                                     else 
  128.                                         hRgn = h;  
  129.                                     pData->rdh.nCount = 0;  
  130.                                     SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);  
  131.                                 }  
  132.                             }  
  133.                         }  
  134.                           
  135.                         // Go to next row (remember, the bitmap is inverted vertically)  
  136.                         p32 -= bm32.bmWidthBytes;  
  137.                     }  
  138.                       
  139.                     // Create or extend the region with the remaining rectangles  
  140.                     HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);  
  141.                     if (hRgn)  
  142.                     {  
  143.                         CombineRgn(hRgn, hRgn, h, RGN_OR);  
  144.                         DeleteObject(h);  
  145.                     }  
  146.                     else 
  147.                         hRgn = h;  
  148.                       
  149.                     // Clean up  
  150.                     GlobalFree(hData);  
  151.                     SelectObject(hDC, holdBmp);  
  152.                     DeleteDC(hDC);  
  153.                 }                 
  154.                 DeleteObject(SelectObject(hMemDC, holdBmp));  
  155.             }             
  156.             DeleteDC(hMemDC);  
  157.         }  
  158.     }     
  159.     return hRgn;      

10.打开"资源视图"选项卡,选择Dialog节点并双击展开,选择IDD_TESTBORDER_DIALOG并双击打开

右键->属性->"属性"选项卡中选择红色方框的按钮,下拉滚动条找到"WM_NCHITTEST"点右面的编辑区,弹出下拉列表后选择" OnNcHitTest"

 

将图1中所示代码替换为图2的代码.CTRL+S保存

图1:

 

 

图2:

再次打开"资源视图"选项卡,选择Dialog节点并双击展开,选择IDD_TESTBORDER_DIALOG并双击打开

删除对话框中的三个控件,如图所示

 调整一下对话框的尺寸,以便于完全显示图片

CTRL+S保存,F5运行即可看到如下图所示的最终效果图.(提示:此装口可直接按ESC键关闭)

 

附件为素材图片

源代码下载地址:http://www.vdisk.cn/down/index/9369459A5242