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

2023-12-21 11:40

本文主要是介绍Windows界面编程第四篇 异形窗体 高富帅版,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

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

 

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

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

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

//   异形窗口2  在WM_ERASEBKGND消息中自贴图
//By MoreWindows-(http://blog.csdn.net/MoreWindows)
#include <windows.h>
const char szAppName[] = "异形窗口2 MoreWindows-(http://blog.csdn.net/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_hdcMems_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.csdn.net/download/morewindows/4966819

 

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

 

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

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

 


 

这篇关于Windows界面编程第四篇 异形窗体 高富帅版的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/519851

相关文章

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

在 Windows 上部署 gitblit

在 Windows 上部署 gitblit 在 Windows 上部署 gitblit 缘起gitblit 是什么安装JDK部署 gitblit 下载 gitblit 并解压配置登录注册为 windows 服务 修改 installService.cmd 文件运行 installService.cmd运行 gitblitw.exe查看 services.msc 缘起

Windows如何添加右键新建菜单

Windows如何添加右键新建菜单 文章目录 Windows如何添加右键新建菜单实验环境缘起以新建`.md`文件为例第一步第二步第三步 总结 实验环境 Windows7 缘起 因为我习惯用 Markdown 格式写文本,每次新建一个.txt后都要手动修改为.md,真的麻烦。如何在右键新建菜单中添加.md选项呢? 网上有很多方法,这些方法我都尝试了,要么太麻烦,要么不凑效

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空

Windows下Nginx的安装及开机启动

1、将nginx-1.16.1.zip解压拷贝至D:\web\nginx目录下。 2、启动Nginx,两种方法: (1)直接双击nginx.exe,双击后一个黑色的弹窗一闪而过。 (2)打开cmd命令窗口,切换到nginx目录下,输入命令 nginx.exe 或者 start nginx ,回车即可。 3、检查nginx是否启动成功。 直接在浏览器地址栏输入网址 http://lo