场景
1.在Win32
窗口开发或基于Win32
的WTL
库开发时,我们经常创建新窗口或新控件都会使用WS_CLIPSIBLINGS | WS_CLIPCHILDREN
两个属性, 那么这两个属性有什么用呢?好像不加也没问题.
2.有时候我们刷新或拉伸父窗口时,它的子控件移动后会显示透明,看起来像是没绘制一样.什么原因?
说明
WS_CLIPCHILDREN
: 这个样式如果设置了,当前窗口刷新指定区域时,该区域的子窗口都不会刷新。没设置这个属性,那么子窗口就会刷新.
WS_CLIPSIBLINGS
: 如果有WS_CLIPSIBLINGS属性,只有接收WM_PAINT消息的子窗口全部刷新,而其他子窗口和它重叠的区域不刷新,只刷新非重叠区域. 去掉 WS_CLIPSIBLINGS 时,子窗口的重叠区域也会刷新。
也就是说,WS_CLIPSIBLINGS
能优化刷新重复区域,只刷新一次,每次创建都可以加上. 而WS_CLIPCHILDREN
根据情况加,如果想自己控制子窗口刷新不受父窗口影响,那么可以在父窗口创建时加上WS_CLIPCHILDREN
;如果不想自己控制子窗口的刷新,需要父窗口刷新时,子窗口也刷新,那么可以去掉WS_CLIPCHILDREN
样式.
代码
MyButton.h
#ifndef MY_BUTTON
#define MY_BUTTON
class MyButton : public CWindowImpl<MyButton,CButton>
{
public:
DECLARE_WND_CLASS(NULL)
BEGIN_MSG_MAP_EX(MyButton)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};
#endif
MyButton.cpp
#include "stdafx.h"
#include "MyButton.h"
#include <string>
LRESULT MyButton::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
auto _id = GetWindowLong(GWL_ID);
auto str_id = std::to_wstring((long long)_id);
str_id.append(L":MyButton::OnPaint\n");
OutputDebugString(str_id.c_str());
bHandled = FALSE;
return 0;
}
View.h
// View.h : interface of the CView class
//
/////////////////////////////////////////////////////////////////////////////
#pragma once
#include "atlmisc.h"
#include "MyButton.h"
enum
{
kButtonId1 = WM_USER +1,
kButtonId2
};
class CView : public CWindowImpl<CView>
{
public:
DECLARE_WND_CLASS(NULL)
BOOL PreTranslateMessage(MSG* pMsg);
BEGIN_MSG_MAP_EX(CView)
MSG_WM_CREATE(OnCreate)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MSG_WM_TIMER(OnTimer)
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
int OnCreate(LPCREATESTRUCT lpCreateStruct);
void OnTimer(UINT_PTR nIDEvent);
private:
MyButton button1_;
CRect rect1_;
MyButton button2_;
CRect rect2_;
};
View.cpp
// View.cpp : implementation of the CView class
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "resource.h"
#include "View.h"
BOOL CView::PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}
LRESULT CView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CPaintDC dc(m_hWnd);
//TODO: Add your drawing code here
return 0;
}
void CView::OnTimer(UINT_PTR nIDEvent)
{
OutputDebugString(L"CView::OnTimer\n");
InvalidateRect(rect1_);
}
int CView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
button1_.Create(m_hWnd,0,L"Tobey",WS_VISIBLE|WS_CHILD,0,kButtonId1);
CSize size;
button1_.GetIdealSize(&size);
rect1_.left = 100;
rect1_.top = 200;
rect1_.right = rect1_.left+size.cx;
rect1_.bottom = rect1_.top+size.cy;
button1_.SetWindowPos(NULL,rect1_,
(SWP_NOZORDER | SWP_NOREPOSITION | SWP_NOACTIVATE));
button2_.Create(m_hWnd,0,L"At Work",WS_VISIBLE|WS_CHILD,0,kButtonId2);
button2_.GetIdealSize(&size);
rect2_.left = 100;
rect2_.top = 220;
rect2_.right = rect2_.left+size.cx;
rect2_.bottom = rect2_.top+size.cy;
button2_.SetWindowPos(NULL,rect2_,
(SWP_NOZORDER | SWP_NOREPOSITION | SWP_NOACTIVATE));
SetTimer(1,2000);
return 0;
}
图示1:
项目下载地址: