Google Groups Home
Help | Sign in
For Vladimir Stefanovic : TAnimatedTrayIcon
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  7 messages - Expand all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
JD  
View profile  
 More options Mar 22 2006, 6:00 am
Newsgroups: borland.public.cppbuilder.thirdpartytools
From: "JD" <nos...@nospam.com>
Date: 22 Mar 2006 04:00:12 -0700
Local: Wed, Mar 22 2006 6:00 am
Subject: For Vladimir Stefanovic : TAnimatedTrayIcon

Vladimir:

I never expected so many people to use TAnimatedTrayIcon
so I never even considered version numbers but with the new
TTrayIcon in BDS, while better than the old, it's still weak so
I'd expect that the more people that are aware of it, the more
people that will use it. Since you last saw it, I've made
several changes to the component and even a couple of custom
jobs for individuals so I've labeled it's version as 1.5.0.

The changes that have been made no longer require it to be
Owned by the main form and it should be fine with multiple
instance in the application but I just haven't had time to get
around to changing the code and testing it.

The only question that I have with it is with the
DetermineShellVersion method that sets the FCanBalloon
property. Currently, ballooning is only allowed if the
SHELL32.dll version is greater than or equal to 5.0 but
I ran across something on MSN that makes me think that
ballooning should also be allowed for win2k (4.0) but I
don't have that OS to test it.

I also haven't tested it as a component installed in the IDE
but I did code it to be installed so I'm presuming that all is
well on that front.

Let me know if you find any bugs or make any improvements.

~ JD

//------------------------------------------------------------------------- --
//-                                                                         -
//- TAnimatedTrayIcon version 1.5.0                                         -
//-                                                                         -
//- You may use this code in whole or in part for any purpose except that   -
//- you may not sell it as a component or part of a component pack. It's    -
//- free for any one who wants it - period.                                 -
//-                                                                         -
//- Direct questions, comments and changes to idea...@hotmail.com or post   -
//- to the vcl.using group.                                                 -
//-                                                                         -
//------------------------------------------------------------------------- --
#ifndef AnimatedTrayIconH
#define AnimatedTrayIconH
//------------------------------------------------------------------------- --
#include <Classes.hpp>
#include <vector>
//------------------------------------------------------------------------- --
// M$ says this should be 0x0500 for shellapi >= 5.0
// but cpp needs it to be 0x0501 or 0x0600
#undef _WIN32_IE
#define _WIN32_IE 0x0501
#include <shellapi.h>
#include <shlwapi.h>
#include <mmsystem.h>
//------------------------------------------------------------------------- --
#include "TrayThread.h"
//------------------------------------------------------------------------- --
enum TBalloonIconType
  {
      itNone = 0,
      itInformation,
      itWarning,
      itError,
      itQuestion,
      itNoSound,
      itUser
  };
//------------------------------------------------------------------------- --
class TAnimatedTrayIcon : public TComponent
{
    private:
        #define NIIF_QUESTION 0x07
        #define NIIF_USER     0x14
        typedef TComponent inherited;
        LPVOID MinimizeWave, RestoreWave;
        DWORD MinimizeSize, RestoreSize;
        unsigned int ClickTimer;
        unsigned int CM_TRAYNOTIFY;
        unsigned int CM_TRAYCREATED;
        unsigned int CM_TASKBARCREATED;
        std::vector<HWND>vZOrder;
        std::vector<TForm*>vForms;

        HWND  FHandle;
        TForm *FParentForm;
        TRect BoundsRect, TrayRect;
        TAnimatedTrayIconThread *FThread;
        bool FMinimized;
        bool FHooked;
        bool FInstalled;
        bool FAnimating;
        bool FCanBalloon;

        bool FAnimateWindow;
        bool FLoopSound;
        bool FUseTray;
        int  FDelay;
        int  FStaticIndex;
        bool FActive;
        int  FTrayID;
        int  FFromIndex;
        int  FToIndex;

