views:

140

answers:

3

Hi,

Using WinXP. What I need to do (pref in VB or c#) is to detect when another (closed source) program displays a notification balloon in the tray - and grab the details. Any help would be appreciated. Thanks

A: 

In similar situations, I have used the Microsoft tool Spy++ to grab the window information and then uses pinvoke calls to FindWindow to detect when the window is present.

I've not tried with a notification balloon, but I imagine that a pinvoke call to GetText would retrieve the contents.

Andrew Rollings
+1  A: 

I think you'll need to use pinvoke to do this from a .net language.

On the system I'm using now (Vista Business SP2), balloon windows always seem to have window class #32769 (reserved for desktop windows) and the windows style bit TTS_BALLOON set.

The following might work: Determine the parent window for all notification balloons by creating a temporary one, getting its hWnd, and calling GetParent() before deleting it. You could then periodically poll the children of this parent hwnd (using EnumWindows() or FindWindowEx()) looking for windows with the required class and style.

This seems highly non-portable to me, and likely to require a lot of testing on a variety of platforms.

pinvoke.net and spy++ might be useful.

Good luck!

Andy Johnson
A: 

You will definitely need to use Win API calls to achieve this. If this is the only thing you're trying to do, you'd be better off using straight C or C++ so you don't have to do a bunch of platform invoke for C# or VB.

Since andyjohnson identified that the window class for all notification balloons is #32769, and that they have the TTS_BALLOON style set, you could use a CBT hook (if you're not familiar with Win32 hooks, you might want to read up on them), to get a callback whenever a window is created, and check for windows of that class and with that style.

I'm not sure, though, if a new balloon window is created for second and subsequent popups or if the same one is just hidden and reshown. If this is the case, you might need a CallWndProc hook, to get WM_SHOWWINDOW messages.

Edit:

I should mention that the hooks that I've mentioned cannot be implemented in .NET. Except for the low-level keyboard and mouse hooks, global system hooks must be implemented in a native (unmanaged) DLL. Windows will load this DLL into other processes, and if a managed DLL gets loaded into a process that doesn't have the .NET CLR loaded, it will crash that process. (Even if the CLR is loaded, it might be at a different address, also causing a crash.)

So you must build your hooks in a native (unmanaged) DLL. It's possible to interface from here to a managed application, such as Michael Kennedy has done on Code Project, but to do it properly, and handle the hook types I've mentioned above, you'd need to use interprocess communication, a step that Michael Kennedy left out. All in all, for the purpose you've described, it would probably be easier to just build the whole thing in native code.

P Daddy
I like the idea of using a hook - better than my suggestion to use polling. Presumably this would only work in unmanaged code though?
Andy Johnson
@andyjohnson: Yes, in fact this is important and I'll update my answer to make this clear.
P Daddy