Managing DVBLink IPTV channels

I’ve been using DVBLink 3.1 for IPTV and Server Network Pack for a week or two now. It is a software that makes IPTV stream available to various clients, Windows Media Center among of them. It works very well with my IPTV provider SIOL (note the SIOL’s IPTV service quality is crap nevertheless) and thus I am quite happy.

While it streams fine DVBLink for IPTV’s UI is a very ascetic one. Very. Imagine having 165 channels and you have to sort them by entering a number for any of them. Horrible, just horrible. Furthermore adding or modifying channels is not easy either if not impossible (luckily channel import works).

And hence here is the first step to the UI solution: Righthand’s DVBLink Editor v1.0.0. It is an application that will let you sort all those channels easily.

editor in action

First you have to load the channels configuration file (application will try to locate it and load automatically upon the start) if it isn’t loaded yet – no channels are listed and no file name is present in the config file editor. Click on […] or enter its full path manually and then hit Load button to load the content. Configuration file is named DVBLinkChannelStorage.xml and is usually found in [Program Files]\DVBLogic\DVBLink2 folder.

Once channels configuration is loaded you can order them. But before sorting the channels make sure grid sorts them by number (default) and they have unique numbers. Reorder button will assign them unique numbers while preserving the original sort order if any (it sorts by exisiting number and then by name). Basically Reorder button is a big friend of yours. Once you have them sorted you can change their order.

You can change channels order in various ways:

  • by rotating mouse wheel while holding Shift key
  • by pressing up or down key while holding Shift key
  • by entering the number directly – the two channels will swap position

Once you’ve done with ordering you have to save the changes by clicking on Save button. By default Stop service checkbox is checked which means that editor will try to stop DVBLink Server service before saving and it will restart it (only if it was running before) afterwards. When unchecked no service will be touched. If you wonder why a service restart is necessary, there is a simple explanation: DVBLink Server won’t pick changes otherwise.

System requirements

.net 4.0 (you will be prompted to downloaded and install it if it is not installed yet on your OS).

Possible problem

DVBLogic stores configuration file under Program Files folder which is a very problematic practice. Due to the security concerns no writable configuration file should be placed in there. Period. Furthermore you’ll need administrator privileges to change the file in question.

Happy sorting and keep an eye on this blog for further improvements to the Righthand’s DVBLink Editor! Feedback is appreciated.

Find the application here.

An annoying non-persistent memory leak in .net framework MDI

I had to investigate a memory leak in an application I am building for my client. It is a MDI application using DevExpress XtraTabbedMdiManager that provides some MDI eyecandy. Anyway, I’ve used ANTS Memory Profiler (an excellent profiler, highly recommended) for my mission. I have soon found the cause of the true memory leak, which wasn’t an actual memory leak but rather a feature of the application – it was logging events in the memory.

One thing puzzled me though. I’ve tried this scenario. Take a memory snapshot, open a MDI child form, close it and take another snapshot. There shouldn’t be any memory leak, should it? But it was. ANTS Memory Profiler reported that the form wasn’t disposed and still held in memory. So I went looking at the Object Retention Graph for the form in question only to see this image (sensitive namespace is removed in Paint.net):

leak

Is is pretty much obvious that there are two references holding my should-be-disposed form. One is from InternalAccessibleObject and the other one is from Form.PropertyStore. Neither is caused by application’s code. So, what’s going on? It turns out that this is a feature of .net framework MDI and not a real memory leak – it stores the last reference of the active MDI child form or something like that and thus the last form isn’t released. If you repeat the open form/close step the memory leak shouldn’t increase. In fact even the memory leak from the first step is cured.

Even though it is not a true memory leak it is a distractive feature when it comes to memory profiling – for any .net memory profiler, not just ANTS. I guess only experience helps you with these kind of distractions when hunting for a real memory leak.

See also this thread in ANTS Memory Profiler support forum.

Meet “Go To Implementator” DXCore plugin for Visual Studio

The problem

