Jump to content

Recommended Posts

Posted

I'm trying to make a script that will add a secondary icon to the taskbar when I have unread emails. Outlook doesn't show this well and I sometimes miss emails for an hour or more.

Currently, the script creates a GUI, draws a red circle with a black border, then draws some text on top of that. The number will eventually be the unread email count, but for testing it's just an incrementing number. That all works fine. The issue seems to be when I'm trying to convert the GDIPlus Graphic into a Icon to display in the taskbar. Instead of drawing the same circle with text over Outlook's icon, it draws a solid black square. According to MS's documentation, I need to pass a HICON (a handle to an icon?) to the function ITaskbarList3::SetOverlayIcon. I've tried a few different things, but here's the current code:

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPIIcons.au3>
; #include <Taskbar.au3> ; A UDF I created for myself. Instead I extracted the necessary things to this file

Global Const $__g_sCLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}"
Global Const $__g_sIID_ITaskbarList3 = "{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"
Global Const $__g_tagITaskbarList3 = _
    "HrInit hresult();" & _
    "AddTab hresult(hwnd);" & _
    "DeleteTab hresult(hwnd);" & _
    "ActivateTab hresult(hwnd);" & _
    "SetActiveAlt hresult(hwnd);" & _
    "MarkFullscreenWindow hresult(hwnd;boolean);" & _
    "SetProgressValue hresult(hwnd;uint64;uint64);" & _
    "SetProgressState hresult(hwnd;int);" & _
    "RegisterTab hresult(hwnd;hwnd);" & _
    "UnregisterTab hresult(hwnd);" & _
    "SetTabOrder hresult(hwnd;hwnd);" & _
    "SetTabActive hresult(hwnd;hwnd;dword);" & _
    "ThumbBarAddButtons hresult(hwnd;uint;ptr);" & _
    "ThumbBarUpdateButtons hresult(hwnd;uint;ptr);" & _
    "ThumbBarSetImageList hresult(hwnd;ptr);" & _
    "SetOverlayIcon hresult(hwnd;ptr;wstr);" & _
    "SetThumbnailTooltip hresult(hwnd;wstr);" & _
    "SetThumbnailClip hresult(hwnd;ptr);"

Global $__g_iFontSize = 12
Main()

Func Main()
    ; Create GUI
    Local $hGUI = GUICreate("GDI+", 400, 300)
    GUISetState(@SW_SHOW)

    Local $iX = 138, $iY = 108, $iWidth = 32, $iHeight = 32, $iBorder = 1

    _GDIPlus_Startup()
    Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    Local $hTextBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
    Local $hFormat = _GDIPlus_StringFormatCreate()
    Local $hFamily = _GDIPlus_FontFamilyCreate("Arial")
    Local $hFont = _GDIPlus_FontCreate($hFamily, $__g_iFontSize)
    Local $tLayout = _GDIPlus_RectFCreate($iX + 2, $iY + 2, $iWidth, $iHeight - 5)
    Local $hBackgroundBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    Local $hPen = _GDIPlus_PenCreate(0xFF000000, $iBorder)
    Local $iIndex = 0
    Local $hTimer = TimerInit()
    Local $oTB = _Taskbar_Init()
    Local $hBitmap, $hIcon
    ; Loop until the user exits.
    Do
        ; only update after 1 second
        If TimerDiff($hTimer) > 1000 Then
            If $iIndex > 0 Then
                _WinAPI_DestroyIcon($hIcon)
                _GDIPlus_BitmapDispose($hBitmap)
            EndIf
            ; Clear the graphics
            _GDIPlus_GraphicsClear($hGraphic, 0xFFFFFFFF)
            ; Draw a filled circle
            _GDIPlus_GraphicsFillEllipse($hGraphic, $iX, $iY, $iWidth, $iHeight, $hBackgroundBrush)
            ; Draw a border circle
            _GDIPlus_GraphicsDrawEllipse($hGraphic, $iX, $iY, $iWidth, $iHeight, $hPen)
            ; Draw the text in the circle
            DrawStringCentered($hGraphic, $iIndex, $hFont, $tLayout, $hFormat, $hTextBrush)
            ; Extract the graphic to a bitmap
            $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphic)
            If ErrMsg(_GDIPlus_BitmapCreateFromGraphics) Then Exit
            ; Convert the Bitmap into an icon
            $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap)
            If ErrMsg(_GDIPlus_HICONCreateFromBitmap) Then Exit

            $hIcon = _WinAPI_Create32BitHICON($hIcon, true)
            If ErrMsg(_WinAPI_Create32BitHICON) Then Exit

            ; Add the icon to the window
            AddIconToWin("Inbox", $oTB, $hIcon)
            $iIndex += 1
            if($iIndex > 99) Then $iIndex = 99
            $hTimer = TimerInit()
        EndIf
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ; Clean up resources
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hTextBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()

    ; Clear the icon
    AddIconToWin("Inbox", $oTB, null)
