使用图片创建不规则窗体 windows sdk

见过搜狗拼音的奥运主题,鸟巢和水立方作背景,而且整个界面是不规则的,看着很有意思,于是想自己用图片做一个。现在所实现的仅是单色背景的图片。

    创建不规则使用下面这个API函数

    int SetWindowRgn( HWND hWnd, // handle to window HRGN hRgn, // handle to region BOOL bRedraw // window redraw option );
    需要做是把非背景色的像素绘制出来即可:可以逐行进行扫描,遇到不为背景色的像素则创建绘制区域。将得到的区域和创建好的空区域作或,合并在一起,然后向下逐行进行扫描,重复即可得到整个图片除背景色外的像素区域。

 

  1. #include "windows.h"
  2. #include "resource.h"
  3. /************************************************************/
  4. #define ButtonID 1000
  5. #define PictureW 480    //图片的宽
  6. #define PictureH 410    //高
  7. HWND     g_hwndButton;  //保存按钮句柄
  8. HWND     g_hWnd;        //保存窗体句柄
  9. HBITMAP  g_hBitMap;     //保存位图句柄
  10. HDC g_hDC;         //保存设备DC句柄
  11. HRGN    wndRgn;        //保存RGN数据句柄
  12. HINSTANCE g_hInstance;
  13. char ClassName[] = "cws_class";
  14. char DisplayName[] = "custom windows shape";
  15. char ButtonClassName[] = "button";
  16. char ButtonText[] = "Click Me!";
  17. char Text[] = "Good bye...";
  18. void SetupRegion(HDC hDC, HBITMAP &cBitmap, COLORREF TransColor)
  19. {
  20.     //创建与传入DC兼容的临时DC
  21.     HDC memDC= ::CreateCompatibleDC(hDC);
  22.     HBITMAP hOldMemBmp(0);
  23.     //将位图选入临时DC
  24.     hOldMemBmp = (HBITMAP)::SelectObject(memDC,cBitmap);
  25.     //创建总的窗体区域,初始region为0
  26.     wndRgn = ::CreateRectRgn(0,0,0,0);
  27.     BITMAP bit; 
  28.          //取得位图参数,这里要用到位图的长和宽   
  29.     GetObject(cBitmap,sizeof(BITMAP),&bit);
  30.     int y;
  31.     for(y=0;y<=bit.bmHeight ;y++)
  32.     {
  33.         HRGN rgnTemp; //保存临时region
  34.         int iX = 0;
  35.         do
  36.         {
  37.             //跳过透明色找到下一个非透明色的点.
  38.             while (iX <= bit.bmWidth && 
  39.                                    GetPixel(memDC,iX, y) == TransColor)
  40.                 iX++;
  41.             //记住这个起始点
  42.             int iLeftX = iX;
  43.             //寻找下个透明色的点
  44.             while (iX <= bit.bmWidth && 
  45.                                      GetPixel(memDC,iX, y) != TransColor)
  46.                 ++iX;
  47.             //创建一个包含起点与终点间高为1像素的临时“region”
  48.             rgnTemp = CreateRectRgn(iLeftX, y, iX, y+1);
  49.             //合并到主"region".
  50.             CombineRgn(wndRgn,wndRgn,rgnTemp, RGN_OR);
  51.             //删除临时"region",否则下次创建时和出错
  52.             DeleteObject(rgnTemp);
  53.         }while(iX <bit.bmWidth );
  54.         iX = 0;
  55.     }
  56.     if(hOldMemBmp)
  57.         SelectObject(memDC,hOldMemBmp);
  58.     HWND hWnd = WindowFromDC(hDC);
  59.     SetWindowRgn(hWnd,wndRgn,TRUE);
  60.     SetForegroundWindow(hWnd);         
  61. }
  62. /************************************************************/
  63. LRESULT CALLBACK WindowProc(          HWND hwnd,
  64.                             UINT uMsg,
  65.                             WPARAM wParam,
  66.                             LPARAM lParam
  67.                             )
  68. {
  69.     switch(uMsg)
  70.     {
  71.     case WM_CREATE:
  72.         g_hBitMap = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));   //加载背景位图
  73.         g_hDC = BeginPaint(g_hWnd,NULL);
  74.         SetupRegion(g_hDC,g_hBitMap,RGB(255,0,0));
  75.         SetWindowRgn(hwnd,wndRgn,TRUE);//设定RGN数据
  76.         g_hwndButton = CreateWindowEx(NULL,ButtonClassName,ButtonText,
  77.             WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
  78.             320,270,120,30,hwnd,(HMENU)ButtonID,g_hInstance,NULL);
  79.         break;
  80.     case WM_COMMAND:
  81.         if(LOWORD(wParam) == ButtonID)
  82.         {
  83.             MessageBox(hwnd,Text,DisplayName,MB_OK);
  84.             SendMessage(hwnd,WM_DESTROY,NULL,NULL);
  85.         }
  86.         break;
  87.     case WM_LBUTTONDOWN:
  88.         SendMessage(hwnd,WM_NCLBUTTONDOWN,HTCAPTION,lParam);
  89.         break;
  90.     case WM_DESTROY:
  91.         PostQuitMessage(NULL);
  92.         break;
  93.     default:
  94.         return DefWindowProc(hwnd,uMsg,wParam,lParam);
  95.     }
  96.     return 0;
  97. }
  98. int APIENTRY WinMain(HINSTANCE hInstance,
  99.                      HINSTANCE hPrevInstance,
  100.                      LPSTR     lpCmdLine,
  101.                      int       nCmdShow)
  102. {
  103.     WNDCLASSEX wc;
  104.     MSG msg;
  105.     g_hInstance = hInstance;
  106.     wc.cbSize = sizeof(WNDCLASSEX);
  107.     wc.style = CS_HREDRAW | CS_VREDRAW |CS_BYTEALIGNWINDOW;
  108.     wc.lpfnWndProc = WindowProc;
  109.     wc.cbClsExtra = NULL;
  110.     wc.cbWndExtra = NULL;
  111.     wc.hInstance = hInstance;
  112.     wc.hbrBackground = CreatePatternBrush(LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP1)));
  113.     wc.lpszMenuName = NULL;
  114.     wc.lpszClassName = ClassName;
  115.     wc.hIcon = NULL;
  116.     wc.hCursor = LoadCursor(NULL,IDC_CROSS);
  117.     wc.hIconSm = NULL;
  118.     RegisterClassEx(&wc);
  119.     g_hWnd = CreateWindowEx(WS_EX_LEFT,
  120.         ClassName,
  121.         DisplayName,
  122.         WS_POPUP,
  123.         (GetSystemMetrics(SM_CXSCREEN) - PictureW)/2,
  124.         (GetSystemMetrics(SM_CYSCREEN) - PictureH)/2,
  125.         PictureW,
  126.         PictureH,
  127.         NULL,
  128.         NULL,
  129.         hInstance,
  130.         NULL
  131.         );
  132.     ShowWindow(g_hWnd,SW_SHOWNORMAL);
  133.     UpdateWindow(g_hWnd);
  134.     while(GetMessage(&msg,NULL,0,0))
  135.     {
  136.         TranslateMessage(&msg);
  137.         DispatchMessage(&msg);
  138.     }
  139.     return msg.wParam;
  140. }

 

资源文件只包含了位图的定义。

这样就可以看到我传的图片的效果了。不是太好,但是一种思路,以前怎么也想不到这种效果,总以为窗口是矩形的,中间如果有空着的区域的话,点住空白区域拖动窗体是随鼠标一起动的,但创建不规则窗口则可以实现“镂空”效果。不信可以试试呵呵。

你可能感兴趣的:(windows,command,null,Class,button,搜狗)