大家先看一个原理图(假设区域2,3,4,5的高度都为1像素):
由图,非圆角矩形是整个虚线围成的矩形区域(rcClient),而所要的圆角矩形是最外围实线形成的区域(
rgnWindow)。 现在我们把整个圆角矩形进行分解:
1. rcClient上下各偏移2像素的矩形区域 Rect( rcClient.left, rcClient.top + 2, rcClient.right, rcClient.bottom - 2)
2. rcClinet 左右偏移2像素,高度为1像素的矩形区域 Rect( rcClient.left + 2, rcClient.top, rcClient.right - 2, rcClient.top + 1)
3. 与2区域上下对称的矩形区域 。
4. rcClient左右偏移1像素,高度为1像素的矩形区域 Rect( rcClient.left + 1, rcClient.top + 1, rcClient.right - 1, rcClient.top + 2)
5. 与4区域上下对称的矩形区域。
我们可以很简单的得到上面的5个区域的矩形,然后利用VC中多边形的组合便可以得到如上想要的圆角矩形区域。
下面是金山卫士开源出来的一段实现圆角矩形的代码(其中注释1----5 的地方法对应于上面的分解的5个矩形区域):
template <class T>
class CWHRoundRectFrameHelper
{
...........
protected:
...........
void OnSize(UINT nType, CSize size)
{
T *pT = static_cast<T*>(this);
if (nType == SIZE_MINIMIZED)
return;
if (size == m_sizeWnd)
return;
CRect rcWindow, rcClient;
CRgn rgnWindow, rgnMinus, rgnAdd;
pT->GetWindowRect(rcWindow);
pT->GetClientRect(rcClient);
pT->ClientToScreen(rcClient);
rcClient.OffsetRect(- rcWindow.TopLeft());
//1
rgnWindow.CreateRectRgn(rcClient.left, rcClient.top + 2, rcClient.right, rcClient.bottom - 2);
//2
rgnAdd.CreateRectRgn(rcClient.left + 2, rcClient.top, rcClient.right - 2, rcClient.top + 1);
rgnWindow.CombineRgn(rgnAdd, RGN_OR);
//3
rgnAdd.OffsetRgn(0, rcClient.Height() - 1);
rgnWindow.CombineRgn(rgnAdd, RGN_OR);
//4
rgnAdd.SetRectRgn(rcClient.left + 1, rcClient.top + 1, rcClient.right - 1, rcClient.top + 2);
rgnWindow.CombineRgn(rgnAdd, RGN_OR);
//5
rgnAdd.OffsetRgn(0, rcClient.Height() - 3);
rgnWindow.CombineRgn(rgnAdd, RGN_OR);
pT->SetWindowRgn(rgnWindow);
m_sizeWnd = size;
}
............
};
1. rcClient上下各偏移2像素的矩形区域 Rect( rcClient.left, rcClient.top + 2, rcClient.right, rcClient.bottom - 2)
2. rcClinet 左右偏移2像素,高度为1像素的矩形区域 Rect( rcClient.left + 2, rcClient.top, rcClient.right - 2, rcClient.top + 1)
3. 与2区域上下对称的矩形区域 。
4. rcClient左右偏移1像素,高度为1像素的矩形区域 Rect( rcClient.left + 1, rcClient.top + 1, rcClient.right - 1, rcClient.top + 2)
5. 与4区域上下对称的矩形区域。
我们可以很简单的得到上面的5个区域的矩形,然后利用VC中多边形的组合便可以得到如上想要的圆角矩形区域。
下面是金山卫士开源出来的一段实现圆角矩形的代码(其中注释1----5 的地方法对应于上面的分解的5个矩形区域):
template <class T>
class CWHRoundRectFrameHelper
{
...........
protected:
...........
void OnSize(UINT nType, CSize size)
{
T *pT = static_cast<T*>(this);
if (nType == SIZE_MINIMIZED)
return;
if (size == m_sizeWnd)
return;
CRect rcWindow, rcClient;
CRgn rgnWindow, rgnMinus, rgnAdd;
pT->GetWindowRect(rcWindow);
pT->GetClientRect(rcClient);
pT->ClientToScreen(rcClient);
rcClient.OffsetRect(- rcWindow.TopLeft());
//1
rgnWindow.CreateRectRgn(rcClient.left, rcClient.top + 2, rcClient.right, rcClient.bottom - 2);
//2
rgnAdd.CreateRectRgn(rcClient.left + 2, rcClient.top, rcClient.right - 2, rcClient.top + 1);
rgnWindow.CombineRgn(rgnAdd, RGN_OR);
//3
rgnAdd.OffsetRgn(0, rcClient.Height() - 1);
rgnWindow.CombineRgn(rgnAdd, RGN_OR);
//4
rgnAdd.SetRectRgn(rcClient.left + 1, rcClient.top + 1, rcClient.right - 1, rcClient.top + 2);
rgnWindow.CombineRgn(rgnAdd, RGN_OR);
//5
rgnAdd.OffsetRgn(0, rcClient.Height() - 3);
rgnWindow.CombineRgn(rgnAdd, RGN_OR);
pT->SetWindowRgn(rgnWindow);
m_sizeWnd = size;
}
............
};