One of the biggest annoyance when doing unit-test-friendly projects is that you have to deal with interfaces much more than you usually would. This isn’t bad by itself but it will effectively kill your F12 aka “Go To Definition”. In other words F12 won’t show you the code anymore but rather the interface definition of the method or property. Which is not what I like and I guess not what you like as well.

Let’s see an example:

imageWhen you F12 (or right click, Go To Definition) on DoTubo() you’ll get catapulted to the interface declaration of the method. Which might be what you want but mostly it isn’t. I’d like to see  the Tubo.DoTubo() method declaration where the code I am interested is. Specially because often an interface is really implemented just by one class, at least in design time.

image

This is what I’d like to see. And this is what you’d get if you weren’t using IAnnoy interface but rather Tubo type directly.

The solution

Good news is that now there is a way to use the go to method implementation. Even better news is that it is free. As a free lunch.

I’ve created a DXCore plugin named “Go To Implementator” that does exactly that. When over a interface’s method or property reference it will give you an option to go directly to (one of the) implementation. Sounds fine?

Installation

1. If you don’t have CodeRush already installed then do install its Express version which is free or even better, go with full version (which is not free but it is well worth it).

2. Download attached zip file and unpack its content into either [USER]\Documents\DevExpress\IDE Tools\Community\PlugIns or [Program files [x86]]\DevExpress [DX version, i.e. 2009.3]\IDETools\System\CodeRush\BIN\PLUGINS.

3. Run Visual Studio. Go to DevExpress/Options… menu and select IDE/Shortcuts node the left.

4. Create a new shortcut: click on the first icon under Shortcuts title. Click on Key 1 text box on the left and press F12 (you are telling which key to respond to). Pick “Go to interface implementation” command from Commands combo box. The last step is to click on checkbox Focus/Documents/Source/Code Editor on the usage tree list on right side – a green checkmark should appear. Note that you can bind this action (or any other) to a different shortcut or even a mouse shortcut or any other way supported by CodeRush.

image

Take also note that there is a “Parameters” text box. I’ll use it pass parameters to my action later on in the article.

Test & use

Create a console application and past in there this code:

class Program
{
static void Main(string[] args)
{
IAnnoy annoy = new Tubo();
annoy.DoTubo();
}
}

interface IAnnoy
{
void DoTubo();
}

class Tubo : IAnnoy
{
public void DoTubo()
{
}
}

Position the caret on DoTubo() method reference. There are two ways to invoke my plugin.

Context menu

Right click, there should be an submenu “Go To Implementator” in context menu:

image

Keyboard shortcut (F12)

Just press F12. But what if you are not on a interface method/property reference? The default “Go To Definition” will be called like it would be without this plugin.

Dealing with more than one interface implementation

So far there was only one interface implementation. But what happens if there are two or more classes that implement the interface?

Let’s add another implementation to the crowd:

class AnotherTubo : IAnnoy
{
public void DoTubo()
{
}
}

Now both Tubo and AnotherTubo implement the IAnnoy interface. Right click context menu should give both options in no particular sort order, like this:

image 

Let’s pick AnotherTubo class. Plugin will remember this choice and next time it will be placed on the top:

image

But what about F12?

If there is no default class assigned then it should present you a smart tag with options:

image

 

 

However, if a default is available it would go straight to the implementation rather then presenting this smart tag.

Customizing the action

Popup menu behavior is fixed and can’t be customized in current version. The action, one that you can bind to a keyboard shortcut or whatever else input CodeRush is supporting can be customized. There are two parameters (parameters are a comma delimited string that you pass to Parameters text box when you are creating/editing shortcut in DevExpress/Options… – see the 4. step in installation) you might use.

NoPassGoToDefinition

You can disable invoking Go To Definition when action doesn’t do anything. The default behavior is to pass through when action does nothing. So why would you need this option? In case you are using the action from non F12 shortcut or if you want the action to do its job and nothing else.

ShowPopupAlways

When there is a default class for action available no smart tag is shown by default. You can override this behavior by passing ShowPopupAlways parameter. Then smart tags menu will be shown always when there is more than one class suitable regardless the default value is present or not.

