VC++界面编程之--获取父窗口背景画刷(附带时钟控件)

来源:互联网 发布:美图秀秀 淘宝 编辑:程序博客网 时间:2024/06/06 19:08

在WTL界面编程中,获取父窗口的背景画刷是经常要用到的,如下图的时钟:

时钟是每隔一秒就变化一次,所以当重画时钟时,需要先为其填充背景,以确保上一次描绘的部分被清理干净。当然,我们描绘时钟的图片是用PNG格式制作的,所以其支持透明背景色。但如果不手动清楚背景图片的话,将会变成下面这个样子:

阴影部分越来越浓了,唯一能做的是刷新父窗口,不过这将引起窗口抖动。所以我们需要在每次绘制时钟时,需要手动获取父窗口画刷,先填充时钟背景,然后再画时钟。


获取父窗口画刷的办法是通过窗口消息:WM_ERASEBKGND、WM_PAINT或者是不常用的WM_PRINTCLIENT来完成的。获取画刷之前,我们须得确定父窗口是在哪个消息下进行重绘的。原始的Windows窗口是在WM_ERASEBKGND下进行重绘的。


如果父窗口是在WM_ERASEBKGND下进行重绘,但获取背景画刷的消息是WM_PAINT,那么我们就不能正常获取其背景画刷,取而代之的是一个空画刷,如下图,左边红色的时钟获取了一个空画刷,背景变成了黑色。

如果父窗口是在WM_PAINT下重绘的,需要在WM_PAINT消息中使用如下处理,需注意wParam是否为空,如果不为空,那么就代表父窗口下的某个子窗体控件,需要获取其背景画刷:

LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/){// wParam not NULL means some sub window want get its background brush.if (wParam != NULL){Graphics g( (HDC)wParam );DoPaint(g);}else{CPaintDC dc(m_hWnd);Graphics g(dc.m_hDC);DoPaint(g);}return 0;}

运行后的效果如下,原来白色花瓣时钟的背景现在变成黑色的了,因为其是通过WM_ERASEBKGND来获取背景画刷的,但这里我只让WM_ERASEBKGND消息返回了1,所以白色花瓣时钟便无法获取背景画刷了。

在GDI+编程中,如果想要获取父窗口背景画刷,须由GDI先来获取,因为WM_PAINT和WM_ERASEBKGND的参数都是属于GDI的。然后将GDI中的CBitmap转为GDI+的Brush即可。下面是获取父窗口背景画刷的代码:

// Get background brush.TextureBrush* GetBackGroundBrush(CWindow Window, CWindow ParentWindow, GET_BRUSH_TYPE brush_type = GET_BY_WM_PAINT){if (Window.m_hWnd == NULL || ParentWindow.m_hWnd == NULL){return NULL;}// Delete old brush.DeleteOldBrush();// Get parent window hdc.CRect rcParent;ParentWindow.GetWindowRect(&rcParent);CClientDC dcParent = ParentWindow;CDC dcCompat;dcCompat.CreateCompatibleDC(dcParent);CBitmap bmpParent;bmpParent.CreateCompatibleBitmap(dcParent, rcParent.Width(), rcParent.Height());dcCompat.SelectBitmap(bmpParent);switch (brush_type){default:case GET_BY_WM_ERASEBKGND:{ ParentWindow.SendMessage(WM_ERASEBKGND, (WPARAM) (HDC) dcCompat, 0); break; }case GET_BY_WM_PAINT:{ ParentWindow.SendMessage(WM_PAINT, (WPARAM) (HDC) dcCompat, (LPARAM)(PRF_ERASEBKGND | PRF_CLIENT | PRF_NONCLIENT)); break; }case GET_BY_WM_PRINTCLIENT:{ ParentWindow.SendMessage(WM_PRINTCLIENT, (WPARAM) (HDC) dcCompat, (LPARAM)(PRF_ERASEBKGND | PRF_CLIENT | PRF_NONCLIENT)); break; }}// Draw parent window image to bitmap.CRect rcWindow;Window.GetWindowRect(&rcWindow);CDC dcWindow;dcWindow.CreateCompatibleDC();CBitmap bmpWidnow;bmpWidnow.CreateCompatibleBitmap(dcCompat, rcWindow.Width(), rcWindow.Height());dcWindow.SelectBitmap(bmpWidnow);CRect rcSnap = rcWindow;::MapWindowPoints(NULL, ParentWindow.m_hWnd, (LPPOINT) (LPRECT) &rcSnap, 2);dcWindow.BitBlt(0, 0, rcWindow.Width(), rcWindow.Height(), dcCompat, rcSnap.left, rcSnap.top, SRCCOPY);// Create Brush via bitmap.m_pBitmap= Bitmap::FromHBITMAP(bmpWidnow.m_hBitmap, NULL);m_pBrush= new TextureBrush(m_pBitmap);return m_pBrush;}};

附本文的源代码工程项目:http://download.csdn.net/detail/renstarone/5773661里面有一个时钟控件及获取父窗口背景画刷类。

原创粉丝点击