MFC对话框标题栏颜色自绘,标题栏由过渡色组成,自绘关闭按钮

xiaoxiao2021-02-28  22

一个简单的标题栏自绘 一:步骤 (1)新建一个基于对话框的MFC程序,打开对话框属性设置界面,去掉对话框的标题栏和边界BORDER(vc和vs的设置相似,这里使用的是vs2015,界面与vc稍有不同), (2)在客户曲自绘一个标题栏和关闭按钮,需要使用到WM_PAINT消息的处理函数,使用Class WIZARD添加OnPaint()消息相应函数 (3)为了使自绘的标题栏能够用鼠标拖动窗口,并且使自绘的关闭按钮能够关闭界面,需要使用到OnNcHitTest(…)消息处理函数和OnLButtonDown(…)消息处理函数

二:函数解释: (1)LRESULT CTest2Dlg::OnNcHitTest(CPoint point) 功能:每当鼠标移动时,框架就为包含光标(或者是用SetCapture成员函数捕获了鼠标输入的CWnd对象)的CWnd对象调用这个成员函数

参数:point,当前鼠标的坐标,相对于屏幕坐标系

返回值:表示点击位置的类型,有以下类型 HTBORDER:在不具有可变大小边框的窗口的边框上 HTBOTTOM:在窗口的水平边框的底部 HTBOTTOMLEFT:在窗口边框的左下角 HTBOTTOMRIGHT:在窗口边框的右下角 HTCAPTION:在标题条中 HTCLIENT:在客户区中 HTERROR:HTERROR 在屏幕背景或窗口之间的分隔线上(与HTNOWHERE相同,除了 Windows的DefWndProc函数产生一个系统响声以指明错误) HTGROWBOX:在尺寸框中 HTHSCROLL:在水平滚动条上 HTLEFT:在窗口的左边框上 HTMAXBUTTON:在最大化按钮上 HTMENU:在菜单区域 HTMINBUTTON:在最小化按钮上 HTNOWHERE:在屏幕背景或窗口之间的分割线上 HTREDUCE:在最小化按钮上 HTRIGHT:在窗口的右边框上 HTSIZE:在尺寸框中(与HTGROWBOX相同) HTSYSMENU:在控制菜单或子窗口的关闭按钮上 HTTOP:在窗口水平边框的上方 HTTOPLEFT:在窗口水平边框的左上角 HTTOPRIGHT:在窗口边框的右上角 HTTRANSPARENT:在一个被其他窗口覆盖的窗口中 HTVSCROLL:在垂直滚动条中 HTZOOM:在最大化按钮上

(2)void CTest2Dlg::OnLButtonDown(UINT nFlags, CPoint point) 功能:当鼠标点击自绘的关闭按钮时,关闭窗口 参数:nFlags,指示各种虚拟键是否按下。此参数可以是下列值的任意组合: 如果按下CTRL键,MK_CONTROL 设置。 如果鼠标左键滚动,MK_LBUTTON 设置。 如果元鼠标按钮处于按下,MK_MBUTTON 设置。 如果鼠标右键滚动,MK_RBUTTON 设置。 如果SHIFT键下降,MK_SHIFT 设置。 point 指定光标的x坐标和y坐标。这些坐标始终是相对于窗口左上角的。

(3) BOOL PtInRect( POINT point ) const throw( ); 功能:检测某个点是否在某个矩形中 参数:point 包含POINT 结构或 CPoint 对象。 返回值 非零,则点在 CRect之间;否则为0。

(4)CDC::DrawText enter description here

三:代码 Test2Dlg.h头文件,添加一个存放关闭按钮矩形位置的CRect对象m_rtBtnClose;然后使用类相对添加相关消息相应函数

// Test2Dlg.h : header file // #pragma once // CTest2Dlg dialog class CTest2Dlg : public CDialogEx { public: CRect m_rtBtnClose; // Construction public: CTest2Dlg(CWnd* pParent = NULL); // standard constructor // Dialog Data #ifdef AFX_DESIGN_TIME enum { IDD = IDD_TEST2_DIALOG }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: HICON m_hIcon; // Generated message map functions virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnNcPaint(); afx_msg LRESULT OnNcHitTest(CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); };

