网站制作案例价格,建筑公司网站董事长致辞,个人博客网站logo,仲恺做网站最近要写一个MFC的对话框程序#xff0c;发现要把MFC的对话框写的有色彩点并不容易#xff0c;不像在C#里设置属性指就好#xff0c;而是要自己去写一些代码完成对话框的绘画操作。比如一个简单的鼠标移入、移出操作#xff0c;都要自己去写代码。由于我只用到了Button和St… 最近要写一个MFC的对话框程序发现要把MFC的对话框写的有色彩点并不容易不像在C#里设置属性指就好而是要自己去写一些代码完成对话框的绘画操作。比如一个简单的鼠标移入、移出操作都要自己去写代码。由于我只用到了Button和Static两种控件一切看上去还是比较顺利所以谈谈自己的经验。1、对话框的背景MFC中没有属性能够设定对话框的背景颜色或是图片需要我们在程序中进行操作。首先需要实现WM_CTLCOLOR的消息操作通过这个消息我们能够控制对话框以及Static控件(包括Group)的背景色、前景色。该消息的处理函数原型如下HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)其中通过pDC能够文件的颜色、背景模式通过pWnd可以获取正在绘制的控件ID通过nCtlColor可以判断当前正在绘制的控件类型。这里我需要控制对话框的背景所以要进行如下操作HBRUSH hbr CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); if (nCtlColor CTLCOLOR_DLG){return m_backgroundBrush; //返回对话框背景的画刷}else if (nCtlColor CTLCOLOR_STATIC){pDC-SetBkMode(TRANSPARENT); //所有Static控件的背景色为透明 if (pWnd-GetDlgCtrlID() IDC_NOTE) { pDC-SetTextColor(RGB(255, 255, 255)); //针对特殊的static控件设置单独的文字颜色 }}return hbr; //不是要自绘的控件返回默认值2、按钮(Button)控件一开始很奇怪在WM_CTLCOLOR的消息处理函数进行如下操作竟然没有用 if (pWnd-GetDlgCtrlID() IDB_TEST) //按钮文字颜色 { pDC-SetTextColor(RGB(0, 0, 255)); } 原来按钮控件的颜色、背景等属性无法通过WM_CTLCOLOR消息实现要改变这些属性就必须要自己从CButton类继承一个类然后改写其绘画函数——DrawItem。通过DrawItem函数的参数可以获取控件的大小、状态、类型、绘画DC等信息有了它们重绘Button就简单了。下面给出简单实例void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){ if (lpDrawItemStruct-CtlType ! ODT_BUTTON) //由于继承自CButton这一句肯定成立 { return; } CRect rect lpDrawItemStruct-rcItem; CDC *pDC CDC::FromHandle(lpDrawItemStruct-hDC); UINT state lpDrawItemStruct-itemState; TCHAR strText[MAX_PATH] {0}; ::GetWindowText(m_hWnd, strText, MAX_PATH); //获取按钮的状态 if (state ODS_FOCUS) { m_bSelected TRUE; } else { m_bSelected FALSE; } //根据按钮的状态填充按钮的底色 if (m_bOver) { pDC-FillRect(rect, m_overBrush); } else if (m_bSelected) { pDC-FillRect(rect, m_selectedBrush); } else { pDC-FillRect(rect, m_normalBrush); } // 画按钮标题水平和垂直都居中。把DC当作一个画布 // 如果要使DT_VCENTER(垂直居中)有效必须同时设置DT_SINGLELINE(单行)风格 if (_tcslen(strText) 0) { pDC-SelectObject(m_font); pDC-SetBkMode(TRANSPARENT); pDC-SetTextColor(RGB(255, 255, 255)); pDC-DrawText(strText, lpDrawItemStruct-rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER); }}但是写了以上代码发现还是不管用原来还需要设置按钮的属性为自绘类型即需要设置BS_OWNERDRAW属性。这个可以在对话框的OnInitDialog函数或Button类的PreSubClassWindow函数中调用Button的SetButtonStyle方法设置如下UINT uStyle GetButtonStyle(); // 得到按钮的愿风格 SetButtonStyle(uStyle | BS_OWNERDRAW); // 加入自画风格为了判断按钮当前的状态如是否有鼠标停留、焦点等就需要跟踪鼠标的移动这个可以通过WM_MOUSEMOVE消息实现。但是鼠标移入、移出的操作无法通过Vc的Wizard实现在Vs2010里可以通过Wizard添加但是函数不会被调用。为了能够知道鼠标移入、移出操作需要在WM_MOUSEMOVE消息中增加如下代码已跟踪鼠标事件if (!m_bTrack) //记录是否已经设置跟踪事件 { TRACKMOUSEEVENT ent {0}; ent.dwFlags TME_HOVER | TME_LEAVE; ent.cbSize sizeof(TRACKMOUSEEVENT); ent.dwHoverTime 10; ent.hwndTrack this-m_hWnd; m_bTrack TrackMouseEvent(ent); }通过以上代码我们就可以收到WM_MOUSEHOVER、WM_MOUSELEAVE事件通过将鼠标停留时间ent.dwHoverTime(触发WM_MOUSEHOVER的时间)设置为足够短我们就可以模拟出鼠标移入事件。为了能够处理这两个消息需要通过MFCWizard增加WM_MOUSEHOVER、WM_MOUSELEAVE的事件处理函数。 void CMyButton::OnMouseHover(UINT nFlags, CPoint point){ m_bOver TRUE; InvalidateRect(NULL, TRUE); CButton::OnMouseHover(nFlags, point);} void CMyButton::OnMouseLeave(){ m_bTrack FALSE; m_bOver FALSE; InvalidateRect(NULL, FALSE); CButton::OnMouseLeave();}3、Static控件虽然可以通过对话框的WM_CTLCOLOR消息设置Static控件的字体颜色和背景模式但是如果要更好地控制其字体、背景等属性以及添加鼠标事件就要自己写代码了。方法很简单和Button类似需要自己写一个继承自CStatic的类然后改写DrawItem方法实现自己的绘画方法。 只是有一点需要注意默认情况下Static是不发送消息的即鼠标点击、移动等事件是没有效果的需要设置SS_NOTIFY属性这可以在继承Static类的PreSubClassWindow中进行入操作设置ModifyStyle(SS_TYPEMASK, SS_OWNERDRAW|SS_NOTIFY);以上代码同时设置自绘和消息通知属性。4、无标题对话框的移动在Windows的应用程序中都可以通过点击标题栏拖拽窗口进行移动但是如果窗口没有标题栏怎么办呢即将对话框的Border属性设置为None如何实现窗口移动呢在我的对话框应用中在窗口顶部放了一个Static控件想把它作为窗口的标题栏通过拖拽Static空间拖动窗口。有两种方法可以实习这个目的。一个很容易想到的方法是写一个继承自CStatic类的自绘控件然后关联该类的对象到充当标题栏的Static控件。通过处理Static控件的WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP消息就可以得知鼠标是否按下、移动、松开然后在WM_MOUSEMOVE的处理函数计算鼠标移动的距离然后获得父窗口的指针通过MoveWindow函数移动父窗口。显然这种方法比较复杂需要进行的操作也比较繁琐。 既然点击标题栏能够移动窗口而点击其他地方却效果不同那么windows肯定通过什么标志来判断要采取什么操作我们应该能够不需要自己去实现移动窗口而是告诉Windows点击Static这个“标题”时就是点击真正的标题栏。控件在响应点击操作之前都会发送WM_NCHITTEST消息用于判断鼠标点击的位置而消息处理函数的返回值就指出了位置。WM_NCHITTEST的处理函数如下 LRESULT CWinAppDlg::OnNcHitTest(CPoint point){ CRect rect; GetDlgItem(IDC_TITLE)-GetClientRect(rect); ClientToScreen(rect); return rect.PtInRect(point) ? HTCAPTION : CDialogEx::OnNcHitTest(point);}在上面的代码中首先获得Static控件IDC_TITLE的位置然后判断鼠标点击位置是否位于控件内如果是则返回HTCAPTION告诉Windows点击的是标题栏否则返回默认值。显然这种移动窗口的做法要简单的多而且它利用MFC的原理进行操作更稳定也更具兼容性。这几句代码也有一个限制即标题栏只能是Static控件因为Static默认是不接收事件、消息所以WM_NCHITTEST由对话框进行处理如果是Button等其他控件WM_NCHITTEST就会发送到控件而不是对话框上。 转载于:https://blog.51cto.com/jslmes/1161756