Updates to my shared code

I’ve made several updates to my shared code, and the files in that share. I don’t think any of them justify an exclusive post for themselves, so I’m devoting this post to all of them (that I can remember) instead.

As always, the zip files are available as public read-only shares on my SkyDrive.
RomyView source code
Romyview Release

For some unknown reason, my Windows Live Writer is doing some weird shit in source view (mouse caret vanishes and typing overwrites some text), so if either or both of those links are broken, let me know.

Changes that I can remember

CreateBackup

I removed the “Zipper” project from the solution. That was a console application that used my async extensions to the .Net Framework 4.5 zip support helper class, because I never used it for both zip and unzip. I replaced it with the almost identical “CreateBackup” project. This one only zips the solution. I invoke it one of two ways; from the IDE… as in Debug, start new instance – to make a backup of the solution (RomyView.zip), or from my build batch file when the solution is closed, to produce both of the files that you can download.

I really should find out how to write a Visual Studio extension instead, but the documentation I downloaded was too vague. (If I don’t get a feeling for how to code something within a few seconds of starting to read the documentation, unless it is a requirement at work that I must implement, I probably don’t do it.) I assume there must be some sort of API that accesses the solution code, but my console app uses the file system.

Windows 7 Custom Logon Background Image

I never did get around to updating the separate application I originally wrote for this – which used my old monitor images in it’s form (image of monitor with 4:3 aspect ratio). I’m still using Windows 7 at work.

The form, which you can open from the Tools menu, looks like this:

GlassForm

The program’s feature to set one of my predefined images (or any other you copy into it’s directory) only works on Windows 7. The form also uses Aero Glass. You can still open it on Windows 8 (and confirm that it looks like shit). It was a fun form to write, and I suppose could be used by a junior programmer who doesn’t know anything about overriding the Paint method, as an example of one approach to custom drawing. i.e. There is a panel with a static background image (my Photoshop-drawn monitors, complete with Romy logo) but when you select any of the ListView items with the mouse (or keyboard since the ListView has focus) it dynamically loads the image and draws it on top of the panel. I experimented with a few ways of drawing it… drawing onto the panel that gets painted automatically vs. drawing everything onto a Bitmap, then drawing that onto the panel – but they made very little difference to performance. I don’t remember which way I left it in the end – but I think it was the one with less code.

And the image after spending (too) many hours in Photoshop is this:

Overcooked

If you are curious how I came up with it… It is the original Windows 7 logon background image, with a colour overlay in blue, set to exclusion (i.e. remove most of the blue from the mostly blue image). On top of that, I added a few layers to further modify the colours and contrast, and manually painted some stuff.

Oops… and remember kiddos… if you create your own Windows 7 background image, make sure the JPG file is smaller than 250kB! Mine wasn’t, and my code accidently checked for 256kB… I’ve just reuploaded it now. (That’s what happens when you work on Windows 8, with a feature that only works on Windows 7.)

Code to check if this is the foreground application

Since I wrote the application mostly for myself (I use it as my default image viewer and movie player), I broke a few rules w.r.t. windows and stealing focus. That is, it annoyed me that when I clicked a toolstrip button on the browser, it would take two clicks if the app was not focused. So I made the window steal focus if the mouse moves over certain buttons. That is kind of rude… (Actually rude enough that I will immediately uninstall any other application that does the same thing.)

This added a requirement to only steal focus from our own windows, but do nothing if the application doesn’t have focus (that is, only act if this is the application the user is working with right now).

Here’s the code:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;

namespace Romy.Core
{
    public static class Example
    {
        /// <summary>Indicates whether this application has input focus.</summary>
        /// <returns><b>True</b> if this application owns the foreground window; 
        /// otherwise <b>false</b>.</returns>
        public static bool IsForegroundApplication()
        {
            var foregroundWindowHandle = NativeMethods.GetForegroundWindow();

            if (foregroundWindowHandle == IntPtr.Zero)
                return false;

            int activeProcessId;
            NativeMethods.GetWindowThreadProcessId(foregroundWindowHandle, out activeProcessId);

            return activeProcessId == Process.GetCurrentProcess().Id;
        }
    }

    [SuppressUnmanagedCodeSecurity]
    internal static class NativeMethods
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();
    }
}

That code actually lives in my base class for enforcing a single instance application (so that I can use it like Romy.UI.Instance.IsForegroundApplication()), which itself breaks a rule resulting in a code analysis warning… something like “Don’t add static methods to generic types, or specify type arguments, you tit!” which I suppressed.

