关于圆型不规则窗口的平滑移动 我现在要实现一个类似于光盘的圆型的非规则窗口,用户点一下之后,这个窗口平滑的移动到桌面的右下角,最后dock在那里,要求圆型窗口有一个从大到小的过程我现在用SetWindowRgn的方法来实现不规则窗口,用SetWindowPos的方法来移动,觉得老是闪烁的厉害,请问有没有消减的方法?或者有没有哪位有别的实现方法? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 CDC *dc=this->GetDC();//CClientDC dc(this);CBitmap m_bmp;CDC m_compatdc;CRect rect;this->GetClientRect(rect);if(!m_compatdc.CreateCompatibleDC(NULL)) { ::PostQuitMessage(0); } m_bmp.CreateCompatibleBitmap(dc, rect.Width(), rect.Height()); m_compatdc.SelectObject( &m_bmp);srand(GetTickCount()); int x,y,z; int i=0,j=0;CPoint point;for(i=0;i<rect.Width();i++) { for(j=0;j<rect.Height();j++) { point.x=i; point.y=j; x=rand()%255; y=rand()%255; z=rand()%255; m_compatdc.SetPixel(point,RGB(x,y,z)); } } dc->BitBlt(rect.left, rect.top,rect.Width(), rect.Height(), &m_compatdc, 0, 0, SRCCOPY); m_bmp.DeleteObject(); this->ReleaseDC(dc);这就是双缓冲的写法 结合SetWindowRgn和MoveWindow来实现, 不会闪的,如果闪,那是你的窗口绘图的问题, 参考楼上的双缓冲方式来做 原来你们所谓的双缓冲就是建立一个内存dc的拷贝,我用的就是内存dc,要不用这个,肯定惨不忍睹了我闪烁的原因是因为SetWindowPos么?难道用movewindow就不会闪烁了? 如果你的那个窗体是有背景的,那就需要用双缓冲来绘图。http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_cdc.3a3a.createcompatibledc.asp 我已经使用了双缓冲但是闪烁依然存在,是不是因为我的timer间隔设的太短了,我用了大概200ms让他移动一步 200 ms 太长。 40 ms 以下, 或者 不要使用 定时器。 应该用一个循环加延时的方式来解决 to krh2001(边城浪子),为什么最好不用timer,而用循环加sleep呢? timer 做动画太慢了呀, 时间又不准. 所以不平滑. 首先获取窗口相对于屏幕左上角的坐标.然后获取窗口DC,把他拷贝到缓冲DC上.再隐藏窗口.接着把缓冲DC中,属于窗口这部分的图像(根据开始的坐标得到),在定时器中一点一点的拷贝到窗口DC上(坐标根据你自己的算法改变).当坐标到达了指定位置,再调用setwindowpos把窗口移动过来,显示就OK了. 还有你可以试试重载BOOL OnEraseBkgnd(CDC* pDC);函数直接返回,看看还有没有闪烁现象 我做了试验, 在普通窗口的情况下, 改为20MS, 感觉很平滑.(使用MoveWindow) 主要原因是我的窗体是非规则窗体啊,老是有尾巴.下面是我每次移动时的主要操作{ //通过一张bmp格式的图片,创建一块圆形区域 HRGN hRgn = CreateRgnFromFile() CDC* dc = GetDC(); //创建内存dc m_dcBkGrnd = CreateCompatibleDC( dc->m_hDC ); //加载背景图 HBITMAP hBmp = (HBITMAP)LoadImage(); //使用内存dc选中背景图 SelectObject( m_dcBkGrnd, hBmp ); //移动窗体 MoveWindow() //设置不规则的圆形区域 SetWindowRgn( hRgn, TRUE); //最后刷新,显示 Invalidate()}画的操作是在重载的OnEraseBkgnd函数中BOOL CShapeDlg::OnEraseBkgnd(CDC* pDC){ if(m_dcBkGrnd != NULL) { //如果内存dc不为NULL,则将它拷贝到窗体的dc上 return BitBlt( pDC->m_hDC, 0, 0, m_dwWidth, m_dwHeight, m_dcBkGrnd, 0, 0, SRCCOPY ); } return CDialog::OnEraseBkgnd(pDC);} Invalidate()只是刷新窗口客户区的范围,而你的窗口在不停的移动,窗口旧坐标的区域并没得到刷新.你可以试试每次刷新的时候,先获取桌面的hWnd,然后刷新桌面::Invalidate(hWnd, FALSE); 获取桌面句柄:HWND hWnd = GetDesktopWindow(); 结果是依然很闪烁如果我在调用MoveWindow时左上角的坐标不变的话,也就是只让我的不规则窗口一点点变小,但是位置不变。这时不会闪烁的 如果我在调用MoveWindow时左上角的坐标不变的话,也就是只让我的不规则窗口一点点变小,但是位置不变。这时不会闪烁的-------------------窗口一点点变小的时候拿鼠标拖动窗口,会不会闪烁呢?如果会闪烁可能就很难解决了。 int OffsetRgn( HRGN hrgn, // handle to region int nXOffset, // offset along x-axis int nYOffset // offset along y-axis);用这个来移动试试 楼主,派生个CWnd类,在里面画好你要的图像,如果想用双缓冲的话也可以。我试了一下,我直接在onpaint里fillrgn(),没用双缓冲也没有闪烁。我的感觉:invalidate()要慎用 求一小算法,或者API 提问关于lotus notes编程中关于邮件搜索的问题 关于fstream对象操作二进制文件的问题 创建弹出式菜单 打包的问题 弱弱的问,在dialog上画图该在什么地方写代码? 谁有音量控制的类,邮给我,谢谢![email protected] 我新定义了一个类,可是呢,调用时,却找不到??为是么?? 请教高手:我用installsheild for VC 6.0打包了一个工程,为什么生成的exe文件在未装VC的机子中不能运行?? 关于从dll中输出class 怎样得到随机数? 请问做ActiveX控件时,怎么限定控件的大小啊?
//CClientDC dc(this);CBitmap m_bmp;
CDC m_compatdc;
CRect rect;
this->GetClientRect(rect);if(!m_compatdc.CreateCompatibleDC(NULL))
{
::PostQuitMessage(0);
}
m_bmp.CreateCompatibleBitmap(dc, rect.Width(), rect.Height()); m_compatdc.SelectObject( &m_bmp);srand(GetTickCount());
int x,y,z;
int i=0,j=0;
CPoint point;
for(i=0;i<rect.Width();i++)
{
for(j=0;j<rect.Height();j++)
{
point.x=i;
point.y=j;
x=rand()%255;
y=rand()%255;
z=rand()%255;
m_compatdc.SetPixel(point,RGB(x,y,z));
}
} dc->BitBlt(rect.left, rect.top,rect.Width(), rect.Height(), &m_compatdc, 0, 0, SRCCOPY); m_bmp.DeleteObject(); this->ReleaseDC(dc);
这就是双缓冲的写法
我闪烁的原因是因为SetWindowPos么?难道用movewindow就不会闪烁了?
但是闪烁依然存在,是不是因为我的timer间隔设的太短了,我用了大概200ms让他移动一步
为什么最好不用timer,而用循环加sleep呢?
然后获取窗口DC,把他拷贝到缓冲DC上.
再隐藏窗口.
接着把缓冲DC中,属于窗口这部分的图像(根据开始的坐标得到),在定时器中一点一点的拷贝到窗口DC上(坐标根据你自己的算法改变).
当坐标到达了指定位置,再调用setwindowpos把窗口移动过来,显示就OK了.
函数直接返回,看看还有没有闪烁现象
{
//通过一张bmp格式的图片,创建一块圆形区域
HRGN hRgn = CreateRgnFromFile() CDC* dc = GetDC(); //创建内存dc
m_dcBkGrnd = CreateCompatibleDC( dc->m_hDC ); //加载背景图
HBITMAP hBmp = (HBITMAP)LoadImage(); //使用内存dc选中背景图
SelectObject( m_dcBkGrnd, hBmp ); //移动窗体
MoveWindow() //设置不规则的圆形区域
SetWindowRgn( hRgn, TRUE); //最后刷新,显示
Invalidate()
}
画的操作是在重载的OnEraseBkgnd函数中
BOOL CShapeDlg::OnEraseBkgnd(CDC* pDC)
{
if(m_dcBkGrnd != NULL)
{
//如果内存dc不为NULL,则将它拷贝到窗体的dc上
return BitBlt( pDC->m_hDC, 0, 0, m_dwWidth, m_dwHeight, m_dcBkGrnd, 0, 0, SRCCOPY );
} return CDialog::OnEraseBkgnd(pDC);
}
窗口旧坐标的区域并没得到刷新.你可以试试每次刷新的时候,先获取桌面的hWnd,然后刷新桌面::Invalidate(hWnd, FALSE);
如果我在调用MoveWindow时左上角的坐标不变的话,也就是只让我的不规则窗口一点点变小,但是位置不变。这时不会闪烁的
-------------------
窗口一点点变小的时候拿鼠标拖动窗口,会不会闪烁呢?如果会闪烁可能就很难解决了。
HRGN hrgn, // handle to region
int nXOffset, // offset along x-axis
int nYOffset // offset along y-axis
);用这个来移动试试