Here is an example of passing both parameters:

image

The conclusion

I hope you’ll find this plugin useful. I am starting to use it and it saves me a lot of clicking. And thanks to DXCore it was really easy to create it.

Let me know if you have ideas how to enhance it or anything else, all feedback is welcome.

1.0.0 (18.1.2010)

  Initial release

1.0.1 (19.1.2010)

  Bug fix: it worked only within project scope.

1.0.2 (19.1.2010)

  Too strict parsing used which might resulted in no go to implementor option at all.

1.0.3 (21.1.2010)

  Didn't work on partial classes.

1.0.4 (26.1.2010)

  Fixed navigational bug (thanks to Quan Truong Anh for finding the bug and creating a repro case)

1.0.5 (16.7.2010)

  Added some logging - make sure DevExpress/Options.../Diagnostics/Message Logs is turned on (if you are turning it on then you have to restart IDE).
  No new functionallity besides logging - you might consider this version if plugin doesn't work well and you want to understand why.

GotoImplementator_1_0_5.zip (10.20 kb)

17.1.2011

Important: this is the last version supporting DXCore/CodeRush 10.1.x and lower.

Even more important: I've created a dedicated page and all further improvements will be published throug that page. This post won't be updated anymore.

About DevExpress skinning and custom skins

Here is the thing. DevExpress WinForms components support custom skinning. Out of the box there are plenty of skins you might use just by assigning a simple property with a name of the skin. Every DevExpress WinForms control will follow the skin settings and will look fancy and so will your application. That’s great. But if you want more advanced skinning you are in for troubles.

Let’s see my case. An application I am building for a customer of mine supports skinning. However I had to slightly modify out of the box skins with some adjustments and I’ve added few new glyphs which I use in my custom controls (they follow skinning UI as well since entire application does). Here is how I started. I’ve opened SkinEditor, a tool provided by DevExpress and created new skins based on their skins, i.e. MyCaramel from Caramel, etc. Once I had “my” skins I’ve adjusted some properties still using SkinEditor. Finally I’ve created a “skin resource” assembly. That’s all easily done via SkinEditor. So far so good. But there are problems ahead.

First problem – adding custom glyphs to skin

Since I have custom controls that have custom glyphs I had to add those glyphs to skins. After all they belong in the skin assembly since they will be also changed when skin changes. I could add them somewhere else, but that would be asking for troubles – better to have “grouped” resources in one place. But there is no way to add custom glyphs to my skin via SkinEditor. By design. Obviously nobody at DevExpress ever supposed that custom skins might be used for custom controls.

Second problem – updating the custom skin

Next, much more annoying problem, is updating custom skin to a newer DevExpress version. Even when a minor DevExpress version is released the out of the box skin definition might change a bit - here and there. So, the template you have built your custom skin from has changed but your custom skin still “sits” on the top of the old template version. It might even result in a runtime exception if you don’t upgrade the skin while application uses newer version of DevExpress components. And go wonder, SkinEditor doesn’t have an “upgrade custom skin” option. You have to recreate the original project (what a fun when you are dealing with 20+ skins – you have to add separately) and reapply all changes you might to out of the box skins. Eeek.

Third problem – skin size

If you use a lot of custom skins they will use a lot of space (each skin is about 500KB) even though you might not be using all of DevExpress controls and thus you don’t require full skins. The relatively big size might be a problem if you distribute your application via internet and even if you don’t your application uses more memory without any apparent benefit. SkinEditor doesn’t support removing of skin elements and even if you modify skin.xml definition (by removing unnecessary nodes) SkinEditor will add them again when you open the project next time.

Fourth problem – nor skin nor its assembly can’t be unloaded

Once the skin assembly is loaded to your application (main AppDomain) it can’t be unloaded. And once skin is registered it creates a hash table of all resources (a ton of Images – I am not 100% about this but it pretty much looks like it) and you can’t unloaded any of them. So, when you register a skin assembly it will remain loaded until the application is closed and all resources will be loaded to hash table in the form of images (souds like a sort of duplication to me). There is no way to load a skin from a custom AppDomain.

