FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Balloon Tooltips for NotifyIcon

 
Post new topic   Reply to topic     Forum Index -> DFL
View previous topic :: View next topic  
Author Message
kbogert



Joined: 18 May 2006
Posts: 5

PostPosted: Wed Jun 21, 2006 9:18 pm    Post subject: Balloon Tooltips for NotifyIcon Reply with quote

Hello all, here are two patches against version 9.2 to enable the NotifyIcon class to display the balloon popup tooltip we all know and love.

Note that you need to fix a small error in environment.d in order to prevent a stack overflow before using these, see my previous post.

Code:

--- notifyicon-old.d   2005-07-26 21:46:04.000000000 -0400
+++ notifyicon.d   2006-06-21 23:49:43.000000000 -0400
@@ -2,11 +2,14 @@
 
 private import dfl.winapi, dfl.base, dfl.drawing, dfl.menu;
 private import dfl.control, dfl.form, dfl.application;
-private import dfl.event;
+private import dfl.event, dfl.environment;
 
 
 class NotifyIcon // docmain
 {
+   
+   const UINT NOTIFYICON_VERSION = 3;
+   
    final void contextMenu(ContextMenu menu) // setter
    {
       this.cmenu = menu;
@@ -44,6 +47,9 @@
       if(txt.length >= nid.szTip.length)
          throw new DflException("Notify icon text too long.");
       
+      if (!mWin2k && txt.length > 64)
+         throw new DflException("Notify icon text too long.");      
+      
       nid.szTip[txt.length] = 0;
       nid.szTip[0 .. txt.length] = txt;
       tipLen = txt.length;
@@ -93,7 +99,11 @@
    
    
    EventHandler click;
-   EventHandler doubleClick;
+   EventHandler doubleClick;
+    EventHandler balloonShow;
+   EventHandler balloonHide;
+   EventHandler balloonClick;
+   EventHandler balloonTimeout;
    MouseEventHandler mouseDown;
    MouseEventHandler mouseUp;
    MouseEventHandler mouseMove;
@@ -103,13 +113,18 @@
    {
       if(!ctrlNotifyIcon)
          _init();
-      
-      nid.cbSize = nid.sizeof;
+            
+      if (mWin2k) {
+         nid.cbSize = nid.sizeof;
+         nid.szInfo[0] = '\0';
+      } else
+         nid.cbSize = NOTIFYICONDATA_V1_SIZE;
       nid.hWnd = ctrlNotifyIcon.handle;
       nid.uID = 0;
       nid.uCallbackMessage = WM_NOTIFYICON;
       nid.hIcon = null;
-      nid.szTip[0] = '\0';
+      nid.szTip[0] = '\0';
+      
    }
    
    
@@ -133,7 +148,40 @@
       }
       +/
    }
-   
+   
+   void showBalloon(char[] balloonText, char[] balloonTitle, DWORD balloonIconFlag, int balloonTimeout) {
+      
+      if (!mWin2k)
+         throw new DflException("Not Supported in this Operating System");
+         
+      if (balloonText.length >= nid.szInfo.length)
+         throw new DflException("Balloon text too long.");
+      if(balloonTitle.length >= nid.szInfoTitle.length)
+         throw new DflException("Balloon title too long.");
+      
+      if(balloonIconFlag != NIIF_NONE && balloonIconFlag != NIIF_WARNING && balloonIconFlag != NIIF_ERROR && balloonIconFlag != NIIF_INFO)
+         throw new DflException("Balloon icon invalid.");
+      
+      if(balloonTimeout < 10 || balloonTimeout > 30)
+         throw new DflException("Balloon timeout invalid.");      
+            
+      nid.szInfo[balloonText.length] = '\0';
+      nid.szInfo[0 .. balloonText.length] = balloonText;
+
+      nid.szInfoTitle[balloonTitle.length] = '\0';
+      nid.szInfoTitle[0 .. balloonTitle.length] = balloonTitle;
+      
+      nid.uTimeout = balloonTimeout * 1000; // convert sec to ms
+       nid.dwInfoFlags = balloonIconFlag;
+   
+      if(visible)
+      {
+         nid.uFlags = NIF_INFO;
+         Shell_NotifyIconA(NIM_MODIFY, &nid);
+         nid.szInfo[0] = '\0';  // prevent re-display of the balloon
+      }
+      
+   }
    
    // Extra.
    void minimize(IWin32Window win)
