若有需要做出非預設樣式的視窗時,可以利用 CWnd::SetWindowRgn() 這個 function
這可以用來指定視窗的全部範圍與型狀,
在型狀之外的部份會自動為我們加上背景的遮罩。
只要是繼承自CWnd的元件都可以使用這個 function
但需注意的是並不是所有的元件 SetWindowRgn 都會幫我們加上遮罩,
例如 CButton 就必須手動加上背景圖片,CDialog 就會自動遮罩。
因為遮罩必須隨著視窗縮放時改變,所以習慣將 SetWindowRgn 放在 OnSize() 中
以下是產生一個四邊皆為圓角的 Dialog 之簡單範例
BOOL CreateRgn(CRgn& rgn,RECT& rcBound, int nRectCount, RECT* paRect);
void CDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if(/*不做遮罩的情況,例如已將 Dialog 切至全螢幕狀態*/)
{
// 不做遮罩
SetWindowRgn(NULL, TRUE);
}
else
{
CRgn rgn;
RECT rc[1+5] =
{
{0, 0, cx, cy}, /* 全部視窗區域 */
{0, 3, 1, cy - 3}, /* 左側第一行 */
{1, 1, 3, cy - 1}, /* 左側第二行 */
{3, 0, cx - 3, cy}, /* 中間區域 */
{cx - 3, 1, cx - 1, cy - 1}, /* 右側第二行 */
{cx - 1, 3, cx, cy - 3}, /* 右側第一行 */
};
CreateRgn(rgn, rc[0], 7, rc+1);
SetWindowRgn((HRGN)rgn, TRUE);
rgn.DeleteObject();
}
Invalidate(); // 強制重繪
}
BOOL CreateRgn(CRgn& rgn, RECT& rcBound, int nRectCount, RECT* paRect)
{
//rgn must be a clean CRgn
ASSERT(nRectCount>0);
RGNDATA* p = (RGNDATA*)malloc(sizeof(RGNDATAHEADER) + sizeof(RECT) * nRectCount);
p->rdh.dwSize = sizeof(RGNDATAHEADER);
p->rdh.iType = RDH_RECTANGLES;
p->rdh.nCount = nRectCount;
p->rdh.rcBound = rcBound;
p->rdh.nRgnSize = 0;
memcpy(p->Buffer, paRect, sizeof(RECT) * nRectCount);
BOOL bResult = rgn.CreateFromData(NULL, sizeof(RGNDATAHEADER) + sizeof(RECT) * nRectCount, p);
free(p);
return bResult;
}
在 OnSize() 中寫上這段 code 就可以產生出這種四個角都是圓角的 Dialog
沒有留言:
張貼留言