        TThreadPriority FPriority;
        AnsiString FStaticHint;
        AnsiString FAnimationHint;
        AnsiString FAnimateWave;
        TImageList *FImageList;
        TPopupMenu *FPopupMenu;
        HIMAGELIST hImageList;

        AnsiString FBalloonCaption;
        AnsiString FBalloonText;
        TBalloonIconType FBalloonIconType;
        UINT FBalloonIcon;
        UINT FBalloonTimeout;

        DWORD FStartTickCount;
        TShiftState  FLeftClickShift;
        TMouseEvent  FOnMouseUp;
        TMouseEvent  FOnMouseDown;
        TNotifyEvent FOnClick;
        TNotifyEvent FOnDblClick;
        TNotifyEvent FOnBalloonClick;
        TNotifyEvent FOnBalloonShow;
        TNotifyEvent FOnBalloonHide;
        TNotifyEvent FOnBalloonClose;
        TNotifyEvent FOnBalloonTimeOut;

        void __fastcall LoadSound( AnsiString ID, DWORD &Size, LPVOID &hMemWave );
        void __fastcall SetClickTimer( bool Enable );
        void __fastcall ModifyTray();
        void __fastcall DetermineShellVersion();
        void __fastcall GetSysTrayRect();

        // setter methods
        void __fastcall SetActive( bool State );
        void __fastcall SetStaticIndex( int Index );
        void __fastcall SetStaticHint( AnsiString Hint );
        void __fastcall SetImageList( TImageList* );
        void __fastcall SetPopupMenu( TPopupMenu* );
    protected:
        virtual void __fastcall Loaded();
        virtual void __fastcall Notification( TComponent *AComponent, TOperation Operation );
        virtual void __fastcall WndProc( TMessage &Message );
        void __fastcall MouseDown(TMouseButton Button, TShiftState Shift );
        void __fastcall MouseUp(TMouseButton Button, TShiftState Shift );
        bool __fastcall AppHook( TMessage &Message );
    public:
        void __fastcall StartAnimation();
        void __fastcall StopAnimation();
        bool __fastcall Minimize();
        bool __fastcall Restore();
        void __fastcall DoBalloonTip();
        __fastcall TAnimatedTrayIcon(TComponent* Owner);
        __fastcall TAnimatedTrayIcon::~TAnimatedTrayIcon();
    __published:
        __property TMouseEvent  OnMouseUp = { read = FOnMouseUp, write = FOnMouseUp };
        __property TMouseEvent  OnMouseDown = { read = FOnMouseDown, write = FOnMouseDown };
        __property TNotifyEvent OnClick = { read = FOnClick, write = FOnClick };
        __property TNotifyEvent OnDblClick = { read = FOnDblClick, write = FOnDblClick };
        __property TNotifyEvent OnBalloonClick = { read = FOnBalloonClick, write = FOnBalloonClick };
        __property TNotifyEvent OnBalloonShow = { read = FOnBalloonShow, write = FOnBalloonShow };
        __property TNotifyEvent OnBalloonHide = { read = FOnBalloonHide, write = FOnBalloonHide };
        __property TNotifyEvent OnBalloonClose = { read = FOnBalloonClose, write = FOnBalloonClose };
        __property TNotifyEvent OnBalloonTimeOut = { read = FOnBalloonTimeOut, write = FOnBalloonTimeOut };
        __property bool AnimateWindow = { read = FAnimateWindow, write = FAnimateWindow, default = false };        
        __property int AnimationDelay = { read = FDelay, write = FDelay, default = 50 };
        __property int TrayID = { read = FTrayID, write = FTrayID, default = 1643 };
        __property int AnimateIndexStart = { read = FFromIndex, write = FFromIndex };
        __property int AnimateIndexEnd = { read = FToIndex, write = FToIndex };
        __property AnsiString AnimationHint = { read = FAnimationHint, write = FAnimationHint };
        __property AnsiString AnimateWaveSound = { read = FAnimateWave, write = FAnimateWave };
        __property TThreadPriority AnimationPriority = { read = FPriority, write = FPriority, default = tpNormal };
        __property TImageList *ImageList = { read = FImageList, write = SetImageList };
        __property TPopupMenu *PopupMenu = { read = FPopupMenu, write = SetPopupMenu };
        __property bool LoopAnimateSound = { read = FLoopSound, write = FLoopSound, default = true };
        __property bool Active = { read = FActive, write = SetActive, default = false };
        __property int StaticIndex = { read = FStaticIndex, write = SetStaticIndex };
        __property AnsiString StaticHint = { read = FStaticHint, write = SetStaticHint };
        __property bool MinimizeToTray = { read = FUseTray, write = FUseTray, default = true };
        __property AnsiString BalloonCaption = { read = FBalloonCaption, write = FBalloonCaption };
        __property AnsiString BalloonText  = { read = FBalloonText,  write = FBalloonText };
        __property TBalloonIconType BalloonIconType  = { read = FBalloonIconType,  write = FBalloonIconType, default = itInformation };
        // HICON is not an allowed type so I just used UINT and cast it when it's used
        __property UINT BalloonIcon = { read = FBalloonIcon,  write = FBalloonIcon };
        __property UINT BalloonTimeout = { read = FBalloonTimeout,  write = FBalloonTimeout, default = 1500 };

};

