上一篇《
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):
-
-
- #include <windows.h>
-
- const char szAppName[] = "异形窗口1 MoreWindows-(http://blog.csdn.net/MoreWindows)";
-
-
-
-
-
-
-
-
- void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);
-
-
-
-
-
-
-
-
-
- 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:
- 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;
- }
-
-
- #include <windows.h>
-
- const char szAppName[] = "异形窗口1 MoreWindows-(http://blog.csdn.net/MoreWindows)";
-
-
-
-
-
-
-
-
- void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);
-
-
-
-
-
-
-
-
-
- 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:
- 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;
- }
运行结果如下:
现在总结下异形窗口的创建,先通过创建位图画刷来做窗口的背景画刷,再通过SetWindowLong为窗体加上WS_EX_LAYERED属性,然后使用SetLayeredWindowAttributes指定窗口的透明色来完成窗口形状的调整。为了支持鼠标的拖曳,在WM_LBUTTONDOWN消息中作了特殊处理,使得异形窗口可以像普通窗口一样在屏幕上移动。
本篇程序中的异形窗口的大小是无法设置的,只能和位图一样。下一篇《Windows界面编程第四篇 异形窗体 高富帅版》将介绍窗口大小可以指定的异形窗口。欢迎继续浏览。
本文配套程序下载地址为:http://download.csdn.net/download/morewindows/4966815
转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8451633