Solutions to problems

The first problem can be solved “manually”. I say manually, but you can pretty easily create some XML manipulation and file copy code. While SkinEditor doesn’t support adding custom glyphs you can still add them manually in two steps – save the graphics to the proper folder of the SkinEditor project and modify skin.xml file by adding proper XML nodes pointing to newly added glyphs. After some trial and error I was able to accomplish this task.

I’ll write about the solution to the second problem in a later post. I’ll also provide an utility that does a part of the job.

I have an idea how to solve the third problem but didn’t solve it yet nor I am sure whether it will work.

The fourth problem is the most hard to solve due to the current implementation. I am not sure whether it is even possible or whether does it make sense to invest much energy into this.

Conclusion

While skinning works pretty nicely in DevExpress controls its implementation is not the best one. Specially support for custom skinning isn’t very well thought and SkinEditor can be enhanced with these problems in mind.

The good news is that with little effort I’ve managed the overcome the most important issue – how to create slightly modified out of the box skins and how to update them to new versions (automatically). I’ll talk more about this solution in a later post.

What do you think? Do you use DevExpress skinning feature? Did you create your own skins?

Developer Express published roadmap for 2010

First new “feature” is stepping down from three releases per year to two releases per year. Regardless how it sounds, it makes sense. A lot of sense. Developers and other staff spent a lot of time preparing releases and I don’t mean implementing new features but just preparing and testing the releases. From now one they will have more time for coding new features. As per DevEx clients this is good news as well – having to do major updates less time per year provides similar benefits. Bottom line is that we have more features, less work and possibly less bugs.

From the technologies perspective it looks like WPF and Silverlight are getting mainstream while WinForms is dropping down from first place (that said it isn’t a dead product, far from it, it is just not the most important anymore – I am very pleased to see this shift happening). ASP.NET MVC will get some beta versions (“we shall be testing the waters with beta versions of the data grid, menu, navigation bar, and tab control”) while ASP.NET is still the most important of the two.

Visual Studio 2010 is going to be supported big time including CodeRush for VS2010.

These are news in brief from what I can read. But don’t take my word for granted, read it yourself at http://www.devexpress.com/Home/Announces/roadmap-2010.xml.

Adjusting DevExpress’ XtraTabControl’s page padding

Look at the picture below, it is a DevExpress' XtraTabControl (WinForms) with a single page hosting a normal Button. Both XtraTabControl and Button are set as Dock = Dock.Fill. Somebody (read: my client) considers that there is just too much wasted space around them (annotated with arrows):

image

There are no properties to modify padding behavior but luckily DevExpress supports skinning and I solved it through the use of slightly modified skin based iMaginary in this case.

Preparation

Fire up SkinEditor (found in All Programs/Developer Express v2009 vol 2/Components/Tools) and create a new skin based on iMaginary out of the box skin. For more info on creating new skins see this help topic. Save the new project and build the skin assembly. Create a new Visual Studio project, reference the skin assembly and code similar to this (substitute SKINPROJECTNAME and SKINNAME with your names):

DevExpress.Skins.SkinManager.Default.RegisterAssembly(typeof(SKINPROJECTNAME).Assembly);!
XtraForm f = new XtraForm();
f.LookAndFeel.SkinName = "SKINNAME";
f.LookAndFeel.UseDefaultLookAndFeel = false;
XtraTabControl ctl1 = new XtraTabControl();
ctl1.Dock = DockStyle.Fill;
XtraTabPage page = new XtraTabPage { Text = "One" };
ctl1.TabPages.Add(page);
Button b = new Button { Text = "Dock.Fill" };
b.Dock = DockStyle.Fill;
page.Controls.Add(b);
f.Controls.Add(ctl1);

Now you have a test project that should output the window above.

Step 1 – The drawing of XtraTabControl the border

DevExpress controls use template images that are properly resized for most of the resizable drawing including XtraTabControl’s borders.

