| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 | 
							- unit TB2Anim;
 
- {
 
-   Toolbar2000
 
-   Copyright (C) 1998-2005 by Jordan Russell
 
-   All rights reserved.
 
-   The contents of this file are subject to the "Toolbar2000 License"; you may
 
-   not use or distribute this file except in compliance with the
 
-   "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in
 
-   TB2k-LICENSE.txt or at:
 
-     http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt
 
-   Alternatively, the contents of this file may be used under the terms of the
 
-   GNU General Public License (the "GPL"), in which case the provisions of the
 
-   GPL are applicable instead of those in the "Toolbar2000 License". A copy of
 
-   the GPL may be found in GPL-LICENSE.txt or at:
 
-     http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt
 
-   If you wish to allow use of your version of this file only under the terms of
 
-   the GPL and not to allow others to use your version of this file under the
 
-   "Toolbar2000 License", indicate your decision by deleting the provisions
 
-   above and replace them with the notice and other provisions required by the
 
-   GPL. If you do not delete the provisions above, a recipient may use your
 
-   version of this file under either the "Toolbar2000 License" or the GPL.
 
-   $jrsoftware: tb2k/Source/TB2Anim.pas,v 1.11 2005/02/16 08:15:58 jr Exp $
 
- }
 
- interface
 
- {$I TB2Ver.inc}
 
- {$Q-}
 
- uses
 
-   Windows, Messages, SysUtils, Classes;
 
- const
 
-   WM_TB2K_STEPANIMATION = WM_USER + $555;
 
-   WM_TB2K_ANIMATIONENDED = WM_USER + $556;
 
- type
 
-   TTBAnimationDirection = set of (tbadLeft, tbadRight, tbadDown, tbadUp);
 
- procedure TBStartAnimation(const AWnd: HWND; const ABlend: Boolean;
 
-   const ADirection: TTBAnimationDirection);
 
- procedure TBStepAnimation(const Msg: TMessage);
 
- procedure TBEndAnimation(const Wnd: HWND);
 
- implementation
 
- { Notes to self:
 
-   - It originally had the NOMIRRORBITMAP flag on the BitBlt calls, because
 
-     Windows 2000's AnimateWindow function has it. But it had to be removed
 
-     because on Windows 98 with the Standard VGA or VMware video driver, it
 
-     caused no bits to be blitted, even though Windows 98 is supposed to
 
-     support NOMIRRORBITMAP according to the documentation. I don't think it's
 
-     necessary anyway.
 
- }
 
- const
 
-   DCX_USESTYLE = $10000;
 
-   WS_EX_LAYERED = $80000;
 
-   NOMIRRORBITMAP = $80000000;
 
-   ULW_ALPHA = 2;
 
- type
 
-   PAnimateThreadFuncData = ^TAnimateThreadFuncData;
 
-   TAnimateThreadFuncData = record
 
-     SequenceID: Integer;
 
-     Wnd: HWND;
 
-     Time: Integer;
 
-     Blending: Boolean;
 
-     CurStep: Integer;
 
-     DC, BmpDC: HDC;
 
-     Bmp: HBITMAP;
 
-     ScreenClientRect: TRect;
 
-     Size: TPoint;
 
-     LastPos: TPoint;
 
-     Direction: TTBAnimationDirection;
 
-     AnimateThreadAbort: BOOL;
 
-     AnimationEnded: BOOL;
 
-     StepMessagePending: BOOL;
 
-   end;
 
- function AnimateThreadFunc(Parameter: Pointer): Integer;
 
- var
 
-   StartTime, FrameStartTime, NextFrameStartTime: DWORD;
 
-   StartStep, ElapsedTime, I: Integer;
 
-   P: TPoint;
 
- begin
 
-   Result := 0;
 
-   StartTime := GetTickCount;
 
-   FrameStartTime := StartTime;
 
-   with PAnimateThreadFuncData(Parameter)^ do begin
 
-     StartStep := CurStep;
 
-     while not AnimateThreadAbort do begin
 
-       ElapsedTime := FrameStartTime - StartTime;
 
-       if (ElapsedTime < 0) or (ElapsedTime >= Time) then
 
-         Break;
 
-       I := StartStep + ((255 * ElapsedTime) div Time);
 
-       if (I < 0) or (I >= 255) then
 
-         Break;
 
-       GetCursorPos(P);
 
-       if (P.X <> LastPos.X) or (P.Y <> LastPos.Y) then begin
 
