<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);
}