Balloon tip met Shell_NotifyIcon

Door Hmail op woensdag 29 februari 2012 13:27 - Reacties (9)
Categorie: -, Views: 3.288

Voor mijn stage moet ik in-, en uitklokken via een web interface. Dat betekent dus: Binnenkomen, laptop aanzetten, koffie pakken, aanmelden, slok koffie, mail lezen, beginnen met werken en na 3 uur realiseren dat ik vergeten ben in te klokken en die uren dus overnieuw moet doen :(

Dus, C++ to the rescue :D

Ik had al met .NET een simpel tooltje gemaakt om een melding te tonen die uitgevoerd wordt als ik me aanmeld, maar omdat ik meer met Win32 wil leren werken, en ik door Raymond Chen's blog geÔnspireerd werd, leek het me wel een leuk idee om door een balloon getipt te worden.
Met daarbij o.a. het idee om later nog functionaliteit toe te voegen die het mogelijk maakt om erop te klikken, en automatisch geforward te worden, of zelfs een schermpje die voor mij de GET/POST opdrachten uitvoert zodat ik helemaal niets meer hoef te doen :D
Maar dat is allemaal later. Nu eerst eens een icon maken die een berichtje toont.

http://geensite.nl/tmp/goedemorgen.png


Op het moment van schrijven heb ik nog maar net het eerste deel van Petzold's Programming Windows uit en een klein beetje ervaring met het schrijven van Windows-programma's. Op en aanmerkingen zijn zeker welkom, maar be kind, het is m'n eerste blog entry ;)

Shell_NotifyIcon heeft twee parameters, DWORD dwMessage en PNOTIFYICONDATA lpdata. Voor dwMessage kunnen we kort zijn, in dit geval hebben we twee flags nodig: NIM_ADD en NIM_DELETE. Vergeet die laatste niet, anders blijft het icon staan, ook na het sluiten.

De NOTIFYICONDATA struct is iets uitgebreider.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Voor enkel het tonen van een balloon kan NULL als handle gebruikt 
// worden. Als je een applicatie hebt met window procedures heb je 
// uiteraard een window handle.
HWND hwnd = NULL;

NOTIFYICONDATA nid = {};

// Dit lijkt simpelweg de grootte in te stellen, maar dit bepaalt ook een 
// groot deel van de functionaliteit. VÚÚr Windows Vista moet je een andere
// grootte instellen, anders wordt bijvoorbeeld de tip niet getoond. Zie 
// hiervoor het kopje 'Remarks' bij 
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773352(v=vs.85).aspx
nid.cbSize = sizeof(NOTIFYICONDATA);

nid.hWnd = hwnd;

// Na Windows Vista kun je van een guid gebruik maken. Deze kan er echter ook
// regelmatig voor zorgen dat de icon niet getoond wordt. Voor het gemak heb 
// ik daarom maar voor een uID gekozen. 
nid.uID = 0;

// Hoewel de Express-versie van Visual Studio geen resource editor heeft, 
// kun je de resource files met de hand aanmaken. Een voorbeeld hiervan 
//is met de post meegeleverd.
nid.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    
// Dit toont een icon en een omschrijving. "Echte" applicaties gebruiken
// uiteraard ook NIF_TIP om een tooltip te tonen die een korte omschrijving
// van de applicatie geeft. 
nid.uFlags = NIF_ICON | NIF_INFO | NIF_SHOWTIP;
    
// Stel de titel en de omschrijving in.
StringCchCopy(nid.szInfoTitle, ARRAYSIZE(nid.szInfoTitle), 
    L"Goedemorgen \\o/");
StringCchCopy(nid.szInfo, ARRAYSIZE(nid.szInfo), 
    L"Geniet van de koffie! Vergeet niet in te klokken!");

// Voeg de icon toe aan de system tray.
Shell_NotifyIcon(NIM_ADD, &nid);

// In dit geval laat ik de icon een tijdlang staan. Op zich is dit 
// niet zo'n groot probleem, het sluit vanzelf, en onder Windows 7
// wordt het icoon netjes verborgen. 
// Het icoon verdwijnt niet als ik niet achter de computer zit, het 
// blijft getoond worden tot ik met de muis beweeg. Dan zit er een 2 sec
// timeout op. Daarna fade het icoon weg. Tenzij ik er op klik, dan verdwijnt
// het meteen.
// Een betere oplossing zou natuurlijk zijn om NIN_BALLOONTIMEOUT en
// NIN_BALLOONUSERCLICK af te vangen en dan het icon te verwijderen. 
// Hier kom ik echter in een latere versie op terug.
Sleep(600000); // Na 10m zou de koffie wel op moeten zijn
Shell_NotifyIcon(NIM_DELETE, &nid);



Natuurlijk is bovenstaande code weinig spannend. Maar het heeft me best even tijd gekost om dit goed werkend te krijgen, en er zijn maar weinig sites waar simpelweg dit te vinden is. Met hulp van deze code kan iemand anders misschien weer verder.

In een volgende post: Context menu die getoond wordt als er met de rechtermuisknop op het icon geklikt wordt en een fatsoenlijke manier om af te sluiten.

Code: http://geensite.nl/tmp/Shell_NotifyIcon1.zip