EndFunc

Func DrawStringCentered($hGraphic, $iIndex, $hFont, $tLayout, $hFormat, $hTextBrush)
    
    ; Determine the width of the string
    Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $iIndex, $hFont, $tLayout, $hFormat)
    Local $tIndex = $aInfo[0]
    ; Offset + Half of (Area's width - font's width)
    $tIndex.X = $tLayout.X + (($tLayout.Width - $tIndex.Width) / 2)
    ; Offset + Half of (Area's width - font's width)
    $tIndex.Y = $tLayout.Y + (($tLayout.Height - _GDIPlus_FontGetHeight($hFont, $hGraphic)) / 2)
    ; Finally, draw the string
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $iIndex, $hFont, $tIndex, $hFormat, $hTextBrush)

EndFunc

Func AddIconToWin($sSearch, $oTB, $hIcon)
    
    Local $hWnd = WinGetHandle($sSearch)
    if ErrMsg(WinGetHandle) Then Exit
    
    _Taskbar_SetOverlayIcon($oTB, $hWnd, $hIcon, "Custom Icon")
    If ErrMsg(_Taskbar_SetOverlayIcon) Then Exit

EndFunc

Func AddIconToOutlook()
    Local $hWnd = WinGetHandle("Inbox")
    if ErrMsg(WinGetHandle) Then Exit
    Debug(WinGetTitle($hWnd))

    Local $oTB = _Taskbar_Init()
    If ErrMsg(_Taskbar_Init) Then Exit

    Local $hIcon = _WinAPI_ShellExtractIcon(@SystemDir & "\shell32.dll", 109, 64, 64)
    If ErrMsg(_WinAPI_ShellExtractIcon) Then Exit

    _Taskbar_SetOverlayIcon($oTB, $hWnd, $hIcon, "No Entry")
    If ErrMsg(_Taskbar_SetOverlayIcon) Then Exit

    Debug("Should've set the icon now? I think?")
EndFunc

Func Debug($sMsg, $sPrefix = "+")
    ConsoleWrite($sPrefix & $sMsg & @CRLF)
EndFunc

Func ErrMsg($sMsg = "", $iError = @error, $iExtended = @extended, $iScriptLineNum = @ScriptLineNumber)
    Local $__g_bUsingVSCode = true
    ; If there is an error, then write the error message
    If $iError Then
        ; If we've used a Function as the message (it looks really nice when I do) then print the name of the function
        If IsFunc($sMsg) Then $sMsg = FuncName($sMsg)
        Local $sText = ""
        If StringInStr(@ScriptName, ".au3") Then 
            If $__g_bUsingVSCode Then
                $sText = @ScriptFullPath & ":" & $iScriptLineNum & ":5 - See below for message" & @CRLF
            Else
                $sText = '"' & @ScriptFullPath & '" (' & $iScriptLineNum & ',5) : (See below for message)' & @CRLF
            EndIf
        EndIf
        If $iExtended <> 0 Then $sMsg = "Extended: " & $iExtended & " - " & $sMsg
        $sText &= "! Error: " & $iError & " - " & $sMsg
        Debug($sText, "")
    EndIf
    ; Preserve the error
    Return SetError($iError, $iExtended, $iError)

