windows下不规则窗体创建的几种方法

Win32创建异形窗口 异型窗口 先来说说什么是异形窗口, 阅读详情
一、序言

  在绝大多数的Windows应用程序中,其窗体都是使用的正规正矩的矩形窗体,例如我们常用的,“ 记事本”,“扫雷”,等等。矩形窗体,具有编程实现简单,风格简洁的优点,所以在普通文档应用程序和简单小游戏中使用足矣。但在某些娱乐游戏程序中使用就略显呆板些了,这时若用 不规则窗体替代原先的矩形窗体,将会使这类程序更添情趣。典型的例子有windows 自代的Media Player,新版本的Media Player有个 控制面板的选项,选中这些面板,播放器就以选中的面板形状出现,这时的播放器比以前版本的Media Player的古老矩形界面要生动有趣的多了。 要实现不规则窗体不是太难,知道了基本原理后,你也可以创建各种有趣的不规则窗体。

   二、实现原理

  所有的 Windows 窗体都位于一个称为“region”中,窗体的大小如果超出“region”的范围,windows 会自动裁剪超出"region"范围那部分的窗体,使其不可见。所以,要创建不规则窗体有两个步骤:第一步就是创建不规则"region".第二步就是将窗体放到创建的“region”中。

  其中第二步很简单就 调用一条语句即可。在SDK中调用API函数SetWindowRgn,该函数原型如下:

int SetWindowRgn( HWND hWnd, HRGN hRgn, BOOL bRedraw );

  其中hWnd为待设置的窗体句柄,hRgn为已经创建的"region"句柄,bRedraw代表是否要重绘窗体。在MFC 中使用窗口类CWnd的成员函数int CWnd::SetWindowRgn(HRGN hRgn, BOOL bRedraw );该函数的参数意义与API中同名函数相同。

  相对与第二步,创建不规则窗体的第一步要复杂许多,并且不规则窗体越复杂,创建其"region"的过程也越复杂。接下去我们将由浅入深地介绍各种创建”region”的方法。

  在MFC中"region"对象,由CRgn类实现。CRgn的几乎每个成员函数都有同名的SDK API函数对应。

   三、简单“region”的创建

  类CRgn创建一个新的"region"的简单方法有以下几个成员函数: BOOL CRgn::CreateRectRgn( int x1, int y1, int x2, int y2 ); 创建矩形的“region”。

BOOL CRgn::CreateEllipticRgn( int x1, int y1, int x2, int y2 ); 创建圆形或椭圆形“region”。
BOOL CRgn::CreateRoundRectRgn( int x1, int y1, int x2, int y2, int x3, int y3 ); 创建圆角矩形“region”。
BOOL CRgn::CreatePolygonRgn( LPPOINT lpPoints, int nCount, int nMode ); 创建多边形“region”。

  这里以创建椭圆窗体为例,介绍椭圆窗体创建的方法。在创建椭圆“region”的CreateEllipticRgn函数中,x1,y1指椭圆所在矩形的左上角坐标,x2,y2指该矩形的右下角坐标。

  下面的代码加入到MFC对话框程序的OnInitDialog函数中,可将该对话框变成椭圆窗体:

BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
CRgn rgn;
rgn. CreateEllipticRgn(0,0,200,100);
SetWindowRgn(rgn,TRUE);
}


图一 椭圆窗体效果图

   四、作图路径法创建”region”

  使用该方法创建”region”的过程如下:

  第一步绘制所要创建的窗体形状。
 
  该步骤中使用到CDC类中的一些成员函数如下:BOOL CDC::BeginPath( );

  调用该函数后当前设备环境(DC)开始追踪 绘图的过程。

int CDC::SetBkMode( int nBkMode );

  设置绘图时的背景模式,此应用中nBkMode必须取值为TRANSPARENT 。即设置绘图时背景不发生变化。

BOOL CDC::EndPath( );

  调用该函数后当前设备环境(DC)结束追踪绘图的过程。

  开始绘图前,先调用BeginPath,然后调用SetBkMode。接下去就可调用CDC的其他绘图函数作图,例如Arc,AngleArc,LineTo,MoveTo,RoundRect,,Textout等等。绘图完毕调用EndPath().

  第二步将绘制的结果转成”region”.

  此步骤中使用SDK API函数

HRGN PathToRegion( HDC hdc );

  Hdc为作图DC的句柄, CDC类中的m_hDC成员变量可做此参数传入。示例,将下面代码加入某个按钮单击事件中,可以将当前窗体变为字符串”hello”的形状

