用MFC做漂亮界面之登录界面

转自:https://blog.csdn.net/u011711997/article/details/79375710

前段时间由于工作原因,一直没有更新博客,今天,继续讲解如何用MFC做漂亮界面,前几次我们讲了如何美化窗口背景,如何美化标题,如何美化按钮,今天我们用以前学过的知识来一起做一个登录界面,这个登录界面的效果图如下:

分析

当我们看到这个界面的时,先不要忙着去做,先要分析一下哪些是代码做的,哪些不是代码做的,这样就可以减少工作量。大家试试看,分析一下哪些是留在背景上的,不需要我们去做?没错,一共有5个部分是留在背景上的,分别如下:

第一个是老虎,这个不用多说。

第二个是账号,因为这个是美术字,加了特效,代码没法实现。

第三个是密码,同上。

第四个是账号输入框,因为这个框的边框加了特效,所以要留下。

第五个是密码输入框,同上。

美化窗口背景

创建一个对话框项目,命名为LoginTigger,去掉取消按钮和确定按钮,并且修改对话框的Border为None,然后在函数OnInitDialog中修改窗口尺寸为背景图片尺寸。具体如下:

[cpp]  view plain  copy
  1. BOOL CLoginTiggerDlg::OnInitDialog()  
  2. {  
  3.     CDialogEx::OnInitDialog();  
  4.   
  5.     // 将“关于...”菜单项添加到系统菜单中。  
  6.   
  7.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  8.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  9.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  10.   
  11.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  12.     if (pSysMenu != NULL)  
  13.     {  
  14.         BOOL bNameValid;  
  15.         CString strAboutMenu;  
  16.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  17.         ASSERT(bNameValid);  
  18.         if (!strAboutMenu.IsEmpty())  
  19.         {  
  20.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  21.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  22.         }  
  23.     }  
  24.   
  25.     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动  
  26.     //  执行此操作  
  27.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  28.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  29.   
  30.     // TODO:  在此添加额外的初始化代码  
  31.   
  32.     //这个是我们自己加的  
  33.     MoveWindow(0, 0, 300, 400);  
  34.   
  35.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  36. }  

然后,编译代码,效果如下:

下面我们显示背景图片到窗口中,就完成了美化背景,首先在我们的对话框的头文件中增加一个CBrush变量,变量名是m_bkBrush,它代表我们的背景图片,在OnInitDialog中加载背景图片Tigger.png,具体如下:

[cpp]  view plain  copy
  1. BOOL CLoginTiggerDlg::OnInitDialog()  
  2. {  
  3.     CDialogEx::OnInitDialog();  
  4.   
  5.     // 将“关于...”菜单项添加到系统菜单中。  
  6.   
  7.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  8.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  9.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  10.   
  11.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  12.     if (pSysMenu != NULL)  
  13.     {  
  14.         BOOL bNameValid;  
  15.         CString strAboutMenu;  
  16.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  17.         ASSERT(bNameValid);  
  18.         if (!strAboutMenu.IsEmpty())  
  19.         {  
  20.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  21.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  22.         }  
  23.     }  
  24.   
  25.     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动  
  26.     //  执行此操作  
  27.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  28.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  29.   
  30.     // TODO:  在此添加额外的初始化代码  
  31.   
  32.     //这个是我们自己加的  
  33.     MoveWindow(0, 0, 300, 400);  
  34.   
  35.     //加载背景图片  
  36.   
  37.     CString strBmpPath = _T(".\\res\\Tigger.png");  
  38.   
  39.     CImage img;  
  40.   
  41.     img.Load(strBmpPath);  
  42.   
  43.     CBitmap bmpTmp;  
  44.   
  45.     bmpTmp.Attach(img.Detach());  
  46.   
  47.     m_bkBrush.CreatePatternBrush(&bmpTmp);  
  48.   
  49.     return TRUE;  
  50. }  

然后添加WM_CTLCOLOR响应函数,不懂得可以翻阅一下前面的文章,具体如下:

[cpp]  view plain  copy
  1. HBRUSH CLoginTiggerDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
  2. {  
  3.     HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);  
  4.   
  5.     // TODO:  在此更改 DC 的任何特性  
  6.   
  7.     // TODO:  如果默认的不是所需画笔,则返回另一个画笔  
  8.   
  9.     if (pWnd == this)  
  10.     {  
  11.         return m_bkBrush;  
  12.     }  
  13.   
  14.     return hbr;  
  15. }  

编译,运行效果如下:


至此,美化背景完成,是不是很简单。

添加标题

