duilib : 滑动显示的窗口实现

<2015-0723>

前几天jhgwqp@csdn留言, 问有没有Demo工程. 做了一个给他.
原来记录这个技术点时, 也想做个Demo留念. 随着时间的推移, 已经忘了这事.

经jhgwqp@csdn提醒, 将这事做了.

工程下载点: srcbk_2015_0722_1819_src-sliding-window-display.rar

编译环境: vs2010 vc++ duilib

效果图:


代码预览:

建立弹出的滑动对话框时, 要以子窗口风格创建, 这样, 主窗口移动时, 我们就不用负责子窗口的位置移动了.

void CMainDlg::CreateDlgSlidingShow()
{
    do 
    {
        if (NULL != m_pDlgSlidingShow)
            break;

        m_pDlgSlidingShow = new CDlgSlidingShow(
            XML_FILE_NAME_dlgSlidingShow_MainDlg, 
            WND_CLASS_NAME_dlgSlidingShow_MainDlg);

        if (NULL == m_pDlgSlidingShow)
            break;

        m_pDlgSlidingShow->SetOwner(this);
        m_pDlgSlidingShow->Create(
            this->GetHWND(),
            WND_DISP_NAME_dlgSlidingShow_MainDlg,
            UI_WNDSTYLE_CHILD,
            WS_EX_WINDOWEDGE);

        /// 先藏起来, 让滑动框自己滑动和显示隐藏, 要不起始位置不对
        /// 所有者没必要之道创建对象的起始条件
        m_pDlgSlidingShow->ShowWindow(false, false);
    } while (0);
}
在消息中处理子窗口的滑动显示, 对DuiLib的显示操作, 最好放在消息中处理, 防止崩溃.

LRESULT CDlgSlidingShow::WndMessageProc_SlidingShow(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    /// 实现一个非模态窗口垂直滑动显示在指定父控件窗口里面
    /// * 从下到上,从最小高度到最大高度
    /// * 然后稳定显示x秒
    /// * 然后从上到下, 从最大高度到最小高度
    /// * 消失

    RECT    rtMain;         ///< 主窗口size
    RECT    rtLayout;       ///< 100%显示在父控件下方的大小
    RECT    rtLayoutRate;   ///< 窗口滑动时, 不通比率下的显示size
    const   UINT uDispTimeMax = 1000 * 6;   ///< 滑动显示窗稳定显示时间

    /// 垂直显示比率步进值, 控制窗口滑动速度
    /// 这里设定是每10MS, 执行一次 Play()
    const   float fDispStep = 0.03f;         
    const   UINT uMinHeight = 10;           ///< 最小窗口高度

    /// 最小高度限制的应对, 开始显示和结束显示的是最小高度
    const   float fRateMin =  0.05f;    ///< fRateMin 比率对应最小窗口高度
    static  UINT uDispTimeTotal = 0;    ///< 稳定显示的时间计数

    do 
    {
        if (!m_bPlay)
            break;

        if (eDispStatus_inc == m_Status)
        {
            m_fRate += fDispStep;
            if (m_fRate > 1.0f)
            {
                m_fRate = 1.0f;
                uDispTimeTotal = 0;
                m_Status = eDispStatus_disp;
            }
            else if (m_fRate < fRateMin)
                m_fRate = fRateMin;
        }
        else if (eDispStatus_disp == m_Status)
        {
            uDispTimeTotal += TIMER_DELAY_PLAY;
            if (uDispTimeTotal >= uDispTimeMax)
                m_Status = eDispStatus_dec;
        }
        else if (eDispStatus_dec == m_Status)
        {
            m_fRate -= fDispStep;
            if (m_fRate <= fRateMin)
            {
                m_fRate = fRateMin;
                uDispTimeTotal = 0;
                m_Status = eDispStatus_inc;
                m_bPlay = FALSE;
            }
        }

        // ::GetWindowRect(m_pOwner->GetHWND(), &rtMain);
        ::GetClientRect(m_pOwner->GetHWND(), &rtMain);

        rtLayout.right = rtMain.right;
        rtLayout.bottom = rtMain.bottom;
        rtLayout.left = rtLayout.right - (m_rtMeOrg.right - m_rtMeOrg.left);
        rtLayout.top = rtLayout.bottom - (m_rtMeOrg.bottom - m_rtMeOrg.top);

        rtLayoutRate.left = rtLayout.left;
        rtLayoutRate.right = rtLayout.right;
        rtLayoutRate.bottom = rtLayout.bottom;
        rtLayoutRate.top = rtLayout.bottom - 1.0f * (rtLayout.bottom - rtLayout.top) * m_fRate;

        /// 界面库的限制吧 ? 无法设置成很低的高度, 有最小高度限制...
        /// 重载 OnGetMinMaxInfo 也没用
        /// 通过试验, 发现最小高度为10左右

        /// 作为所有者的非子窗口(~UI_WNDSTYLE_CHILD), 用SetWindowPos
        /// 如果是非子窗口, 位置也要重新实验一下, 不能用::GetClientRect.
        /// 要用::GetWindowRect
//         ::SetWindowPos(
//             this->GetHWND(), 
//             m_pOwner->GetHWND(), 
//             rtLayoutRate.left, 
//             rtLayoutRate.top, 
//             rtLayoutRate.right - rtLayoutRate.left, 
//             rtLayoutRate.bottom - rtLayoutRate.top, 
//             SWP_SHOWWINDOW);

        /// 作为所有者的子窗口(UI_WNDSTYLE_CHILD), 用MoveWindow
        ::MoveWindow(
            this->GetHWND(), 
            rtLayoutRate.left, 
            rtLayoutRate.top, 
            rtLayoutRate.right, 
            rtLayoutRate.bottom, 
            TRUE);

        ::ShowWindow(this->GetHWND(), m_bPlay ? SW_SHOW : SW_HIDE);
        if (!m_bPlay)
        {
            ::PostMessageW(this->GetHWND(), WM_CLOSE, 0, 0);
        }
    } while (0);

    return S_OK;
}