EndFunc


Func _Taskbar_Init()
    
    Local $oTB = ObjCreateInterface($__g_sCLSID_TaskbarList, $__g_sIID_ITaskbarList3, $__g_tagITaskbarList3)
    Local $oErrHnd = ObjEvent("AutoIt.Error", FuncName(__Taskbar_ErrorHandler))
    $oTB.HrInit()
    If @error Then Return SetError(@error, @extended, False)
    Return $oTB

EndFunc   ;==>_Taskbar_Init

; These are icons added to your taskbar icon, showing status usually. Each window only gets 1. Set $hIcon to NULL to clear. 
; (Win11) Teams uses this to show your status (busy, free, inactive) and Outlook uses it to show if you have an unread email
; Returns True on success, sets @error on failure
Func _Taskbar_SetOverlayIcon(ByRef $oTB, $hWnd, $hIcon, $sAltText = "")
    
    Local $oErrHnd = ObjEvent("AutoIt.Error", FuncName(__Taskbar_ErrorHandler))
    Local $vRet = $oTB.SetOverlayIcon($hWnd, $hIcon, $sAltText)
    If @error Then Return SetError(@error, @extended, False)
    If $vRet = 0 Then Return True
    Return SetError($vRet, 0, False)

EndFunc   ;==>_Taskbar_SetOverlayIcon

Func __Taskbar_ErrorHandler()
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
        @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
        @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
        @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
        @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
        @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
        @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
        @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
        @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
        @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc

I think I might be doing something wrong when I'm converting Graphics > Bitmap > Icon > Icon, but I'm not sure what to try instead.

I'm also doing something wrong when I'm centering the string in the circle, but I can figure that out if I spend a little more time on it.

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

  • Solution
Posted

You can simply try this code:
It uses GDI+ to draw a red circle with centered text, creates a 32-bit ARGB icon, and sets it as a taskbar overlay using ITaskbarList3::SetOverlayIcon.
It updates the icon every second. You can easily adjust it to fit your own needs.

Let me know if it works for you!

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPIIcons.au3>

Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("! COM Error ! Number: 0x" & Hex($oError.number, 8) & " Line: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
EndFunc

; Define ITaskbarList3 COM interface
Global Const $sCLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}"
Global Const $sIID_ITaskbarList3 = "{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"
Global Const $tagITaskbarList3 = _
    "HrInit hresult();" & _
    "AddTab hresult(hwnd);" & _
    "DeleteTab hresult(hwnd);" & _
    "ActivateTab hresult(hwnd);" & _
    "SetActiveAlt hresult(hwnd);" & _
    "MarkFullscreenWindow hresult(hwnd;boolean);" & _
    "SetProgressValue hresult(hwnd;uint64;uint64);" & _
    "SetProgressState hresult(hwnd;int);" & _
    "RegisterTab hresult(hwnd;hwnd);" & _
    "UnregisterTab hresult(hwnd);" & _
    "SetTabOrder hresult(hwnd;hwnd);" & _
    "SetTabActive hresult(hwnd;hwnd;dword);" & _
    "ThumbBarAddButtons hresult(hwnd;uint;ptr);" & _
    "ThumbBarUpdateButtons hresult(hwnd;uint;ptr);" & _
    "ThumbBarSetImageList hresult(hwnd;ptr);" & _
    "SetOverlayIcon hresult(hwnd;ptr;wstr);" & _
    "SetThumbnailTooltip hresult(hwnd;wstr);" & _
    "SetThumbnailClip hresult(hwnd;ptr);"

; Global variables
Global $hGraphic, $hTextBrush, $hFormat, $hFamily, $hFont, $hBackgroundBrush, $hPen
Global $oList, $hWnd
Global $iWidth = 32, $iHeight = 32, $iFontSize = 12
Global $iCounter = 0