@@ -209,11 +257,24 @@
    ContextMenu cmenu;
    Icon _icon;
    
-   
    package final void _forceAdd()
    {
-      nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+      nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+      
+      if (mWin2k) {
+         if (nid.szInfo[0] != '\0')
+            nid.uFlags |= NIF_INFO;
+         nid.uTimeout = NOTIFYICON_VERSION;
+         nid.dwState = NIS_SHAREDICON;
+      }
+      
       Shell_NotifyIconA(NIM_ADD, &nid);
+      
+      if (mWin2k) {
+         Shell_NotifyIconA(NIM_SETVERSION, &nid);
+         nid.szInfo[0] = '\0';         
+      }
+      
    }
    
    
@@ -303,7 +364,8 @@
 NotifyIcon[UINT] allNotifyIcons; // Indexed by ID.
 UINT lastId = 1;
 NotifyIconControl ctrlNotifyIcon;
-
+LONG windowProc;
+bool mWin2k;
 
 class NotifyIconControl: Control
 {
@@ -324,8 +386,20 @@
          Application.getInstance(), null);
       if(!hwnd)
          goto create_err;
+      
+//      if (mWin2k)
+   //      windowProc = SetWindowLongA(hwnd, GWL_WNDPROC, cast(LONG*)&wndProc);
+
    }
    
+   override void destroyHandle()
+   {
+      if (mWin2k && hwnd) {
+         SetWindowLongA(hwnd, GWL_WNDPROC, windowProc);
+         windowProc = 0;
+      }
+      super.destroyHandle();
+   }
    
    protected override void wndProc(inout Message msg)
    {
@@ -337,7 +411,7 @@
             Point pt;
             
             ni = allNotifyIcons[cast(UINT)msg.wParam];
-            
+   
             switch(cast(UINT)msg.lParam) // msg.
             {
                case WM_MOUSEMOVE:
@@ -372,8 +446,24 @@
                
                case WM_LBUTTONDBLCLK:
                   ni.doubleClick(ni, EventArgs.empty);
-                  break;
-               
+                  break;
+                  
+                   case NIN_BALLOONSHOW:
+                          ni.balloonShow(ni, EventArgs.empty);
+                          break;
+     
+                   case NIN_BALLOONHIDE:
+                  ni.balloonHide(ni, EventArgs.empty);
+                  break;
+
+               case NIN_BALLOONUSERCLICK:
+                  ni.balloonClick(ni, EventArgs.empty);
+                  break;
+                        
+                    case NIN_BALLOONTIMEOUT:
+                  ni.balloonTimeout(ni, EventArgs.empty);
+                  break;
+
                default: ;
             }
          }
@@ -428,6 +518,11 @@
 
 void _init()
 {
+   OperatingSystem curOS = Environment.osVersion();
+      
+   if ( curOS.ver().major() >= 5 && curOS.platform() == PlatformId.WIN32_NT)
+      mWin2k = true;
+
    wmTaskbarCreated = RegisterWindowMessageA("TaskbarCreated");
    
    ctrlNotifyIcon = new NotifyIconControl;


Code:

--- winapi-old.d   2006-01-20 19:46:02.000000000 -0500
+++ winapi.d   2006-06-21 22:59:00.000000000 -0400
@@ -1265,7 +1265,8 @@
 {
    NIF_MESSAGE = 0x00000001,
    NIF_ICON = 0x00000002,
-   NIF_TIP = 0x00000004,
+   NIF_TIP = 0x00000004,
+   NIF_INFO = 0x00000010,
 }
 
 
@@ -1274,6 +1275,7 @@
    NIM_ADD = 0x00000000,
    NIM_MODIFY = 0x00000001,
    NIM_DELETE = 0x00000002,
+   NIM_SETVERSION = 0x00000004,
 }
 
 