我们首先创建一个CCaption类,继承自CStatic,然后添加成员函数HBRUSH CtlColor(CDC* pDC, UINT nCtlColor),不懂得可以翻阅前面的文章,具体如下:

[cpp]  view plain  copy
  1. HBRUSH CCaption::CtlColor(CDC* pDC, UINT /*nCtlColor*/)  
  2. {  
  3.     CFont font;  
  4.     LOGFONT lf;  
  5.     if (!pDC)  
  6.         return NULL;  
  7.     //创建一个空画刷,返回这个画刷可以让静态控件的背景透明    
  8.     HBRUSH hr = (HBRUSH)GetStockObject(NULL_BRUSH);  
  9.     //让文字的背景透明        
  10.     pDC->SetBkMode(TRANSPARENT);  
  11.     //设置文字的颜色为白色    
  12.     pDC->SetTextColor(RGB(255, 255, 255));  
  13.     ::ZeroMemory(&lf, sizeof(lf));  
  14.     //设置逻辑字体的高度  
  15.     lf.lfHeight = 24;  
  16.     //设置逻辑字体为粗体字    
  17.     lf.lfWeight = FW_BOLD;  
  18.     //设置字体为宋体    
  19.     ::lstrcpy(lf.lfFaceName, _T("宋体"));  
  20.     //用逻辑字体创建一个CFont对象    
  21.     font.CreateFontIndirect(&lf);  
  22.     //应用字体    
  23.     pDC->SelectObject(&font);  
  24.     return hr;  
  25. }  

然后再添加一个成员函数,控制这个标题的显示位置和范围,具体如下:

[cpp]  view plain  copy
  1. void CCaption::Init(int nX, int nY, int nW, int nH)  
  2. {  
  3.     MoveWindow(nX, nY, nW, nH);  
  4. }  

然后,在对话框上添加一个静态控件,ID为IDC_STATIC_CAPTION,并且为它定义一个控件变量,命名为m_staticCap,再然后,修改它的类型为CCaption,并在OnInitDialog中设置标题的位置和范围,具体代码如下:

[cpp]  view plain  copy
  1. BOOL CLoginTiggerDlg::OnInitDialog()  
  2. {  
  3.     CDialogEx::OnInitDialog();  
  4.   
  5.     // 将“关于...”菜单项添加到系统菜单中。  
  6.   
  7.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  8.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  9.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  10.   
  11.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  12.     if (pSysMenu != NULL)  
  13.     {  
  14.         BOOL bNameValid;  
  15.         CString strAboutMenu;  
  16.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  17.         ASSERT(bNameValid);  
  18.         if (!strAboutMenu.IsEmpty())  
  19.         {  
  20.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  21.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  22.         }  
  23.     }  
  24.   
  25.     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动  
  26.     //  执行此操作  
  27.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  28.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  29.   
  30.     // TODO:  在此添加额外的初始化代码  
  31.   
  32.     //这个是我们自己加的  
  33.     MoveWindow(0, 0, 300, 400);  
  34.   
  35.     //加载背景图片  
  36.   
  37.     CString strBmpPath = _T(".\\res\\Tigger.png");  
  38.   
  39.     CImage img;  
  40.   
  41.     img.Load(strBmpPath);  
  42.   
  43.     CBitmap bmpTmp;  
  44.   
  45.     bmpTmp.Attach(img.Detach());  
  46.   
  47.     m_bkBrush.CreatePatternBrush(&bmpTmp);  
  48.   
  49.     //调整标题位置  
  50.   
  51.     m_staticCap.Init(4, 8,105, 30);  
  52.   
  53.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  54. }  

编译程序,显示效果如下:

根据前面的学习,相信肯定有同学会说,还没有加窗口移动,对,别着急,现在就加,具体代码如下:

[cpp]  view plain  copy
  1. LRESULT CLoginTiggerDlg::OnNcHitTest(CPoint point)  
  2. {  
  3.     // TODO:  在此添加消息处理程序代码和/或调用默认值  
  4.     LRESULT ret = CDialogEx::OnNcHitTest(point);  
  5.     return (ret == HTCLIENT) ? HTCAPTION : ret;  
  6. }  
不懂得,可以看一下前面的文章,这里就不做过多介绍了。

添加关闭按钮

关闭按钮一共有三张图片分别对应正常,按下,悬浮(鼠标移动在上面的时候),具体如下:


首先我们需要为对话框添加一个关闭按钮的控件,命名为IDC_BUTTON_CLOSE,然后设置为Owner Draw,并添加一个控件变量,命名为m_btnClose,然后定义一个美化的按钮类,继承自CButton,命名为CMyButton,具体代码如下:

MyButton.h内容如下:

[cpp]  view plain  copy
  1. #pragma once  
  2.   
  3. // CMyButton  
  4.   
  5. class CMyButton : public CButton  
  6. {  
  7.     DECLARE_DYNAMIC(CMyButton)  
  8.   
  9. public:  
  10.     CMyButton();  
  11.     virtual ~CMyButton();  
  12.   
  13. protected:  
  14.     //正常状态图像路径  
  15.     CString m_strNormalImgPath;  
  16.     //按下状态图像路径  
  17.     CString m_strPressImgPath;  
  18.     //悬浮状态图像路径  
  19.     CString m_strFloatImgPath;  
  20.   
  21.     //正常状态图像  
  22.     CImage m_imgNormal;  
  23.     //按下状态图像  
  24.     CImage m_imgPress;  
  25.     //悬浮状态图像  
  26.     CImage m_imgFloat;  
  27.   
  28.     //窗口背景图片  
  29.     CImage m_BkImg;  
  30.   
  31. public:  
  32.   
  33.     //设置按钮图片路径  
  34.     void SetImagePath(CString strNoramlImgPath, CString strPressImgPath, CString strFloatImgPath);  
  35.     //初始化按钮,主要是调整按钮的位置,处理透明色    
  36.     bool InitMyButton(int nX/*左上角X坐标*/int nY/*左上角Y坐标*/int nW/*图像宽*/int nH/*图像高*/bool bIsPng/*是否是PNG图片*/);  
  37.     //自绘制函数    
  38.     void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);  
  39.   
  40.     //初始化窗口背景  
  41.     void SetBkImg(CString strBkImg);  
  42.   
  43. protected:  
  44.     //光标是否在窗口内  
  45.     BOOL m_bIsInWnd;  
  46.     DECLARE_MESSAGE_MAP()  
  47. public:  
  48.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
  49.     afx_msg void OnMouseHover(UINT nFlags, CPoint point);  
  50.     afx_msg void OnMouseLeave();  
  51.   
  52.       
  53. };  

MyButton.cpp内容如下:

