cdh:
我的还行吧!
今天上网又发现一篇用写的原贴出大家看看。
创 建 任 意 形 状 的 窗 口
北 京 市 朝 阳 区 光 华 路 汉 威 大 厦B1609 室 崔 英 善
---- 在Windows 系 统 中 窗 口 的 默 认 形 状 是 矩 形, 在 实 际 应 用 中 绝 大 多 数 窗 口 都 是 标 准 矩 形 窗 口。 如 果 一 个 窗 口 有 着 与 众 不 同 的 形 状, 则 会 非 常 引 人 注 目, 如 何 创 建 非 标 准 窗 口 呢?
----在Windows, 可 以 通 过 调 用SetWindowRgn ( 在MFC 类 库 中 对 应 的 函 数 为CWnd::SetWindowRgn) 来 设 置 窗 口 的 形 状, 函 数 的 定 义 如 下:
---- int SetWindowRgn( HWND hWnd, HRGN hRgn, BOOL bRedrawflag);
----窗 口 的 形 状 由 参 数 hRgn 所 标 志 的 的 区 域 (region) 决 定。 通 过 创 建 不 同 的 区 域 就 可 以 创 建 不 同 形 状 的 窗 口。 下 面 的 代 码, 可 以 产 生 圆 角 矩 形 的 窗 口。
CRgn trgn ;
trgn.CreateRoundRectRgn( 0 , 0 , 200 , 200 , 30 , 30 ) ;
SetWindowRgn( trgn , TRUE ) ;
----效 果 如 下 图 所 示:
----Windows 还 支 持 由 路 径( Path ) 创 建 区 域 ( Region ), 通 过 这 个 途 径 我 们 还 可 以 创 建 文 字 形 状 的 窗 口。
----下 面 的 代 码 可 以 创 建 形 状 为“ 计 算 机 世 界" 五 个 字 的 窗 口。
+CDC * pDC = GetDC() ;
CFont rfont , *pOldFont ;
CRgn m_rgn ;
rfont.CreatePointFont( 1000 , “ 隶 书" ) ;
pOldFont = pDC ->SelectObject( &rfont ) ;
pDC ->BeginPath() ;
pDC ->SetBkMode( TRANSPARENT ) ;
CString stxt = “ 计 算 机 世 界" ;
pDC ->TextOut( 0 , 0 , stxt ) ;
pDC ->EndPath() ;
m_rgn.CreateFromPath( pDC ) ;
pDC ->SelectObject( pOldFont ) ;
ReleaseDC( pDC ) ;
SetWindowRgn( m_rgn , TRUE ) ;
----效 果 如 下 图 所 示:
----那 么 我 们 能 不 能 创 建 任 意 形 状 的 窗 口 呢? 也 就 是 创 建 任 意 形 状 的 区 域 呢? 答 案 是 肯 定 的。 大 家 请 看 下 面 这 个 圆 号 形 状 的 窗 口。
----创 建 这 样 的 一 个 区 域 是 调 用 SDK 的 ExtCreateRegion 来 实 现( MFC 中 的 对 应 函 数 为CRgn::CreateFromData)。 这 个 函 数 是 通 过 提 供 一 个 矩 形 数 组, 来 创 建 一 个 由 这 些 矩 形 组 成 的 区 域。 而 创 建 圆 号 区 域 的 过 程 就 是 由 一 个 圆 号 的 位 图 生 成 矩 形 数 组, 再 由 这 个 矩 形 数 组 生 成 区 域 的 过 程。
----下 面 是 由 圆 号 位 图 创 建 区 域 的 函 数 代 码。
CDib m_dib ;
CRgn m_rgn ;
COLORREF m_dwColorKey = 0x0000ff; // 透 明 色, 纯 蓝
BOOL CAswDlg::CreateRegionFromBmp( LPCSTR lpsFName )
{
// 读 入 位 图
if( !m_dib.Open( lpsFName ) )
return FALSE ;
SIZE dibsize ;
// 获 取 位 图 尺 寸
dibsize = m_dib.GetSize( ) ;
int i , j ;
BOOL bkey ;
int iCount = 0 ;
// 统 计 需 要 的 矩 形 个 数
for( i = 0 ; i < dibsize.cy ; i + + )
{
bkey = TRUE ;
for( j = 0 ; j < dibsize.cx ; j + + )
{
if( m_dib.GetPixel( j , i ) == m_dwColorKey )
{
bkey = TRUE ;
}
else
{
if( bkey )
{
iCount + + ;
}
bkey = FALSE ;
}
}
}
BYTE *pData ;
RGNDATA *pRgnData ;
RECT *pRect ;
int iIndex = 0 ;
pData = new BYTE[ sizeof
( RGNDATAHEADER ) + sizeof( RECT ) * iCount ] ;
pRgnData = ( RGNDATA * )pData ;
pRect = ( RECT * )( pData + sizeof( RGNDATAHEADER ) ) ;
pRgnData ->rdh.dwSize =sizeo(RGNDATAHEADER ) ;
pRgnData ->rdh.iType =RDH_RECTANGLES ;
pRgnData ->rdh.nCount = iCount ;
pRgnData ->rdh.nRgnSize = sizeof( RECT ) *iCount ;
pRgnData ->rdh.rcBound.left = 0 ;
pRgnData ->rdh.rcBound.top = 0 ;
pRgnData ->rdh.rcBound.right =dibsize.cx ;
pRgnData ->rdh.rcBound.bottom = dibsize.cy ;
int iLeft = 0 ;
for( i = dibsize.cy - 1 ; i >= 0 ; i - - )
// 因 为Bitmap 位 图 在Y 方 向 是 颠 倒
的 所 以 要 从 底 部 开 始
{
bkey = TRUE ;
iLeft = -1 ;
for( j = 0 ; j < dibsize.cx ; j + + )
{
if( m_dib.GetPixel( j , i ) == m_dwColorKey )
{
if( !bkey )
{
pRect[ iIndex ].left = iLeft ;
pRect[ iIndex ].right = j ;
pRect[ iIndex ].top = dibsize.cy - i - 1 ;
pRect[iIndex].bottom = dibsize.cy -i;
bkey = TRUE ;
iIndex + + ;
iLeft = -1 ;
}
}
else
{
if( bkey )
{
iLeft = j ;
bkey = FALSE ;
}
}
}
if( iLeft >= 0 )
{
pRect[ iIndex ].left = iLeft ;
pRect[ iIndex ].right = dibsize.cx ;
pRect[ iIndex ].top = i ;
pRect[ iIndex ].bottom = i ;
iIndex + + ;
}
}
BOOL br = m_rgn.CreateFromData
( NULL , sizeof( RGNDATAHEADER ) +sizeof
( RECT ) * iCount , pRgnData ) ;
return br ;
}
----有 了 这 个 方 法, 任 意 形 状 的 窗 口 都 可 以 被 创 建, 只 要 先 画 出 想 要 的 形 状 位 图 即 可。
----这 里 还 要 谈 到 一 个 问 题, 任 意 形 状 的 窗 口 没 有 标 题 栏, 那 么 用 户 如 何 拖 动 窗 口 呢? 其 实 只 要 在 响 应 左 键 点 击 消 息 时 调 用SendMessage( WM_SYSCOMMAND , SC_MOVE | HTCLIENT , 0 ) 即 可。