//------------------------------------------------------------------------- --
#endif

//------------------------------------------------------------------------- --
#include <vcl.h>
//------------------------------------------------------------------------- --
#pragma hdrstop
//------------------------------------------------------------------------- --
#include "AnimatedTrayIcon.h"
//------------------------------------------------------------------------- --
// Tray.res is not included with the sample.
// All it is [was] is the sound resources.
//#pragma resource "Tray.res"
//------------------------------------------------------------------------- --
#pragma package(smart_init)

// Used to ensure only a single instance of this object type application wide
TAnimatedTrayIcon *ThisAnimatedTrayIconInstance = NULL;
//------------------------------------------------------------------------- --
__fastcall TAnimatedTrayIcon::TAnimatedTrayIcon( TComponent *Owner ) : TComponent(Owner)
{
    if( ThisAnimatedTrayIconInstance )
      {
...

read more »


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Vladimir Stefanovic  
View profile  
 More options Mar 22 2006, 3:55 pm
Newsgroups: borland.public.cppbuilder.thirdpartytools
From: "Vladimir Stefanovic" <antiv...@po.sbb.co.yu>
Date: Wed, 22 Mar 2006 21:55:13 +0100
Local: Wed, Mar 22 2006 3:55 pm
Subject: Re: For Vladimir Stefanovic : TAnimatedTrayIcon
Hi JD,

Thank you very much for the effort and for sharing
the latest code with us:)

Now, we can track changes and possibly participate in
improving it, if there is room yet.

I'll do my best to find some bugs :)

--
Best Regards,
Vladimir Stefanovic


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Chris  
View profile  
 More options Mar 22 2006, 4:51 pm
Newsgroups: borland.public.cppbuilder.thirdpartytools
From: "Chris" <nos...@nospam.com>
Date: Wed, 22 Mar 2006 21:51:23 -0000
Local: Wed, Mar 22 2006 4:51 pm
Subject: Re: For Vladimir Stefanovic : TAnimatedTrayIcon
Brilliant.

Chris

PS.  How would I set my app to start minimized to the tray?


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
JD  
View profile  
 More options Mar 23 2006, 3:54 am
Newsgroups: borland.public.cppbuilder.thirdpartytools
From: "JD" <nos...@nospam.com>
Date: 23 Mar 2006 01:54:40 -0700
Local: Thurs, Mar 23 2006 3:54 am
Subject: Re: For Vladimir Stefanovic : TAnimatedTrayIcon

"Chris" <nos...@nospam.com> wrote:

> [...] How would I set my app to start minimized to the tray?

Wise Guy!! I don't know why I never thought of that option and
I wish I had because the design as it is will make it difficult
to implement.

Ok, here's the deal ... a propper solution requires more work
than I have time to spend right now but I do have a temporary
solution for you. The easiest thing is to just post a message
in the component's constructor. For example:

    if( !ComponentState.Contains(csDesigning) )
      {
          ....
          // as the last line
          ::PostMessage( Application->Handle, WM_SYSCOMMAND, SC_MINIMIZE, NULL );
      }

That will get the form minimized but it still gets shown prior
to minimizing. If you want to prevent that (seeing the form
for a moment), you need to add a line of code to the WinMain:

    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
        try
          {
              Application->Initialize();
              Application->ShowMainForm = false; // <-- add this here
              ....
          }
        ....
    }

