不规则窗口

oicqkill 2002-02-02 12:50:56
《不规则窗口》
1.到MSDN中去查CRgn(HRGN)的用法便知。
2.窗口可以建立在区域的基础上,所以用window里区域的概念可以实现
3.在Create()中调用:
CreateEx(0,
AfxRegisterWndClass(0),
pTitle,
WS_POPUP and WS_SYSMENU,
rect,
NULL,
NULL,
NULL );
SetWindowRgn((HRGN)wndRgn, TRUE);
其中,wndRgn是一个不规则的区域.
4.可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一
个指定的区域,实际上使窗口成为指定的不规则形状。
使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删
除所在的缺省控件、标题以及边界。
给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。
Class CRoundDlg : public CDialog
{

private :
Crgn m_rgn : // window region

} ;
修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给
窗口:
BOOL CRoundDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( ) ;
//Get size of dialog .
CRect rcDialog ;
GetClientRect (rcDialog );
// Create region and assign to window .
m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width ( ) , rcDialog .Height ( ) );
SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn , TRUE );
return TRUE ;
}
通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例
子程序是修改OnPaint函数使窗口形状看起来象一个球形体。
voik CRoundDlg : : OnPaint ( )
{
CPaintDC de (this) ; // device context for painting .
//draw ellipse with out any border
dc. SelecStockObject (NULL_PEN);
//get the RGB colour components of the sphere color
COLORREF color= RGB( 0 , 0 , 255);
BYTE byRed =GetRValue (color);
BYTE byGreen = GetGValue (color);
BYTE byBlue = GetBValue (color);
// get the size of the view window
Crect rect ;
GetClientRect (rect);
// get minimun number of units
int nUnits =min (rect.right , rect.bottom );
//calculate he horiaontal and vertical step size
float fltStepHorz = (float) rect.right /nUnits ;
float fltStepVert = (float) rect.bottom /nUnits ;
int nEllipse = nUnits/3; // calculate how many to draw
int nIndex ; // current ellipse that is being draw
CBrush brush ; // bursh used for ellipse fill color
CBrush *pBrushOld; // previous brush that was selected into dc
//draw ellipse , gradually moving towards upper-right corner
for (nIndex = 0 ; nIndes < + nEllipse ; nIndes ++)
{
//creat solid brush
brush . CreatSolidBrush (RGB ( ( (nIndex *byRed ) /nEllipse ).
( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue) /nEllipse ) ) );
//select brush into dc
pBrushOld= dc .SelectObject (&brhsh);
//draw ellipse
dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,
rect. right -( (int) fltStepHorz * nIndex )+ 1,
rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1) ;
//delete the brush
brush.DelecteObject ( );
}
}
最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。
UINT CRoundDlg : : OnNchitTest (Cpoint point )
{
//Let user move window by clickign anywhere on the window .
UINT nHitTest = CDialog : : OnNcHitTest (point) ;
rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest ;
}
5.借助CWnd类的SetWindowRgn函数可以创建不规则形状窗口。
函数原型int SetWindowRgn( HRGN hRgn, // 窗口区域句柄
BOOL bRedraw ); // 是否重画窗口
CRgn类封装了关于区域的数据和操作。通过(HRGN)强制操作可以从CRgn类中取得其HRGN值。CRgn提供了CreateRectRgn、CreateEllipticRgn和CreatePolygonRgn成员函数,
分别用以创建矩形、(椭)圆形和多边形区域。
创建非矩形窗口的方法
在窗口类中定义区域类成员数据(如CRgn m_rgnWnd);
在窗口的OnCreate函数或对话框的OnInitDialog函数中调用CRgn类的CreateRectRgn、CreateEllipticRgn或CreatePolygonRgn函数创建所需的区域,并调用SetWindowRgn函数。

《如何实现点一下对话框外面的区域,自动隐藏对话框?》
(chn_gdgf发表于2001-9-7 17:53:05)

[问题提出]
如果想在点击对话框外面的地方使得对话框关闭,该如何做?

[解决方法]
试试下面的代码,原理是在激活对话框时,捕获鼠标的动作,当鼠标点击时判断是否点击在对话框外,是的话就释放对话框.

[程序实现]
建立名为My的对话框程序.实现如下步骤:
在MyDlg.h中加入:

class CShowWindow1Dlg : public CDialog
{
// Construction
public:
int m_cx;
int m_cy;
......
};

在MyDlg.cpp中:

//定义消息映象,处理鼠标单击及激活
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
//{{AFX_MSG_MAP(CMyDlg)
ON_WM_LBUTTONDOWN()
ON_WM_ACTIVATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CRect rect;
GetClientRect(&rect);
rect.InflateRect(m_cx, m_cy);

//Release dialog if the user click outside it.
if(!rect.PtInRect(point))
{
EndDialog(IDCANCEL);
}

CDialog::OnLButtonDown(nFlags, point);
}

void CMyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
CDialog::OnActivate(nState, pWndOther, bMinimized);

if( nState == WA_ACTIVE || nState == WA_CLICKACTIVE)
SetCapture();
else
ReleaseCapture();
}

BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
.....

OSVERSIONINFO info;
memset((char*)&info, 0, sizeof(OSVERSIONINFO));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if(GetVersionEx(&info))
{ //we don't run on Win32s, so check only two values
if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{ //On windows 95
m_cx = GetSystemMetrics(SM_CXFIXEDFRAME);
m_cy = GetSystemMetrics(SM_CYFIXEDFRAME);
}
else
{ //On NT
m_cx = GetSystemMetrics(SM_CXDLGFRAME);
m_cy = GetSystemMetrics(SM_CYDLGFRAME);
}
}
}

说明:
1)WM_ACTIVATE消息在ClassWizard中没有,按如下步骤添加,右击CMyDlg类,选Add Windows Message Handle,接着在Filter for messages available to中选Window,在New Windows messages/events列表中就会出现WM_ACTIVATE,选中,点击Add Handler
2)SM_CXDLGFRAME,SM_CYDLGFRAME NT中取得有WS_DLGFRAMEstyle风格的窗口的高和宽
95中已经废弃而采用SM_CX_FIXEDFRAME和SM_CYFIXEDFRAME
...全文
273 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

1,649

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 非技术类
社区管理员
  • 非技术类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