[cpp]  view plain  copy
  1. // MyButton.cpp : 实现文件  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "LoginTigger.h"  
  6. #include "MyButton.h"  
  7.   
  8.   
  9. // CMyButton  
  10.   
  11. IMPLEMENT_DYNAMIC(CMyButton, CButton)  
  12.   
  13. CMyButton::CMyButton()  
  14. {  
  15.     m_bIsInWnd = FALSE;  
  16. }  
  17.   
  18. CMyButton::~CMyButton()  
  19. {  
  20. }  
  21.   
  22.   
  23. BEGIN_MESSAGE_MAP(CMyButton, CButton)  
  24.     ON_WM_MOUSEMOVE()  
  25.     ON_WM_MOUSEHOVER()  
  26.     ON_WM_MOUSELEAVE()  
  27. END_MESSAGE_MAP()  
  28.   
  29.   
  30.   
  31. // CMyButton 消息处理程序  
  32.   
  33. //设置按钮图片路径  
  34. void CMyButton::SetImagePath(CString strNoramlImgPath, CString strPressImgPath, CString strFloatImgPath)  
  35. {  
  36.     m_strNormalImgPath = strNoramlImgPath;  
  37.     m_strPressImgPath = strPressImgPath;  
  38.     m_strFloatImgPath = strFloatImgPath;  
  39. }  
  40.   
  41. void CMyButton::SetBkImg(CString strBkImg)  
  42. {  
  43.     if (strBkImg.IsEmpty())  
  44.         return;  
  45.     m_BkImg.Load(strBkImg);  
  46. }  
  47.   
  48. //初始化按钮,主要是调整按钮的位置,处理透明色    
  49. bool CMyButton::InitMyButton(int nX/*左上角X坐标*/int nY/*左上角Y坐标*/int nW/*图像宽*/int nH/*图像高*/bool bIsPng/*是否是PNG图片*/)  
  50. {  
  51.     HRESULT hr = 0;  
  52.   
  53.     if (m_strNormalImgPath.IsEmpty())  
  54.         return false;  
  55.     if (m_strPressImgPath.IsEmpty())  
  56.         return false;  
  57.     if (m_strFloatImgPath.IsEmpty())  
  58.         return false;  
  59.   
  60.     hr = m_imgNormal.Load(m_strNormalImgPath);  
  61.   
  62.     int a = GetLastError();  
  63.   
  64.     if (FAILED(hr))  
  65.         return false;  
  66.   
  67.     hr = m_imgPress.Load(m_strPressImgPath);  
  68.   
  69.     if (FAILED(hr))  
  70.         return false;  
  71.   
  72.     hr = m_imgFloat.Load(m_strFloatImgPath);  
  73.   
  74.     if (FAILED(hr))  
  75.         return false;  
  76.   
  77.     if (bIsPng)  
  78.     {  
  79.         if (m_imgNormal.GetBPP() == 32)  
  80.         {  
  81.             int i = 0;  
  82.             int j = 0;  
  83.             for (i = 0; i < m_imgNormal.GetWidth(); i++)  
  84.             {  
  85.                 for (j = 0; j < m_imgNormal.GetHeight(); j++)  
  86.                 {  
  87.                     byte * pbyte = (byte *)m_imgNormal.GetPixelAddress(i, j);  
  88.                     pbyte[0] = pbyte[0] * pbyte[3] / 255;  
  89.                     pbyte[1] = pbyte[1] * pbyte[3] / 255;  
  90.                     pbyte[2] = pbyte[2] * pbyte[3] / 255;  
  91.                 }  
  92.             }  
  93.         }  
  94.   
  95.         if (m_imgPress.GetBPP() == 32)  
  96.         {  
  97.             int i = 0;  
  98.             int j = 0;  
  99.             for (i = 0; i < m_imgPress.GetWidth(); i++)  
  100.             {  
  101.                 for (j = 0; j < m_imgPress.GetHeight(); j++)  
  102.                 {  
  103.                     byte * pbyte = (byte *)m_imgPress.GetPixelAddress(i, j);  
  104.                     pbyte[0] = pbyte[0] * pbyte[3] / 255;  
  105.                     pbyte[1] = pbyte[1] * pbyte[3] / 255;  
  106.                     pbyte[2] = pbyte[2] * pbyte[3] / 255;  
  107.                 }  
  108.             }  
  109.         }  
  110.   
  111.         if (m_imgFloat.GetBPP() == 32)  
  112.         {  
  113.             int i = 0;  
  114.             int j = 0;  
  115.             for (i = 0; i < m_imgFloat.GetWidth(); i++)  
  116.             {  
  117.                 for (j = 0; j < m_imgFloat.GetHeight(); j++)  
  118.                 {  
  119.                     byte * pbyte = (byte *)m_imgFloat.GetPixelAddress(i, j);  
  120.                     pbyte[0] = pbyte[0] * pbyte[3] / 255;  
  121.                     pbyte[1] = pbyte[1] * pbyte[3] / 255;  
  122.                     pbyte[2] = pbyte[2] * pbyte[3] / 255;  
  123.                 }  
  124.             }  
  125.         }  
  126.     }  
  127.   
  128.     MoveWindow(nX, nY, nW, nH);  
  129.   
  130.     return true;  
  131.   
  132. }  
  133. //自绘制函数    
  134. void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)  
  135. {  
  136.     if (!lpDrawItemStruct)  
  137.         return;  
  138.     HDC hMemDC;  
  139.     HBITMAP bmpMem;  
  140.     HGDIOBJ hOldObj;  
  141.     bmpMem = CreateCompatibleBitmap(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top);  
  142.     if (!bmpMem)  
  143.         return;  
  144.     hMemDC = CreateCompatibleDC(lpDrawItemStruct->hDC);  
  145.     if (!hMemDC)  
  146.     {  
  147.         if (bmpMem)  
  148.         {  
  149.             ::DeleteObject(bmpMem);  
  150.             bmpMem = NULL;  
  151.         }  
  152.         return;  
  153.     }  
  154.   
  155.     hOldObj = ::SelectObject(hMemDC, bmpMem);  
  156.   
  157.     int nW = lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left;  
  158.   
  159.     int nH = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top;  
  160.   
  161.     RECT rectTmp = { 0 };  
  162.   
  163.     rectTmp = lpDrawItemStruct->rcItem;  
  164.   
  165.     MapWindowPoints(GetParent(), &rectTmp);  
  166.   
  167.     if (m_BkImg.IsNull() == false)  
  168.         m_BkImg.Draw(hMemDC, 0, 0, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top, rectTmp.left, rectTmp.top, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top);  
  169.       
  170.     if (lpDrawItemStruct->itemState & ODS_SELECTED)  
  171.     {  
  172.         //按钮被选择    
  173.         m_imgPress.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);  
  174.     }  
  175.     else  
  176.     {  
  177.         //默认状态    
  178.         m_imgNormal.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);  
  179.   
  180.     }  
  181.   
  182.     ::BitBlt(lpDrawItemStruct->hDC, 0, 0, nW, nH, hMemDC,0,0,SRCCOPY);  
  183.   
  184.     SelectObject(hMemDC, hOldObj);  
  185.   
  186.     if (bmpMem)  
  187.     {  
  188.         ::DeleteObject(bmpMem);  
  189.         bmpMem = NULL;  
  190.     }  
  191.   
  192.     if (hMemDC)  
  193.     {  
  194.         ::DeleteDC(hMemDC);  
  195.         hMemDC = NULL;  
  196.     }  
  197.     return;  
  198. }  
  199.   
  200. void CMyButton::OnMouseMove(UINT nFlags, CPoint point)  
  201. {  
  202.     // TODO:  在此添加消息处理程序代码和/或调用默认值  
  203.   
  204.     CButton::OnMouseMove(nFlags, point);  
  205.     if (!m_bIsInWnd)  
  206.     {  
  207.         TRACKMOUSEEVENT       tme;  
  208.         tme.cbSize = sizeof(TRACKMOUSEEVENT);  
  209.         tme.dwFlags = TME_HOVER | TME_LEAVE;  
  210.         tme.dwHoverTime = 10;  
  211.         tme.hwndTrack = m_hWnd;  
  212.         _TrackMouseEvent(&tme);  
  213.         m_bIsInWnd = TRUE;  
  214.     }  
  215. }  
  216.   
  217.   
  218. void CMyButton::OnMouseHover(UINT nFlags, CPoint point)  
  219. {  
  220.     // TODO:  在此添加消息处理程序代码和/或调用默认值  
  221.   
  222.     HDC hMemDC;  
  223.     HBITMAP bmpMem;  
  224.     HGDIOBJ hOldObj;  
  225.     HDC hDC = ::GetDC(GetSafeHwnd());  
  226.     CRect rcItem;  
  227.     GetClientRect(&rcItem);  
  228.   
  229.     if (hDC)  
  230.     {  
  231.         bmpMem = CreateCompatibleBitmap(hDC, rcItem.Width(), rcItem.Height());  
  232.         if (!bmpMem)  
  233.         {  
  234.             ::ReleaseDC(GetSafeHwnd(), hDC);  
  235.             return;  
  236.         }  
  237.         hMemDC = CreateCompatibleDC(hDC);  
  238.         if (!hMemDC)  
  239.         {  
  240.             if (bmpMem)  
  241.             {  
  242.                 ::DeleteObject(bmpMem);  
  243.                 bmpMem = NULL;  
  244.             }  
  245.             ::ReleaseDC(GetSafeHwnd(), hDC);  
  246.             return;  
  247.         }  
  248.   
  249.         hOldObj = ::SelectObject(hMemDC, bmpMem);  
  250.   
  251.         RECT rectTmp = { 0 };  
  252.   
  253.         rectTmp = rcItem;  
  254.   
  255.         MapWindowPoints(GetParent(), &rectTmp);  
  256.   
  257.         if (m_BkImg.IsNull() == false)  
  258.             m_BkImg.Draw(hMemDC, 0, 0, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top, rectTmp.left, rectTmp.top, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top);  
  259.   
  260.         int nW = rcItem.right - rcItem.left;  
  261.   
  262.         int nH = rcItem.bottom - rcItem.top;  
  263.   
  264.         m_imgFloat.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0,nW,nH);  
  265.   
  266.         ::BitBlt(hDC, 0, 0, nW, nH, hMemDC, 0, 0, SRCCOPY);  
  267.   
  268.         SelectObject(hMemDC, hOldObj);  
  269.   
  270.         if (bmpMem)  
  271.         {  
  272.             ::DeleteObject(bmpMem);  
  273.             bmpMem = NULL;  
  274.         }  
  275.   
  276.         if (hMemDC)  
  277.         {  
  278.             ::DeleteDC(hMemDC);  
  279.             hMemDC = NULL;  
  280.         }  
  281.   
  282.         ::ReleaseDC(GetSafeHwnd(), hDC);  
  283.     }  
  284.   
  285.     CButton::OnMouseHover(nFlags, point);  
  286. }  
  287.   
  288.   
  289. void CMyButton::OnMouseLeave()  
  290. {  
  291.     // TODO:  在此添加消息处理程序代码和/或调用默认值  
  292.   
  293.     CButton::OnMouseLeave();  
  294.     InvalidateRect(NULL);  
  295.     m_bIsInWnd = FALSE;  
  296. }  

