BeginBufferedAnimation function
Applies to: desktop apps only
Begins a buffered animation operation. The animation consists of a cross-fade between the contents of two buffers over a specified period of time.
Syntax
HANIMATIONBUFFER BeginBufferedAnimation( HWND hwnd, HDC hdcTarget, const RECT *rcTarget, BP_BUFFERFORMAT dwFormat, __in BP_PAINTPARAMS *pPaintParams, __in BP_ANIMATIONPARAMS *pAnimationParams, __out HDC *phdcFrom, __out HDC *phdcTo );
Parameters
- hwnd
-
Type: HWND
A handle to the window in which the animations play.
- hdcTarget
-
Type: HDC
A handle of the target DC on which the buffer is animated.
- rcTarget
-
Type: const RECT*
A pointer to a structure that specifies the area of the target DC in which to draw.
- dwFormat
-
Type: BP_BUFFERFORMAT
The format of the buffer.
- pPaintParams [in]
-
Type: BP_PAINTPARAMS*
A pointer to a structure that defines the paint operation parameters. This value can be NULL.
- pAnimationParams [in]
-
Type: BP_ANIMATIONPARAMS*
A pointer to a structure that defines the animation operation parameters.
- phdcFrom [out]
-
Type: HDC*
When this function returns, this value points to the handle of the DC where the application should paint the initial state of the animation, if not NULL.
- phdcTo [out]
-
Type: HDC*
When this function returns, this value points to the handle of the DC where the application should paint the final state of the animation, if not NULL.
Return value
Type: HANIMATIONBUFFER
A handle to the buffered paint animation.
Remarks
BeginBufferedAnimation will take care of drawing the intermediate frames between those two states by generating multiple WM_PAINT messages.
BeginBufferedAnimation starts a timer that generates WM_PAINT messages on which BufferedPaintRenderAnimation should be called. During these messages, BufferedPaintRenderAnimation will return TRUE when it paints an intermediate frame, to signify that the application has no further painting to do.
If the animation duration is zero, then only phdcTo is returned and phdcFrom is set to NULL. In this case, the application should paint the final state using phdcTo to get the behavior similar to BeginBufferedPaint.
Examples
The following code example shows how to use this function.
#include <windows.h> #include <tchar.h> #include <uxtheme.h> #pragma comment(lib, "uxtheme.lib") #define WNDCLASSNAME L"BufferedPaintSample_WndClass" #define ANIMATION_DURATION 500 bool g_fCurrentState = true; bool g_fNewState = true; void StartAnimation(HWND hWnd) { g_fNewState = !g_fCurrentState; InvalidateRect(hWnd, NULL, TRUE); } void Paint(HWND hWnd, HDC hdc, bool state) { RECT rc; GetClientRect(hWnd, &rc); FillRect(hdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH)); LPCTSTR pszIconId = state ? IDI_APPLICATION : IDI_ERROR; HICON hIcon = LoadIcon(NULL, pszIconId); if (hIcon) { DrawIcon(hdc, 10, 10, hIcon); DestroyIcon(hIcon); } } void OnPaint(HWND hWnd) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); if (hdc) { // See if this paint was generated by a soft-fade animation if (!BufferedPaintRenderAnimation(hWnd, hdc)) { BP_ANIMATIONPARAMS animParams; ZeroMemory(&animParams, sizeof(animParams)); animParams.cbSize = sizeof(BP_ANIMATIONPARAMS); animParams.style = BPAS_LINEAR; // Check if animation is needed. If not set dwDuration to 0 animParams.dwDuration = (g_fCurrentState != g_fNewState ? ANIMATION_DURATION : 0); RECT rc; GetClientRect(hWnd, &rc); HDC hdcFrom, hdcTo; HANIMATIONBUFFER hbpAnimation = BeginBufferedAnimation(hWnd, hdc, &rc, BPBF_COMPATIBLEBITMAP, NULL, &animParams, &hdcFrom, &hdcTo); if (hbpAnimation) { if (hdcFrom) { Paint(hWnd, hdcFrom, g_fCurrentState); } if (hdcTo) { Paint(hWnd, hdcTo, g_fNewState); } g_fCurrentState = g_fNewState; EndBufferedAnimation(hbpAnimation, TRUE); } else { Paint(hWnd, hdc, g_fCurrentState); } } EndPaint(hWnd, &ps); } } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_LBUTTONDOWN: StartAnimation(hWnd); break; case WM_PAINT: OnPaint(hWnd); break; case WM_SIZE: BufferedPaintStopAllAnimations(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); if (SUCCEEDED(BufferedPaintInit())) { WNDCLASSEX wcex; ZeroMemory(&wcex, sizeof(wcex)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW|CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.lpszClassName = WNDCLASSNAME; RegisterClassEx(&wcex); HWND hWnd = CreateWindow(WNDCLASSNAME, L"Buffered Paint Sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (hWnd) { ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } BufferedPaintUnInit(); } return 0; }
void BufferedPaint(HDC hdc, const RECT *prcPaint) { BP_PAINTPARAMS paintParams = {0}; paintParams.cbSize = sizeof(paintParams); HDC hdcBuffer; HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, prcPaint, BPBF_COMPATIBLEBITMAP, &paintParams, &hdcBuffer); if (hBufferedPaint) { // Application specific painting code AppPaint(hdcBuffer, prcPaint); EndBufferedPaint(hBufferedPaint, TRUE); } else { // Error occurred, default to unbuffered painting AppPaint(hdc, prcPaint); } }
Requirements
|
Minimum supported client | Windows Vista |
|---|---|
|
Minimum supported server | Windows Server 2008 |
|
Header |
|
|
DLL |
|
Send comments about this topic to Microsoft
Build date: 3/6/2012
- 6/9/2011
- Dyado Pras
- 6/9/2011
- Dyado Pras
- 4/19/2011
- Christopher
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace BufferedAnimation
{
public class BufferedAnimationControl : Control
{
public BufferedAnimationControl()
: base()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
BufferedPaintInit();
}
~BufferedAnimationControl()
{
BufferedPaintStopAllAnimations(this.Handle);
BufferedPaintUnInit();
}
protected override Size DefaultSize
{
get
{
return Size.Add(SystemInformation.IconSize, new Size(20,20));
}
}
bool g_fCurrentState = true;
bool g_fNewState = true;
void StartAnimation(IntPtr hWnd)
{
g_fNewState = !g_fCurrentState;
this.Invalidate(true);
}
private void PaintAnimationState(IntPtr hdc, bool state)
{
Graphics g = Graphics.FromHdc(hdc);
using (Brush brush = new SolidBrush(this.BackColor))
g.FillRectangle(brush, this.ClientRectangle);
Icon stateIcon = state ? SystemIcons.Application : SystemIcons.Error;
g.DrawIcon(stateIcon, 10, 10);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
IntPtr hdc = e.Graphics.GetHdc();
if (hdc != IntPtr.Zero)
{
// See if this paint was generated by a soft-fade animation
if (!BufferedPaintRenderAnimation(this.Handle, hdc))
{
BP_ANIMATIONPARAMS animParams = new BP_ANIMATIONPARAMS();
animParams.cbSize = Marshal.SizeOf(animParams);
animParams.style = BP_ANIMATIONSTYLE.BPAS_LINEAR;
// Check if animation is needed. If not set dwDuration to 0
animParams.dwDuration = (g_fCurrentState != g_fNewState ? ANIMATION_DURATION : 0);
RECT rc = new RECT(this.ClientRectangle);
IntPtr hdcFrom, hdcTo;
IntPtr hbpAnimation = BeginBufferedAnimation(this.Handle, hdc, ref rc, BP_BUFFERFORMAT.BPBF_COMPATIBLEBITMAP, IntPtr.Zero, ref animParams, out hdcFrom, out hdcTo);
if (hbpAnimation != IntPtr.Zero)
{
if (hdcFrom != IntPtr.Zero)
{
PaintAnimationState(hdcFrom, g_fCurrentState);
}
if (hdcTo != IntPtr.Zero)
{
PaintAnimationState(hdcTo, g_fNewState);
}
g_fCurrentState = g_fNewState;
EndBufferedAnimation(hbpAnimation, true);
}
else
{
PaintAnimationState(hdc, g_fCurrentState);
}
}
e.Graphics.ReleaseHdc(hdc);
}
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
//base.OnPaintBackground(pevent);
}
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
StartAnimation(this.Handle);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
BufferedPaintStopAllAnimations(this.Handle);
}
#region Interop
[DllImport("uxtheme")]
private static extern IntPtr BufferedPaintInit();
[DllImport("uxtheme")]
private static extern IntPtr BufferedPaintUnInit();
[DllImport("uxtheme")]
private static extern IntPtr BeginBufferedAnimation(IntPtr hwnd, IntPtr hdcTarget, ref RECT rcTarget, BP_BUFFERFORMAT dwFormat, IntPtr pPaintParams, ref BP_ANIMATIONPARAMS pAnimationParams, out IntPtr phdcFrom, out IntPtr phdcTo);
[DllImport("uxtheme")]
private static extern IntPtr EndBufferedAnimation(IntPtr hbpAnimation, bool fUpdateTarget);
[DllImport("uxtheme")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool BufferedPaintRenderAnimation(IntPtr hwnd, IntPtr hdcTarget);
[DllImport("uxtheme")]
private static extern IntPtr BufferedPaintStopAllAnimations(IntPtr hwnd);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public RECT(Rectangle rc)
{
left = rc.Left;
top = rc.Top;
right = rc.Right;
bottom = rc.Bottom;
}
}
[StructLayout(LayoutKind.Sequential)]
private struct BP_ANIMATIONPARAMS
{
public Int32 cbSize, dwFlags;
public BP_ANIMATIONSTYLE style;
public Int32 dwDuration;
}
private enum BP_BUFFERFORMAT
{
BPBF_COMPATIBLEBITMAP,
BPBF_DIB,
BPBF_TOPDOWNDIB,
BPBF_TOPDOWNMONODIB
}
[Flags]
private enum BP_ANIMATIONSTYLE
{
BPAS_NONE = 0,
BPAS_LINEAR = 1,
BPAS_CUBIC = 2,
BPAS_SINE = 3
}
private const int ANIMATION_DURATION = 500;
#endregion
}
}
- 4/2/2011
- Mick Doherty