2014-03-28 03:23 的备份

void CFloatTextMsgDlg::Play()
{
    /// 实现一个非模态窗口垂直滑动显示在指定父控件窗口里面
    /// * 从下到上,从最小高度到最大高度
    /// * 然后稳定显示x秒
    /// * 然后从上到下, 从最大高度到最小高度
    /// * 消失

    RECT    rtTabView;      ///< 要显示的父控件size
    RECT    rtMain;         ///< 主窗口size
    RECT    rtLayout;       ///< 100%显示在父控件下方的大小
    RECT    rtLayoutRate;   ///< 窗口滑动时, 不通比率下的显示size
    const   UINT uDispTimeMax = 1000 * 6;   ///< 滑动显示窗稳定显示时间

    /// 垂直显示比率步进值, 控制窗口滑动速度
    /// 这里设定是每10MS, 执行一次 Play()
    const   float fDispStep = 0.03f;         
    const   UINT uMinHeight = 10;           ///< 最小窗口高度
    
    /// 最小高度限制的应对, 开始显示和结束显示的是最小高度
    const   float fRateMin =  0.05f;    ///< fRateMin 比率对应最小窗口高度
    static  UINT uDispTimeTotal = 0;    ///< 稳定显示的时间计数
    
    if (!m_bPlay)
        return;

    if (eDispStatus_inc == m_Status)
    {
        m_fRate += fDispStep;
        if (m_fRate > 1.0f)
        {
            m_fRate = 1.0f;
            uDispTimeTotal = 0;
            m_Status = eDispStatus_disp;
        }
        else if (m_fRate < fRateMin)
            m_fRate = fRateMin;
    }
    else if (eDispStatus_disp == m_Status)
    {
        uDispTimeTotal += TIMER_DELAY_PLAY;
        if (uDispTimeTotal >= uDispTimeMax)
            m_Status = eDispStatus_dec;
    }
    else if (eDispStatus_dec == m_Status)
    {
        m_fRate -= fDispStep;
        if (m_fRate <= fRateMin)
        {
            m_fRate = fRateMin;
            uDispTimeTotal = 0;
            m_Status = eDispStatus_inc;
            m_bPlay = FALSE;
        }
    }

    m_pOwner->GetTabViewFramePosition(rtTabView);
    ::GetWindowRect(m_pOwner->GetHWND(), &rtMain);

    rtLayout.left = rtMain.left + rtTabView.left;
    rtLayout.right = rtLayout.left + (m_rtMeOrg.right - m_rtMeOrg.left);
    rtLayout.top = rtMain.top + rtTabView.bottom - (m_rtMeOrg.bottom - m_rtMeOrg.top);
    rtLayout.bottom = rtMain.top + rtTabView.bottom;

    rtLayoutRate.left = rtLayout.left;
    rtLayoutRate.right = rtLayout.right;
    rtLayoutRate.bottom = rtLayout.bottom;
    rtLayoutRate.top = rtLayout.bottom - 1.0f * (rtLayout.bottom - rtLayout.top) * m_fRate;

    /// 界面库的限制吧 ? 无法设置成很低的高度, 有最小高度限制...
    /// 重载 OnGetMinMaxInfo 也没用
    /// 通过试验, 发现最小高度为10左右

    ::SetWindowPos(
        this->GetHWND(), 
        m_pOwner->GetHWND(), 
        rtLayoutRate.left, 
        rtLayoutRate.top, 
        rtLayoutRate.right - rtLayoutRate.left, 
        rtLayoutRate.bottom - rtLayoutRate.top, 
        SWP_SHOWWINDOW);

    ::ShowWindow(this->GetHWND(), m_bPlay ? SW_SHOW : SW_HIDE);
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值