If you do change the WinMain, then you need to also add an
additional line of code to counter act it in the component's
Restore method:

    bool __fastcall TAnimatedTrayIcon::Restore()
    {
        bool Result = false;
        if( FUseTray && FActive && FMinimized )
          {
              ....
              ::ShowWindow( Application->Handle, SW_SHOW );
              Application->MainForm->Visible = true;  // <- add this here
              ....
          }
        ....
    }

For an SDI application, that's all that's needed. For an MDI
application, the application's Icon show's up on the TaskBar
for an instant and then disappears. To prevent this, one needs
to override the main form's CreateParams method so that the
WS_EX_TOOLWINDOW flag can be applied to it's ExStyle. For
example:

    protected:
        virtual void __fastcall CreateParams( TCreateParams &Params );

    void __fastcall TForm1::CreateParams( TCreateParams &Params )
    {
        TForm::CreateParams( Params );
        Params.ExStyle |= WS_EX_TOOLWINDOW;
    }

However, if you do that, the icon will never appear on the
TaskBar even when the application is restored unless you call
SetWindowLong from somewhere - most likely some sort of timer.
For example:

    ::SetWindowLong( Application->Handle, GWL_EXSTYLE, ::GetWindowLong(Application->Handle, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW );

~ JD


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
JD  
View profile  
 More options Mar 23 2006, 4:37 pm
Newsgroups: borland.public.cppbuilder.thirdpartytools
From: "JD" <nos...@nospam.com>
Date: 23 Mar 2006 14:37:22 -0700
Local: Thurs, Mar 23 2006 4:37 pm
Subject: Re: For Vladimir Stefanovic : TAnimatedTrayIcon

"JD" <nos...@nospam.com> wrote:

> [...] the design as it is will make it difficult to
> implement.

Hello Chris:

Well ,,, it was easier than I expected so here's the fix for
minimizing to the tray at start-up and it works for SDI and
MDI applications but only if you dynamically allocate the
object (note FBeginMinimized set in the constructor). If the
component is installed into the IDE, the Loaded method would
have to be overriden so it could know what to do after the
property values have been streamed in. I'm thinking that to
solve the conflict with dynamically allocated and streamed
that an overloaded constructor would take care of it but
that's not going to happen any time soon.

Good Luck.

~ JD

    private:
        #define UWM_MDISTARTMINIMIZED (WM_USER + 100 )
        bool FBeginMinimized;
        unsigned int FExStyle;
        void __fastcall BeginMinimized();

//------------------------------------------------------------------------- --
__fastcall TAnimatedTrayIcon::TAnimatedTrayIcon( TComponent *Owner ) : TComponent(Owner)
{
    ....
    FBeginMinimized = true;    
    if( !ComponentState.Contains(csDesigning) )
      {
          ....
          ::PostMessage( FHandle, CM_TRAYCREATED, 0, 0 );
          if( FBeginMinimized ) BeginMinimized(); // <-- add this here
      }

}

//------------------------------------------------------------------------- --
void __fastcall TAnimatedTrayIcon::BeginMinimized()
{
    BoundsRect = FParentForm->BoundsRect;
    if( FParentForm->FormStyle != fsMDIForm )
      {
          ::SendMessage( Application->Handle, WM_SYSCOMMAND, SC_MINIMIZE, NULL );
          vForms.clear();
          vZOrder.clear();
          vForms.push_back( FParentForm );
          vZOrder.push_back( FParentForm->Handle );
      }
    else
      {
          FExStyle = ::GetWindowLong( Application->Handle, GWL_EXSTYLE );
          if( FExStyle & WS_EX_TOOLWINDOW )
            {
                ::SetWindowLong( Application->Handle, GWL_EXSTYLE, FExStyle | WS_EX_TOOLWINDOW );
                ::PostMessage( FHandle, UWM_MDISTARTMINIMIZED, 0, 0 );
            }
      }
    FParentForm->Visible = false;
    Application->ShowMainForm = false;
    ::ShowWindow( Application->Handle, SW_HIDE );
    if( FParentForm->FormStyle == fsMDIForm )
      {
          ::SendMessage( Application->Handle, WM_SYSCOMMAND, SC_MINIMIZE, NULL );
      }
    FMinimized = true;
}

//------------------------------------------------------------------------- --
bool __fastcall TAnimatedTrayIcon::AppHook( TMessage &Message )
{
    if( Message.Msg == WM_SYSCOMMAND )
      {
          switch( Message.WParam )
            {
                case  SC_RESTORE:
                case SC_MAXIMIZE: return Restore();
                case SC_MINIMIZE: if( FBeginMinimized )
                                    {
                                        FBeginMinimized = false;
                                    }
                                  else return Minimize();
            }
      }
    return false;
}

//------------------------------------------------------------------------- --
void __fastcall TAnimatedTrayIcon::WndProc( TMessage &Message )
{
    ....
    else if( Message.Msg == UWM_MDISTARTMINIMIZED )
      {
          ::SetWindowLong( Application->Handle, GWL_EXSTYLE, FExStyle & ~WS_EX_TOOLWINDOW );
      }
    ....
}

//------------------------------------------------------------------------- --

~ End


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Chris  
View profile  
 More options Mar 24 2006, 3:11 am
Newsgroups: borland.public.cppbuilder.thirdpartytools
From: "Chris" <nos...@nospam.com>
Date: Fri, 24 Mar 2006 08:11:59 -0000
Local: Fri, Mar 24 2006 3:11 am
Subject: Re: For Vladimir Stefanovic : TAnimatedTrayIcon
Fantastic, works like a charm.

Thanks for all the hard work and for sharing this.

Chris

PS.  May I respectfully suggest a slight modification:

Unless I missunderstood, there are a few occasions where the balloon tip
might not be supported, if this is correct could you add some way to check
whether it will work or not i,e

bool __fastcall BallonTipSupported()

or perhaps change

void __fastcall DoBalloonTip() to bool __fastcall DoBalloonTip()

which would allow code like this:

if (!pTray->DoBalloonTip())
    ShowMessage(pTray->BalloonText);

Thanks again.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
JD  
View profile  
(1 user)  More options Mar 24 2006, 2:42 am
Newsgroups: borland.public.cppbuilder.thirdpartytools
From: "JD" <nos...@nospam.com>
Date: 24 Mar 2006 00:42:14 -0700
Local: Fri, Mar 24 2006 2:42 am
Subject: Re: For Vladimir Stefanovic : TAnimatedTrayIcon

"Chris" <nos...@nospam.com> wrote:

> [...] May I respectfully suggest a slight modification:

You could even do it in a disrespectful way! If it has merit,
it will be considered.

> Unless I missunderstood, there are a few occasions where the
> balloon tip might not be supported, if this is correct

That is correct but I'm unclear as to how early it was first
supported which depends on the Shell32.dll. My information is
it has to be v5.0 but I saw something that I haven't tracked
down that hinted that v4.0 will also support ballooning.

> could you add

There's nothing that's stopping you from making any changes
that you desire. I would ask only that you send Vladimir or
myself information on the changes that you (or anyone else
for that matter) have implemented.

> some way to check whether it will work or not

That's reasonable and I think the best way to accomplish that
is to add a read-only property (which I have done). For example:

    __published:
        __property bool CanBalloon = { read = FCanBalloon };

Now your sample would become:

    if( pTray->CanBalloon )
      {
          pTray->DoBalloonTip();
      }
    else
      {
          // programmers choice
      }

~ JD


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google