• 自绘Tab控件


    自绘tab按钮效果图如下:

     

    使用例子:

    MyTabControl *tabControl = NULL;

    tabControl = new MyTabControl();
    tabControl->Create(this, CRect(0,0,125,27), L"花生", ID_BTN_MYTAB);
    tabControl->SetTabIndex(index);

    tabControl->SetShowText(L"花生");

    tabControl->SetTabState(TAB_STATE_DOWN);

    tabControl->SetToolTipText(L"花生");

    头文件:

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #pragma once  
    2. #include "LhsButton.h"  
    3.   
    4. // MyTabControl  
    5.   
    6. #define ID_BTN_MYTAB_CLOSE  2100            //关闭按钮的id  
    7. #define MYWM_BTN_TAB_CLOSE WM_USER+2001     //关闭按钮单击响应  
    8. #define MYWM_BTN_TAB_CLICK WM_USER+2002     //tab按钮单击  
    9.   
    10. //tab按钮的状态  
    11. enum TabState  
    12. {  
    13.     TAB_STATE_NOR           = 0,  
    14.     TAB_STATE_DOWN          = 1,  
    15. };  
    16. class MyTabControl : public CWnd  
    17. {  
    18.     DECLARE_DYNAMIC(MyTabControl)  
    19.   
    20. public:  
    21.     MyTabControl();  
    22.     virtual ~MyTabControl();  
    23.   
    24.      bool Create(CWnd* pParent,CRect rc,CString text,DWORD id = 0,DWORD style = WS_VISIBLE|WS_CHILD);    
    25.   
    26.     DECLARE_MESSAGE_MAP()  
    27.   
    28. public:  
    29.     void SetShowText(CString strShowText);  
    30.   
    31. protected:  
    32.     CString szClassName;    
    33.     bool m_isMouseHover;        //鼠标是否悬浮  
    34.     bool m_isMouseClicked;      //鼠标是否单击  
    35.     CString m_strShowText;      //要显示的文字  
    36.     CString m_strTabText;       //绘制在tab按钮下的文字  
    37.   
    38.     Image*                      m_pImgNor;          //正常时的图片  
    39.     Image*                      m_pImgHot;          //鼠标悬浮时的图片  
    40.     Image*                      m_pImgDown;         //单击按下时的图片  
    41.       
    42.     void PostClickEvent();  
    43.     afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);  
    44.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);    
    45.     afx_msg void OnMouseHover(UINT nFlags, CPoint point);    
    46.     afx_msg void OnMouseLeave();    
    47.     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);    
    48.     afx_msg void OnLButtonUp(UINT nFlags, CPoint point);    
    49.     afx_msg BOOL OnEraseBkgnd(CDC* pDC);    
    50.     afx_msg void OnPaint();    
    51.     afx_msg void OnSize(UINT nType, int cx, int cy);  
    52.     afx_msg LRESULT OnBtnClose(WPARAM wParam, LPARAM lParam);  
    53.     virtual BOOL PreTranslateMessage(MSG* pMsg);  
    54. public:  
    55.     void SetTabState(TabState state){m_tabState = state; Invalidate();} //设置tab状态  
    56.     TabState GetTabState(){return m_tabState;}  
    57.     void SetToolTipText(CString spText, BOOL bActivate = TRUE);  
    58.     void SetTabIndex(int idx){m_nIndex = idx;}  
    59.     int GetTabIndex(){return m_nIndex;}  
    60. private:  
    61.     DWORD GetComfortSize(HDC hdc, DWORD dwWidth, CString &strText);  
    62. private:  
    63.     TabState m_tabState;                            //tab的状态  
    64.     CLhsButton m_btnClose;                          //关闭按钮  
    65.     CToolTipCtrl*   m_pToolTip;  
    66.     CString m_tooltext;  
    67.     bool m_bCenterAlign;                            //是否居中对齐  
    68.     int m_nIndex;                                   //tab按钮的索引  
    69.   
    70. public:  
    71.     afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);  
    72. };  
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. // MyTabControl.cpp : 实现文件  
    2. //  
    3.   
    4. #include "stdafx.h"  
    5. #include "../Lander_mini.h"  
    6. #include "MyTabControl.h"  
    7. #include "memdc.h"  
    8. #include "../Utility.h"  
    9. // MyTabControl  
    10.   
    11. IMPLEMENT_DYNAMIC(MyTabControl, CWnd)  
    12.   
    13. MyTabControl::MyTabControl()  
    14. {  
    15.     m_isMouseHover = false;    
    16.     m_isMouseClicked = false;    
    17.     // 注册控件类    
    18.     szClassName = AfxRegisterWndClass(0);   
    19.     m_pImgNor = NULL;  
    20.     m_pImgHot = NULL;  
    21.     m_pImgDown = NULL;  
    22.     m_tabState = TAB_STATE_NOR;  
    23.     m_pToolTip = NULL;  
    24.     m_bCenterAlign = false;  
    25.     m_nIndex = 0;  
    26. }  
    27.   
    28. MyTabControl::~MyTabControl()  
    29. {  
    30.     SAFE_RELEASE(m_pToolTip);  
    31.     SAFE_RELEASE(m_pImgNor);  
    32.     SAFE_RELEASE(m_pImgHot);  
    33.     SAFE_RELEASE(m_pImgDown);  
    34. }  
    35.   
    36.   
    37. BEGIN_MESSAGE_MAP(MyTabControl, CWnd)  
    38.     ON_WM_MOUSEMOVE()    
    39.     ON_WM_MOUSEHOVER()  // 此消息系统并不会给我们发送    
    40.     ON_WM_MOUSELEAVE()    
    41.     ON_WM_LBUTTONDOWN()    
    42.     ON_WM_LBUTTONUP()    
    43.     ON_WM_PAINT()    
    44.     ON_WM_SIZE()  
    45.     ON_WM_ERASEBKGND()    
    46.     ON_WM_CREATE()  
    47.     ON_MESSAGE(MYWM_BTN_CLICK, &MyTabControl::OnBtnClose)  
    48.     ON_WM_CTLCOLOR()  
    49. END_MESSAGE_MAP()  
    50.   
    51. // MyTabControl 消息处理程序  
    52. bool MyTabControl::Create(CWnd* pParent,CRect rc,CString text,DWORD id /* = 0 */,DWORD style /* = WS_VISIBLE|WS_CHILD */)    
    53. {    
    54.     // 动态创建控件     
    55.     BOOL ret = CWnd::CreateEx(0, szClassName, text, style, rc, pParent, id);  
    56.     return ret ? true : false;    
    57. }    
    58.   
    59. int MyTabControl::OnCreate(LPCREATESTRUCT lpCreateStruct)  
    60. {  
    61.       
    62.     //::SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED);  
    63.     m_pImgNor = CQYUtility::LoadImgFromRes(_T("PNG"), IDB_PNG_TAB_NOR);  
    64.     m_pImgHot = CQYUtility::LoadImgFromRes(_T("PNG"), IDB_PNG_TAB_HOT);  
    65.     m_pImgDown = CQYUtility::LoadImgFromRes(_T("PNG"), IDB_PNG_TAB_DOWN);  
    66.       
    67.     RECT rc = {0, 0, 20, 20};  
    68.     m_btnClose.LoadBtnImg(_T("PNG"),IDB_PNG_TAB_CLOSE_NOR, IDB_PNG_TAB_CLOSE_HOT,IDB_PNG_TAB_CLOSE_HOT);  
    69.     m_btnClose.Create(this, rc, L"",ID_BTN_MYTAB_CLOSE);          
    70.     m_btnClose.SetToolTipText(_T("关闭"));          
    71.     EnableToolTips(TRUE);  
    72.     return 0;  
    73. }  
    74.   
    75. void MyTabControl::PostClickEvent()    
    76. {    
    77.     if (m_tabState == TAB_STATE_DOWN)  
    78.         return;     //选中的tab不响应单击了  
    79.     // 该函数用来向父窗口发送 单击 消息    
    80.     CWnd* parent = GetParent();    
    81.     if(parent)    
    82.         parent->SendMessage(MYWM_BTN_TAB_CLICK,m_nIndex,0);        
    83. }    
    84.   
    85. void MyTabControl::OnMouseHover(UINT nFlags, CPoint point)    
    86. {    
    87.     // 鼠标进入    
    88.     Invalidate();    
    89. }    
    90.   
    91. void MyTabControl::OnMouseMove(UINT nFlags, CPoint point)  
    92. {  
    93.     // 只处理鼠标第一次进入时的情况    
    94.     if(!m_isMouseHover)    
    95.     {    
    96.         m_isMouseHover = true;    
    97.   
    98.         TRACKMOUSEEVENT evt = { sizeof(evt), TME_LEAVE|TME_HOVER, m_hWnd, 0 };    
    99.         TrackMouseEvent(&evt);    
    100.   
    101.         OnMouseHover(0,CPoint());    
    102.     }    
    103. }  
    104.   
    105. void MyTabControl::OnMouseLeave()    
    106. {    
    107.     // 鼠标离开    
    108.     m_isMouseHover = false;    
    109.     m_isMouseClicked = false;    
    110.     Invalidate();    
    111. }    
    112.   
    113. void MyTabControl::OnLButtonDown(UINT nFlags, CPoint point)    
    114. {    
    115.     // 鼠标按下    
    116.     m_isMouseClicked = true;    
    117.     Invalidate();    
    118. }    
    119.   
    120. void MyTabControl::OnLButtonUp(UINT nFlags, CPoint point)    
    121. {    
    122.     // 鼠标松开    
    123.     if(m_isMouseClicked)    
    124.     {    
    125.         m_isMouseClicked = false;    
    126.         Invalidate();   
    127.         PostClickEvent();    
    128.     }    
    129. }    
    130.   
    131. BOOL MyTabControl::OnEraseBkgnd(CDC* pDC)    
    132. {    
    133. //  return CWnd::OnEraseBkgnd(pDC);  
    134.     return TRUE;    // 阻止擦除背景,防止闪烁    
    135. }    
    136.   
    137. void MyTabControl::OnPaint()    
    138. {    
    139.     CPaintDC dc(this);     
    140.     CRect rc;    
    141.     GetClientRect(&rc);   
    142.       
    143.     // 采用双缓存,防止闪烁    
    144.     CMemDC memdc(&dc,&rc,TRUE);  
    145.     Graphics graphic(memdc);  
    146.     if (!m_pImgNor || !m_pImgHot || !m_pImgDown)  
    147.     {//没有提供按钮图片就刷下背景  
    148.         // 刷背景    
    149.         COLORREF bkgnd = RGB(100,0,0);    
    150.         if(m_isMouseHover)    
    151.         {    
    152.             if(m_isMouseClicked)    
    153.                 bkgnd = RGB(250,0,0);    
    154.             else    
    155.                 bkgnd = RGB(180,0,0);    
    156.         }    
    157.         memdc.FillSolidRect(&rc,bkgnd);    
    158.     }  
    159.       
    160.     if (m_isMouseClicked || m_tabState == TAB_STATE_DOWN)  
    161.     {//单击一定画单击状态  
    162.         graphic.DrawImage(m_pImgDown, 0, 0, m_pImgDown->GetWidth(), m_pImgDown->GetHeight());  
    163.     }  
    164.     else if (m_isMouseHover && !m_isMouseClicked)  
    165.     {  
    166.         //悬浮,但是没单击  
    167.         graphic.DrawImage(m_pImgHot, 0, 0, m_pImgHot->GetWidth(), m_pImgHot->GetHeight());          
    168.     }  
    169.     else  
    170.     {  
    171.         graphic.DrawImage(m_pImgNor, 0, 0, m_pImgNor->GetWidth(), m_pImgNor->GetHeight());      
    172.     }  
    173.   
    174.     if (!m_strTabText.IsEmpty())  
    175.     {  
    176.         // 设置文字字体    
    177.         CFont font;    
    178.         font.CreatePointFont(100,L"宋体"); // 11号字体,该参数与实际字体号有10倍的关系    
    179.         CFont* poldFont = memdc.SelectObject(&font);    
    180.         // 设置文字属性    
    181.         memdc.SetBkMode(TRANSPARENT);    
    182.         if (m_tabState == TAB_STATE_DOWN)  
    183.             memdc.SetTextColor(RGB(136,76,25));    
    184.         else  
    185.             memdc.SetTextColor(RGB(255,245,190));    
    186.         // 绘制文本    
    187.         DWORD style = DT_SINGLELINE | DT_VCENTER ;   // 文本格式:单行+水平居中+垂直居中    
    188.         //if (m_bCenterAlign)  
    189.         //  style |= DT_CENTER;  
    190.         CRect fontRect(rc);  
    191.         fontRect.left += 13;  
    192.         fontRect.right -= 22;  
    193.         memdc.DrawText(m_strTabText, -1, &fontRect, style);    // 更多文本显示格式可参考百度百科DrawText说明   
    194.         memdc->SelectObject(poldFont);         
    195.     }  
    196.       
    197.     // 使绘制生效    
    198.     graphic.ReleaseHDC(memdc);            
    199. }    
    200.   
    201.   
    202. BOOL MyTabControl::PreTranslateMessage(MSG* pMsg)   
    203. {  
    204.     if (m_pToolTip)  
    205.     {  
    206.         if (::IsWindow(m_pToolTip->m_hWnd))  
    207.         {  
    208.             m_pToolTip->RelayEvent(pMsg);          
    209.         }  
    210.     }  
    211.   
    212.     return CWnd::PreTranslateMessage(pMsg);  
    213. }  
    214.   
    215.   
    216. void MyTabControl::OnSize(UINT nType, int cx, int cy)   
    217. {  
    218.     CRect rect;  
    219.     GetClientRect(&rect);     
    220.     m_btnClose.SetWindowPos(NULL, rect.right - 22, rect.top + 2, 20, 20, SWP_NOZORDER);  
    221. }  
    222.   
    223. LRESULT MyTabControl::OnBtnClose(WPARAM wParam, LPARAM lParam)  
    224. {  
    225.     // 该函数用来向父窗口发送 单击 消息    
    226.     CWnd* parent = GetParent();    
    227.     if(parent != NULL)    
    228.     {    
    229.         parent->SendMessage(MYWM_BTN_TAB_CLOSE, m_nIndex, 0);  
    230.     }    
    231.     return 0;  
    232. }  
    233.   
    234. void MyTabControl::SetToolTipText(CString spText, BOOL bActivate)  
    235. {  
    236.     if (m_pToolTip == NULL)  
    237.     {  
    238.         m_pToolTip = new CToolTipCtrl;  
    239.         // Create ToolTip control  
    240.         m_pToolTip->Create(this);  
    241.         m_pToolTip->Activate(TRUE);  
    242.     }  
    243.   
    244.     m_tooltext = spText;  
    245.   
    246.     // If there is no tooltip defined then add it  
    247.     if (m_pToolTip->GetToolCount() == 0)  
    248.     {  
    249.         CRect rectBtn;   
    250.         GetClientRect(rectBtn);  
    251.         m_pToolTip->AddTool(this, m_tooltext, rectBtn, 1);  
    252.     }  
    253.   
    254.     // Set text for tooltip  
    255.     m_pToolTip->UpdateTipText(m_tooltext, this, 1);  
    256.     m_pToolTip->SetDelayTime(2000);  
    257.     m_pToolTip->Activate(bActivate);  
    258. }  
    259.   
    260.   
    261. DWORD MyTabControl::GetComfortSize(HDC hdc,DWORD dwWidth,CString &strText)  
    262. {  
    263.     //二分法查找  
    264.     DWORD dwComfortSize = 0;  
    265.     DWORD dwBeginSize = 0;  
    266.     DWORD dwEndSize = strText.GetLength();  
    267.   
    268.     while(TRUE)  
    269.     {  
    270.         DWORD dwMiddleSize = (dwEndSize + dwBeginSize) / 2;  
    271.         if(dwMiddleSize == dwBeginSize || dwMiddleSize == dwEndSize)  
    272.         {  
    273.             //两个点之间已经没有数值可以检测,退出循环  
    274.             dwComfortSize = dwBeginSize;  
    275.             break;  
    276.         }  
    277.   
    278.         SIZE sizeChk = {0};  
    279.         ::GetTextExtentPoint(hdc, strText.GetBuffer(), dwMiddleSize, &sizeChk);  
    280.   
    281.         if(sizeChk.cx == dwWidth)  
    282.         {  
    283.             //数值刚好合适,跳出循环  
    284.             dwComfortSize = dwMiddleSize;  
    285.             break;  
    286.         }  
    287.         else if(static_cast<DWORD>(sizeChk.cx) > dwWidth)  
    288.         {  
    289.             //重新设置边界  
    290.             dwEndSize = dwMiddleSize;  
    291.         }  
    292.         else  
    293.         {  
    294.             //重新设置边界  
    295.             dwBeginSize = dwMiddleSize;  
    296.         }  
    297.   
    298.     }  
    299.   
    300.     return dwComfortSize;  
    301. }  
    302.   
    303. void MyTabControl::SetShowText(CString strShowText)  
    304. {  
    305.     m_strShowText = strShowText;  
    306.   
    307.     CRect rect;  
    308.     GetClientRect(&rect);  
    309.     SIZE sizeEllipsis = {0};  
    310.     ::GetTextExtentPoint(GetDC()->GetSafeHdc(), strShowText.GetBuffer(), lstrlen(strShowText.GetBuffer()), &sizeEllipsis);  
    311.     if (sizeEllipsis.cx  < rect.Width() - 40)  
    312.     {//显示区域够宽  
    313.         m_bCenterAlign = true;  
    314.         m_strTabText = strShowText;  
    315.         return;  
    316.     }  
    317.     memset(&sizeEllipsis,0, sizeof(sizeEllipsis));  
    318.     CString ellipsStr = _T("...");  
    319.     ::GetTextExtentPoint(GetDC()->GetSafeHdc(), ellipsStr.GetBuffer(), lstrlen(ellipsStr.GetBuffer()), &sizeEllipsis);  
    320.     DWORD dwMaxDisp = GetComfortSize(GetDC()->GetSafeHdc(), rect.Width() - sizeEllipsis.cx - 20, strShowText);  
    321.     if (dwMaxDisp >= strShowText.GetLength())  
    322.     {  
    323.         m_strTabText = strShowText;  
    324.     }  
    325.     else  
    326.     {  
    327.         m_strTabText = m_strShowText.Left(dwMaxDisp);  
    328.         m_strTabText += ellipsStr;        
    329.     }     
    330.   
    331. }  
    332.   
    333.   
    334.   
    335. HBRUSH MyTabControl::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
    336. {  
    337.     HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor);  
    338.   
    339.     // TODO:  在此更改 DC 的任何属性  
    340. //  m_btnClose.SetBkGnd(pDC);  
    341.     // TODO:  如果默认的不是所需画笔,则返回另一个画笔  
    342.     return hbr;  
    343. }  


    //内存DC类和按钮类见链接:点击打开链接

    http://blog.csdn.net/huasonl88/article/details/43227291

  • 相关阅读:
    纸壳CMS替换默认实现
    ASP.Net Core 2.2 InProcess托管的Bug:unable to open database file
    GitHub设置使用SSH Key,用TortoiseGit进行Clone仓库
    在Docker中运行纸壳CMS并配置使用MySql
    使用vs code开发纸壳CMS并启用Razor智能提示
    ASP .Net Core路由(Route)
    .Net Core在Middleware中解析RouteData
    纸壳CMS可视化建站系统搭建多语言网站
    Redis的初识
    C#/Java 动态生成电子发票
  • 原文地址:https://www.cnblogs.com/findumars/p/5625143.html
Copyright © 2020-2023  润新知