void CTestDlg::OnTest()
{
 HRGN wndRgn;
 CClientDC dc(this);
 CFont mFont;

 if (dc.m_hDC!=NULL)
 {
  VERIFY(mFont.CreateFont(200, 50, 0, 0, FW_HEAVY, TRUE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "宋体"));

  //开始记录窗体轮廓路径
  dc.BeginPath();

  //设置背景为透明模式,这句话是必须有的。
  dc.SetBkMode(TRANSPARENT);

  CFont * pOldFont;
  pOldFont = dc.SelectObject( &mFont );
  dc.TextOut(0, 0, "Hello");

  //结束记录窗体轮廓路径
  dc.SelectObject( pOldFont );
  dc.EndPath();

  //把所记录的路径转化为窗体轮廓句柄
  wndRgn = ::PathToRegion(dc.m_hDC);

  //赋予窗体指定的轮廓形状
  this->SetWindowRgn(wndRgn, TRUE);
 }
}

  CClientDC是CDC的派生类,故此该类具有所有CDC类的成员变量和成员函数。


图二 hello形状的窗体效果图

   五、根据图像创建”region”

  此法创建不规则窗体比较复杂。首先准备一张含有目标窗体形状的图片,设置透明色即将图片中部不属于窗体形状的部分,标记成同一种颜色,例如蓝色RGB(0,0,255).程序运行后先装入图片。然后逐个扫描图片的每个像素,如这个像素不属于透明色,则在相应位置创建一个只含一个像素的“region”然后将这些小”region ”合并起来组成一个任意形状的”region”.这里将使用到CRgn的一个成员函数 :int CRgn::CombineRgn( CRgn* pRgn1, CRgn* pRgn2, int nCombineMode );

  其中pRgn1,pRgn2为要合并的两个“region”,nCombineMode为合并的方式,此应用中取RGN_OR,即两”region”全部合并去处重复部分。代码实现如下:

void SetupRegion(
 CDC *pDC, //窗体的DC指针
 CBitmap &cBitmap, //含有窗体形状的位图对象
 COLORREF TransColor //透明色
)
{
 CDC memDC;
 //创建与传入DC兼容的临时DC
 memDC.CreateCompatibleDC(pDC);

 CBitmap *pOldMemBmp=NULL;
 //将位图选入临时DC
 pOldMemBmp=memDC.SelectObject(&cBitmap);

 CRgn wndRgn;
 //创建总的窗体区域,初始region为0
 wndRgn.CreateRectRgn(0,0,0,0);

 BITMAP bit;
 cBitmap.GetBitmap (&bit);//取得位图参数,这里要用到位图的长和宽

 int y;
 for(y=0;y<=bit.bmHeight ;y++)
 {
  CRgn rgnTemp; //保存临时region

  int iX = 0;
  do
  {
   //跳过透明色找到下一个非透明色的点.
   while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) == TransColor)
    iX++;
    //记住这个起始点
    int iLeftX = iX;

    //寻找下个透明色的点
    while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) != TransColor)
     ++iX;

    //创建一个包含起点与重点间高为1像素的临时“region”
    rgnTemp.CreateRectRgn(iLeftX, y, iX, y+1);

    //合并到主"region".
    wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR);

   //删除临时"region",否则下次创建时和出错
   rgnTemp.DeleteObject();
  }while(iX GetWindow();
  pWnd->SetWindowRgn(wndRgn,TRUE);
  pWnd->SetForegroundWindow();
 }

  上述代码创建的不规则窗体中,在OnEraseBkgnd事件中绘制该位图,就可得到与该位图形状一模一样的窗体。


图三 根据位图和位图中的透明色创建的窗体效果图

   六、小结

  三种创建“region”的方法,第一种最简单,如果所需的窗体形状是简单的几何图形,这种方法最合适;第二种稍微复杂些,但是创建的窗体形状更多些;第三种方法可以创建任何在图片中画出的窗体形状,但是实现的复杂度也最高。  
Win32 API创建不规则窗口 Win32 API支持创建不规则窗口,现在很多软件使用这个技术,如:QuickTime,Windows Media Player 7等。AB使用API创建不规则窗口主要有两种方式,即矢量形状叠加(布尔运算)和位图区域两种。无论哪种方式,都可以实现上面两图的效果。在编写这样的窗口代码前,我们必须清楚要创建的窗口的形状是否复杂,如图片B的窗口很复杂,为极不规则的窗口,很 阅读详情

相关推荐

Windows不规则窗体的编程实现