Main()

Func Main()
    _GDIPlus_Startup()

    $hWnd = GUICreate("Taskbar Overlay Icon Test", 400, 300)
    Local $label = GUICtrlCreateLabel("Starting...", 10, 10, 380, 100)
    GUISetState()

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $hTextBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
    $hFormat = _GDIPlus_StringFormatCreate()
    $hFamily = _GDIPlus_FontFamilyCreate("Arial")
    $hFont = _GDIPlus_FontCreate($hFamily, $iFontSize)
    $hBackgroundBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    $hPen = _GDIPlus_PenCreate(0xFF000000, 2)

    $oList = ObjCreateInterface($sCLSID_TaskbarList, $sIID_ITaskbarList3, $tagITaskbarList3)
    If Not IsObj($oList) Then
        MsgBox(16, "Error", "Failed to initialize ITaskbarList3.")
        Exit
    EndIf

    $oList.HrInit()
    If @error Then
        MsgBox(16, "Error", "HrInit failed: " & @error)
        Exit
    EndIf

    GUICtrlSetData($label, "$oList.AddTab")
    $oList.AddTab($hWnd)
    If @error Then
        MsgBox(16, "Error", "Failed to add taskbar tab: " & @error)
        Exit
    EndIf

    _UpdateOverlayIcon($iCounter)
    GUICtrlSetData($label, "Overlay icon initialized with counter: " & $iCounter)

    Local $hTimer = TimerInit()
    While 1
        If TimerDiff($hTimer) > 1000 Then
            $iCounter += 1
            If $iCounter > 99 Then $iCounter = 99
            _UpdateOverlayIcon($iCounter)
            GUICtrlSetData($label, "Counter: " & $iCounter)
            $hTimer = TimerInit()
        EndIf
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
        Sleep(10)
    WEnd

    GUICtrlSetData($label, "Removing overlay icon and tab")
    _Taskbar_SetOverlayIcon($oList, $hWnd, Null, "")
    $oList.DeleteTab($hWnd)

    $oList = 0
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hTextBrush)
    _GDIPlus_BrushDispose($hBackgroundBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
EndFunc

Func _UpdateOverlayIcon($iCount)
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $GDIP_PXF32ARGB)
    Local $hGraphicBitmap = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphicBitmap, 2)

    _GDIPlus_GraphicsClear($hGraphicBitmap, 0x00000000)
    _GDIPlus_GraphicsFillEllipse($hGraphicBitmap, 0, 0, $iWidth - 2, $iHeight - 2, $hBackgroundBrush)
    _GDIPlus_GraphicsDrawEllipse($hGraphicBitmap, 0, 0, $iWidth - 2, $iHeight - 2, $hPen)

    Local $tLayout = _GDIPlus_RectFCreate(2, 2, $iWidth - 4, $iHeight - 8)
    DrawStringCentered($hGraphicBitmap, $iCount, $hFont, $tLayout, $hFormat, $hTextBrush)

    Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap)
    If @error Then
        MsgBox(16, "Error", "Failed to create HICON: " & @error)
        Exit
    EndIf

    _Taskbar_SetOverlayIcon($oList, $hWnd, $hIcon, "Counter: " & $iCount)

    _WinAPI_DestroyIcon($hIcon)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphicBitmap)
EndFunc

Func DrawStringCentered($hGraphic, $iIndex, $hFont, $tLayout, $hFormat, $hTextBrush)
    Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $iIndex, $hFont, $tLayout, $hFormat)
    Local $tIndex = $aInfo[0]
    $tIndex.X = $tLayout.X + (($tLayout.Width - $tIndex.Width) / 2)
    $tIndex.Y = $tLayout.Y + (($tLayout.Height - _GDIPlus_FontGetHeight($hFont, $hGraphic)) / 2)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $iIndex, $hFont, $tIndex, $hFormat, $hTextBrush)