不懂的同学可以看一下前面的文章,编译程序,运行效果如下:


上面的图片显示了关闭按钮的三种状态效果,即正常,悬浮,按下。

添加账号和密码输入框

首先添加一个编辑框,命名为IDC_EDIT_NAME,设置边框属性为False,为它添加一个控件变量,命名为m_editName,然后为它设置一个字体需求,宋体,24点,具体代码如下:

[cpp]  view plain  copy
  1. BOOL CLoginTiggerDlg::OnInitDialog()  
  2. {  
  3.     CDialogEx::OnInitDialog();  
  4.   
  5.     // 将“关于...”菜单项添加到系统菜单中。  
  6.   
  7.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  8.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  9.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  10.   
  11.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  12.     if (pSysMenu != NULL)  
  13.     {  
  14.         BOOL bNameValid;  
  15.         CString strAboutMenu;  
  16.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  17.         ASSERT(bNameValid);  
  18.         if (!strAboutMenu.IsEmpty())  
  19.         {  
  20.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  21.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  22.         }  
  23.     }  
  24.   
  25.     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动  
  26.     //  执行此操作  
  27.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  28.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  29.   
  30.     // TODO:  在此添加额外的初始化代码  
  31.   
  32.     //这个是我们自己加的  
  33.     MoveWindow(0, 0, 300, 400);  
  34.   
  35.     //加载背景图片  
  36.   
  37.     CString strBmpPath = _T(".\\res\\Tigger.png");  
  38.   
  39.     CImage img;  
  40.   
  41.     img.Load(strBmpPath);  
  42.   
  43.     CBitmap bmpTmp;  
  44.   
  45.     bmpTmp.Attach(img.Detach());  
  46.   
  47.     m_bkBrush.CreatePatternBrush(&bmpTmp);  
  48.   
  49.     //调整标题位置  
  50.   
  51.     m_staticCap.Init(4, 8,105, 30);  
  52.   
  53.     //关闭按钮设置  
  54.   
  55.     m_btnClose.SetImagePath(_T("./res/TigerCloseNormal.png"), _T("./res/TigerClosePress.png"), _T("./res/TigerCloseFloat.png"));  
  56.       
  57.     m_btnClose.InitMyButton(271, 8, 20, 20, true);  
  58.   
  59.     //调整光标的位置适中  
  60.   
  61.     m_editName.MoveWindow(82, 261 + 4, 200, 31 - 4);  
  62.   
  63.     CFont*  pFont = m_editName.GetFont();  
  64.   
  65.     LOGFONT  lf;  
  66.   
  67.     if (pFont)  
  68.     {  
  69.         pFont->GetLogFont(&lf);  
  70.   
  71.         lf.lfHeight = 24;//改变字体高度      
  72.   
  73.         _tcscpy(lf.lfFaceName, _T("宋体"));//改变字体名称      
  74.   
  75.         m_fontEdit.CreateFontIndirect(&lf);  
  76.   
  77.         m_editName.SetFont(&m_fontEdit);  
  78.     }  
  79.   
  80.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  81. }  