Find the TabPane node in the tree view on the right

image

and you’ll see the border template image:

image

Note that the shadows are drawn within this template, not programmatically. Red lines are borders that determine what part of the image is copied to provide dynamically size final image. First, close SkinEditor. Then find the template image on the disk ([SKIN PROJECT]/[SKIN NAME]/Tab/TabPane.png) and use on of the paint applications to get ride of the shades (by copy paste the parts without shades) and expand the usable area to get a result like below, reopen SkinEditor and load the skin project (I did move borders to 2,2,2,2 as well – you can drag them with mouse or by setting proper values on the left).

image

If you run the test application it will show painted borders as expected but the button will remain on the original position regardless of this change. For now only the drawing changed but not the behavior.

image

We are half way now. Obviously the page content margins have to be adjusted as well.

Step 2 – adjust page content margins

First instinct was to adjust Tab’s parameters of my skin in the SkinEditor, it has to be one of these I thought:

image

Left and RightContentIndent were the obvious choices.  But no, they have no effect in our case. So I resorted to what every developer does: I looked at the sources of the XtraTabControl. It turns out that the solution is rather simple yet not supported by SkinEditor for some reason. Instead I had to manually modify the skin’s XML definition you’ll find in [SKIN PROJECT]/[SKIN NAME]/skin.xml file.

Open the skin.xml and find the line that contains this content: SkinProduct="Tab" SkinName="[SKIN NAME]". It should look like:

<Skin4 SkinProduct="Tab" SkinName="SKIN NAME">

(don’t ask me why there is a node named Skin4 and others numbered from 1 on). So, within this node find the node named TabPane. Within TabPane node adjust the attributes of ContentMargins node to values you want. I.e. try this:

<ContentMargins Bottom="1" Top="1" Left="1" Right="1" />
The result is the 2nd picture below – compare both original and modified skin to see which one you prefer.

imageimage

This would be a lot more straightforward if ContentMargins were available through SkinEditor’s UI. I hope that SkinEditor will get more treatment in the future as it lacks other features as well.

Reversing for loops with CodeRush

Imagine you have to delete a bunch of items from a list, something like this:

List<int> items = new List<int>();
...
for (int i = 2; i < items.Count; i++)
{
items.RemoveAt(i);
}

Will it work? Of course not because you are removing items while your are looping the entire list. That means sooner or later you’ll bump against out of index exception or items silently won’t be removed. And this is a common mistake we all do I suppose.

The solution is a pretty easy one – reverse the for loop, like this:

for (int i = items.Count - 1; i >= 2; i--)
{
items.RemoveAt(i);
}

However I find writing reverse loops harder than the former one. Not sure why but I guess that’s how I am used to do the maths – addition is always easier compared to subtraction.

Luckily there is CodeRush to the rescue. Just execute the Reverse For Loop code reformatting (not refactoring because you do change the meaning of the code with this one) and you are done.

cr

It works the other direction as well. Until today I didn’t even know that this trick exists. I just assumed it does and it sure did exist. This and a “million” of other features makes CodeRush really a must have coding tool.

Suppress system menu when right clicking on DevExpress skinned form's icon

Task

Today I've got a requirement from my customer to prevent showing the system menu when WinForm's icon (top left) is right-clicked. The form is painted by DevExpress skin. Here is how I've done it.

Solution

1. Intercept proper mouse messages

I had to intercept two mouse messages: WM_NCRBUTTONDOWN (0xa4) and WM_NCRBUTTONUP (0xa5). These two guys shows up when right click is performed on non client (NC) are of the form (where icon is located). That’s also the reason I couldn’t use Mouse* events which fire only for client area.

The interception is done by overriding Form's WndProc method and it looks something like this:

...
enum MouseMessage
{
WM_NCRBUTTONDOWN = 0xA4,
WM_NCRBUTTONUP = 0xA5
}
...
protected override void WndProc(ref Message msg)
{
switch ((MouseMessage)msg.Msg)
{
case MouseMessage.WM_NCRBUTTONDOWN:
case MouseMessage.WM_NCRBUTTONUP:
// code here
break;
}
base.WndProc(ref msg);
}

