Windows界面编程第四篇 异形窗体 高富帅版

本文详细讲解了创建异形窗体的方法,包括使用WS_EX_LAYERED属性、位图作为背景以及指定透明色的技巧。通过缩放位图至窗口大小,实现了窗口背景的自贴图,提高了程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

    上一篇《Windows界面编程第三篇 异形窗体 普通版》介绍了异形窗口(异形窗体)的创建,其主要步骤为——先通过创建位图画刷来做窗口的背景画刷,再通过SetWindowLong为窗体加上WS_EX_LAYERED属性,然后使用SetLayeredWindowAttributes指定窗口的透明色来完成窗口形状的调整。并且为了使异形窗口支持鼠标的拖曳,在WM_LBUTTONDOWN消息中作了特殊处理。

然后在下图中有非常相似的两个异形窗体,只不过,左边的异形窗体小,右边的异形窗体大。这个可以怎么实现了?

 

先通过其它软件来缩放位图,然后再让程序加载这种方式来指定异形窗口的大小。这种方法虽然可以完成任务,但毕竟太OUT了。

由《Windows界面编程第一篇位图背景与位图画刷》可以想到不用位图画刷,而直接在窗口背景绘制时使用StretchBlt来缩放位图至窗口大小,这样就可以达到指定窗口大小的功能。

由于异形窗口运行后无法通过鼠标来动态调整窗口大小,因此可以窗口初始化时就可以先缩放位图并加载到一个缓冲HDC中,然后再在窗口背景绘制时使用BitBlt来贴图。这种做法只需要缩放位图一次,在每次背景绘制时只须拷贝位图,对程序的效率会有提高。下面给出完整源代码(下载地址:http://download.youkuaiyun.com/download/morewindows/4966819

//   异形窗口2  在WM_ERASEBKGND消息中自贴图//By MoreWindows-(http://blog.youkuaiyun.com/MoreWindows)#include <windows.h>const char szAppName[] = "异形窗口2 MoreWindows-(http://blog.youkuaiyun.com/MoreWindows)";/* * 函数名称: GetWindowSize * 函数功能: 得到窗口的宽高 * hwnd      窗口句柄 * pnWidth   窗口宽 * pnHeight  窗口高*/void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);/* * 函数名称: InitBitmapWindow * 函数功能: 位图窗口初始化 * hinstance 进程实例 * nWidth    窗口宽 * nHeight   窗口高 * nCmdshow  显示方式-与ShowWindow函数的第二个参数相同*/BOOL InitBitmapWindow(HINSTANCE hinstance, int nWidth, int nHeight, int nCmdshow);// 位图窗口消息处理函数LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm);          HBITMAP  g_hBitmap;int APIENTRY WinMain(HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPSTR     lpCmdLine,                     int       nCmdShow){    //先创建一个无背影画刷窗口, //然后在WM_CREATE中并指定透明颜色, 缩放位图后加载至s_hdcMem中. //最后在WM_ERASEBKGND中用s_hdcMem贴图即可 g_hBitmap = (HBITMAP)LoadImage(NULL, "Kitty.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); if (g_hBitmap == NULL) {  MessageBox(NULL, "位图加载失败", "Error", MB_ICONERROR);  return 0; } // 设置异形窗口大小 BITMAP bm; GetObject(g_hBitmap, sizeof(bm), &bm); int nWindowWidth = bm.bmWidth; int nWindowHeight = bm.bmHeight + 100; //拉高100高度 if (!InitBitmapWindow(hInstance, nWindowWidth, nWindowHeight, nCmdShow))  return 0; MSG msg; while (GetMessage(&msg, NULL, 0, 0)) {  TranslateMessage(&msg);  DispatchMessage(&msg); } DeleteObject(g_hBitmap); return msg.wParam;}BOOL InitBitmapWindow(HINSTANCE hinstance, int nWidth, int nHeight, 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 = (HBRUSH)GetStockObject(NULL_BRUSH);//窗口背影画刷为空 wndclass.lpszMenuName  = NULL; wndclass.lpszClassName = szAppName;  if (!RegisterClass(&wndclass)) {  MessageBox(NULL, "Program Need Windows NT!", "Error", MB_ICONERROR);  return FALSE; }  hwnd = CreateWindowEx(WS_EX_TOPMOST,      szAppName,      szAppName,       WS_POPUP,      CW_USEDEFAULT,       CW_USEDEFAULT,       nWidth,       nHeight,      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; //放置缩放后的位图  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);      //   缩放位图   // 加载位图到hdcTemp中   HDC hdc = GetDC(hwnd);   HDC hdcTemp = CreateCompatibleDC(hdc);   SelectObject(hdcTemp, g_hBitmap);   // 得到窗口大小   int nWidth, nHeight;   GetWindowSize(hwnd, &nWidth, &nHeight);   // 创建与窗口大小相等且能容纳位图的HDC - s_hdcMem   s_hdcMem = CreateCompatibleDC(hdc);   HBITMAP hbmp = CreateCompatibleBitmap(hdc, nWidth, nHeight);   SelectObject(s_hdcMem, hbmp);   // 将原位图缩放到窗口大小   BITMAP bm;   GetObject(g_hBitmap, sizeof(bm), &bm);   StretchBlt(s_hdcMem, 0, 0, nWidth, nHeight, hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);      // 释放资源   DeleteDC(hdcTemp);   ReleaseDC(hwnd, hdc);  }  return 0;   case WM_KEYDOWN:   switch (wParam)  {  case VK_ESCAPE: //按下Esc键时退出   SendMessage(hwnd, WM_DESTROY, 0, 0);   return TRUE;  }  break;  case WM_LBUTTONDOWN: //当鼠标左键点击时可以拖曳窗口  PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);   return TRUE;     case WM_ERASEBKGND: //在窗口背景中直接贴图  {   HDC hdc = (HDC)wParam;   int nWidth, nHeight;   GetWindowSize(hwnd, &nWidth, &nHeight);   BitBlt(hdc, 0, 0, nWidth, nHeight, s_hdcMem, 0, 0, SRCCOPY);   return TRUE;  } case WM_DESTROY:  DeleteDC(s_hdcMem);  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;}

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

 

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

1.WS_EX_LAYERED属性

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

3.指定透明色

 

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

 

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

 

转载请标明出处,原文地址:http://blog.youkuaiyun.com/morewindows/article/details/8451638

欢迎关注微博:http://weibo.com/MoreWindows

 


 

           

给我老师的人工智能教程打call!http://blog.youkuaiyun.com/jiangjunshow
这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值