EndFunc

Func _Taskbar_SetOverlayIcon(ByRef $oTB, $hWnd, $hIcon, $sAltText = "")
    Local $vRet = $oTB.SetOverlayIcon($hWnd, $hIcon, $sAltText)
    If @error Then Return SetError(@error, @extended, False)
    If $vRet = 0 Then Return True
    Return SetError($vRet, 0, False)
EndFunc

 

Posted

This worked great, thank you! I kept getting lost in a couple of bugs and forgot to respond. One weird thing I discovered is that Outlook likes to clear the icon especially if a message is marked as read or unread, so my testing was very unreliable. Here's my semi-final script that includes getting the unread count from Outlook and managing the icon:

#include <GDIPlus.au3>
#include <WinAPIIcons.au3>
#include <OutlookEX.au3>
#include <TrayConstants.au3>
#include <Taskbar.au3> ; This is just the Taskbar stuff reorganized into a UDF

AutoItSetOption("TrayIconHide", 1)
AutoItSetOption("TrayMenuMode", 1 + 2)

; Global Constants
Global Const $__g_iWIDTH = 128, $__g_iHEIGHT = 128, $__g_iBACKGROUND_COLOR = 0xFFFF0000
Global Const $__g_iFONT_SIZE = 56, $__g_sFAMILY = "Arial", $__g_iFONT_COLOR = 0xFFFFFFFF
Global Const $__g_iBORDER_WIDTH = 6, $__g_iBORDER_COLOR = 0xFF000000
Global Const $__g_iEMAIL_DELAY_SECONDS = 5

; Global GDIPlus
_GDIPlus_Startup()
Global $__g_hFormat = _GDIPlus_StringFormatCreate()
Global $__g_hFamily = _GDIPlus_FontFamilyCreate($__g_sFAMILY)
Global $__g_hFont = _GDIPlus_FontCreate($__g_hFamily, $__g_iFONT_SIZE)
Global $__g_hTextBrush = _GDIPlus_BrushCreateSolid($__g_iFONT_COLOR)
Global $__g_hBackgroundBrush = _GDIPlus_BrushCreateSolid($__g_iBACKGROUND_COLOR)
Global $__g_hBorderPen = _GDIPlus_PenCreate($__g_iBORDER_COLOR, $__g_iBORDER_WIDTH)

Main()
Cleanup()

Func Main()

    Local $hOutlook = WinGetHandle("[REGEXPTITLE:(.*Outlook); CLASS:rctrl_renwnd32]")

    TrayCreateItem("Email Overlay Icon")
    TrayItemSetState(-1, $TRAY_DISABLE)
    Local $idExit = TrayCreateItem("Exit")
    TraySetState()
    TraySetToolTip("Email Overlay Icon")

    Local $oTB = _Taskbar_Init()
    Local $hTimer = TimerInit()
    Local $iCurrentEmails = 0, $iNewEmails = 0
    
    Local $oOutlook = _OL_Open()

    Local $aFolder = _OL_FolderAccess($oOutlook, Default, $olFolderInbox)
    
    Local $oFolder = $aFolder[1]
    
    Local $hCurrentIcon = Null

    While True
        If TimerDiff($hTimer) > ($__g_iEMAIL_DELAY_SECONDS * 1000) Then
            $iNewEmails = GetUnreadEmails($oOutlook, $oFolder)
            If $iNewEmails > 99 Then $iNewEmails = 99
            ; If the counts differ and there are now no emails
            If ($iCurrentEmails <> $iNewEmails) And ($iNewEmails = 0) Then 
                ; remove the overlay icon
                _Taskbar_SetOverlayIcon($oTB, $hOutlook, Null, "")
                $hCurrentIcon = Null
            ; Else if the counts differ
            ElseIf $iCurrentEmails <> $iNewEmails Then 
                _WinAPI_DestroyIcon($hCurrentIcon)
                $hCurrentIcon = UpdateOverlayIcon($oTB, $hOutlook, $iNewEmails)
            Else
                ; Outlook likes to remove the icon sometimes so keep resetting it
                _Taskbar_SetOverlayIcon($oTB, $hOutlook, $hCurrentIcon)
            EndIf
            ; Update the current count
            $iCurrentEmails = $iNewEmails
            ; Reset the timer
            $hTimer = TimerInit()
        EndIf
        ; Do tray stuff
        If TrayGetMsg() = $idExit Then ExitLoop
    WEnd

    _WinAPI_DestroyIcon($hCurrentIcon)
    _Taskbar_SetOverlayIcon($oTB, $hOutlook, Null, "")

    _GDIPlus_Shutdown()
    TraySetState($TRAY_ICONSTATE_HIDE)