然后修改控件字体的颜色,具体代码如下:

[cpp]  view plain  copy
  1. HBRUSH CLoginTiggerDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
  2. {  
  3.     HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);  
  4.   
  5.     // TODO:  在此更改 DC 的任何特性  
  6.   
  7.     if (pWnd == this)  
  8.     {  
  9.         return m_bkBrush;  
  10.     }  
  11.   
  12.     // TODO:  如果默认的不是所需画笔,则返回另一个画笔  
  13.   
  14.     //输入账号  
  15.     if (pWnd == &m_editName)  
  16.     {  
  17.         CFont font;  
  18.         LOGFONT lf;  
  19.         if (!pDC)  
  20.             return NULL;  
  21.   
  22.         //创建一个空画刷,返回这个画刷可以让静态控件的背景透明    
  23.         HBRUSH hr = (HBRUSH)GetStockObject(NULL_BRUSH);  
  24.         //让文字的背景透明        
  25.         pDC->SetBkMode(TRANSPARENT);  
  26.         //设置文字的颜色为白色    
  27.         pDC->SetTextColor(RGB(200, 200, 200));  
  28.     }  
  29.   
  30.     return hbr;  
  31. }  

编译程序,运行效果如下:

密码输入框的制作与账号输入框相同,唯一不同的地方就是设置Password属性为真,密码输入框的ID为IDC_EDIT_PWD,为其添加一个控件变量m_editPwd,然后调整它的位置,并设置字体,具体代码如下:

[cpp]  view plain  copy
  1. BOOL CLoginTiggerDlg::OnInitDialog()  
  2. {  
  3.     CDialogEx::OnInitDialog();  
  4.   
  5.     // 将“关于...”菜单项添加到系统菜单中。  
  6.   
  7.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  8.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  9.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  10.   
  11.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  12.     if (pSysMenu != NULL)  
  13.     {  
  14.         BOOL bNameValid;  
  15.         CString strAboutMenu;  
  16.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  17.         ASSERT(bNameValid);  
  18.         if (!strAboutMenu.IsEmpty())  
  19.         {  
  20.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  21.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  22.         }  
  23.     }  
  24.   
  25.     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动  
  26.     //  执行此操作  
  27.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  28.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  29.   
  30.     // TODO:  在此添加额外的初始化代码  
  31.   
  32.     //这个是我们自己加的  
  33.     MoveWindow(0, 0, 300, 400);  
  34.   
  35.     //加载背景图片  
  36.   
  37.     CString strBmpPath = _T(".\\res\\Tigger.png");  
  38.   
  39.     CImage img;  
  40.   
  41.     img.Load(strBmpPath);  
  42.   
  43.     CBitmap bmpTmp;  
  44.   
  45.     bmpTmp.Attach(img.Detach());  
  46.   
  47.     m_bkBrush.CreatePatternBrush(&bmpTmp);  
  48.   
  49.     //调整标题位置  
  50.   
  51.     m_staticCap.Init(4, 8,105, 30);  
  52.   
  53.     //关闭按钮设置  
  54.   
  55.     m_btnClose.SetImagePath(_T("./res/TigerCloseNormal.png"), _T("./res/TigerClosePress.png"), _T("./res/TigerCloseFloat.png"));  
  56.       
  57.     m_btnClose.InitMyButton(271, 8, 20, 20, true);  
  58.   
  59.     //账号输入框  
  60.   
  61.     //调整光标的位置适中  
  62.   
  63.     m_editName.MoveWindow(82, 261 + 4, 200, 31 - 4);  
  64.   
  65.     CFont*  pFont = m_editName.GetFont();  
  66.   
  67.     LOGFONT  lf;  
  68.   
  69.     if (pFont)  
  70.     {  
  71.         pFont->GetLogFont(&lf);  
  72.   
  73.         lf.lfHeight = 24;//改变字体高度      
  74.   
  75.         _tcscpy(lf.lfFaceName, _T("宋体"));//改变字体名称      
  76.   
  77.         m_fontEdit.CreateFontIndirect(&lf);  
  78.   
  79.         m_editName.SetFont(&m_fontEdit);  
  80.     }  
  81.   
  82.     //密码输入框  
  83.   
  84.     m_editPwd.MoveWindow(82, 308, 200, 25);  
  85.   
  86.     m_editPwd.SetFont(&m_fontEdit);  
  87.   
  88.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  89. }  

为其设置字体颜色,具体代码与账号输入框一样,具体代码如下:

[cpp]  view plain  copy
  1. HBRUSH CLoginTiggerDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
  2. {  
  3.     HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);  
  4.   
  5.     // TODO:  在此更改 DC 的任何特性  
  6.   
  7.     if (pWnd == this)  
  8.     {  
  9.         return m_bkBrush;  
  10.     }  
  11.   
  12.     // TODO:  如果默认的不是所需画笔,则返回另一个画笔  
  13.   
  14.     //输入账号  
  15.     if (pWnd == &m_editName)  
  16.     {  
  17.         CFont font;  
  18.         LOGFONT lf;  
  19.         if (!pDC)  
  20.             return NULL;  
  21.   
  22.         //创建一个空画刷,返回这个画刷可以让静态控件的背景透明    
  23.         HBRUSH hr = (HBRUSH)GetStockObject(NULL_BRUSH);  
  24.         //让文字的背景透明        
  25.         pDC->SetBkMode(TRANSPARENT);  
  26.         //设置文字的颜色为白色    
  27.         pDC->SetTextColor(RGB(200, 200, 200));  
  28.     }  
  29.   
  30.     //输入密码  
  31.     if (pWnd == &m_editPwd)  
  32.     {  
  33.         CFont font;  
  34.         LOGFONT lf;  
  35.         if (!pDC)  
  36.             return NULL;  
  37.   
  38.         //创建一个空画刷,返回这个画刷可以让静态控件的背景透明    
  39.         HBRUSH hr = (HBRUSH)GetStockObject(NULL_BRUSH);  
  40.         //让文字的背景透明        
  41.         pDC->SetBkMode(TRANSPARENT);  
  42.         //设置文字的颜色为白色    
  43.         pDC->SetTextColor(RGB(200, 200, 200));  
  44.     }  
  45.   
  46.     return hbr;  
  47. }  

编译程序,运行效果如下:


