Click here to Skip to main content
15,922,584 members
Articles / DevOps
Tip/Trick

Super Message Box

Rate me:
Please Sign up or sign in to vote.
3.35/5 (6 votes)
18 Dec 2015CPOL6 min read 12.1K   520   7   2
A customizable MessageBox() DLL and test application with dozens of built-in icons and color schemes

Introduction

Solving a simple Windows Desktop Z-order problem with a modal dialog box took me more than just the half hour to code the solution. I soon found myself writing a completely custom MessageBox() class. And if that weren't enough, I then started adding icons, color schemes and a passel of overrides. What the heck is wrong with me? As if there aren't already a number of these projects here. Well, none of them seem to solve the original problem -- dialog boxes disappearing behind other windows.

This one solves that problem. Read on...

Background

Numerous MessageBox() projects and programming articles erroneously suggest or imply that by setting the 'TopMost' property, that the form/dialogbox/graphic will always stay foremost in the Windows desktop 'Z-order' (or, simply, on top of the rest of the open windows) no matter what happens.

Nope.

This is not true and is evidenced after clicking on any other window on the desktop. Doing so will cause your dialog box to instantly vanish despite this simple yet deceiving property setting; your important modal dialog box is now buried somewhere under all the other open applications vying for your attention.

While this may not be the end of the world, at the very least it is really annoying. When you're running a collection of other applications, the last thing you want to do is go on an Easter-egg like hunt for your lost dialog box that's locking-up one of your apps. I've mistaken a hidden dialog box for an unresponsive app several times and have force-closed the app all because I didn't recognize or see the dialog box pop-up in the first place.

And, besides, I'm fast approaching the time I'll be able to hide my own Easter eggs, so I don't need any help hiding things.

All fun and inconvenience aside, it can be the end of the world if your code is running on a closed system, e.g., a kiosk, or other locked-down finite state system where the user may not have access to special key combinations that allow you to cycle through and re-discover the elusive and now hidden dialog box.

Hidden modal dialogs on these types of systems can be really bad news. Think of an ATM use-case scenario in Alaska. 'JR' rolls up and wants some cash from the machine late at night. It's 15 below outside and a 20 mile ride back home. Only, tonight, the ATM alerts JR that he qualifies for a low interest loan while it processes his request. Oh, oops, JR misses the tiny "No thanks" button and hits another part of the touch screen by mistake. Poof! There goes the main menu, and with it, JR's card and his chances of buying another six-pack.

And a few seconds later, poof! There goes the ATM, shot 30 times at close range...

Solution

Simply stated, the rather easy solution to all this is to have a background timer or thread that re-asserts the TopMost property of the form. Continuously. It's really that simple, but you'd be amazed at how many developers have missed this important requirement.

They may have missed, but JR didn't.

Sadly, even in this day and age, several industrial and commercial packages lack this needed feature. Now you can do this with ease by instantiating an instance of SuperMessageBox and setting the alwaysOnTop argument to true in the constructor. Once set, nothing; no window, no system dialog, no other app will cause any SuperMessageBox dialog to be hidden behind any another window. Not even Windows Task manager with the 'Always On Top' option set will mask over SuperMessageBox.

Using the Code

There's two separate projects here: the SuperMessageBox.dll code and a test app to help you get started using SuperMessageBox. I recommend looking at the SuperMessageBoxTester application to familiarize yourself, otherwise the constructor / public methods are fully XML commented and should be reasonably straightforward... Unless, maybe if you're an angry Alaskan Python coder with an empty AR-15... :-)

To use the Supermessagebox class, you can use the default constructor or start by creating a ColorScheme object to specify the upper and lower colors to be displayed. Next, instantiate a Supermessagebox object, passing the ColorScheme object in the constructor and set the Alwaysontop variable in the constructor to true if desired.

Once the SuperMessageBox object is created, simply access one of the .Show() overloads, passing it your message text, header text, button(s) selection, icon selection, a time-out timespan if desired, an animation style if wanted, and a windows sound type. In all, there are 21 overloads to the .Show() method to mix and match options with.

Example:
//                                   Dialog box colors           Text color
ColorScheme CS = new ColorScheme(ColorScheme.PresetColor.Salmon, Color.White);

SuperMessageBox SMB = new SuperMessageBox(CS, true);

DialogResult DR = SMB.Show("Want a low-interest loan?", 
	"Don'tShoot!", SuperMessageBox.Buttons.YesNo);

