源代码:下载

VC开发程序单调的界面相信大家都是深有感触,提到界面美化编程,人们都会说做界面不要用VC写,太难了。
一句俗语:难者不会,会者不难。VC的美化界面编程并没有人们想像的那么难。这篇文章是我写的一个用户登录界面,但界面被我美化了,我将一步一步的来讲解它的美化界面的实现步骤。相信有了这篇文章,你的VC界面从此也能绚丽多彩。

实现步骤:

第一步:美化界面的非客户区(重绘标题栏和界面边框)。
关键代码如下:

// 函 数 名:DrawTitleBar
// 功能描述:绘制标题栏、边框颜色,绘制标题内容、图标和按钮
// 输入参数:pDC:设备指针
// 输出参数:void
// 创建日期:2006-2-20
// 修改日期:2006-2-20
// 作 者:joinclear
// 附加说明:无
void CTitleBarColorDlg::DrawTitleBar(CDC *pDC)
{
if (m_hWnd)
{
CBrush Brush(RGB(187,200,143));
CBrush* pOldBrush = pDC->SelectObject(&Brush); CRect rtWnd, rtTitle, rtButtons;
GetWindowRect(&rtWnd); //取得标题栏的位置
//SM_CXFRAME 窗口边框的边缘宽度
//SM_CYFRAME 窗口边框的边缘高度
//SM_CXSIZE 窗口标题栏宽度
//SM_CYSIZE 窗口标题栏高度
rtTitle.left = GetSystemMetrics(SM_CXFRAME);
rtTitle.top = GetSystemMetrics(SM_CYFRAME);
rtTitle.right = rtWnd.right - rtWnd.left - GetSystemMetrics(SM_CXFRAME);
rtTitle.bottom = rtTitle.top + GetSystemMetrics(SM_CYSIZE); CPoint point;
//填充顶部框架
point.x = rtWnd.Width();
point.y = GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYFRAME) +0;
pDC->PatBlt(0, 0, point.x, point.y, PATCOPY);
//填充左侧框架
point.x = GetSystemMetrics(SM_CXFRAME) -1;
point.y = rtWnd.Height()-1;
pDC->PatBlt(0, 0, point.x, point.y, PATCOPY);
//填充底部框架
point.x = rtWnd.Width();
point.y = GetSystemMetrics(SM_CYFRAME);
pDC->PatBlt(0, rtWnd.Height()-point.y, point.x, point.y, PATCOPY);
//填充右侧框架
point.x = GetSystemMetrics(SM_CXFRAME);
point.y = rtWnd.Height();
pDC->PatBlt(rtWnd.Width()-point.x, 0, point.x, point.y, PATCOPY); //重画标题栏图标
m_rtIcon.left = rtTitle.left ;
m_rtIcon.top = rtTitle.top;
m_rtIcon.right = m_rtIcon.left +16;
m_rtIcon.bottom = m_rtIcon.top +15;
::DrawIconEx(pDC->m_hDC, m_rtIcon.left, m_rtIcon.top, AfxGetApp()->LoadIcon(IDR_MAINFRAME),
m_rtIcon.Width(), m_rtIcon.Height(), 0, NULL, DI_NORMAL);
m_rtIcon.OffsetRect(rtWnd.TopLeft()); CBitmap* pBitmap =new CBitmap;
CBitmap* pOldBitmap;
CDC* pDisplayMemDC=new CDC;
pDisplayMemDC->CreateCompatibleDC(pDC); //重画关闭button
rtButtons.left = rtTitle.right -16;
rtButtons.top = rtTitle.top -1;
rtButtons.right = rtButtons.left +16;
rtButtons.bottom = rtButtons.top +15;
pBitmap->LoadBitmap(IDB_EXIT_FOCUS);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
m_rtButtExit = rtButtons;
m_rtButtExit.OffsetRect(rtWnd.TopLeft());
pBitmap->DeleteObject(); //重画最大化/恢复button
rtButtons.right = rtButtons.left -3;
rtButtons.left = rtButtons.right -16;
if (IsZoomed())
pBitmap->LoadBitmap(IDB_RESTORE_NORMAL);
else
pBitmap->LoadBitmap(IDB_MAX_NORMAL);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
m_rtButtMax = rtButtons;
m_rtButtMax.OffsetRect(rtWnd.TopLeft());
pBitmap->DeleteObject(); //重画最小化button
rtButtons.right = rtButtons.left -3;
rtButtons.left = rtButtons.right -16;
pBitmap->LoadBitmap(IDB_MIN_NORMAL);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
m_rtButtMin = rtButtons;
m_rtButtMin.OffsetRect(rtWnd.TopLeft());
pBitmap->DeleteObject(); //重画caption
int nOldMode = pDC->SetBkMode(TRANSPARENT);
COLORREF clOldText=pDC->SetTextColor(RGB(255, 255, 255)); CFont m_captionFont;
m_captionFont.CreateFont(
18, // 字体的高度
0, // 字体的宽度
0, // 字体显示的角度
0, // 字体的角度
FW_BOLD, // 字体的磅数
FALSE, // 斜体字体
FALSE, // 带下划线的字体
0, // 带删除线的字体
ANSI_CHARSET, // 所需的字符集
OUT_DEFAULT_PRECIS, // 输出的精度
CLIP_DEFAULT_PRECIS, // 裁减的精度
DEFAULT_QUALITY, // 逻辑字体与输出设备的实际字体之间的精度
DEFAULT_PITCH | FF_SWISS, // 字体间距和字体集
_T("Arial")); // 字体名称 CFont* pOldFont = NULL;
pOldFont = pDC->SelectObject(&m_captionFont); rtTitle.left += m_rtIcon.Width ()+3;
rtTitle.top = rtTitle.top;
rtTitle.bottom = rtTitle.top +30;
CString m_strTitle;
GetWindowText(m_strTitle);
pDC->DrawText(m_strTitle, &rtTitle, DT_LEFT);
pDC->SetBkMode(nOldMode);
pDC->SetTextColor(clOldText); ReleaseDC(pDisplayMemDC);
delete pDisplayMemDC;
delete pBitmap;
}
}