Convenience methods to run async Tasks using the configured custom TaskScheduler

I’ve written a few posts about my custom TaskScheduler, but haven’t made it all that clear how to invoke it. Well, the main way I use it is when I have lots of tasks that need to be offloaded, because running the tasks grouped into batches, in parallel, is very effective – and that’s what my custom TaskSchedulers are designed to do. I added these to my static Tasks class, which is defined in the same source file as my global TaskFactory.

Now calling it is similar to the built-in class… I just call it using Tasks.Run (instead of Task.Run). This is the code:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Schedulers;

namespace Romy.Core
{
    /// <summary>Set up some common options for async Tasks. The <b>TaskSchedulers.Parallel</b>
    /// scheduler references the static <b>Scheduler</b> property of this class. The value of
    /// <b>Factory.UseThreadPool</b> defines which <B>ParallelTaskSchedulerBase</B> 
    /// implementation is used and hence whether to run ThreadPool threads or dedicated threads.
    /// When using dedicated threads, <b>Factory.UseForeGroundThreads</b> configures whether they 
    /// are foreground or background threads.</summary>
    /// <remarks>For offloading Tasks to the custom TaskScheduler, call <see cref="Romy.Core.Tasks.Run()"/>.</remarks>
    public static class Tasks
    {
        private static ParallelTaskFactory factory = new ParallelTaskFactory();

        public static ParallelTaskFactory Factory
        {
            get { return Tasks.factory; }
        }

        public static TaskScheduler Scheduler
        {
            get { return factory.Scheduler; }
        }

        public static Task Run(Func<Task> body)
        {
            return factory.StartNew(async () => await body()).Unwrap();
        }

        public static Task<T> Run<T>(Func<Task<T>> body)
        {
            return factory.StartNew(async () => await body()).Unwrap();
        }

        public static Task<T> Run<T>(Func<Task<T>> body, CancellationToken cancellationToken)
        {
            return factory.StartNew(async () => await body(), cancellationToken, TaskCreationOptions.PreferFairness, Scheduler).Unwrap();
        }
    }

    /// <summary>A TaskFactory to define which custom TaskScheduler to use.</summary>
    public class ParallelTaskFactory : TaskFactory
    {
        private bool useForeGroundThreads;

        private bool useThreadPool = true;

        private static Lazy<ParallelDedicatedThreadsTaskScheduler> dedicatedThreadsScheduler = new Lazy<ParallelDedicatedThreadsTaskScheduler>(() => new ParallelDedicatedThreadsTaskScheduler());

        private static Lazy<ParallelThreadPoolTaskScheduler> threadPoolScheduler = new Lazy<ParallelThreadPoolTaskScheduler>(() => new ParallelThreadPoolTaskScheduler());

        public ParallelTaskFactory()
            : base(CancellationToken.None,
                TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler,
                TaskContinuationOptions.ExecuteSynchronously, ThreadPoolScheduler) { }

        public bool UseForeGroundThreads
        {
            get { return useForeGroundThreads; }
            set
            {
                useForeGroundThreads = value;
                DedicatedThreadsScheduler.UseForegroundThreads = useForeGroundThreads;
            }
        }

        public bool UseThreadPool
        {
            get { return useThreadPool; }
            set { useThreadPool = value; }
        }

        public static ParallelDedicatedThreadsTaskScheduler DedicatedThreadsScheduler
        {
            get { return ParallelTaskFactory.dedicatedThreadsScheduler.Value; }
        }

        public static ParallelThreadPoolTaskScheduler ThreadPoolScheduler
        {
            get { return ParallelTaskFactory.threadPoolScheduler.Value; }
        }

        public new TaskScheduler Scheduler
        {
            get { return useThreadPool ? (TaskScheduler)ThreadPoolScheduler : (TaskScheduler)DedicatedThreadsScheduler; }
        }
    }
}

That’s it for today, unless I remember some more that could be included here. Enjoy!

Advertisements

About Jerome

I am a senior C# developer in Johannesburg, South Africa. I am also a recovering addict, who spent nearly eight years using methamphetamine. I write on my recovery blog about my lessons learned and sometimes give advice to others who have made similar mistakes, often from my viewpoint as an atheist, and I also write some C# programming articles on my programming blog.
This entry was posted in Programming and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s