添加登录和注册按钮

登录按钮和注册按钮与关闭按钮的代码一样,所以我们只需要使用CMyButton类就可以,唯一需要调整的就是它们的图片不一样,所以这里我们只说说不同的地方,首先添加两个按钮控件,ID分别为IDC_BUTTON_LOGIN和IDC_BUTTON_REG,分别为它们添加两个控件变量m_btnLogin和m_btnReg,然后修改它们的控件类型为CMyButton,最后在OnInitDialog中初始化它们的位置和图片,具体代码如下:

[cpp]  view plain  copy
  1. BOOL CLoginTiggerDlg::OnInitDialog()  
  2. {  
  3.     CDialogEx::OnInitDialog();  
  4.   
  5.     // 将“关于...”菜单项添加到系统菜单中。  
  6.   
  7.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  8.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  9.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  10.   
  11.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  12.     if (pSysMenu != NULL)  
  13.     {  
  14.         BOOL bNameValid;  
  15.         CString strAboutMenu;  
  16.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  17.         ASSERT(bNameValid);  
  18.         if (!strAboutMenu.IsEmpty())  
  19.         {  
  20.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  21.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  22.         }  
  23.     }  
  24.   
  25.     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动  
  26.     //  执行此操作  
  27.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  28.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  29.   
  30.     // TODO:  在此添加额外的初始化代码  
  31.   
  32.     //这个是我们自己加的  
  33.     MoveWindow(0, 0, 300, 400);  
  34.   
  35.     //加载背景图片  
  36.   
  37.     CString strBmpPath = _T(".\\res\\Tigger.png");  
  38.   
  39.     CImage img;  
  40.   
  41.     img.Load(strBmpPath);  
  42.   
  43.     CBitmap bmpTmp;  
  44.   
  45.     bmpTmp.Attach(img.Detach());  
  46.   
  47.     m_bkBrush.CreatePatternBrush(&bmpTmp);  
  48.   
  49.     //调整标题位置  
  50.   
  51.     m_staticCap.Init(4, 8,105, 30);  
  52.   
  53.     //关闭按钮设置  
  54.   
  55.     m_btnClose.SetImagePath(_T("./res/TigerCloseNormal.png"), _T("./res/TigerClosePress.png"), _T("./res/TigerCloseFloat.png"));  
  56.       
  57.     m_btnClose.InitMyButton(271, 8, 20, 20, true);  
  58.   
  59.     //登录和注册按钮设置  
  60.   
  61.     m_btnLogin.SetImagePath(_T("./res/tigerLoginNormal.png"), _T("./res/tigerLoginPress.png"), _T("./res/TigerLoginFloat.png"));  
  62.   
  63.     m_btnLogin.InitMyButton(23, 355, 115, 35, true);  
  64.   
  65.     m_btnReg.SetImagePath(_T("./res/tigerRegisterNormal.png"), _T("./res/tigerRegisterPress.png"), _T("./res/TigerRegisterFloat.png"));  
  66.   
  67.     m_btnReg.InitMyButton(167, 355, 115, 35,true);  
  68.   
  69.     m_btnLogin.SetBkImg(strBmpPath);  
  70.   
  71.     m_btnReg.SetBkImg(strBmpPath);  
  72.   
  73.     //账号输入框  
  74.   
  75.     //调整光标的位置适中  
  76.   
  77.     m_editName.MoveWindow(82, 261 + 4, 200, 31 - 4);  
  78.   
  79.     CFont*  pFont = m_editName.GetFont();  
  80.   
  81.     LOGFONT  lf;  
  82.   
  83.     if (pFont)  
  84.     {  
  85.         pFont->GetLogFont(&lf);  
  86.   
  87.         lf.lfHeight = 24;//改变字体高度      
  88.   
  89.         _tcscpy(lf.lfFaceName, _T("宋体"));//改变字体名称      
  90.   
  91.         m_fontEdit.CreateFontIndirect(&lf);  
  92.   
  93.         m_editName.SetFont(&m_fontEdit);  
  94.     }  
  95.   
  96.     //密码输入框  
  97.   
  98.     m_editPwd.MoveWindow(82, 308, 200, 25);  
  99.   
  100.     m_editPwd.SetFont(&m_fontEdit);   
  101.   
  102.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  103. }  

编译程序,运行效果如下:

至此我们的登录界面就做完了,有不懂得地方可以翻阅一下前面的文章,需要下载源码的同学,可以从下面的地址下载:

http://download.csdn.net/download/u011711997/10261765



猜你喜欢

转载自blog.csdn.net/m0_37290785/article/details/80222183