还有在非客户区 绘制鼠标的消息。分别为:

void CTitleBarColorDlg::OnNcLButtonDown(UINT nHitTest, CPoint point) 
{
if (m_rtButtExit.PtInRect(point)) //关闭
SendMessage(WM_CLOSE);
elseif (m_rtButtMin.PtInRect(point)) //最小化
SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, MAKELPARAM(point.x, point.y));
elseif (m_rtButtMax.PtInRect(point))
{
if (IsZoomed()) //最大化
{
SendMessage(WM_SYSCOMMAND, SC_RESTORE, MAKELPARAM(point.x, point.y));
CRect rtWnd;
GetWindowRect(&rtWnd);
CRgn rgn;
rgn.CreateRoundRectRgn(0,0,rtWnd.Width(),rtWnd.Height(),5,5);
SetWindowRgn((HRGN)rgn,true);
Invalidate();
}
else
{
SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, MAKELPARAM(point.x, point.y)); CRect rtWnd;
GetWindowRect(&rtWnd);
CRgn rgn;
rgn.CreateRoundRectRgn(0,0,rtWnd.Width(),rtWnd.Height(),5,5);
SetWindowRgn((HRGN)rgn,true);
Invalidate();
}
}
elseif (!IsZoomed())
Default();
}
void CTitleBarColorDlg::OnNcMouseMove(UINT nHitTest, CPoint point)
{
CWindowDC dc(this);
CWindowDC* pDC =&dc;
CDC* pDisplayMemDC=new CDC;
pDisplayMemDC->CreateCompatibleDC(pDC);
CBitmap* pBitmap =new CBitmap;
CBitmap* pOldBitmap;
CRect rtWnd, rtButton; if (pDC)
{
GetWindowRect(&rtWnd); //关闭button
if (m_rtButtExit.PtInRect(point))
pBitmap->LoadBitmap(IDB_EXIT_NORMAL);
else
pBitmap->LoadBitmap(IDB_EXIT_FOCUS);
rtButton = m_rtButtExit;
rtButton.OffsetRect(-rtWnd.left, -rtWnd.top);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtButton.left, rtButton.top, rtButton.Width(), rtButton.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject(); //最大化/恢复button
if (m_rtButtMax.PtInRect(point))
{
if (IsZoomed())
pBitmap->LoadBitmap(IDB_RESTORE_FOCUS);
else
pBitmap->LoadBitmap(IDB_MAX_FOCUS);
}
else
{
if (IsZoomed())
pBitmap->LoadBitmap(IDB_RESTORE_NORMAL);
else
pBitmap->LoadBitmap(IDB_MAX_NORMAL);
}
rtButton = m_rtButtMax;
rtButton.OffsetRect(-rtWnd.left, -rtWnd.top);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtButton.left, rtButton.top, rtButton.Width(), rtButton.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject(); //最小化button
if (m_rtButtMin.PtInRect(point))
pBitmap->LoadBitmap(IDB_MIN_FOCUS);
else
pBitmap->LoadBitmap(IDB_MIN_NORMAL);
rtButton = m_rtButtMin;
rtButton.OffsetRect(-rtWnd.left, -rtWnd.top);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtButton.left, rtButton.top, rtButton.Width(), rtButton.Height(), pDisplayMemDC, 0, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject(); } pDisplayMemDC->DeleteDC(); delete pDisplayMemDC;
delete pBitmap; CDialog::OnNcMouseMove(nHitTest, point);
}

