我现在要实现一个类似于光盘的圆型的非规则窗口,用户点一下之后,这个窗口平滑的移动到桌面的右下角,最后dock在那里,要求圆型窗口有一个从大到小的过程我现在用SetWindowRgn的方法来实现不规则窗口,用SetWindowPos的方法来移动,觉得老是闪烁的厉害,请问有没有消减的方法?或者有没有哪位有别的实现方法?

解决方案 »

  1.   

    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);
    这就是双缓冲的写法
      

  2.   

    结合SetWindowRgn和MoveWindow来实现, 不会闪的,如果闪,那是你的窗口绘图的问题, 参考楼上的双缓冲方式来做
      

  3.   

    原来你们所谓的双缓冲就是建立一个内存dc的拷贝,我用的就是内存dc,要不用这个,肯定惨不忍睹了
    我闪烁的原因是因为SetWindowPos么?难道用movewindow就不会闪烁了?
      

  4.   

    如果你的那个窗体是有背景的,那就需要用双缓冲来绘图。http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_cdc.3a3a.createcompatibledc.asp
      

  5.   

    我已经使用了双缓冲
    但是闪烁依然存在,是不是因为我的timer间隔设的太短了,我用了大概200ms让他移动一步
      

  6.   

    200 ms 太长。 40 ms 以下, 或者 不要使用 定时器。 应该用一个循环加延时的方式来解决
      

  7.   

    to krh2001(边城浪子),
    为什么最好不用timer,而用循环加sleep呢?
      

  8.   

    timer 做动画太慢了呀, 时间又不准. 所以不平滑.
      

  9.   

    首先获取窗口相对于屏幕左上角的坐标.
    然后获取窗口DC,把他拷贝到缓冲DC上.
    再隐藏窗口.
    接着把缓冲DC中,属于窗口这部分的图像(根据开始的坐标得到),在定时器中一点一点的拷贝到窗口DC上(坐标根据你自己的算法改变).
    当坐标到达了指定位置,再调用setwindowpos把窗口移动过来,显示就OK了.
      

  10.   

    还有你可以试试重载BOOL OnEraseBkgnd(CDC* pDC);
    函数直接返回,看看还有没有闪烁现象
      

  11.   

    我做了试验, 在普通窗口的情况下, 改为20MS, 感觉很平滑.(使用MoveWindow)
      

  12.   

    主要原因是我的窗体是非规则窗体啊,老是有尾巴.下面是我每次移动时的主要操作
    {
        //通过一张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);
    }
      

  13.   

    Invalidate()只是刷新窗口客户区的范围,而你的窗口在不停的移动,
    窗口旧坐标的区域并没得到刷新.你可以试试每次刷新的时候,先获取桌面的hWnd,然后刷新桌面::Invalidate(hWnd, FALSE);
      

  14.   

    获取桌面句柄:HWND hWnd = GetDesktopWindow();
      

  15.   

    结果是依然很闪烁
    如果我在调用MoveWindow时左上角的坐标不变的话,也就是只让我的不规则窗口一点点变小,但是位置不变。这时不会闪烁的
      

  16.   

    如果我在调用MoveWindow时左上角的坐标不变的话,也就是只让我的不规则窗口一点点变小,但是位置不变。这时不会闪烁的
    -------------------
    窗口一点点变小的时候拿鼠标拖动窗口,会不会闪烁呢?如果会闪烁可能就很难解决了。
      

  17.   

    int OffsetRgn(
      HRGN hrgn,     // handle to region
      int nXOffset,  // offset along x-axis
      int nYOffset   // offset along y-axis
    );用这个来移动试试
      

  18.   

    楼主,派生个CWnd类,在里面画好你要的图像,如果想用双缓冲的话也可以。我试了一下,我直接在onpaint里fillrgn(),没用双缓冲也没有闪烁。我的感觉:invalidate()要慎用