We have a fairly advanced windowing system for the app I’m developing, and one of the side effects is that when using controls inside a Popup control, the keyboard focus does not always behave correctly for the controls inside the popup.
I found this great article which immediately solved my problem : http://www.hardcodet.net/2009/09/activating-wpf-popups-ensures-controls-are-enabled
The root cause of my issue is that a Popup’s HWND has the WS_EX_NOACTIVATE flag set, meaning that the focus is not set properly.
Credit to Philipp Sumi and Andrew Smith.
For a while now we’ve been using a very simple pattern for opening custom popups by binding to the IsChecked property of a ToggleButton. It’s simple, needs no code-behind, and works 99% of the time.
However, it has a very annoying 1% which is the following:
- You want your popup to open when the toggle button is clicked – OK
- You want your popup to close when the user clicks elsewhere – off the window, etc – OK
- You want your popup to close when you click the toggle button again- BUT THIS DOESN’T WORK
The reason is because the events happen as follows:
- Open the Popup by clicking on the Toggle Button
- Click on the Toggle button again
- Before the “Click” is processed by the toggle button, the Popup handles the fact that the user has clicked elsewhere and so closes
- By closing, the popup sets the IsChecked state of the toggle button back to unchecked via the 2-way binding
- Now the “Click” is handled by the toggle button, but at this point the popup is closed, and the toggle button is not checked, so it re-checks itself, and re-opens the Popup !
Many people have tried to solve this by using Timers, behaviours, fiddling with the Binding, but there is an annoyingly simple solution:
On the ToggleButton set the Property ClickMode=”Press”
…and you’re done…
Filed under UI Hints, UX, WPF
A while back, I posted about using the iTunes API for automating tasks in my music & video collection.
However, I didn’t go into a lot of detail, and so now I thought I’d share a bit more – in particular how to automatically organise videos into the “TV shows” section in iTunes.
Previously I had tried to drag my freshly downloaded/ripped videos into the “TV Shows” area, but they always ended up in “Films” – and the only videos in my TV shows section were ones that I actually bought off the iTunes store.
A quick bit of googling, and lots of experimentation later – I wrote a fairly simple jscript:
var iTunesApp = WScript.CreateObject("iTunes.Application");
var tracks = iTunesApp.SelectedTracks;
var numTracks = tracks.Count;
for (i = 1; i <= numTracks; i++)
var currTrack = tracks.Item(i);
var name = currTrack.Name
var se= name.substring(name.lastIndexOf(".")+1);
var show = name.substring(0,name.lastIndexOf("."));
var bits = se.substring(1).toUpperCase().split("E");
var season = bits;
var episode = bits;
currTrack.Show = show;
currTrack.SeasonNumber = season;
currTrack.EpisodeNumber = episode;
currTrack.Album = show;
currTrack.Artist = show;
currTrack.TrackNumber = episode;
for (i = numTracks; i >= 1; i--)
var currTrack = tracks.Item(i);
urrTrack.VideoKind = 3;
The script splits the filename up into show name, season number and episode number, and then sets the “VideoKind” to 3, which means TV Show.
The only requirement is that the starting filename should be in the format Show.Name.S01E01.mp4
Filed under Apple, Useful
I just came across an interesting use case which I thought I’d share – why let your application churn away doing unnecessary processing if the user isn’t paying attention?
So I started looking into detecting whether the workstation is locked, or if the screensaver is running – two fairly reliable ways of telling that the user has gone walkabout…
To detect a locked workstation, you need to listen out for:
…which fires each time the user locks or unlocks the workstation.
To detect the state of the screensaver, you have to do slightly more work – there are no helpful events – instead you need some sort of polling mechanism to call away to a Win32 function:
private const int SPI_GETSCREENSAVERRUNNING = 0x0072;
static extern bool SystemParametersInfo(int action, int param, ref int retval, int updini);
int active = 1;
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref active, 0);
bool screenSaverActive = (active == 1);
So I stitched these 2 bits of logic together into a nice helper class and now I can tell (within reason) when my users are there or not, and give our servers a break every now and then.
It’s been a while since a last posted, but as with any new love there’s always an intense honeymoon period when you can’t keep your hands off! In my case, it’s WPF – a new toy that is ticking all the right boxes for a GUI nut like me.
The initial buzz soon wore off when I realised that you shouldn’t really try to write WPF apps like you did with Winforms – and then the real fun started as I rapidly scaled the learning curves of styling, databinding, MVVM and MEF.
One resource that really helped switch my brain over from old-school winforms was a video by Jason Dollinger over at Lab49 : http://www.lab49.com/2011/12/06/model-view-viewmodel-tutorial/
The video starts with a “badly written” WPF app (i.e. WPF written as if it was winforms) and then, over the course of 90 minutes, Jason gently refactors it towards a slick, high-performance MVVM implementation.
Filed under C#, UI Hints, WPF
I’m currently building a multi-process desktop application suite that has a “launch bar” tool to start up instances of all the available widgets. A simple Winforms ToolStrip control seemed the obvious choice for creating a nice consistent strip of buttons, but I came across the issue that if the launch bar did not have focus, then it took 2 clicks to launch a widget when clicking on a button – one to activate the application and one to click the button.
Having Googled extensively I found that this interaction is not in fact a bug, but actually designed behaviour. I would normally accept this and move on, but I found it particularly inconsistent that the ToolStrip buttons actually illuminate/highlight on mouseover even when the app doesn’t have focus – thus fooling the user into thinking that they need only click once.
Finally,I found a few helpful articles – especially this one by Rick Brewster. The solution lies in overriding the WndProc method for the ToolStrip (or MenuStrip):
protected override void WndProc(ref Message m)
if (this.clickThrough &&
m.Msg == NativeConstants.WM_MOUSEACTIVATE &&
m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT)
m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;