EndFunc

Func UpdateOverlayIcon($oTB, $hWnd, $sText)

    If Not WinExists($hWnd) Then Exit Debug("Outlook is closed now?")
    
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($__g_iWIDTH, $__g_iHEIGHT, $GDIP_PXF32ARGB)
    ; If ErrMsg(_GDIPlus_BitmapCreateFromScan0) Then Exit

    Local $hGraphicBitmap = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    ; If ErrMsg(_GDIPlus_ImageGetGraphicsContext) Then Exit

    _GDIPlus_GraphicsSetSmoothingMode($hGraphicBitmap, 2)

    _GDIPlus_GraphicsClear($hGraphicBitmap, 0x00000000)
    _GDIPlus_GraphicsFillEllipse($hGraphicBitmap, 0, 0, $__g_iWIDTH - 2, $__g_iHEIGHT - 2, $__g_hBackgroundBrush)
    _GDIPlus_GraphicsDrawEllipse($hGraphicBitmap, 0, 0, $__g_iWIDTH - 2, $__g_iHEIGHT - 2, $__g_hBorderPen)

    Local $tLayout = _GDIPlus_RectFCreate(2, 2, $__g_iWIDTH - 4, $__g_iHEIGHT - 8)
    DrawStringCentered($hGraphicBitmap, $sText, $tLayout)

    Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap)
    _Taskbar_SetOverlayIcon($oTB, $hWnd, $hIcon, $sText)
    
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphicBitmap)
    Return $hIcon
    
EndFunc

Func DrawStringCentered($hGraphic, $sText, $tLayout)
    
    ; Calculate
    Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sText, $__g_hFont, $tLayout, $__g_hFormat)
    ; If ErrMsg(_GDIPlus_GraphicsMeasureString) Then Exit
    Local $tIndex = $aInfo[0]
    $tIndex.X = $tLayout.X + (($tLayout.Width - $tIndex.Width) / 2)
    $tIndex.Y = $tLayout.Y + (($tLayout.Height - _GDIPlus_FontGetHeight($__g_hFont, $hGraphic)) / 2)
    ; Draw
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $sText, $__g_hFont, $tIndex, $__g_hFormat, $__g_hTextBrush)
    
EndFunc

Func GetUnreadEmails($oOL, $oFolder)

    Local $iNewMail = _OL_FolderGet($oOL, $oFolder)
    ; If ErrMsg(_OL_FolderGet) Then Return -1
    
    $iNewMail = $iNewMail[7] ;= unread count
    
    Return $iNewMail

EndFunc

Func Cleanup()
    
    _GDIPlus_PenDispose($__g_hBorderPen)
    _GDIPlus_BrushDispose($__g_hBackgroundBrush)
    _GDIPlus_BrushDispose($__g_hTextBrush)
    _GDIPlus_FontDispose($__g_hFont)
    _GDIPlus_FontFamilyDispose($__g_hFamily)
    _GDIPlus_StringFormatDispose($__g_hFormat)
    _GDIPlus_Shutdown()

EndFunc

I found that making the graphic larger made the text more readable. Anything beyond 64x64 looked the same to me, so I left it alone at 128. It still needs error handling (especially to check if Outlook is closed), but I'll add that later. Probably.

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...