使用 DrawAnimatedRects() 函数






2.95/5 (9投票s)
展示如何使用 DrawAnimatedRects 函数来改善你的应用程序的外观。
引言
如果你查看 MS Word 并调用查找对话框,你可以看到一个简洁的动画。我希望模仿这个动画,然后发现了 DrawAnimatedRects() 函数。DrawAnimatedRects() 函数绘制一个线框矩形,并通过动画来指示图标的打开,或者窗口的最小化或最大化。语法如下
BOOL WINAPI DrawAnimatedRects( HWND hwnd, // handle to clipping window int idAni, // type of animation CONST RECT *lprcFrom, // rectangle coordinates (minimized) CONST RECT *lprcTo // rectangle coordinates (restored) );
lprcFrom 参数设置动画的起点,lprcTo 值设置动画的终点。例如,如果你希望使一个窗口看起来像是从一个按钮扩展到窗口,你可以将 lprcFrom 设置为按钮的尺寸,将 lprcTo 设置为最终窗口位置的尺寸。效果不如 MS Word 好,但如果任何 GUI 专家能够提供 MS Word 示例,那将非常有帮助。
使用该函数
示例应用程序展示了该函数的一个很好的用法。在演示中,关于框通过动画显示,使其看起来像是从对话框内部的一个按钮展开和折叠。
为了实现这一点,你只需在“关于框”对话框类中重写 OnCreate 和 OnDestroy 函数,并在适当的位置添加对 DrawAnimatedRects() 的调用。
为了使事情简单,我们首先存储“关于框”将从其展开的按钮的尺寸。我们向“关于框”类添加一个成员变量 m_rectFrom,为了使“关于框”出现,我们使用以下方法。
    CAboutDlg about;
    m_ctlButton.GetWindowRect(about.m_rectFrom);
    about.DoModal();
其中 m_ctlButton 是“关于框”似乎要从其展开的按钮控件。
接下来,你需要在你的“关于框”类中添加对 OnCreate 和 OnDestroy 的重写
int CAboutDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; if (!m_rectFrom.IsRectEmpty()) { CRect rectTo(lpCreateStruct->x,lpCreateStruct->y, lpCreateStruct->x + lpCreateStruct->cx, lpCreateStruct->y + lpCreateStruct->cy); DrawAnimatedRects(m_hWnd, IDANI_CAPTION, m_rectFrom, rectTo); } return 0; } void CAboutDlg::OnDestroy() { CDialog::OnDestroy(); if (!m_rectFrom.IsRectEmpty()) { CRect rect; GetWindowRect(rect); DrawAnimatedRects(m_hWnd, IDANI_CAPTION, rect, m_rectFrom); } }
这有效地在窗口本身出现之前或窗口消失之后绘制 Windows 动画序列。
就是这样!一个简单但有效的方法。
已更新: Norm Almond 提供了一些使用线框生成窗口爆炸/内爆效果的代码。他的函数的语法如下
void WINAPI DrawWireRects(LPRECT lprcFrom, LPRECT lprcTo, UINT nMilliSecSpeed)
lprcFrom 参数设置动画的起点,lprcTo 值设置动画的终点。nMilliSecSpeed 是每个线框显示之间的延迟时间(以毫秒为单位)(20 毫秒的值效果很好)。
//////////////////////////////////////////////////////////////////////////// // // FUNCTION: DrawWireRects // // DESCRIPTION: Creates exploding wire rectanges // // INPUTS: LPRECT lprcFrom Source Rectangle // LPRECT lprcTo Destination Rectangle // UINT nMilliSecSpeed Speed in millisecs for animation // // RETURN: None // NOTES: None // // Maintenance Log // Author Date Version Notes // NT Almond 011199 1.0 Origin // CJ Maunder 010899 1.1 Modified rectangle transition code // ///////////////////////////////////////////////////////////////////////// void WINAPI DrawWireRects(LPRECT lprcFrom, LPRECT lprcTo, UINT nMilliSecSpeed) { const int nNumSteps = 10; GdiFlush(); Sleep(50); // Let the desktop window sort itself out // if hwnd is null - "you have the CON". HDC hDC = ::GetDC(NULL); // Pen size, urmmm not too thick HPEN hPen = ::CreatePen(PS_SOLID, 2, RGB(0,0,0)); int nMode = ::SetROP2(hDC, R2_NOT); HPEN hOldPen = (HPEN) ::SelectObject(hDC, hPen); for (int i = 0; i < nNumSteps; i++) { double dFraction = (double) i / (double) nNumSteps; RECT transition; transition.left = lprcFrom->left + (int)((lprcTo->left - lprcFrom->left) * dFraction); transition.right = lprcFrom->right + (int)((lprcTo->right - lprcFrom->right) * dFraction); transition.top = lprcFrom->top + (int)((lprcTo->top - lprcFrom->top) * dFraction); transition.bottom = lprcFrom->bottom + (int)((lprcTo->bottom - lprcFrom->bottom) * dFraction); POINT pt[5]; pt[0] = CPoint(transition.left, transition.top); pt[1] = CPoint(transition.right,transition.top); pt[2] = CPoint(transition.right,transition.bottom); pt[3] = CPoint(transition.left, transition.bottom); pt[4] = CPoint(transition.left, transition.top); // We use Polyline because we can determine our own pen size // Draw Sides ::Polyline(hDC,pt,5); GdiFlush(); Sleep(nMilliSecSpeed); // UnDraw Sides ::Polyline(hDC,pt,5); GdiFlush(); } ::SetROP2(hDC, nMode); ::SelectObject(hDC, hOldPen); ::ReleaseDC(NULL,hDC); }
演示项目编号 1 包含此新代码。 Norm 还创建了一个类,该类是 演示项目编号 2 的一部分,演示了一个类 CZoomRect,该类可用于实现他更新的 Zoom Rect 代码。
要使用他的类,请包含 ZoomRect.h 头文件,创建一个 CZoomRect 对象并调用其 Draw() 方法
CRect rcStart(10,600,10,600); CRect rcEnd(600,0,800,200); int nDelay = 10; CZoomRect ZoomRect; ZoomRect.Draw(NULL, rcStart, rcEnd, nDelay);
第一个参数是用于绘图的窗口句柄(或 NULL 用于桌面窗口),第二个和第三个是开始和目标矩形,最后一个是帧之间的延迟(以毫秒为单位)。
Michael Dunn 写道,关于 Word 97 的缩放轮廓效果,他记得很久以前一位同事提到过,早期版本的 Win 95(1994 年的版本)使用了相同的效果。它可能类似于 CE 2.0 在打开/关闭应用程序时的效果。
如果你查看 winuser.h,你会发现两个遗留常量 IDANI_OPEN 和 IDANI_CLOSE。第一个想法是将它们传递给 DrawAnimatedRects() 会产生缩放轮廓效果,但不幸的是,事实并非如此。 DrawAnimatedRects() 只有在你传递 IDANI_CAPTION 时才有效。
这更多地变成了一堂历史课,而不是一个解决方案 :),但我只是想传递这个花絮,以防你对其他两个 IDANI_* 常数感到好奇。