2. Finding icon bounds

If you are doing DevExpress form skinning it means that your form has to derive from XtraForm which does all of the skinning work for you. XtraForm holds a reference to FormPainter instance (which is responsible for painting the skin) through FormPainter property which in turn holds the icon bounds through its IconBounds property of Rectangle type. Now, the problem is that FormPainter.IconBounds property is protected and reflection has to be used to retrieve the value:

...
private PropertyInfo iconBoundsInfo;
...
public MyForm()
{
...
// store reference to IconBounds property to increase the performance
iconBoundsInfo = typeof(FormPainter).GetProperty("IconBounds", BindingFlags.Instance | BindingFlags.NonPublic);
...
}
protected override void WndProc(ref Message msg)
{
...
Rectangle iconBounds = (Rectangle)iconBoundsInfo.GetValue(FormPainter, null);
...
}

3. Figuring out if right click is within icon bounds and ignore such clicks

To get the click’s location I simply used Cursor.Position which is easier than retrieving the position from Message but less accurate – still enough for me.The position is in screen coordinates and they have to be transformed to form's coordinates. Form.PointToClient method won’t help because it transforms to form’s client area which border isn’t. The solution to this is rather simple – just Offset the position by Form’s –Left, –Top.

If click is positioned within icon bounds just return without delegating to base.WndProc. That’s it. Here is the complete code:

public IgnoreRightIconClickForm: XtraForm
{
enum MouseMessage
{
WM_NCRBUTTONDOWN = 0xA4,
WM_NCRBUTTONUP = 0xA5
}
private PropertyInfo iconBoundsInfo;

public IgnoreRightIconClickForm()
{
iconBoundsInfo = typeof(FormPainter).GetProperty("IconBounds", BindingFlags.Instance | BindingFlags.NonPublic);
}

protected override void WndProc(ref Message msg)
{
switch ((MouseMessage)msg.Msg)
{
case MouseMessage.WM_NCRBUTTONDOWN:
case MouseMessage.WM_NCRBUTTONUP:
// prevent showing system menu on window's icon rightclick
Rectangle iconBounds = (Rectangle)iconBoundsInfo.GetValue(FormPainter, null);
Point cursorPosition = Cursor.Position;
// offset to the raw window's coordinates (PointToClient transforms to window's client coordinates)
cursorPosition.Offset(-Left, -Top);
if (iconBounds.Contains(cursorPosition))
return;
break;
}
base.WndProc(ref msg);
}
}

Notes

This method works only for DevExpress skinned forms. If you want to use for normal forms the you should modify the icon bounds retrieval.

Suppress system menu when right clicking on DevExpress skinned form's icon

Task

Today I've got a requirement from my customer to prevent showing the system menu when WinForm's icon (top left) is right-clicked. The form is painted by DevExpress skin. Here is how I've done it.

Solution

1. Intercept proper mouse messages

I had to intercept two mouse messages: WM_NCRBUTTONDOWN (0xa4) and WM_NCRBUTTONUP (0xa5). These two guys shows up when right click is performed on non client (NC) are of the form (where icon is located). That’s also the reason I couldn’t use Mouse* events which fire only for client area.

The interception is done by overriding Form's WndProc method and it looks something like this:

...
enum MouseMessage
{
WM_NCRBUTTONDOWN = 0xA4,
WM_NCRBUTTONUP = 0xA5
}
...
protected override void WndProc(ref Message msg)
{
switch ((MouseMessage)msg.Msg)
{
case MouseMessage.WM_NCRBUTTONDOWN:
case MouseMessage.WM_NCRBUTTONUP:
// code here
break;
}
base.WndProc(ref msg);
}

2. Finding icon bounds

If you are doing DevExpress form skinning it means that your form has to derive from XtraForm which does all of the skinning work for you. XtraForm holds a reference to FormPainter instance (which is responsible for painting the skin) through FormPainter property which in turn holds the icon bounds through its IconBounds property of Rectangle type. Now, the problem is that FormPainter.IconBounds property is protected and reflection has to be used to retrieve the value:

...
private PropertyInfo iconBoundsInfo;
...
public MyForm()
{
...
// store reference to IconBounds property to increase the performance
iconBoundsInfo = typeof(FormPainter).GetProperty("IconBounds", BindingFlags.Instance | BindingFlags.NonPublic);
...
}
protected override void WndProc(ref Message msg)
{
...
Rectangle iconBounds = (Rectangle)iconBoundsInfo.GetValue(FormPainter, null);
...
}

3. Figuring out if right click is within icon bounds and ignore such clicks

To get the click’s location I simply used Cursor.Position which is easier than retrieving the position from Message but less accurate – still enough for me.The position is in screen coordinates and they have to be transformed to form's coordinates. Form.PointToClient method won’t help because it transforms to form’s client area which border isn’t. The solution to this is rather simple – just Offset the position by Form’s –Left, –Top.

If click is positioned within icon bounds just return without delegating to base.WndProc. That’s it. Here is the complete code:

public IgnoreRightIconClickForm: XtraForm
{
enum MouseMessage
{
WM_NCRBUTTONDOWN = 0xA4,
WM_NCRBUTTONUP = 0xA5
}
private PropertyInfo iconBoundsInfo;

public IgnoreRightIconClickForm()
{
iconBoundsInfo = typeof(FormPainter).GetProperty("IconBounds", BindingFlags.Instance | BindingFlags.NonPublic);
}

protected override void WndProc(ref Message msg)
{
switch ((MouseMessage)msg.Msg)
{
case MouseMessage.WM_NCRBUTTONDOWN:
case MouseMessage.WM_NCRBUTTONUP:
// prevent showing system menu on window's icon rightclick
Rectangle iconBounds = (Rectangle)iconBoundsInfo.GetValue(FormPainter, null);
Point cursorPosition = Cursor.Position;
// offset to the raw window's coordinates (PointToClient transforms to window's client coordinates)
cursorPosition.Offset(-Left, -Top);
if (iconBounds.Contains(cursorPosition))
return;
break;
}
base.WndProc(ref msg);
}
}

Notes

This method works only for DevExpress skinned forms. If you want to use for normal forms the you should modify the icon bounds retrieval.

ClickOnce and DevExpress components deployment

Let’s say you’ve build a WinForms application and put some DevExpress (or any other 3rd party controls installed in GAC I suppose) controls in there. At some point you have to deploy the application and let’s say you’ll use ClickOnce technology. Its easy, go to Project Properties/Publish tab, select where to publish and click Publish button. The next step is to try the application and of course you try it at your development computer – it works, no surprise there. However, when your client runs it on his computer it will most probably throw some sort of exception at the very beginning. Besides the obvious Murphy law involvement, why’s that? After all it worked on *development* computer.

There are two problems in this process.

1. ClickOnce doesn’t include 3rd party assemblies by default. This is probably true for all 3rd party assemblies that reside in GAC on development computer or in other words, those which are marked with CopyLocal=false (I admit it, I never researched in details). It should include those who are marked CopyLocal=true. Now, if you look at your Application Files in Publish tab of Project Properties you’ll see that all three DevExpress assemblies are marked with Publish Status = Prerequisite (Auto) flag – it means that your application expects those assemblies already installed on target machine:

pre

To include them in your deployment package change their Publish Status flag to Include. Like this:

post

All required assemblies will be published to client’s computer and the application will work, or at least will work as good or as bad as on development computer.

2. Your testing process isn’t good. You should always test deployment scenarios on non-development machine(s). VMWare Workstation is of great help. Besides the great virtualization desktop platform it also support integration in Visual Studio itself so you can pretty easily launch application in guest OS or even remotely debug it and even record the session. The other virtualization option on desktop is MS’ VirtualPC, an inferior application but free. You could use virtualization servers as well (MS HyperV,  VMWare Server, etc.).

That’s it.