I created the ColorScheme class so that there was an available set of pre-defined colors. When I'm writing code, one of the last things I want to hassle with is tracking down the RGB values of colors (or spend time wandering around in the named colors in System.Drawing.Colors ) looking for a halfway decent contrast to the main application's color scheme.

As seen above in the first line, choosing a color scheme is as simple as perusing the ColorScheme.PresetColor enumeration prior to calling the constructor and picking one you like. If none of the 25 or so canned color schemes work for you, you can always use one of the other five constructors for ColorScheme and specify your own custom color scheme using RGB values or colors from the often tiresome System.Drawing.Colors set.

Your choice. And I guess that's the point - you get to have a choice, and is why I wrote this solution.

Fold / Spindle / Mutilate and change whatever you need here - it's just a starting point. Add your own custom PreSet colors, or change the ones I've provided. The test application provides a kind of WYSIWYG interface that should help you get going.

Improvements

There are a number of clever and intelligent folks on here - I just don't have the time or need to further improve the class. If I did, I'd be guilty of what a manager of mine once said, "polishing apples." So, if you have the time and inclination, here's some apple-polishing ideas I've dismissed for the lack of need and for the sake of time:

  • Adding video / animated icons
  • Add a custom sound option - ability to feed it MP3's or .WAV's
  • Add borders (Hint: Add an OnPaint() override)
  • If you really insist, add a drop-shadow option.
  • Add a vertical scroll bar for those of you who like to *abuse* dialog boxes ;-) [I'm looking at you, KEITH P.]
  • Add a screen position option so you can tell it what part (or in the case of multiple screens) which display

Icon Licenses

All the icons used and included in the SuperMessageBox project are from the Open Icon Library originally created on 10th of November, 2009 by Jeff Israel. Icons in this library fall under GPL / Creative Commons licenses. (License file is included with the source package.) Yup, and if you look, there's one in there that I made; that one falls under the CPOL license. :)

Disclaimer

There are likely a hundred better ways to do things - I'm a hardware and software engineer, so if you're a software guru and can point out a cleaner approach on some things, you'll find I'm all ears. Otherwise, I'm generally of the mindset that readable code is almost always far better than someone's idea of 'elegant' anyday. My hat's off to you if you're willing to share your knowledge - just always do so with patience and humility!

History

  • Version 1.1 December 2015
  • Initial release (Since Mike's rule of happy computing #1 is NEVER buy/use version dot-zero of anything

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer
United States United States
Redgum is a hardware and software engineer working in electronics and industrial control systems since he played with his first personal computer - a Commodore Vic-20. His love for all things hardware and software stems from the fact that there's always something new to learn, do better, or discover every day.

Hobby areas: making, finding and interfacing new sensors for test, measurement, monitoring and control. Mobile robotics & remote telemetry; smart drones. Amateur radio.

Preferred languages: C, C++ and C#

Someday when I have time project: A distributed network passive radar system.

Comments and Discussions

 
QuestionTwo applications with a Super Message Box Pin
adrian9921-Dec-15 21:22
professionaladrian9921-Dec-15 21:22 
AnswerRe: Two applications with a Super Message Box Pin
Redgum23-Dec-15 4:49
professionalRedgum23-Dec-15 4:49 
I was waiting for someone to ask this question. Ha.

So in my unit tests, I did just that. The SuperMessageBoxTester app wasn't written as a Singleton, so you can run more than one copy to test it yourself. My tests show that they fight - overlapping edges will flicker and when same size, you'll see one, then the other four times a second.

I have the UI timer set to 250msec which under any other circumstance should be plenty fast, but when you have two of these dialog "immovable objects" clashing in the same space, you will get flicker as each asserts itself on top of the desktop Z-order.

A similar problem exists for regular dialog boxes - if one application pops up a dialog box, it can (depending on size) mask over another application's modal dialog box effectively hiding it. Bit of a quandary, but not really addressable from an application standpoint. This is something the OS could and should take care of, but doesn't.

In the meantime, if you have two apps running with the SuperMessageBox dialogs, you'll get flicker where they overlap, and they'll fight like rival siblings for the last slice of pie when they're one on top of the other.

Otherwise, if they're not overlapping, BOTH will stay on top of everything else.

Fix idea: Update the SuperMessageBox DLL so that it accepts screen coordinates for placement as right now, in the
C#
Initialize()
method, I set it to center screen. Or, remove the center screen placement and what will normally happen is the dialog box will show up where the main window is for your application.

Cheers,

Red
The madman is not the man who has lost his reason; the madman is the man who has lost everything except his reason.

--G.K. Chesterton

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.