如何使用MFC编写自定义UI界面【附高仿QQ 2014登陆界面范例程序】
来源:互联网 发布:php模拟ajax请求 编辑:程序博客网 时间:2024/05/02 11:18
地址: http://blog.csdn.net/hujkay
作者:Jekkay Hu(34538980@qq.com)
关键词:MFC, 编写异行窗体,自定义UI控件,VC++,异形控件,高仿QQ登陆界面, 截取QQ密码,QQ钓鱼
时间: 2014/4/12
1. 概述
在开发客户端程序的时候,稍微有点正常审美观的人都会对微软的默认UI界面表示深恶痛绝,连最简单的默认程序ICON都用那么低的像素的ICON,质量差的令人发指啊。所以,但凡好一点的软件,都会去找一些界面库,或者干脆自己写个界面库来美化一下用户交互界面,免得用户吐血暴毙。网络上有许多界面库,其中不少是免费的,这里推荐一款我经常用的界面库:Skinsharp。这个界面库,动态编译版本是免费的,静态编译版本是收费的,当然网上肯定有不少破解版本,但是为了中国软件的前途,大家还是稍微掏点钱买正版吧,有点扯远了,拽回来!使用第三方提供的界面库固然能美化程序界面,但有的程序需要一些比较特殊的异形界面,那么这些界面库就很难满足需求了,这样我们就必须自己去编写UI插件了。
2. 编写自定义UI界面
编写自定义UI插件,涉及到三方面:形状,界面绘制和事件响应。下面分别对着三个方面进行详细阐述一下。2.1 形状
我们先随便找个软件,比如金山毒霸吧,如下:界面是不是很酷,相比Windows自身的界面是不是感觉是天上天下之别。而我们看到这些好看的界面形状都不是方方正正,全是不规则的形状,所以我们第一步要做的就是设定窗口的形状。微软提供了一个API函数,可以设定窗体的形状:
int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw);
其中HRGN是一个用于表示形状的对象,我们可以用另外一个封装好的类CRGN来进行操作。该CRGN提供了许多非常友好的接口函数,比如添加一块区域,减少一块区域等,具体的可以查看一下官网的MSDN,下面列举一些常用的操作。
a. 创建一个矩形的区域 CRgnrgn; rgn.CreateRectRgn(0, 0, nWidth,nHeight); b. 在当前的区域中添加一块的区域 rcXor.SetRect(0, 0, 1, 2); rgn_xor.CreateRectRgn(0, y, border_offset[y], y + 1); rgn.CombineRgn(&rgn, &rgn_xor, RGN_OR); c. 在当前的区域中只取共同区域 rcXor.SetRect(0, 0, 1, 2); rgn_xor.CreateRectRgn(0, y, border_offset[y], y + 1); rgn.CombineRgn(&rgn, &rgn_xor, RGN_AND); d. 在当前的区域中异或一块的区域 rcXor.SetRect(0, 0, 1, 2); rgn_xor.CreateRectRgn(0, y, border_offset[y], y + 1); rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR);
区域创建了好了之后,就设定一下窗体的区域:
SetWindowRgn((HRGN)rgn, TRUE);
下面一段完整的代码,供大家参考一下:
CDC* pDC = GetDC(); CRectrc; GetWindowRect(rc); rc.OffsetRect(-rc.left, -rc.top); CRgnrgn; rgn.CreateRectRgn(0, 0, rc.Width(), rc.Height()); CRgnrgn_xor; CRectrcXor; for (int y = 0; y < nSize; ++y) { rcXor.SetRect(0, y, border_offset[y], y + 1); rgn_xor.CreateRectRgn(0, y, border_offset[y], y + 1); rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR); rgn_xor.DeleteObject(); } for (int y = 0; y < nSize; ++y) { rcXor.SetRect(rc.right - border_offset[y], y, rc.right, y + 1); rgn_xor.CreateRectRgn(rc.right - border_offset[y], y, rc.right, y + 1); rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR); rgn_xor.DeleteObject(); } for (int y = 0; y < nSize; ++y) { rcXor.SetRect(0, rc.bottom - y - 1, border_offset[y], rc.bottom - y); rgn_xor.CreateRectRgn(0, rc.bottom - y - 1, border_offset[y], rc.bottom - y); rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR); rgn_xor.DeleteObject(); } for (int y = 0; y < nSize; ++y) { rcXor.SetRect(rc.right - border_offset[y], rc.bottom - y - 1, rc.right, rc.bottom - y); rgn_xor.CreateRectRgn(rc.right - border_offset[y], rc.bottom - y - 1, rc.right,rc.bottom - y); rgn.CombineRgn(&rgn, &rgn_xor, RGN_XOR); rgn_xor.DeleteObject(); } SetWindowRgn((HRGN)rgn, TRUE); m_Rgn.DeleteObject(); m_Rgn.Attach(rgn.Detach()); ReleaseDC(pDC);
2.2 界面绘制
界面绘制是繁琐的工作,推荐使用Gdiplus库来支持一下,在stdafx.h加入如下的代码,将其包含进来即可:#include <gdiplus.h> using namespace Gdiplus; #pragma comment(lib, "gdiplus.lib")自定义绘制界面需要重载一下主要下面的几个函数:
绘制客户区域的函数:ON_WM_PAINT()绘制非客户区域的函数:ON_WM_NCPAINT()背景擦除函数:ON_WM_ERASEBKGND()限定窗体大小的函数:ON_WM_GETMINMAXINFO()一般来说,自绘窗体控件最主要的就是ON_WM_PAINT()方法,大部分时间都耗在就是在里面,这个活比较细致,像素一个一个地调,没有耐心的人估计会砸电脑。
在这里有技巧需要提一下,如果绘制的界面插件老一闪一闪的,可以先在内存里面创建一块画板,在里面画好了之后然后在显示到界面上,可参考如下的代码:
CRectrcClient; GetClientRect(&rcClient); CPaintDCdc(this); CDC MemDC; MemDC.CreateCompatibleDC(&dc); CBitmap memBmp; memBmp.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height()); CBitmap *pOldmap = MemDC.SelectObject(&memBmp); DrawImageStyle(MemDC, rcClient); dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &MemDC, 0, 0, SRCCOPY); MemDC.SelectObject(pOldmap); MemDC.DeleteDC();
2.3 事件
事件是指根据用户的交互动作而触发某些动作,主要是鼠标和键盘两种。我这里主要介绍下鼠标事件,鼠标事件可分为:移动,按下,弹起,移入,移出,单击,双击和滚动。在创建自定义创建窗口的时候,千万不要重载单击和双击的事件,这是非常不好的习惯,而且容易引发各种问题,最好的办法是自己在按下按钮的时候模拟单击或者双击的信息,所以一般来说,重载下面几个方法即可:ON_WM_MOUSEMOVE() ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave) ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_LBUTTONDBLCLK()事件和窗体绘制有着紧密的关系,比如一个按钮,用户鼠标移入时是一种状态,按下时又是一种状态,弹起式又是一状态。因此,在绘制窗体时,要根据当前的用于的交互状态绘制不同的形态,非常考验一个人的变成能力。
3. 小结
绘制自定义UI插件是个细活,必须如加工艺术品一样有耐心,所以我但凡见到做UI插件的同仁,都心生佩服。周末闲来无事,根据其他高手的一些代码,高仿了一下QQ的登陆界面,很酷吧,呵呵。
高仿的QQ 2014登陆程序的下载地址:http://download.csdn.net/user/hujkay
别干坏事啊~~~
胡杨, Jekkay Hu
2014/4/12
0 0
- 如何使用MFC编写自定义UI界面【附高仿QQ 2014登陆界面范例程序】
- UI界面编写(仿QQ聊天界面)
- 使用skin++进行MFC界面美化范例
- QQ登陆界面
- QQ登陆界面
- QQ登陆界面
- QQ登陆界面
- QQ登陆界面
- 山寨qq登陆界面
- 仿qq登陆界面
- qq登陆界面模拟
- qq登陆界面
- QQ登陆界面
- UI简易登陆界面
- 用Java写的一个类似QQ登陆界面的程序 Java QQ登陆界面
- 使用PyQT编写界面程序
- Domino 自定义登陆界面
- 自定义登陆界面样式
- 2018
- 汇编跳转指令
- [LeetCode] Median of Two Sorted Arrays
- scheme序对与表的进阶
- kinect, openkinect以及softkinect
- 如何使用MFC编写自定义UI界面【附高仿QQ 2014登陆界面范例程序】
- 互联网协议入门(下)
- PHP5.6在Unix 系统下的 Apache 2.x 下的安装
- iOS 根据 crash 崩溃 报告的内存地址定位到代码位置
- Unicode伟大的创想
- 论“知己”
- 计算机机房的软件维护
- Linux内核代码风格摘要
- Sharepoint webpart 自定义属性