大部分实现如上代码所示具体实现请参照程序附带的源代码。

第二步:改变窗口边框为圆角。
关键代码如下:

int CTitleBarColorDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
if (CDialog::OnCreate(lpCreateStruct) ==-1)
return-1; CRect rtWnd;
GetWindowRect(&rtWnd); CRgn rgn;
rgn.CreateRoundRectRgn(0,0,rtWnd.Width(),rtWnd.Height(),5,5);
SetWindowRgn((HRGN)rgn,true); return0;
}

第三步:填充背景。
关键代码如下:

BOOL CTitleBarColorDlg::OnEraseBkgnd(CDC* pDC) 
{
BOOL retValue= CDialog::OnEraseBkgnd(pDC); CRect rc;
GetClientRect(&rc);
pDC->FillSolidRect(&rc,RGB(236,233,216)); return retValue;
}

第四步:绘制按钮。
具体请参考源代码中类CXPButton.h、CXPButton.cpp

第五步:绘制编辑框。
具体请参考源代码中类COwnerEdit.h、COwnerEdit.cpp

第六步:绘制静态字体和颜色。
这一步本来也写了一个类的,但想想用OnCtlColor()还是能很好的实现的,就没写。具体实现请看OnCtlColor()中的实现。

以上代码具体实现的细节问题,你可以下载例子代码,仔细查看其源码实现(内有详细注释)。

版权声明: 本博客地址 http://www.cnblogs.com/joinclear,欢迎转载,转载请标明原文作者和链接。

文章说明: 一家之辞难免有误,欢迎您中肯的指正;如对您有帮助,不胜荣幸,但更希望能够抛砖引玉。

- joinclear