一、序言   在绝大多数的Windows应用程序中,其窗体都是使用的正规正矩的矩形窗体,例如我们常用的,“记事本”,“扫雷”,等等。矩形窗体,具有编程实现简单,风格简洁的优点,所以在普通文档应用程序和简单小游戏中使用足矣。但在某些娱乐游戏程序中使用就略显呆板些了,这时若用不规则窗体替代原先的矩形窗体,将会使这类程序更添情趣。典型的例子有windows 自代的Media Player,新版本的Media Player有个控制面板的选项,选中这些面板,播放器就以选中的面板形状出现,这时的播放器比以前版本的Media Player的古老矩形界面要生动有趣的多了。 要实现不规则窗体不是太难,知道了基本原理后,你也可以创建各种有趣的不规则窗体。 二、实现原理   所有的 Windows 窗体都位于一个称为“region”中,窗体的大小如果超出“region”的范围,windows 会自动裁剪超出"region"范围那部分的窗体,使其不可见。所以,要创建不规则窗体有两个步骤:第一步就是创建不规则"region".第二步就是将窗体放到创建的“region”中。   其中第二步很简单就调用一条语句即可。在SDK中调用API函数SetWindowRgn,该函数原型如下:int SetWindowRgn( HWND hWnd, HRGN hRgn, BOOL bRedraw );   其中hWnd为待设置的窗体句柄,hRgn为已经创建的"region"句柄,bRedraw代表是否要重绘窗体。在MFC 中使用窗口类CWnd的成员函数int CWnd::SetWindowRgn(HRGN hRgn, BOOL bRedraw );该函数的参数意义与API中同名函数相同。   相对与第二步,创建不规则窗体的第一步要复杂许多,并且不规则窗体越复杂,创建其"region"的过程也越复杂。接下去我们将由浅入深地介绍各种创建”region”的方法。   在MFC中"region"对象,由CRgn类实现。CRgn的几乎每个成员函数都有同名的SDK API函数对应。 三、简单“region”的创建   类CRgn创建一个新的"region"的简单方法有以下几个成员函数: BOOL CRgn::CreateRectRgn( int x1, int y1, int x2, int y2 ); 创建矩形的“region”。 BOOL CRgn::CreateEllipticRgn( int x1, int y1, int x2, int y2 ); 创建圆形或椭圆形“region”。 BOOL CRgn::CreateRoundRectRgn( int x1, int y1, int x2, int y2, int x3, int y3 ); 创建圆角矩形“region”。 BOOL CRgn::CreatePolygonRgn( LPPOINT lpPoints, int nCount, int nMode ); 创建多边形“region”。   这里以创建椭圆窗体为例,介绍椭圆窗体创建方法。在创建椭圆“region”的CreateEllipticRgn函数中,x1,y1指椭圆所在矩形的左上角坐标,x2,y2指该矩形的右下角坐标。 ....... ....... ....... (附代码实现)

从0开始学习《Windows程序设计》:窗口、窗口!!!