Test2Dlg.cpp实现

// Test2Dlg.cpp : implementation file // #include "stdafx.h" #include "Test2.h" #include "Test2Dlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CAboutDlg dialog used for App About class CAboutDlg : public CDialogEx { public: CAboutDlg(); // Dialog Data #ifdef AFX_DESIGN_TIME enum { IDD = IDD_ABOUTBOX }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CTest2Dlg dialog CTest2Dlg::CTest2Dlg(CWnd* pParent /*=NULL*/) : CDialogEx(IDD_TEST2_DIALOG, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CTest2Dlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CTest2Dlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_NCPAINT() ON_WM_NCHITTEST() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() END_MESSAGE_MAP() // CTest2Dlg message handlers BOOL CTest2Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } void CTest2Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CTest2Dlg::OnPaint() { CPaintDC dc(this); CRect rect; CRect tmprect; GetClientRect(&rect); rect.bottom = 30; tmprect = rect; int nCount = 165 - 115 + 186 - 158 + 190 - 115; int nIncrecs = (rect.right - rect.left) / nCount; rect.left = rect.right = 0; for(int i=115;i<=165;i++) for(int j=158;j<=186;j++) for(int k=115;k<=190;k++) { rect.left = rect.right; rect.right += nIncrecs; dc.FillSolidRect(rect, RGB(i, j, k)); } // dc.FillSolidRect(rect, RGB(0, 0, 255)); dc.SetBkMode(TRANSPARENT); CString str = TEXT("欢迎使用本软件"); dc.SetTextColor(RGB(255, 0, 0)); dc.DrawText(str, tmprect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//水平居中和垂直居中必须和DT_SINGLELINE搭配,否则起不到效果 //绘制关闭按钮 CRect rtBtnClo; GetClientRect(&rtBtnClo); rtBtnClo.left = rtBtnClo.right - 30; rtBtnClo.right = rtBtnClo.right - 10; rtBtnClo.top = 5; rtBtnClo.bottom = 25; m_rtBtnClose = rtBtnClo; dc.Rectangle(rtBtnClo); dc.MoveTo(rtBtnClo.left, rtBtnClo.top); dc.LineTo(rtBtnClo.right, rtBtnClo.bottom); dc.MoveTo(rtBtnClo.right, rtBtnClo.top); dc.LineTo(rtBtnClo.left, rtBtnClo.bottom); } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CTest2Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CTest2Dlg::OnNcPaint() { // TODO: Add your message handler code here // Do not call CDialogEx::OnNcPaint() for painting messages } LRESULT CTest2Dlg::OnNcHitTest(CPoint point) { // TODO: Add your message handler code here and/or call default UINT nHitTest=CDialogEx::OnNcHitTest(point); CRect rect; GetClientRect(&rect); rect.bottom = 30; //函数参数point是相对于屏幕坐标的,需要将其转换为 //客户区坐标才能使用PtInRect(),否则会因为坐标的不同使判断失误 ScreenToClient(&point); if (rect.PtInRect(point)) { if (HTCLIENT == nHitTest) nHitTest = HTCAPTION; //如果鼠标点中的是关闭按钮的位置,需要将上一步的设置还原, //否则鼠标点击自绘的标题栏的时候,系统无法发送WM_LBUTTONDOWN消息,也就无法处理关闭按钮 if (m_rtBtnClose.PtInRect(point)) { nHitTest = HTCLIENT; } } return nHitTest; } void CTest2Dlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default // ScreenToClient(&point); if (m_rtBtnClose.PtInRect(point)) { //AfxMessageBox(TEXT("测试关闭按钮")); CDialog::OnCancel(); } CDialogEx::OnLButtonDown(nFlags, point); } void CTest2Dlg::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default /*ScreenToClient(&point); if (m_rtBtnClose.PtInRect(point)) { AfxMessageBox(TEXT("测试关闭按钮")); }*/ CDialogEx::OnLButtonUp(nFlags, point); }
转载请注明原文地址: https://www.6miu.com/read-250426.html

最新回复(0)