Announcement

Collapse
No announcement yet.

Dynamic Icon in Task Bar

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dynamic Icon in Task Bar

    This is probably a stupid question, but here goes....

    I would like to be able to create a task bar icon which displayes
    a number. Basically, I am happy with the stuff to do the task
    bar Icon and that all works lovely - but I would like to be able
    to change the Icon by writting a number on it. For example,
    imagine I have a cute little Icon doing its thing on the task bar
    and the app that it belongs to decides that the user needs to
    know that he/she has a message or task waiting. I would like to
    be able to draw that number on the Icon in the task bar.

    Yup its that simple. I guess I am really asking if it is possible
    to get a DC for an Icon object, use the drawtext or other GDI
    thingy's to dynamically create it, then update the task bar with the
    new Icon object. Where my brain goes out to lunch is when an
    Icon becomes a Bitmap and a Bitmap becomes and Icon.

    When I load the Icon from wherever (file or resource), I get a
    handle. Is it possible to make a CompatibleDC for it, then
    do my stuff, then put it back as an Icon object which the task
    bar will accept?

    I do realise the amount of room for my numbers is VERY limited,
    but I would still like to try this out!!

    I also wonder if the new GRAPHICS stuff in PB8 will be of help
    but I have not really looked at it yet!

    ------------------
    Global Database Management Ltd
    www.globaldm.co.uk
    Database Developer, Volume Ltd, UK
    www.volume.co.uk

  • #2
    A simpler way I use to do something simular:
    I have an Icon, a phone. If all is well, a green phone icon is shown. If medium
    important issue comes up, I show a yellow phone icon, if important issue arises, I
    show a red phone icon. I use it's tooltip for giving more info to the user...


    ------------------
    Regards,
    Peter
    Regards,
    Peter

    Comment


    • #3
      Thanks Peter

      Your quite right - it is a lot simpler. In fact, it is kinda what
      I'm doing at the moment. I have a memory monitor which displayes
      a 3 digit count of the available RAM in the task bar as an Icon
      and it got me thinking! I suppose this is more a case of wanting
      to do it rather than needing to. I just had it in my mind that
      I could use the DrawText to dynamically paint the digits onto the
      icon and then re-display it. It's no big deal - I'm just curious
      as to how it could be done!!



      ------------------
      Global Database Management Ltd
      www.globaldm.co.uk
      Database Developer, Volume Ltd, UK
      www.volume.co.uk

      Comment


      • #4
        Chris,

        I've had no need to do any task bar tricks, so can't help there. The new graphics can however be used with an approach like VB's Picture Clip. That might be useful if you can get a method that does on-the-fly icon-bmp-icon transitions. The reasoning here is that a pic-clip might be more useful than say a lot of loose icons to get to the max number you might want. See the PBWin80 Samples\DDT\Graphic\Digital example and the bitmap for a demo on how this is easily done. Using that you could introduce colors for significance as well. But obviously the first hurdle is the icon-bmp-icon bit.

        ------------------
        Rick Angell
        Rick Angell

        Comment


        • #5
          chris,

          i have a ddt dynamic icon example in the source code forum in an ez post program.

          ~bob

          ------------------

          Comment


          • #6
            I it's just a number you want to show, do you really need an icon or bitmap at all?

            Can't you just do a 'drawtext' or 'textout' on either WM_PAINT or maybe WM_DRAWITEM on a static control?

            I'm not a 'tray' guy but I have to believe there is some way to specify 'owner drawing' of the image which appears there.

            [later]
            Come to think if it, Don Dickinson made up a utily "PopWiz" which shows 'number of email messages waiting for you' in the tray. AFAIK he did not make source code available, but its existence proves something like this is 'do-able'
            [/later]




            [This message has been edited by Michael Mattias (edited March 08, 2005).]

            Comment


            • #7
              Chris,

              If a number is truly all you want in the title then it is easy in DDT.

              Code:
                    DIALOG SET TEXT hDlg, FORMAT$(Number)
              ~Bob

              ------------------


              [This message has been edited by Bob Scott (edited March 08, 2005).]

              Comment


              • #8
                I have an Astroid game that in Win 3.x you could minimize it and play
                the game on the icon, so I know it is possible to somehow draw
                on it unless they just created an icon in memory and set the icon to it...
                but even then they must be only changing the LargeIcon cause it doesn't
                show the game in the Titlebar or Taskbar in Win9x+

                ------------------
                If you aim at nothing...you will hit it.
                sigpic
                Mobile Solutions
                Sys Analyst and Development

                Comment


                • #9
                  After doing some research it appears Icons could be owner drawn back then:
                  http://blogs.msdn.com/oldnewthing/ar...28/249044.aspx

                  ------------------
                  If you aim at nothing...you will hit it.
                  sigpic
                  Mobile Solutions
                  Sys Analyst and Development

                  Comment


                  • #10
                    In the good old days, there was the WM_PAI NTICON Notification and W M_ICONERASEBKGND Notification messages. These days, they are not in vogue and have been deprecated.

                    Have you tried creating an icon resource at run-time and updating the icon image with the necessary dynamic elements, and then using the WM_SETICON message (remembering to remove the icon from the window when you are done, so Windows won't get upset when you destroy the icon resource) to cause it to be your windows taskbar icon? I don't know exactly how this might be accomplished, as I don't have any example code.

                    ------------------
                    If you try to make something idiot-proof, someone will invent a better idiot.
                    If you try to make something idiot-proof, someone will invent a better idiot.

                    Comment


                    • #11
                      I love these forums! So much info and so quickly obtained!

                      Thanks guys for all you help here. I think I need to clarify what
                      I'm after, just so we are all clear!

                      I want the ICON in the system TRAY to be dynamic. I have an app
                      which places an Icon there (where the clock is displayed etc) and
                      when you right click on it the app creates a menu etc etc.

                      Anyway, imagine this icon is just a red circle and I load it from
                      a resource file as usual and then set the icon by doing the:-
                      Code:
                      Global ti As NOTIFYICONDATA 'Tray Icon 
                      ...
                      ti.hIcon = LoadImage(App.hInstance, "PROGRAM", %IMAGE_ICON, 16, 16, %LR_SHARED) 
                      ...
                      Shell_NotifyIcon %NIM_ADD, ti
                      Now, what I'm really after is something like:
                      Code:
                      hIcon = LoadImage(blah blah)
                      hDC = MagicAPIThatCreatesADCforIcon(hIcon)
                      DrawText(hDC,"21",2,lpRect,%DT_CENTER)
                      hDC = MagicAPIThatCreatesAnIconFromADC(hDC,hIcon)
                      ti.hIcon = hIcon
                      Now, I know the two functions above will not exist, but I suspect
                      it will be something along the lines of Load the Icon, then
                      create a compatibleDC, convert the loaded Icon to a bitmap and
                      load the bitmap to the DC. Then do the drawtext stuff then get
                      the bitmap from the DC and make it back into an Icon, or update
                      the loaded icon with the new bitmap.

                      I may be way off the mark here, but this is not an area I've done
                      anything with before.

                      Anyway, I hope this is clearer!



                      ------------------
                      Global Database Management Ltd
                      www.globaldm.co.uk
                      Database Developer, Volume Ltd, UK
                      www.volume.co.uk

                      Comment


                      • #12
                        Hi Chris,

                        I think you need to take a look at GetIconInfo and CreateIconIndirect.

                        The GetIconInfo function takes an icon handle and fills an ICONINFO
                        structure containing two handles to bitmaps that represent the icon
                        (one for the bitmask, one for the color).

                        The CreateIconIndirect takes an ICONINFO structure and returns a handle
                        to a new icon.

                        All you need to do (!) is figure out how to modify the bitmaps in between
                        and you should be there.

                        Hope that helps.

                        Regards,

                        Pete.

                        Comment


                        • #13
                          Peter

                          All you need to do (!) is figure out how to modify the bitmaps in between
                          and you should be there.
                          Wow! CreateIconIndirect I had found in the MSDN stuff, but I completely
                          missed the Handles to the bitmaps in the ICONINFO structure!

                          This should be interesting! I'm gonna go play

                          Many thanks for that!



                          ------------------
                          Global Database Management Ltd
                          www.globaldm.co.uk
                          Database Developer, Volume Ltd, UK
                          www.volume.co.uk

                          Comment


                          • #14
                            Hi Chris,

                            I expect you've got this all figured out by now, but just in case you haven't,
                            or for any lurkers, here's a quick example of how to modify an icon;

                            Code:
                            '----------------------------------------------------------------
                            SUB ModifyIcon(hIcon AS DWORD, BYVAL lCount AS LONG)
                            '----------------------------------------------------------------
                                ' Draw a number (lCount) over the icon (hIcon), then create a
                                '  new icon from the resulting image and return a handle to it
                                
                                LOCAL uInfo AS ICONINFO, lRes AS LONG
                                LOCAL hMemDC AS DWORD, hOldBMP AS DWORD, sText AS STRING
                                LOCAL hNewIcon AS DWORD, rectDraw AS RECT, uBitmap AS BITMAP
                            
                                lRes = GetIconInfo(hIcon, uInfo)
                                IF lRes <> 0 THEN
                                    ' Call succeeded
                                    hMemDC = CreateCompatibleDC(BYVAL %NULL)
                                    IF hMemDC = 0 THEN
                                        MSGBOX "CreateCompatibleDC failed : " & STR$(hMemDC), %MB_TASKMODAL
                                    ELSE
                                        ' Get info for the bitmap
                                        GetObject uInfo.hbmColor, SIZEOF(uBitmap), uBitmap
                                        ' and setup RECT
                                        rectDraw.nLeft = 0 : rectDraw.nTop = 0 : rectDraw.nRight = uBitmap.bmWidth - 1 : rectDraw.nBottom = uBitmap.bmHeight - 1
                                        ' Get our bitmap ready to draw on
                                        hOldBMP = SelectObject(hMemDC, uInfo.hbmColor)
                                        ' Format the count
                                        sText = FORMAT$(lCount, "#0")
                                        ' Draw it
                                        lRes = DrawText(hMemDC, BYCOPY sText, LEN(sText), rectDraw, %DT_CENTER OR %DT_VCENTER OR %DT_SINGLELINE)
                                        ' Put old bitmap back
                                        SelectObject hMemDC, hOldBMP
                                        ' Create the new icon from the modified structure
                                        hNewIcon = CreateIconIndirect(uInfo)
                            
                                        IF hNewIcon <> 0 THEN
                                            ' Worked ok - delete the old icon
                                            DestroyIcon hIcon
                                            ' And pass the handle to the new one back
                                            hIcon = hNewIcon
                                        ELSE
                                            MSGBOX "CreateIconIndirect failed", %MB_TASKMODAL
                                        END IF
                            
                                        ' Clean up the memory DC
                                        DeleteDC hMemDC
                                    END IF
                                    
                                    ' Note that we also need to clean up the 2 bitmaps we got in the structure
                                    DeleteObject uInfo.hbmMask
                                    DeleteObject uInfo.hbmColor
                                    
                                ELSE
                                    MSGBOX "GetIconInfo failed", %MB_TASKMODAL
                                END IF
                            END SUB
                            I added this function to the Tray example that comes with PB (in Samples\SDK\Tray\),
                            then just modify the following CASE statement elsewhere in the program, to;

                            Code:
                                    CASE 101 TO 105
                                        ' Change tray icon
                                        ti.hIcon = LoadIcon(g_hInst, "FACE" + FORMAT$(LOWRD(wParam) - 100))
                                        ModifyIcon ti.hIcon, wParam  ' <=== Added to demonstrate
                                        Shell_NotifyIcon %NIM_MODIFY, ti
                                        DestroyIcon ti.hIcon
                            Regards,

                            Pete.

                            (Added: Changed END FUNCTION to END SUB!)


                            [This message has been edited by Peter Jinks (edited March 12, 2005).]

                            Comment


                            • #15
                              Code:
                              Pete, great example, thanks !
                              [ change the END FUNCTION to END SUB ]
                              Thanks,
                              P
                              ------------------

                              Comment


                              • #16
                                Peter

                                Er..Yeah! I had it all figured out all right!! Mind you, I can't
                                seem to find my code, oh well, I guess I'll use yours!!

                                This is fantastic! Thanks a lot! I would have got there under
                                my own steam, probably around 2009!

                                I will test this out and, I'm sure it'll work just peachy!



                                ------------------
                                Global Database Management Ltd
                                www.globaldm.co.uk
                                Database Developer, Volume Ltd, UK
                                www.volume.co.uk

                                Comment


                                • #17
                                  Ok, here is the 'final' code. I only made a tiny tweek, which is
                                  to allow any text to be drawn, and you can set the font as well!

                                  Uses the firefly ff_makefont function which was created by Paul
                                  but I'm sure its easy to adapt to any other function!

                                  Code:
                                  '----------------------------------------------------------------
                                  Function ModifyIcon(hIcon As Dword, ByVal cText As String, ByVal cFont As String) As Long
                                  '----------------------------------------------------------------
                                      ' Draw a bit of text on the icon supplied as the hIcon handle
                                      ' and set the font.  Font is supplied as fontname,pointsize,BIU  where B=bold, I= Italic and U=Underlined
                                      ' Makes use of the firefly makefont function, but could be converted to use the PBFORMs one or any other
                                      ' which works in a similar fashion.
                                      ' ALL of the main original code was created by Peter Jinks and placed on the PowerBASIC forum
                                      ' him - for which I am very grateful!
                                      
                                      Local uInfo As ICONINFO
                                      Local lRes As Long
                                      Local hMemDC As Dword
                                      Local hOldBMP As Dword
                                      Local hNewIcon As Dword
                                      Local rectDraw As Rect
                                      Local uBitmap As BITMAP
                                      Local hOldFont As Dword
                                      Local cName As String
                                      Local cStyle As String  
                                      Local nPoint As Long
                                      Static cOldFont As String 
                                      If cOldFont = "" Then
                                      	' We use this is the user does not specify.  If they do, we remember it!
                                      	cOldFont = "Arial,16"
                                      End If
                                      
                                      If Len(cFont) Then cOldFont = cFont
                                  	cName = Parse$(cOldFont,",",1)							' Get the font name
                                  	cStyle = UCase$(Parse$(cOldFont,",",3))					' Get the style bits (BI or I in a string)
                                  	nPoint = Min(Max(Val(Parse$(cOldFont,",",2)),8),36)    	' Get the point size between 8 and 36
                                      'MsgBox Using$("Font = [&], #_, [&]", cName, nPoint, cStyle)
                                      lRes = GetIconInfo(hIcon, uInfo) 
                                      If lRes = 0 Then
                                      	Function = %False
                                      	Exit Function
                                      End If
                                      ' Call succeeded
                                      hMemDC = CreateCompatibleDC(ByVal %Null)
                                      If hMemDC = 0 Then
                                      	Function = %False
                                      	Exit Function
                                      End If
                                  
                                      ' Get info for the bitmap
                                      GetObject uInfo.hbmColor, SizeOf(uBitmap), uBitmap
                                      ' and setup RECT
                                      rectDraw.nLeft = 0 : rectDraw.nTop = 0 : rectDraw.nRight = uBitmap.bmWidth - 1 : rectDraw.nBottom = uBitmap.bmHeight - 0
                                      ' Get our bitmap ready to draw on
                                      hOldBMP = SelectObject(hMemDC, uInfo.hbmColor)
                                      ' Set the font
                                      hOldFont = SelectObject(hMemDC, FF_MakeFontEx(cName,nPoint,Tally(cStyle,"B"),Tally(cStyle,"I"),Tally(cStyle,"U"),%False))
                                      lRes = DrawText(hMemDC, ByCopy cText, Len(cText), rectDraw, %DT_CENTER Or %DT_VCENTER Or %DT_SINGLELINE)
                                      ' Put old bitmap back
                                      SelectObject hMemDC, hOldBMP
                                      ' put back the old font and delete the new one
                                      hOldFont = SelectObject(hMemDC, hOldFont)
                                      DeleteObject hOldFont
                                      ' Create the new icon from the modified structure
                                      hNewIcon = CreateIconIndirect(uInfo)
                                      If hNewIcon <> 0 Then
                                          ' Worked ok - delete the old icon
                                          DestroyIcon hIcon
                                          ' And pass the handle to the new one back
                                          hIcon = hNewIcon
                                          Function = %True
                                      Else
                                          Function = %False
                                      End If
                                      ' Clean up the memory DC
                                      DeleteDC hMemDC
                                      
                                      ' Note that we also need to clean up the 2 bitmaps we got in the structure
                                      DeleteObject uInfo.hbmMask
                                      DeleteObject uInfo.hbmColor
                                          
                                  End Function
                                  I also made it a function, so that you can test if it worked and
                                  it does not interupt program flow.

                                  Thanks so very much Peter for your great code (99% of this one!)





                                  ------------------
                                  Global Database Management Ltd
                                  www.globaldm.co.uk
                                  Database Developer, Volume Ltd, UK
                                  www.volume.co.uk

                                  Comment

                                  Working...
                                  X