-         if PtInRect(ScreenClientRect, P) then
 
-           Break;
 
-         LastPos := P;
 
-       end;
 
-       if I > CurStep then begin
 
-         CurStep := I;
 
-         if InterlockedExchange(Integer(StepMessagePending), 1) = 0 then
 
-           SendNotifyMessage(Wnd, WM_TB2K_STEPANIMATION, 0, SequenceID);
 
-       end;
 
-       { Wait until the timer has ticked at least 10 msec }
 
-       NextFrameStartTime := GetTickCount;
 
-       while NextFrameStartTime - FrameStartTime < 10 do begin
 
-         { We don't know the rate of the system timer, so check every 5 msec
 
-           to see if it's incremented }
 
-         Sleep(5);
 
-         NextFrameStartTime := GetTickCount;
 
-       end;
 
-       FrameStartTime := NextFrameStartTime;
 
-     end;
 
-     AnimationEnded := True;
 
-     SendNotifyMessage(Wnd, WM_TB2K_STEPANIMATION, 0, SequenceID);
 
-   end;
 
- end;
 
- threadvar
 
-   AnimateThreadHandle: THandle;
 
-   AnimateData: TAnimateThreadFuncData;
 
-   AnimationSequenceID: Integer;
 
- procedure FinalizeAnimation;
 
- begin
 
-   with PAnimateThreadFuncData(@AnimateData)^ do begin
 
-     if Blending then
 
-       SetWindowLong(Wnd, GWL_EXSTYLE,
 
-         GetWindowLong(Wnd, GWL_EXSTYLE) and not WS_EX_LAYERED)
 
-     else
 
-       SetWindowRgn(Wnd, 0, False);
 
-     BitBlt(DC, 0, 0, Size.X, Size.Y, BmpDC, 0, 0, SRCCOPY);
 
-     DeleteDC(BmpDC);
 
-     DeleteObject(Bmp);
 
-     ReleaseDC(Wnd, DC);
 
-     SendNotifyMessage(Wnd, WM_TB2K_ANIMATIONENDED, 0, 0);
 
-   end;
 
- end;
 
- procedure TBEndAnimation(const Wnd: HWND);
 
- begin
 
-   if (AnimateThreadHandle <> 0) and
 
-      ((Wnd = 0) or (AnimateData.Wnd = Wnd)) then begin
 
-     AnimateData.AnimateThreadAbort := True;
 
-     WaitForSingleObject(AnimateThreadHandle, INFINITE);
 
-     CloseHandle(AnimateThreadHandle);
 
-     AnimateThreadHandle := 0;
 
-     FinalizeAnimation;
 
-   end;
 
- end;
 
- procedure TBStartAnimation(const AWnd: HWND; const ABlend: Boolean;
 
-   const ADirection: TTBAnimationDirection);
 
- var
 
-   ZeroPt: TPoint;
 
-   R: TRect;
 
-   ThreadID: TThreadID;
 
-   Blend: TBlendFunction;
 
-   Rgn: HRGN;
 
- begin
 
-   TBEndAnimation(0);
 
-   ZeroPt.X := 0;
 
-   ZeroPt.Y := 0;
 
-   Inc(AnimationSequenceID);
 
-   FillChar(AnimateData, SizeOf(AnimateData), 0);
 
-   { Note: The pointer cast avoids GetTls calls for every field access }
 
-   with PAnimateThreadFuncData(@AnimateData)^ do begin
 
-     SequenceID := AnimationSequenceID;
 
-     Wnd := AWnd;
 
-     Blending := ABlend;
 
-     Direction := ADirection;
 
-     GetCursorPos(LastPos);
 
-     GetClientRect(Wnd, ScreenClientRect);
 
-     MapWindowPoints(Wnd, 0, ScreenClientRect, 2);
 
-     GetWindowRect(Wnd, R);
 
-     DC := GetDCEx(Wnd, 0, DCX_WINDOW or DCX_CACHE {or DCX_USESTYLE ?});
 
-     Size.X := R.Right - R.Left;
 
-     Size.Y := R.Bottom - R.Top;
 
-     Bmp := CreateCompatibleBitmap(DC, Size.X, Size.Y {or $01000000 ?});
 
-     BmpDC := CreateCompatibleDC(DC);
 
-     // AnimateWindow calls SetLayout, but I'm not sure that we need to.
 
-     //if Assigned(SetLayoutProc) then
 
-     //  SetLayoutProc(BmpDC, 0);
 
-     SelectObject(BmpDC, Bmp);
 
-     //SetBoundsRect(BmpDC, nil, DCB_RESET or DCB_ENABLE);
 
-     SendMessage(Wnd, WM_PRINT, WPARAM(BmpDC), PRF_NONCLIENT or PRF_CLIENT or
 
-       PRF_ERASEBKGND or PRF_CHILDREN);
 
-     //GetBoundsRect
 
-     if Blending then begin
 
-       SetWindowLong(Wnd, GWL_EXSTYLE, GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_LAYERED);
 
-       Time := 175;  { actually more like ~147 because CurStep starts at 40 }
 
-       CurStep := 40;
 
-       Longint(Blend) := 0;
 
-       Blend.BlendOp := AC_SRC_OVER;
 
-       Blend.SourceConstantAlpha := CurStep;
 
-       UpdateLayeredWindow(Wnd, 0, @R.TopLeft, @Size, BmpDC, @ZeroPt, 0,
 
-         @Blend, ULW_ALPHA);
 
-     end
 
-     else begin
 
-       Time := 150;
 
-       CurStep := 0;
 
-       Rgn := CreateRectRgn(0, 0, 0, 0);
 
-       if not BOOL(SetWindowRgn(Wnd, Rgn, False)) then
 
-         DeleteObject(Rgn);  { just in case }
 
-     end;
 
-     { These are the same flags AnimateWindow uses. SWP_ASYNCWINDOWPOS is
 
-       needed or else it doesn't "save bits" properly.
 
-       Note: SWP_ASYNCWINDOWPOS seems to have no effect on Windows 95 & NT 4.0,
 
-       so bits behind the window are not saved & restored correctly. }
 
-     SetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or
 
-       SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOREDRAW or
 
-       SWP_NOOWNERZORDER or SWP_ASYNCWINDOWPOS);
 
