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

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

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

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

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

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

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

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 ):

[cpp] view plain copy print ?
  • //   异形窗口1  窗口背景使用位图画刷再指定透明色
  • //By MoreWindows-(http://blog.csdn.net/MoreWindows)
  • #include <windows.h>
  • const char szAppName[] = "异形窗口1 MoreWindows-(http://blog.csdn.net/MoreWindows)" ;
  • /*
  • * 函数名称: GetWindowSize
  • * 函数功能: 得到窗口的宽高
  • * hwnd      窗口句柄
  • * pnWidth   窗口宽
  • * pnHeight  窗口高
  • */
  • void GetWindowSize( HWND hwnd, int *pnWidth, int *pnHeight);
  • /*
  • * 函数名称: InitBitmapWindow
  • * 函数功能: 位图窗口初始化
  • * hinstance 进程实例
  • * hBitmap   位图句柄
  • * nCmdshow  显示方式-与ShowWindow函数的第二个参数相同
  • */
  • BOOL InitBitmapWindow( HINSTANCE hinstance, HBITMAP hBitmap, int nCmdshow);
  • // 位图窗口消息处理函数
  • LRESULT CALLBACK BitmapWindowWndPrco( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm);
  • int APIENTRY WinMain( HINSTANCE hInstance,
  • HINSTANCE hPrevInstance,  LPSTR lpCmdLine,
  • int nCmdShow)  //设置窗口背景画刷为图片画刷,再指定透明颜色即可以创建透明区域。
  • HBITMAP hBitmap;
  • hBitmap = ( HBITMAP )LoadImage(NULL, "Kitty.bmp" , IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  • if (hBitmap == NULL)
  • {
  • MessageBox(NULL, "位图加载失败" , "Error" , MB_ICONERROR);
  • return 0;
  • }
  • if (!InitBitmapWindow(hInstance, hBitmap, nCmdShow))
  • return 0;
  • MSG msg;
  • while (GetMessage(&msg, NULL, 0, 0))
  • {
  • TranslateMessage(&msg);
  • DispatchMessage(&msg);
  • }
  • DeleteObject(hBitmap);
  • return msg.wParam;
  • }
  • BOOL InitBitmapWindow( HINSTANCE hinstance, HBITMAP hBitmap, int nCmdshow)
  • {
  • HWND hwnd;
  • WNDCLASS wndclass;
  • wndclass.style       = CS_VREDRAW | CS_HREDRAW;
  • wndclass.lpfnWndProc = BitmapWindowWndPrco;
  • wndclass.cbClsExtra  = 0;
  • wndclass.cbWndExtra  = 0;
  • wndclass.hInstance   = hinstance;
  • wndclass.hIcon       = LoadIcon(NULL, IDI_APPLICATION);
  • wndclass.hCursor     = LoadCursor(NULL, IDC_ARROW);
  • wndclass.hbrBackground = CreatePatternBrush(hBitmap); //位图画刷
  • wndclass.lpszMenuName  = NULL;
  • wndclass.lpszClassName = szAppName;
  • if (!RegisterClass(&wndclass))
  • {
  • MessageBox(NULL, "Program Need Windows NT!" , "Error" , MB_ICONERROR);
  • return FALSE;
  • }
  • BITMAP bm;
  • GetObject(hBitmap, sizeof (bm), &bm);
  • hwnd = CreateWindowEx(WS_EX_TOPMOST,
  • szAppName,
  • szAppName,
  • WS_POPUP,
  • CW_USEDEFAULT,
  • CW_USEDEFAULT,
  • bm.bmWidth,
  • bm.bmHeight,
  • NULL,
  • NULL,
  • hinstance,
  • NULL);
  • if (hwnd == NULL)
  • return FALSE;
  • ShowWindow(hwnd, nCmdshow);
  • UpdateWindow(hwnd);
  • return TRUE;
  • }
  • LRESULT CALLBACK BitmapWindowWndPrco( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm)  static HDC s_hdcMem;
  • static HBRUSH s_hBackBrush;
  • switch (message)
  • {
  • case WM_CREATE:
  • { // 设置分层属性
  • SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
  • // 设置透明色
  • COLORREF clTransparent = RGB(0, 0, 0);
  • SetLayeredWindowAttributes(hwnd, clTransparent, 0, LWA_COLORKEY);
  • } return 0;
  • case WM_KEYDOWN:
  • switch (wParam)
  • { case VK_ESCAPE: //按下Esc键时退出
  • SendMessage(hwnd, WM_DESTROY, 0, 0);
  • return 0;
  • } break ;
  • case WM_LBUTTONDOWN: //当鼠标左键点击时可以拖曳窗口
  • PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
  • return 0;
  • case WM_DESTROY:
  • PostQuitMessage(0);
  • return 0;
  • }
  • return DefWindowProc(hwnd, message, wParam, lParm);
  • }
  • void GetWindowSize( HWND hwnd, int *pnWidth, int *pnHeight)
  • {
  • RECT rc;
  • GetWindowRect(hwnd, &rc);
  • *pnWidth = rc.right - rc.left;
  • *pnHeight = rc.bottom - rc.top;
  • }
  •