本期将自己从底层中抽离出来,来搞点UI设计相关的,毕竟UI是本人强项(矮子里面拔高个吧)。你的UI界面是不是都是矩形框,你有想过其他形状的界面吗?是不是感觉计算机应用就应该是方方正正的。答案肯定是NO。异形窗体就能打破此限制,异形可不是那个电影里的怪物,异形是形状不规则的意思。在聊异形之前我们先看看如何创建常规的窗体,这里不使用MFC,而是Windows自带api:CreateWindow,本节中其他的api都是围绕这个api展开的。

目录

一、CreateWindow参数介绍

二、WNDCLASS类

三、实现异形的方法

四、总结

demo


一、CreateWindow参数介绍

#define CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\

参数

含义

lpClassName

1. 窗口类名称,可以是一个指向 NULL 结束的字符串或一个整型数值
2. 如果是字符串,它指定了窗口的类名。这个类名可以是任何用函数 RegisterClass 注册的类名,或是任何预定义的控制类名
3. 如是一个整型量,它是由此前调用 theGlobalAddAtom 函数产生的全局量。这个小于 0xC000 的 16 位数必须是 lpClassName 参数字的低 16 位,该参数的高位必须是 0

lpWindowName

1. 窗口标题,一个指向 NULL 结束的字符串指针
2. 如果窗口风格指定了标题条,由 lpWindowName 指向的窗口标题将显示在标题条上
3. 当使用 Createwindow 函数来创建控制例如按钮,选择框和静态控制时,可使用 lpWindowName 来指定控制文本

dwStyle

指定创建窗口的风格(详见下方↓)

x

1. 指定窗口的初始水平位置(x 坐标)
2. 对一个层叠或弹出式窗口,x 参数是屏幕坐标系的窗口的左上角的初始 x 坐标
3. 对于子窗口,x 是子窗口左上角相对父窗口客户区左上角的初始 x 坐标
4. 如果该参数被设为 CW_USEDEFAULT 则系统为窗口选择缺省的左上角坐标并忽略 y 参数,CW_USEDEFAULT 只对层叠窗口有效,如果为弹出式窗口或子窗口设定,则 x 和 y 参数被设为零。

y

1. 指定窗口的初始垂直位置(y 坐标)
2. 对一个层叠或弹出式窗口,y 参数是屏幕坐标系的窗口的左上角的初始 y 坐标
3. 对于子窗口,y 是子窗口左上角相对父窗口客户区左上角的初始 y 坐标
4. 对于列表框,y 是列表框客户区左上角相对父窗口客户区左上角的初始 y 坐标
5. 如果层叠窗口是使用 WS_VISIBLE 风格位创建的并且 x 参数被设为 CW_USEDEFAULT,则系统将忽略 y 参数

nWidth

1. 以设备单元指明窗口的宽度
2. 对于层叠窗口,nWidth 的值或是屏幕坐标的窗口宽度或是 CW_USEDEFAULT
3. 若 nWidth 是 CW_USEDEFAULT,则系统为窗口选择一个默认的高度和宽度(默认宽度为从初始 x 坐标开始到屏幕的右边界,缺省高度为从初始 y 坐标开始到目标区域的顶部。),CW_USEDEFAULT 只对层叠窗口有效,如果为弹出式窗口和子窗口设定 CW_USEDEFAULT 标志则 nWidth 和 nHeight 被设为零

nHeight

1. 以设备单元指明窗口的高度
2. 对于层叠窗口,nHeight 是屏幕坐标的窗口宽度
3. 若 nWidth 被设为 CW_USEDEFAULT,则系统忽略 nHeight 参数,自动为 nWidth 和 nHeight 设置默认参数

hWndParent

1. 指向被创建窗口的父窗口或所有者窗口的句柄
2. 若要创建一个子窗口或一个从属窗口,需提供一个有效的窗口句柄
3. 创建一个单纯的消息窗口,可以提供 HWND_MESSAGE 或提供一个己存在的消息窗口的句柄

hMenu