一、消息框 在之前的学习中,我们通过MessageBox创建了一个消息框程序! 消息框是什么,消息框就是我们用来跟用户交流的界面!! /* ------------------------------------------------------------------- MyWindows.c -- 基本窗口模型 《Windows 程序设计(SDK)》视频教程 ----------------...

aixintianshideshouhu的博客 8619

API win32程序 不规则窗口

http://www.cnblogs.com/moodlxs/archive/2012/09/29/2708351.html

Win32API不规则窗口制作

一、前述 也许您在其他软件中经常看到下面这样的界面,除了感叹视觉设计的绚丽外,也注意到了和其他软件的不同,窗口不是正规的正方形。这就是传说中的非规则窗体,也叫多边形窗口、不规则窗体(=。=名字够俗的) 最初找这方面的资料,学习制作一个类似程序,结果发现很多资料都是说的不是很明白,或者是UI控件之类的东东,有一些范例程序还都运行不起来,经过一番折腾,发现一个共...

weixin_33895657的博客 366

Windows创建不规则窗口

        不规则窗口的实现是通过区域对象来实现,通过MFC中CRgn类创建不规则区域来实现,好吧,下面就来实现一个小精灵不规则窗口: 准备一张背景为黑色的图片    接下来在初始化对话框中加载位图,创建一个不规则区域,原理就是获取每一个像素点颜色,如果为黑色,就将他剔除。  更多精彩教程,视频教学、源码分享请加入QQ群:569268376     //加载一下位图 ...

码农 1011

在银行里软禁了一天,快疯掉了!

在银行里软禁了一天,快疯掉了! 7小时前   早上去建行,罗筹一看,有32人在等候,曾经想放弃,但最后还是坚持等下去了,因为来一次银行真的不容易。   下午,我去农行质询问题,入门口的时候,问个靓女,貌似觉得距对业务不熟悉,给我的回复也是模棱两可的,于是我还是决定乖乖排队到业务窗口咨询吧。罗筹一看,有55人在等候,我快疯掉了,好吧,我还是继续等吧。            突然发...

kleu10kleu 212

黄金:被软禁的货币之王

  “黄金拥有很多不稳定的因素,几个大国政府一直试图震荡黄金价格就是其中之一。如果你关注一下过去20年来政府对黄金的政策,就会发现在金价高达 800美元一盎司(1980年)的时候,没有政府出售黄金。那时出售应该是很合算的买卖,而且可以稳定金价。但是政府却在最低价时出售(1999年)黄金,英国政府正是如此。政府的这种在最低价抛售黄金的做法正是造成金价不稳定的因素之一。”[9.11]  199

天行健 ● 君子以自强不息 2175

C语言气泡不规则窗体

C语言气泡不规则窗体windows sdk实现

小说里的编程 【连载之二十】元宇宙里月亮弯弯

当时勾叫转入系统底层,查找系统运行日志,里面的字符全是乱码。直到后来弗兰克送来维修好的机器人,内嵌的那张纸条,写的是被超强磁场损坏机器人的维修办法。

C/C++/C#/JAVA的博客 704

付费DDoS服务——18岁以色列黑客运营“vDos”网站被捕

看到最后忍不住笑了 被自己的东西坑到简直防不胜防 少年运营“vDos”服务不正当牟利 报道称,两名18岁的少年要对15万起 DDoS攻击负责,他们基于此两年内牟利价值约60万美元的比特币。他们的服务可称为vDos,向目标网站发起DDoS攻击。vDos每起攻击的收入由30美元到200美元不等。 两名黑客是Itay Huri 和Yarden Bidani,网络安全专家Brian Kr

SAKAISON的博客 4719

《欧也妮葛朗台》的优秀读后感范文2500字

《欧也妮葛朗台》的优秀读后感范文2500字: 法国文学巨匠巴尔扎克的不朽之作《欧也妮·葛朗台》,是翻译大家傅雷的经典译注。我反复读了几次,读来读去,最喜欢的人物还是欧也妮。 当落难的高富帅遇上隐形的白富美,他们能收获爱情吗?得到幸福吗? 欧也妮出身巨富之家,却有个吝惜鬼般的父亲——葛朗台,欧也...

chixinbao0560的博客 354

华为孟晚舟:从最惨千金 到最强战士

华为25号开发布会,有何深意?从最惨千金到最强战士,孟晚舟和华为都回来了

468

重磅新书 | 《智能跃迁:人类起源、意识觉醒与文明未来》

本书是一部全景式的人类文明进化史诗,从人类早期的“脆弱与重生”揭开序幕,从蛮荒、图腾与信仰一路讲到王朝兴衰与文化诞生,接着将目光转向蒸汽机、流水线和工业革命等机械变革,再深入现代社会的信息浪潮,剖析数字时代的光与影。本书通过一场跨越数千年文明的阅读之旅,为读者梳理了人类所历经的每一次重大变革,也带来了对“人类究竟是谁、又将走向何方”的终极追问。本书既回顾了这些历史,又正视了当下的能源消耗、信息失真、社会分化等问题,更尝试着展望,当“意识延展”与“人工生命”真正出现时,人类该如何理解“生命”和“文明”。

人机与认知实验室 246

萧红二不二?人是在最日常的生活中流逝的……你窗边革命洪流过去的时候,可能你正在剥一颗鸡蛋

电影《黄金时代》里讲到了萧红怀着汪恩甲的孩子出逃。不久后,萧红主动选择流产。那个年代,不想要孩子的女性不止萧红,且避孕手段有限。 (《黄金时代》剧组供图/图) 萧红是一个很有预见性的女作家。她说:我写的东西以后不会有人看,但我的绯闻将一直流传下去。这话居然应验了。看完电影《黄金时代》,有人得出了萧红“二”、“贱”的结论。 “二”和“贱”是我们这个时代的新词,其观点却并不新鲜

tomotayuki的专栏 1272
上一篇: Web创业的10条戒律
下一篇: CWebBrowser2中获得鼠标点击后的链接地址的方法
snz
snz
博客等级 码龄25年 30粉丝 48原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值