@@ -1527,10 +1529,40 @@
     UINT uFlags;
     UINT uCallbackMessage;
     HICON hIcon;
-    char[64] szTip;
+    char[128] szTip;
+    DWORD dwState;
+    DWORD dwStateMask;
+    char[256] szInfo;
+    UINT uTimeout;
+    char[64] szInfoTitle;
+    DWORD dwInfoFlags;
 }
 alias NOTIFYICONDATA* PNOTIFYICONDATA;
-
+
+const DWORD NOTIFYICONDATA_V1_SIZE = 88;  //pre-5.0 structure size
+// const DWORD NOTIFYICONDATA_V2_SIZE = 488; //pre-6.0 structure size
+
+enum : DWORD
+{
+   NIIF_NONE = 0x0,
+   NIIF_WARNING = 0x2,
+   NIIF_ERROR = 0x3,
+   NIIF_INFO = 0x1,
+}
+
+enum : DWORD
+{
+   NIS_HIDDEN = 1,
+   NIS_SHAREDICON = 2,
+}
+
+enum : UINT
+{
+   NIN_BALLOONSHOW = WM_USER + 2,
+   NIN_BALLOONHIDE = WM_USER + 3,
+   NIN_BALLOONTIMEOUT = WM_USER + 4,
+   NIN_BALLOONUSERCLICK = WM_USER + 5,
+}
 
 // Unaligned!
 struct SHITEMID



kdb
_________________
- kdb
Back to top
View user's profile Send private message
kbogert



Joined: 18 May 2006
Posts: 5

PostPosted: Thu Jun 22, 2006 3:13 pm    Post subject: Remove the DWORD from showBalloon Reply with quote

I don't know what I was thinking. C heritage I guess ...

Code:

--- notifyicon-old2.d   2006-06-22 17:10:01.000000000 -0400
+++ notifyicon.d   2006-06-22 17:09:08.000000000 -0400
@@ -4,6 +4,14 @@
 private import dfl.control, dfl.form, dfl.application;
 private import dfl.event, dfl.environment;
 
+   
+public enum BalloonIcon : DWORD
+{
+   NONE = NIIF_NONE,
+   INFO = NIIF_INFO,
+   WARNING = NIIF_WARNING,
+   ERROR = NIIF_ERROR,
+}
 
 class NotifyIcon // docmain
 {
@@ -149,7 +157,7 @@
       +/
    }
    
-   void showBalloon(char[] balloonText, char[] balloonTitle, DWORD balloonIconFlag, int balloonTimeout) {
+   void showBalloon(char[] balloonText, char[] balloonTitle, BalloonIcon balloonIconFlag, int balloonTimeout) {
       
       if (!mWin2k)
          throw new DflException("Not Supported in this Operating System");
@@ -159,9 +167,6 @@
       if(balloonTitle.length >= nid.szInfoTitle.length)
          throw new DflException("Balloon title too long.");
       
-      if(balloonIconFlag != NIIF_NONE && balloonIconFlag != NIIF_WARNING && balloonIconFlag != NIIF_ERROR && balloonIconFlag != NIIF_INFO)
-         throw new DflException("Balloon icon invalid.");
-      
       if(balloonTimeout < 10 || balloonTimeout > 30)
          throw new DflException("Balloon timeout invalid.");      
             
@@ -387,9 +392,6 @@
       if(!hwnd)
          goto create_err;
       
-//      if (mWin2k)
-   //      windowProc = SetWindowLongA(hwnd, GWL_WNDPROC, cast(LONG*)&wndProc);
-
    }
    
    override void destroyHandle()


That should provide a nice enum for setting the baloon's icon. Apply to the above patch.
_________________
- kdb
Back to top
View user's profile Send private message
Chris Miller



Joined: 27 Mar 2004
Posts: 514
Location: The Internet

PostPosted: Thu Jun 22, 2006 9:47 pm    Post subject: Re: Balloon Tooltips for NotifyIcon Reply with quote

Cool, I'll take a look at it later.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> DFL All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group