1. 指向窗口菜单句柄,或依据窗口风格指明一个子窗口标识
2. 对于层叠或弹出式窗口,hMenu 指定窗口使用的菜单:如果使用了菜单类,则 hMenu 可以为 NULL
3. 对于子窗口,hMenu 指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的

hInstance

与窗口相关联的模块实例的句柄

lpParam

1. 指向一个值的指针,该值传递给窗口 WM_CREATE 消息。该值通过在 IParam 参数中的 CREATESTRUCT 结构传递
2. 如果应用程序调用 CreateWindow 创建一个 MDI 客户窗口,则 lpParam 必须指向一个 CLIENTCREATESTRUCT 结构

    转载来自: CreateWindow函数详解_lixingyun123的博客-CSDN博客_createwindow

这其中第三个参数和倒数第二个参数比较重要: dwStyle与hInstance。其中dwStyle为窗口的形式,我目前接触到的就是弹窗和可嵌入窗体。hInstance为窗口句柄,必须传入。

dwStyle:

    WS_BORDER:创建一个单边框的窗口。WS_CAPTION:创建一个有标题框的窗口(包括WS_BODER风格)。WS_CHIlD:创建一个子窗口。这个风格不能与WS_POPUP风格合用。WS_CHLDWINDOW:与WS_CHILD相同。WS_CLIPCHILDREN:当在父窗口内绘图时,排除子窗口区域。在创建父窗口时使用这个风格。WS_CLlPBLINGS;排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到WM_PAINT消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口。如果未指定WS_CLIPSIBLINGS风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口。WS_DISABLED:创建一个初始状态为禁止的子窗口。一个禁止状态的窗日不能接受来自用户的输入信息。WS_DLGFRAME:创建一个带对话框边框风格的窗口。这种风格的窗口不能带标题条。WS_GROUP:指定一组控制的第一个控制。这个控制组由第一个控制和随后定义的控制组成,自第二个控制开始每个控制,具有WS_GROUP风格,每个组的第一个控制带有WS_TABSTOP风格,从而使用户可以在组间移动。用户随后可以使用光标在组内的控制间改变键盘焦点。WS_HSCROLL:创建一个有水平滚动条的窗口。WS_ICONIC:创建一个初始状态为最小化状态的窗口。与WS_MINIMIZE风格相同。WS_MAXIMIZE:创建一个具有最大化按钮的窗口。该风格不能与WS_EX_CONTEXTHELP风格同时出现,同时必须指定WS_SYSMENU风格。WS_OVERLAPPED:产生一个层叠的窗口。一个层叠的窗口有一个标题条和一个边框。与WS_TILED风格相同。WS_OVERtAPPEDWINDOW:创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXMIZEBOX风格的层叠窗口,与WS_TILEDWINDOW风格相同。WS_POPUP;创建一个弹出式窗口。该风格不能与WS_CHLD风格同时使用。WS_POPUWINDOW:创建一个具有WS_BORDER,WS_POPUP,WS_SYSMENU风格的窗口,WS_CAPTION和WS_POPUPWINDOW必须同时设定才能使窗口某单可见。WS_SIZEBOX:创建一个可调边框的窗口,与WS_THICKFRAME风格相同。WS_SYSMENU:创建一个在标题条上带有窗口菜单的窗口,必须同时设定WS_CAPTION风格。WS_TABSTOP:创建一个控制,这个控制在用户按下Tab键时可以获得键盘焦点。按下Tab键后使键盘焦点转移到下一具有WS_TABSTOP风格的控制。WS_THICKFRAME:创建一个具有可调边框的窗口,与WS_SIZEBOX风格相同。WS_TILED:产生一个层叠的窗口。一个层叠的窗口有一个标题和一个边框。与WS_OVERLAPPED风格相同。WS_TILEDWINDOW:创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU MS_THICKFRAME.WS_MINIMIZEBOX,WS_MAXMIZEBOX风格的层叠窗口。与WS_OVERLAPPEDWINDOW风格相同。WS_VISIBLE:创建一个初始状态为可见的窗口。WS_VSCROLL:创建一个有垂直滚动条的窗口。