美化VC界面(用户登录界面)的更多相关文章

  1. 很漂亮的用户登录界面HTML模板

    效果预览:http://keleyi.com/keleyi/phtml/divcss/21.htm HoverTree开源项目实现了分层后,准备实现管理员后台登录,这里先把登录界面的HTML模板整理好 ...

  2. html简约风用户登录界面网页制作html5-css-jquary-学习模版

    2018--12-12 喜迎双十二,咳咳,,,,我不是打广告哈,购物的节日也不要忘记学习. 大家好,我又来了. 今天抽出来空把自己的学习心得给大家分享,这是一个可开发可扩展的用户登录界面,用于开发学习 ...

  3. Android studio 开发一个用户登录界面

    Android studio 开发一个用户登录界面 activity_main.xml <?xml version="1.0" encoding="utf-8&qu ...

  4. jQuery和CSS3炫酷GOOGLE样式的用户登录界面

    这是一款使用jQuery和CSS3打造的GOOGLE样式的用户登录界面特效.该登录界面特效中,右上角的小问号和错误提示小图标使用SVG来制作.username和password输入框採用浮动标签特效. ...

  5. 编写Java程序,使用Swing布局管理器与常用控件,实现用户登录界面

    返回本章节 返回作业目录 需求说明: 使用Swing布局管理器与常用控件,实现用户登录界面 实现思路: 创建用户登录界面的类LoginFrame,在该类中创建无参数的构造方法,在构造方法中,设置窗体大 ...

  6. Ubuntu系统---Ubuntu16.04进不了界面(登录界面循环,密码正确)(一体化安装(CUDA +NVIDIA驱动)+ cuDNN)

                                                 Ubuntu16.04进不了界面(登录界面循环,密码正确)(一体化安装(CUDA +NVIDIA驱动)+ cu ...

  7. java web用户登录界面

    做这次实验,主要用到了mysql  java web 的 内容 实验代码: IUserDao.java package com.jaovo.msg.dao; import java.util.List ...

  8. Qt 用户登录界面

     使用QT创建自己的登录窗口: 主要步骤:    1.窗口界面的绘制     2.沟通数据库进行密码验证 void MainWindow::on_pushButton_clicked() { // 连 ...

  9. 记一次自启动的docker容器将宿主机的开机用户登录界面覆盖事件

    宿主机的系统为CentOS7_7.7.1908,默认为GUI启动,安装了宝塔面板,docker-ce为最新版. 在启动了一个centos7的容器(镜像为centos官方镜像)后,将该容器重启策略设置为 ...

随机推荐

  1. Jquery—Jquery异步功能实例

    Jquery确实是一个非常好的JavaScript框架,今天利用闲暇时间给大家一个借助Jquery异步实现校验username的唯一性的样例: 代码1--index.jsp文件: <%@ pag ...

  2. java NIO中的buffer和channel

    缓冲区(Buffer):一,在 Java NIO 中负责数据的存取.缓冲区就是数组.用于存储不同数据类型的数据 根据数据类型不同(boolean 除外),提供了相应类型的缓冲区:ByteBufferC ...

  3. SICP-Exercise 1.5

    Exercise 1.5.  Ben Bitdiddle has invented a test to determine whether the interpreterhe is faced wit ...

  4. oracle日期合并 分别用逗号或者分号隔开

    逗号隔开',' select LISTAGG(SUBSTR(TO_CHAR(FREESTARTTIME,,) ,)),',')WITHIN GROUP (ORDER BY TPF.FREEID) AS ...

  5. iOS开发之地域选择

    代码地址: https://github.com/boundlessocean/AreaPickViewDome.git 效果:   第一步: 将BLAreaPickerView 导入工程     第 ...

  6. [转]编写 android.mk 中 LOCAL_C_INCLUDES 的技巧

    看原文请移步:编写 android.mk 中 LOCAL_C_INCLUDES 的技巧 在编写android.mk的过程中,免不了要修改LOCAL_C_INCLUDES来设置头文件的include目录 ...

  7. Along with all the above benefits, you cannot overlook the space efficiency and performance gains in using DataFrames and Dataset APIs for two reasons.

    Of all the developers’ delight, a set of APIs that makes them productive, that are easy to use, and ...

  8. Spark性能优化(1)——序列化、内存、并行度、数据存储格式、Shuffle

    序列化 背景: 在以下过程中,需要对数据进行序列化: shuffling data时需要通过网络传输数据 RDD序列化到磁盘时 性能优化点: Spark默认的序列化类型是Java序列化.Java序列化 ...

  9. rzsz安装【转】

    环境:CentOS 发生情况:需要安装工具:szrz 工具进行 windows 和linux传文件 安装方式:从网上其他教程找的所以就按照如下方式操作 1. 下载软件 rzsz-3.34.tar.gz ...

  10. JavaEE各种Javadoc的下载

    刚才突然发现,很多servlet的api都不熟悉,但是又没有给eclipse导入api,就google了一下 关键字,servlet api / doc 或者java ee api / doc 注意版 ...