-   end;
 
-   AnimateThreadHandle := BeginThread(nil, 0, AnimateThreadFunc, @AnimateData,
 
-     CREATE_SUSPENDED, ThreadID);
 
-   if AnimateThreadHandle = 0 then begin
 
-     { just in case... }
 
-     FinalizeAnimation;
 
-     Exit;
 
-   end;
 
-   ResumeThread(AnimateThreadHandle);
 
- end;
 
- procedure TBStepAnimation(const Msg: TMessage);
 
- var
 
-   Rgn: HRGN;
 
-   Blend: TBlendFunction;
 
-   X, Y: Integer;
 
- begin
 
-   if Msg.LParam <> AnimationSequenceID then
 
-     { ignore messages dangling in the queue from aborted animation sequences }
 
-     Exit;
 
-   with PAnimateThreadFuncData(@AnimateData)^ do begin
 
-     if not AnimationEnded then begin
 
-       if Blending then begin
 
-         Longint(Blend) := 0;
 
-         Blend.BlendOp := AC_SRC_OVER;
 
-         Blend.SourceConstantAlpha := AnimateData.CurStep;
 
-         UpdateLayeredWindow(Wnd, 0, nil, nil, 0, nil, 0, @Blend, ULW_ALPHA);
 
-       end
 
-       else begin
 
-         if tbadDown in Direction then
 
-           Y := MulDiv(Size.Y, AnimateData.CurStep, 255) - Size.Y
 
-         else if tbadUp in Direction then
 
-           Y := Size.Y - MulDiv(Size.Y, AnimateData.CurStep, 255)
 
-         else
 
-           Y := 0;
 
-         if tbadRight in Direction then
 
-           X := MulDiv(Size.X, AnimateData.CurStep, 255) - Size.X
 
-         else if tbadLeft in Direction then
 
-           X := Size.X - MulDiv(Size.X, AnimateData.CurStep, 255)
 
-         else
 
-           X := 0;
 
-         Rgn := CreateRectRgn(X, Y, X + Size.X, Y + Size.Y);
 
-         if not BOOL(SetWindowRgn(Wnd, Rgn, False)) then
 
-           DeleteObject(Rgn);  { just in case }
 
-         BitBlt(DC, X, Y, Size.X, Size.Y, BmpDC, 0, 0, SRCCOPY);
 
-       end;
 
-     end
 
-     else
 
-       TBEndAnimation(Wnd);
 
-     StepMessagePending := False;
 
-   end;
 
- end;
 
- initialization
 
- finalization
 
-   TBEndAnimation(0);
 
- end.
 
 
  |