如果想要一个弹窗,将dwStyle设置为WS_POPUP。如果想要一个可嵌入内容的窗口,设置为WS_OVELAPPEDWINDOW。

hInstance为传入的窗口句柄,一般在WinMain入口传入。

二、WNDCLASS类

在正式创建窗体前,我们需要将其中一些固定参数设定好,也称注册。类中的数据结构如下:

typedef struct tagWNDCLASSW {UINT        style;WNDPROC     lpfnWndProc;int         cbClsExtra;int         cbWndExtra;HINSTANCE   hInstance;HICON       hIcon;HCURSOR     hCursor;HBRUSH      hbrBackground;LPCWSTR     lpszMenuName;LPCWSTR     lpszClassName;
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;

成员解析:

成员 含义
style 指定窗口类型,各种“类风格”可以使用按位或操作符组合起来
IpfnWndProc 指定窗口过程(必须是回调函数)
cbClsExtra 预留的额外空间,一般为0
cbWndExtra 预留的额外空间,一般为0
hInstance 应为程序的实例句柄
hIcon 为所有基于该窗口类的窗口设定一个图标
hCursor 为所有基于该窗口类的窗口设定一个鼠标指针
hbrBackground 指定窗口背景色
IpszMenuName 指定窗口菜单
IpszClassName 指定窗口类名

style成员如下:

类风格 含义
CS_VREDRAW 移动或者调整窗口的高度(垂直方向)时,重绘整个窗口
CW_HREDRAW 移动或者调整窗口的宽度(水平方向)时,重绘整个窗口
CS_DBLCLKS 当用户光标在窗口内双击时,允许发送双击消息给窗口过程
CS_OWNDC 给予每一个窗口实例分配一个唯一的DC(注意,尽管这样很方便,但它必须慎重使用,因为每一个DC大约要占800个字节的内存)
CS_CLASSDC 该窗口类的所有窗口实例都共享一个窗口类DC
CS_PARENTDC 1.将子窗口的裁剪区域设置到父窗口的DC中去,这样子窗口便可以在父窗口上绘制自身。(注意:这是子窗口从系统缓存中获取DC,而不是使用父窗口的DC。)
2.指定该分格可以提高系统性能
CS_NOCLOSE 禁止系统菜单的关闭选项
CS_SAVEBITS 1.以位图形式保存被该窗口遮挡的屏幕部分,当该窗口移动以后,系统便可以用该保存的位图恢复屏幕移动的相应部分,从而系统不用向被该窗口遮挡的窗口发送WM_PAINT消息。
2.该特性对于菜单类型的窗口比较合适,因为它通常是简短的显示一下之后便消失。
3.设置该特性将增加显示该窗口的时间,因为它通常要先分配保存位图的内存。
CS_BYTEALIGNCLIENT 在字节边界上(x方向上)定位窗口的用户区域的位置
CS_BYTEALIGNWINDOW 在字符边界上(x方向上)定位窗口的位置
CS_GLOBALCLASS 1.当调用CreateWindow或CreateWindowEx函数来创建窗口时允许它的hInstance参数和注册窗口类时传递给RegisterClass的hInstace参数不同.
2.如果不指定该风格,则这两个hInstace必须相同

这些设置要在CreateWindow前,并且最好写一个判断是否设置成功的函数,保险些。(其实我也是看其他人这么写的哈哈哈哈哈)!

IpfnWndProc必须是一个回调函数,非常重要,非常重要,非常重要!也就是必须这样写:

wc.lpfnWndProc = WndProc;

关于回调函数可以看这:

C++学习之回调函数_HAH-M的博客-CSDN博客_c++ 回调函数

一般将需要嵌入窗体的内容、对窗体的操作写在WndProc中。给他传入的参数也需要带上消息类。

嵌入内容时需要获得窗体的大小,这里使用如下代码即可:

RECT rc;
GetClientRect(hWnd, &rc);

传出来的rc即是窗体尺寸,为RECT结构体,结构体内容如下:

typedef struct tagRECT
{LONG    left;LONG    top;LONG    right;LONG    bottom;
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

三、实现异形的方法

别忘了我们的主题是异形窗体,这个困扰了我一段时间的问题,没想到如此简单。。。来,展示。

首先,我们要确定是用已有的形状实现还是散点实现,已有的形状无非就是圆角矩形、椭圆这种,在设计上不是特别出彩。散点实现就很酷了,在CV中,有一种标注数据的方式是polygon,就是散点围成一个圈,在C++函数里竟然也有这个东西,百闻不如一见啊。

在afxwin.h中,有CRgn类,我们来看看其中都有什么方法:

class CRgn : public CGdiObject
{DECLARE_DYNAMIC(CRgn)public:static CRgn* PASCAL FromHandle(HRGN hRgn);operator HRGN() const;// ConstructorsCRgn();BOOL CreateRectRgn(int x1, int y1, int x2, int y2);BOOL CreateRectRgnIndirect(LPCRECT lpRect);BOOL CreateEllipticRgn(int x1, int y1, int x2, int y2);BOOL CreateEllipticRgnIndirect(LPCRECT lpRect);BOOL CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode);BOOL CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts,int nCount, int nPolyFillMode);BOOL CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);BOOL CreateFromPath(CDC* pDC);BOOL CreateFromData(const XFORM* lpXForm, int nCount,const RGNDATA* pRgnData);// Operationsvoid SetRectRgn(int x1, int y1, int x2, int y2);void SetRectRgn(LPCRECT lpRect);int CombineRgn(const CRgn* pRgn1, const CRgn* pRgn2, int nCombineMode);int CopyRgn(const CRgn* pRgnSrc);BOOL EqualRgn(const CRgn* pRgn) const;int OffsetRgn(int x, int y);int OffsetRgn(POINT point);int GetRgnBox(LPRECT lpRect) const;BOOL PtInRegion(int x, int y) const;BOOL PtInRegion(POINT point) const;BOOL RectInRegion(LPCRECT lpRect) const;int GetRegionData(LPRGNDATA lpRgnData, int nCount) const;// Implementationvirtual ~CRgn();
};

看到CreatePolygonRgn就懂了,我们来试着使用它:

 POINT pts[5] ={{ 200, 0},{ 0, 160 },{ 120, 400 },{ 285, 400 },{ 400, 160 }};//五边形散点CRgn wndRgn;wndRgn.CreatePolygonRgn(pts,5, WINDING);//wndRgn.CreateEllipticRgn(rcClient.left, 0, rcClient.right, rcClient.bottom);SetWindowRgn(hWndMain, wndRgn, true);

声明一个CRgn的wndRgn,然后将其执行CreatePolygonRgn方法,然后SetWindowRgn(hWndMain, wndRgn, true);

将消息放入循环体中循环:

 while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}

大功告成:

四、总结

windows SDK有很多好用的、好玩的东西等我们去发现!异形窗体可以作为趣味的弹窗来给产品增加活力和乐趣。我们将设计好的内容放入html中,再通过ie网页打开,这种实现方式不用带来额外的开销,相比较于内嵌ie内核与QT等异形实现,可谓是真正的轻装上阵了。

demo

后续贴出源代码,请等待。

CreateWindow创建异形窗口(不规则窗口) - WINDOWS API 第三弹 异形窗口。相关推荐

  1. C#通过Windows API捕获窗,获取窗口文本(FindWindow、GetWindowText),附录:Windows窗口消息大全、Windows API大全

    文章目录 一.前言 二.使用Spy++工具分析窗口 三.C#通过Windows API捕获窗口,获取窗口文本 四.附录:Windows窗口消息 五.Windows API大全 1.API之网络函数 2 ...

  2. Windows API(三)线程

    Windows API笔记(一)内核对象 Windows API笔记(二)进程和进程间通信.进程边界 Windows API笔记(三)线程和线程同步.线程局部存储 Windows API笔记(三)线程 ...

  3. Windows Phone 7 自定义弹出窗口

    Windows Phone内置的MessageBox弹出窗口局限性太大,不能满足各种个性化的弹出窗口的需求,即使使用第三方的控件库也会有一些局限性,又或者封装的东西太多了,那么这时候就需要自己去根据自 ...

  4. CreateFile | ReadFile | WriteFile - WINDOWS API 第五弹 C++创建任意格式的文件用于读取和写入。

    Windows api系列第五弹强烈来袭,本期介绍Windows上c++有关文件创建.读取和写入的api:CreateFile.ReadFile.WriteFile. 目录 一.CreateFile ...

  5. vc 只有顶级窗口可以弹出窗口_如何在Mac上允许弹出窗口

    通常,我们尝试避免弹出窗口,但是有时您需要让它们通过.下面这样做的方法. 由于浏览器阻止了弹出窗口,您是否在macOS上遇到网站问题?幸运的是,您可以在计算机上的主要浏览器(例如Safari,Chro ...

  6. php屏蔽弹出窗口,可以不被浏览器拦截的弹出窗口JS代码

    转载: 一个强制弹出窗口的JavaScript类:ForceWindow 一个可以不被广告拦截器拦截的弹出窗口 ForceWindow.iclass.js代码如下(使用.讲解.相关说明全部在注释中): ...

  7. Beep() - WINDOWS API 第六弹 C++调用蜂鸣器播放简单的曲调。

    今天搞个好玩的东西,windows上自带的蜂鸣器,调用beep()函数即可实现,它位于windows.h中,话说目前我们听到的歌曲似乎都是来自机器,来自纯乐器的声音很奢侈,所以你对机器发出的音色一定不 ...

  8. Delphi 下用Windows API 创建窗体

    Delphi 下用Windows API 创建窗体 副标题: 作者:佚名 文章来源:大富翁 点击数:119 更新时间:2005-2-25     Delphi 下用Windows API 创建窗体 / ...

  9. swing退出子窗口事件_如何创建有效的退出弹出窗口?

    如何创建有效的退出弹出窗口? 下面的退出弹出窗口为电子邮件列表增加了4153个订阅者: 这个提供折扣的弹出窗口,帮助Storiarts在60天之内挽回了96个弃单客户,从而额外创造了5000美元的销售 ...

最新文章

  1. window下实现在线预览功能
  2. .NET Core 以及与 .NET Framework的关系
  3. Linux技巧:自动挂载UDF光盘的技巧
  4. Opencv显示创建Mat对象的七种方式
  5. MySQL Hardware--FIO压测
  6. 出现503错误 怎么办
  7. 信号与系统sa函数求积分_瞎扯数学分析微积分(1~4)
  8. javascript访问frame,iframe框架和href的定向
  9. 计算机专业知识综合应用题,2015年计算机综合考研及解析之综合应用题(一)...
  10. debug安装包安装在别人手机上闪退?
  11. 福建农林大学外事处界面设计
  12. 数学-盲点题:九个点用四条直线连起来
  13. 【Android实习】20场面试斩获大厂offer,我学会了什么
  14. wordpress 数据库_如何一键优化您的WordPress数据库
  15. 一年级上册计算机教学计划,人教版数学一年级上册教学计划
  16. for循环里面的break;和continue;语句
  17. [ STK ](十一)STK 中搭建铱星星座
  18. unity安装问题:启动编译器时出错:许可证无效
  19. 图像处理之平滑滤波、高斯滤波和中值滤波
  20. 小米盒子的远程安装实现

热门文章

  1. 教你如何实现一步完成线上线下一体化的购物体验
  2. java的choice什么意思_choice是什么意思_choice的翻译_音标_读音_用法_例句_爱词霸在线词典...
  3. 如何用C++实现一个简易数据库(十一)
  4. FLASH 中的场景,图层以及层的理解
  5. 长期稳定的搬砖项目——steam搬砖
  6. 下一代区块链底层基础设施是什么样的?——Nervos@2019 杭州区块链周
  7. 京东宣布涨薪,两年内将员工平均年薪从14薪涨到16薪!
  8. FuzzFactory: Domain-Specific Fuzzing with Waypoints
  9. 悟空CRM (基于jfinal+vue+ElementUI的前后端分离CRM系统)
  10. 别等了!下一代操作系统Windows 10X,彻底凉凉了