不规则窗口和控件的封装(win32 API)——TinyDlg
2017-10-08 09:26
645 查看
不规则窗口和控件的封装(win32 API)——TinyDlg
简介:1)这里使用win32 API创建不规则窗口和控件;
2)通过设置透明像素或设置有效区域,使窗口呈现自定义的形状;
3)建议先用win32 API创建一个普通的窗口,再继续观看;
相关内容:
1)TinyDlg的介绍;
2)win32 API创建有背景的窗口;
3)设置不规则窗口的两种方式;
4)TinyDlg类间关系;
一、TinyDlg的介绍
TinyDlg可以根据提供的bmp图像,生成相应的窗口或者控件,如下图所示。
图中包含了一个窗口和三个按钮。它们根据四个bmp图像生成,且在透明部分可以被鼠标穿过。此外,对于窗体和控件可以自定义相应事件。比如,在鼠标点击黄色圆形按钮或者蓝色五角星按钮时,跳出小框显示它们各自的名字;在鼠标点击红色带X的按钮时,整个窗体可以被关闭。
二、win32 API创建有背景的窗口
在创建有背景的窗口时,主要是对窗口控制类进行设置,如下:
// 加载bmp图像,存储到HBITMAP类型的变量 m_skin = (HBITMAP)LoadImage(0, skinPath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); // 根据HBITMAP,创建HBRUSH m_brush = CreatePatternBrush(m_skin); // 设置窗口控制类中的背景 m_wcex.hbrBackground = m_brush;
这部分并没有什么特别的。不过,有一点需要注意,就是资源的释放,如:
DeleteObject(m_skin); DeleteObject(m_brush);
三、设置不规则窗口的两种方式;
1、首先需要提的一点就是,窗口的创建和按钮的创建并没有太大的区别,如下:
// 创建窗口 HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, "windowName", WS_OVERLAPPEDWINDOW, 0, 100, 200, 300, NULL, NULL, hInstance, NULL); // 使用预定义的类名"Button",创建按钮 CreateWindowEx(0, "Button", "OK", WS_VISIBLE | WS_CHILD, 0, 100, 50, 50, hWnd, NULL, hInstance, NULL);
2、创建不规则形状窗口的两种方式
1)设置透明像素
这种方式就是将某个色彩的透明度设置为0。这样,只要将背景色设置为透明,窗口就会呈现为不规则的形状。在透明的区域,鼠标也可以穿透它,对窗口后面的对象进行操作。
它大体可以分为两步。首先,创建窗口时,将窗口设置为分层窗口;然后,设置分层窗口属性,修改某个色彩对应的透明度。相关代码如下:
HWND hWnd = CreateWindowEx(WS_EX_LAYERED, wcex.lpszClassName, "windowName", WS_OVERLAPPEDWINDOW, 0, 100, 200, 300, NULL, NULL, hInstance, NULL); // 使纯白色变为透明 SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 0, LWA_COLORKEY);
像这样:
2)设置有效区域
这种方式通过为已创建好的窗口,设置有效区域,从而实现自定义形状的窗口效果。它基本上可以分成三步:1)创建区域HRGN结构;2)创建窗体;3)设置窗体有效区域。以圆形窗口为例:
HRGN region = CreateEllipticRgn(0, 0, 100, 100); HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, "windowName", WS_OVERLAPPEDWINDOW, 0, 100, 200, 300, NULL, NULL, hInstance, NULL); SetWindowRgn(hWnd, region, TRUE);
而在按这种方式创建不规则窗体时,主要是在region的创建上做一些改变。例如,根据图像的前景像素创建有效区域。此时,我们可以对图像中的每一个像素进行扫描,若某个像素不是纯白色,我们就在这个位置创建只有一个像素的区域,然后将这些前景像素对应的区域合并成我们真正想要的不规则区域,如下:
// 创建一个临时区域,然后合并到总区域region中 HRGN temp = CreateRectRgn(x, y, x + 1, y + 1); CombineRgn(region, region, temp, RGN_OR);
四、TinyDlg类间关系
这幅图展示了TinyDlg相关类的继承和组合关系。
1)TinyBase和TinyCtrl都是接口类,如下图:
2)TinyDlg和TinyCtrl
TinyDlg的成员变量中包含一个以TinyCtrl指针为元素的vector。这样,主窗口可以通过vector<TinyCtrl*>,对窗口上的创建和释放。
3)TinyBtn
TinyBtn是TinyCtrl的一个实现类。这里作为一个示例,后续自己封装其它控件时,可以作为参考。这个类除了构造函数和析构函数外,其它成员都是对于TinyCtrl(TinyBase)接口的实现。
另外,参照第三节提的两种创建不规则窗口的方式,这里在创建窗口时使用了第一种,而在创建按钮时,使用了第二种。其中差异,可以自己尝试。
四、使用示例
#include "TinyDlg.h" LRESULT CALLBACK proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch (msg) { case WM_LBUTTONDOWN: case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { POINT wndPos = { 100, 100 }; TinyDlg td(hInstance, "test", wndPos, "..\\img\\test.bmp"); POINT btnPos1 = { 0, 0 }; TinyBtn tb1(hInstance, "btnA", btnPos1, "..\\img\\btnA.bmp"); POINT btnPos2 = { 240, 300 }; TinyBtn tb2(hInstance, "btnB", btnPos2, "..\\img\\btnB.bmp"); POINT btnPos3 = {240, 0}; TinyBtn tb3(hInstance, "btnC", btnPos3, "..\\img\\btnC.bmp"); tb3.SetWndProc(proc); td.AppendCtrl(&tb1); td.AppendCtrl(&tb2); td.AppendCtrl(&tb3); td.Create(NULL); TinyDlg::MsgLoop(); return 0; }
五、说明和下载链接
正如开头简介里说的,建议先用win32 API创建一个普通的窗口,然后根据上面提到的这些,对代码进行调整。这样,可能比较有意思。
总的来说,TinyDlg做的有点粗糙。不过,好在它产生的东西跟预期是相符的。而且,它在使用上非常方便:只需要include一个TinyDlg.h,然后给出窗口的名字、位置、图像就行。
码云链接:https://gitee.com/Chieng/TinyDlg
相关文章推荐
- 用Win32 API创建不规则窗口
- 使用Win32 API创建不规则形状&带透明色的窗口
- 用Win32 API创建不规则窗口
- 学习win32 API开发7-在窗口中使用控件
- win32 api 子控件在主窗口中的位置大小
- 用Win32 API创建不规则窗口
- Win32 API 窗口控件
- win32 api CreateWindow创建窗口控件及设置字体
- 窗口启动特效,使用win32 api
- 从Win32 API封装Thread类[2]
- 学习win32 API开发3-一个窗口创建的经典步骤
- 基于Win32 SDK的树状控件属性表的封装
- 重温WIN32 API ------ 最简单的Windows窗口封装类
- 窗口启动特效,使用win32 api
- 封装 lhgDialog弹出窗口组件 为C#的api
- win32 控件的api和消息函数
- OWA或Messenger样式的信息提示窗口&mdash;&mdash;编写ASP.NET AJAX Extender控件(中):封装成服务器端控件
- Win32 API 封装类总结
- win32 sdk api 子窗口不闪烁,避免频繁闪烁,子窗口不重绘
- WIN32汇编: 9.子窗口控件