Please click this logo to help me get on their beta program:

Xobni outlook add-in for your inbox








30/8/2005

Your next desktop clock?

Filed under: General — Oliver Sturm @ 7:31 pm - 2 years, 11 months ago

I imagine it’s quite unnerving in the long run, but I thought someone might be interested in this clock I just stumbled upon.

Video on WinFS

Filed under: General, Programming, .NET — Oliver Sturm @ 11:57 am - 2 years, 11 months ago

WinFS beta 1 is available, as I’m sure I’m not the first to report. I just watched this new Channel9 video about WinFS, which has a few really good demos and a lot of talk about WinFS. Highly recommended!

26/8/2005

Drawing a selection rubber band like Explorer - improved

Filed under: General, Programming, .NET — Oliver Sturm @ 7:14 pm - 2 years, 11 months ago

I heard criticism about my first post on the topic: if a control was on the form, apart from the background drawing, the rubber rectangle would appear behind the control, not in front of it. Of course there are several ways to change this, I decided to implement one of them just for fun :-)

This is what things look like before and after my changes:

Here’s the complete code again, which will need the same changes as before if it is to be used in VS 2003 (see the comments on the first post for this).

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
	
namespace SelectionRectTest {
	public class Form1 : Form {
		public Form1( ) {
			InitializeComponent( );
			BackColor = Color.White;
		}
	
		protected override void OnPaint(PaintEventArgs e) {
			if (selectionPanel == null) {
				e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
	
				// Draw some stuff so the transparent selection becomes visible
				int height = ClientRectangle.Height;
				int heightTenth = height / 10;
				int width = ClientRectangle.Width;
				int widthTenth = width / 10;
	
				e.Graphics.DrawLines(Pens.Red, new Point[] {
					new Point(widthTenth, heightTenth * 3),
					new Point(widthTenth * 5, heightTenth),
					new Point(widthTenth * 8, heightTenth * 9),
					new Point(widthTenth, heightTenth * 3)
				});
				e.Graphics.DrawEllipse(Pens.Blue, widthTenth * 4, heightTenth * 3, widthTenth * 5, heightTenth * 4);
			}
		}
	
		protected override void OnResize(EventArgs e) {
			base.OnResize(e);
			Invalidate( );
		}
	
		Point mouseDownPos = Point.Empty;
	
		protected override void OnMouseDown(MouseEventArgs e) {
			base.OnMouseDown(e);
	
			if (e.Button == MouseButtons.Left)
				mouseDownPos = e.Location;
	
			Bitmap contentBitmap = new Bitmap(Bounds.Width, Bounds.Height);
			Rectangle targetRect = Bounds;
			targetRect.X = 0 ;
			targetRect.Y = 0;
			DrawToBitmap(contentBitmap, targetRect);
	
			Point originScreen = PointToScreen(new Point(0, 0));
			Rectangle usableRect = new Rectangle(new Point(originScreen.X - Bounds.X, originScreen.Y - Bounds.Y), ClientRectangle.Size);
	
			selectionPanel = new SelectionPanel(contentBitmap, usableRect, mouseDownPos);
			Controls.Add(selectionPanel);
			selectionPanel.BringToFront( );
		}
	
		SelectionPanel selectionPanel;
	
		protected override void OnMouseMove(MouseEventArgs e) {
			base.OnMouseMove(e);
			if (e.Button == MouseButtons.Left && mouseDownPos != Point.Empty && selectionPanel != null)
				selectionPanel.Invalidate( );
		}
	
		protected override void OnMouseUp(MouseEventArgs e) {
			base.OnMouseUp(e);
			mouseDownPos = Point.Empty;
			Controls.Remove(selectionPanel);
			selectionPanel = null;
		}
	
		private Button button1;
	
		private void InitializeComponent( ) {
			this.button1 = new System.Windows.Forms.Button( );
			this.SuspendLayout( );
			//
			// button1
			//
			this.button1.Location = new System.Drawing.Point(114, 108);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(75, 33);
			this.button1.TabIndex = 0;
			this.button1.Text = "button1";
			//
			// Form1
			//
			this.ClientSize = new System.Drawing.Size(292, 266);
			this.Controls.Add(this.button1);
			this.Name = "Form1";
			this.ResumeLayout(false);
	
		}
	}
	
	public class SelectionPanel : Panel {
		public SelectionPanel(Bitmap backgroundBitmap, Rectangle usableRect, Point mouseDownPos) {
			DoubleBuffered = true;
	
			this.backgroundBitmap = backgroundBitmap;
			this.mouseDownPos = mouseDownPos;
			this.usableRect = usableRect;
	
			this.Size = usableRect.Size;
			this.Location = new Point(0, 0);
	
			selectionColor = Color.FromArgb(200, 0xE8, 0xED, 0xF5);
			selectionBrush = new SolidBrush(selectionColor);
			frameColor = Color.FromArgb(0x33, 0x5E, 0xA8);
			framePen = new Pen(frameColor);
		}
	
		Bitmap backgroundBitmap;
		Point mouseDownPos;
		Color selectionColor;
		Brush selectionBrush;
		Color frameColor;
		Pen framePen;
		Rectangle usableRect;
	
		protected override void OnPaint(PaintEventArgs e) {
			// copy the backgroundImage
			e.Graphics.DrawImage(backgroundBitmap, ClientRectangle, usableRect, GraphicsUnit.Pixel);
	
			// Now, if needed, draw the selection rectangle
			if (mouseDownPos != Point.Empty) {
				Point mousePos = PointToClient(MousePosition);
				Rectangle selectedRect = new Rectangle(
					Math.Min(mouseDownPos.X, mousePos.X),
					Math.Min(mouseDownPos.Y, mousePos.Y),
					Math.Abs(mousePos.X - mouseDownPos.X),
					Math.Abs(mousePos.Y - mouseDownPos.Y));
				e.Graphics.FillRectangle(selectionBrush, selectedRect);
				e.Graphics.DrawRectangle(framePen, selectedRect);
			}
		}
	}
}

Drawing a selection rubber band like Explorer

Filed under: General, Programming, .NET — Oliver Sturm @ 1:40 pm - 2 years, 11 months ago

I saw the question coming up in a newsgroup today: how do you draw a selection rubber band just like the one Explorer uses, in C#? The first thing that came to mind was the ControlPaint.DrawReversibleFrame() method, but that’s rather restricted. It’s fine to draw a rectangle around an area to select, but it can’t do anything more than that and it also has problems because it draws over windows that are supposed to be in front of the current app window.

Here are screenshots of a selection made in Explorer and a selection made in my sample program. Nice, huh? :-)

So, here’s the code. I created this in VS 2005 beta 2, but I don’t think I used any .NET 2 specific things - if you find any, let me know. To use the sample, just create a new project and replace your newly created Form1 mainform by this code (and throw away the .Designer.cs and resource files).

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
	
namespace SelectionRectTest {
	public class Form1 : Form {
		public Form1( ) {
			DoubleBuffered = true;
			BackColor = Color.White;
	
			selectionColor = Color.FromArgb(200, 0xE8, 0xED, 0xF5);
			selectionBrush = new SolidBrush(selectionColor);
			frameColor =  Color.FromArgb(0x33, 0x5E, 0xA8);
			framePen = new Pen(frameColor);
		}
	
		Color selectionColor;
		Brush selectionBrush;
		Color frameColor;
		Pen framePen;
	
		protected override void OnPaint(PaintEventArgs e) {
			e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
	
			// Draw some stuff so the transparent selection becomes visible
			int height = ClientRectangle.Height;
			int heightTenth = height / 10;
			int width = ClientRectangle.Width;
			int widthTenth = width / 10;
	
			e.Graphics.DrawLines(Pens.Red, new Point[] {
				new Point(widthTenth, heightTenth * 3),
				new Point(widthTenth * 5, heightTenth),
				new Point(widthTenth * 8, heightTenth * 9),
				new Point(widthTenth, heightTenth * 3)
			});
			e.Graphics.DrawEllipse(Pens.Blue, widthTenth * 4, heightTenth * 3, widthTenth * 5, heightTenth * 4);
	
			// Now, if needed, draw the selection rectangle
			if (mouseDownPos != Point.Empty) {
				Point mousePos = PointToClient(MousePosition);
				Rectangle selectedRect = new Rectangle(
					Math.Min(mouseDownPos.X, mousePos.X),
					Math.Min(mouseDownPos.Y, mousePos.Y),
					Math.Abs(mousePos.X - mouseDownPos.X),
					Math.Abs(mousePos.Y - mouseDownPos.Y));
				e.Graphics.FillRectangle(selectionBrush, selectedRect);
				e.Graphics.DrawRectangle(framePen, selectedRect);
			}
		}
	
		protected override void OnResize(EventArgs e) {
			base.OnResize(e);
			Invalidate( );
		}
	
		Point mouseDownPos = Point.Empty;
	
		protected override void OnMouseDown(MouseEventArgs e) {
			base.OnMouseDown(e);
	
			if (e.Button == MouseButtons.Left)
				mouseDownPos = e.Location;
		}
	
		protected override void OnMouseMove(MouseEventArgs e) {
			base.OnMouseMove(e);
			if (e.Button == MouseButtons.Left && mouseDownPos != Point.Empty)
				Invalidate( );
		}
	
		protected override void OnMouseUp(MouseEventArgs e) {
			base.OnMouseUp(e);
			mouseDownPos = Point.Empty;
			Invalidate( );
		}
	}
}

22/8/2005

Using methods that get passed (Generic) delegates

Filed under: General, Programming, .NET — Oliver Sturm @ 12:12 pm - 2 years, 11 months ago

I recently saw this question regarding the use of methods that get passed delegates - specifically, the .NET 2 collection classes make use of this, like for example the List<T> class, which takes a Predicate<T> as a parameter to its Find method.

Now the question is how to make use of this method? How does the delegate know what to do when it’s called? As I see it, there are two (good) approaches to this: using an anonymous method and using a separate class. I’m going to illustrate both approaches below, with a sample that makes a few assumptions:

  • You have a class called MyObject that has a property called Id, of type Guid.
  • You have a list of MyObject instances, declared List<MyObject> list = new ..., which contains a few instances.
  • Now you want to write a method called FindById, that takes a Guid and makes use of the method List<T>.Find to find a MyObject in the list which has the given Id.
Anonymous methods

I’m not going to explain the complete concept of anonymous methods in this article. Suffice it to say that they can be used in places where delegates would otherwise be expected in .NET, but without the overhead of having to create a named method to pass in to the delegate’s constructor.

Using an anonymous method, you could write your FindById method like this:

MyObject FindById(Guid searchId) {
  return list.Find(delegate(MyObject myObject) {
    return myObject.Id == searchId;
  });
}

As you can see, an anonymous method is created that has the exact signature of the Predicate<T> delegate, getting passed a MyObject and returning a bool. This anonymous method has direct access to the searchId that was passed in to FindById, so a comparison is easily possible.

A separate class

The worst drawback of the anonymous method approach is that it’s not easily reusable. If you need a similar comparison algorithm in another place, you’ll have to write the complete code again. This may not be a problem in the sample, but if the code were a bit more complex it wouldn’t be a good idea. So why am I talking about a separate class? Because the value that’s needed for the comparison needs to be stored somewhere, and this shouldn’t be done in the same class that defines the FindById method - it’s much cleaner (and easier to make thread-safe) to put the value into a separate class. Of course, this class could be within the other, so it won’t polute your namespace. So the code for that extra class and the FindById method could look like this:

class MySearchByIdClass {
  Guid searchId;
  public MySearchByIdClass(Guid searchId) {
    this.searchId = searchId;
  }
	
  public bool PredicateDelegate(MyObject myObject) {
    return myObject == searchId;
  }
}
	
MyObject FindById(Guid searchId) {
  return list.Find(new Predicate<MyObject>(
    new MySearchByIdClass(searchId).PredicateDelegate));
}

Obviously the coding overhead is a bit higher here, but then we get complete reusability in return. The FindById method simply creates an instance of the encapsulation class to store the search parameter and uses that class’s delegate implementation to pass in to the Find method.

20/8/2005

global, ::, huh?

Filed under: General, Programming, .NET — Oliver Sturm @ 6:56 pm - 2 years, 11 months ago

I guess you know the way you can define aliases with the using statement:

using SWF = System.Windows.Forms;

Then you can use the shortcut SWF to reference a type in the namespace. In C# 1, the syntax was like this:

SWF.Button button = new SWF.Button();

Obviously this could be ambiguous, because there could have been any kind of different identifier in scope called SWF. To get rid of this ambiguity, C# 2 introduced the :: qualifier. So now you’ll write the same thing differently:

SWF::Button button = new SWF::Button();

So, the identifier to the left of the :: qualifier (called the namespace alias qualifier, by the way) defines the namespace that is searched for the identifier to the right of the qualifier. This is where global comes into play: this is an identifier you can use if you want to look only at the global namespace. For example, to make absolutely sure that a reference to a class called String can only ever mean (the framework standard) System.String, you could put something like this:

global::System.String mystring = new global::System.String('x', 10);

I feel colour blind…

Filed under: General — Oliver Sturm @ 4:09 pm - 2 years, 11 months ago

… after having stumbled upon this unbelievable demonstration on colour perception. I’ll never trust my eyes again! :-)

Update: And here’s another interesting page, on a similar note.

15/8/2005

Nullable types are being changed - late but not too late

Filed under: General, Programming, .NET — Oliver Sturm @ 11:15 am - 2 years, 11 months ago

This blog article explains that, and why, a late change to the implementation of nullable types is being made in the runtime, making nullables an intrinsic type. This solves the problems that many had reported when nullables were used in situations where boxing occurred, and where null comparisons were made involving generic types. Read the original article for the details, this is good news!

Next version of AutomatedQA TestComplete will do OCR

Filed under: General, Programming, .NET — Oliver Sturm @ 10:02 am - 2 years, 11 months ago

TestComplete by AutomatedQA is a tool for automated testing, useful in many software testing scenarios ranging from internal unit testing to black box UI testing. The next major version 4 has been in the making for a while now and they still don’t announce a release date, but every now and then they make previews of various new features available (for example on their new community site).

The latest thing that caught my eye was that OCR is going to come to automated testing in TestComplete 4. From TestComplete’s scripting languages, it will be possible to use OCR to parse text on screen that has been drawn there, in other words, which is part of an image. Apparently it can work with a configurable selection of arbitrary Windows fonts - I’m looking forward to trying how well it will work with my TabletPC-generated handwritten Oliver Sturm font :-) . A great idea, it will certainly make black box testing much easier in many cases.

Here’s the article about this on the AQA community site, which has a few more details: TestComplete 4 Sneak Peak - OCR

12/8/2005

Fuzzy fonts in MindManager X5

Filed under: General — Oliver Sturm @ 5:07 pm - 2 years, 12 months ago

I’ve been evaluating MindManager X5 and I really dig it. It’s a great program, it’s able to work with ink on my Tablet PC, it can integrate with MS Project. I have tried eight other mind mapping tools (FreeMind, Visual Mind, ConceptDraw MINDMAP, Thought Mapper, MYmap, BrainMine, Mind Pad, Map it!, MindMapper and OpenMind, in case someone’s interested) and they just can’t compete with MindManager’s feature set.

So, one seemingly small problem I’m having is that the fonts that MindManager shows in the diagrams are fuzzy. Look here:

Update: Have a look at the comments for a few more screenshots that may help you understand what I’m seeing.

The problem is worst for the subtopic, slightly better for the other node types, but it depends on a style’s font settings - in smaller font sizes, the problem is more clearly visible (and it’s much more clearly visible if the whole screen is full of text, something I couldn’t show in the small screenshot). This doesn’t have anything to do with the font I use, nor with the Windows setting for font smoothing.

Now, the thing is I contacted Mindjet support about this and got this reply:

The automatic antialiazing of MM X5 sadly causes on some screens a fuzzy appearance of the fonts.

Unfortunately the antialiazing cannot be switched off in the actual MM X5-version and at this time I cannot tell you eihter, if this feature will be detachable in a future version.

I´m sorry, that in this case I cannot offer you a solution for your problem.

What? I’m evaluating the best and most expensive mind mapping software in the market, the support guys acknowledge that they have a bad display bug, but they don’t feel they should promise a fix for the bug for any time in the future? Unbelievable!

Looking around the peer to peer forums at Mindjet, I found that three others have posted about this problem in the past, here, here and here. The oldest post dates back to December 2003.

So, if I can’t find a solution to this problem, it looks like I won’t buy MindManager, however great the functionality may be. I don’t like the bug because it makes the maps look ugly, and I don’t like the attitude any better, when I see how long this problem has apparently been known. Or does anybody have a solution to this problem?

11/8/2005

Accessing directory owner information in .NET 2

Filed under: General, Programming, .NET — Oliver Sturm @ 10:14 am - 2 years, 12 months ago

I just came upon this question in a newsgroup and had a quick look at the new classes that .NET 2 offers for access to the Windows file system ACLs and general system security information. In short, to get to the name of a user or group that’s the owner of a directory in the file system, you can use the following code:

  DirectoryInfo directoryInfo = new DirectoryInfo(@"c:\Windows");
  DirectorySecurity directorySecurity =
    directoryInfo.GetAccessControl(AccessControlSections.Owner);
  IdentityReference identityReference =
    directorySecurity.GetOwner(typeof(NTAccount));
  // now access identityReference.Value for the readable name

The one thing here that’s a bit hard to find out is the usage of the GetOwner method. Current MS docs tell only that the type you need to pass in is “the primary group for which to get the owner”. I needed to use Reflector to find out that the method that’s actually being called in the end is SecurityIdentifier.Translate, and that the type in question must be one of those that the SecurityIdentifier.IsValidTargetType method likes. The docs for that method, finally, told me that the only two types currently considered valid are the SecurityIdentifier itself and the System.Security.Principal.NTAccount. Good, works fine :-)

10/8/2005

Lookahead (or -behind) assertions in regular expressions

Filed under: General, Programming, .NET — Oliver Sturm @ 5:48 pm - 2 years, 12 months ago

Lookahead and lookbehind assertions are a feature of regular expressions that’s not needed as often as others. The .NET regular expression implementation has full support for them and the documentation is here. But what exactly are they good for? What do you do with them?

One answer is, they can be quite important when using regular expressions for replacing parts of strings. The reason for this is that a regex replacement always replaces the complete matched text. It’s possible to use substitutions to build a replacement string, but there are situations where it’s extremely difficult if not impossible to construct the correct replament string. Consider a string like this:

c:\program files;e:\tmp\%var1%;d:\apps\%var3%\foo;e:\tmp\%var2%

Now assume for a moment that you want to replace the %varX% expressions to say $varX$ instead, but only if they mark the end of a “part” of the original string. IOW, you want to catch var1 and var2, but not var3.

So, to start with, the following regex finds all the relevant parts: (?<var>%(?<varname>[^%]+)%)(;|$). In English, this expression finds expressions of the form %...%, which are followed by either ; or the end of the line. It has a group called var that holds the complete %...% part, and another one called varname that holds only the part between the %’s. Nice.

Now for the replacement. As I said, the replacement always replaces the whole matched string, so that will include the delimiter that was found, either the ; or the end of the line. So, if we use a replacement like $$${varname}$$, the delimiter that used to be there will be gone and the string would look like this: c:\program files;e:\tmp\$var1$d:\apps\%var3%\foo;e:\tmp\$var2$.

This is where the lookahead assertion comes in handy. By using it, we can tell the regular expression engine that while we are interested in the string that’s behind the %...% part, we don’t want to make it part of the match! It’s simple: we modify the regex to look like this: (?<var>%(?<varname>[^%]+)%)(?=;|$) (I have made the modification yellow, to make sure you see it :-) )

What this means is simple: look ahead to see whether the following characters actually match the expression in the parens. But don’t include the matched characters in the expression’s match! Now this is exactly what we want. Because the delimiter is no longer part of the match, it’s not going to be replaced either. By replacing (?<var>%(?<varname>[^%]+)%)(?=;|$) with $$${varname}$$, we get c:\program files;e:\tmp\$var1$;d:\apps\%var3%\foo;e:\tmp\$var2$.

The alternative

In this case, there would have been an alternative way to do the same thing. We’d have had to modify the expression like this: (?<var>%(?<varname>[^%]+)%)(?<delimiter>;|$). Then the delimiter would have been stored away in the group delimiter and we could have used it in a modified replacement string like this: $$${varname}$$${delimiter}. But this is a solution that requires far more modifications to the actual matching expression, and it can get extremely confusing to implement when the expressions are more complicated or there are simply more alternatives to watch out for. Using lookahead or lookbehind assertions just takes parts of the matched text out of the replaced match, which is a much more elegant way.

5/8/2005

New versions of Electric Editing and OpenToolWindow plugins

Filed under: General, Programming, .NET — Oliver Sturm @ 6:22 pm - 3 years ago

Yesterday, Developer Express released new versions of their fantastic tools CodeRush and Refactor! Pro (I already blogged about the latter today).

I have made new versions of my two CodeRush plugins available, both compiled against the new CodeRush version 1.1.28. An important change was made to the OpenToolWindow plugin (find the original announcement for that one here), to make use of a property in the CodeRush core that’s now public. So if you want to use OpenToolWindow with CodeRush >= 1.1.28, be sure to download the new version 1.0.1 of the plugin! (On the other hand, don’t use this new version if you are on an older version of CodeRush!)

Electric Editing doesn’t have any important changes in itself, but it has been changed in a few places where methods in the CodeRush core had been made obsolete. Get the download for the new version 1.2.3.1 from the plugin’s own page.

Vista: Accessing Samba server?

Filed under: General — Oliver Sturm @ 1:52 pm - 3 years ago

I can’t find anything about it in Google and I don’t have time right now to pursue the matter, but my new Vista installation steadfastly refuses to talk to my file server, running Samba on a Linux machine. I can try to connect to the share and I’m asked for my authentication, but Vista doesn’t like my username/password combination, no matter what I do. I did manage to connect to a Windows XP machine, so I guess they just killed the protocol once again…

Vista: IE tabs and Aero

Filed under: General — Oliver Sturm @ 1:49 pm - 3 years ago

Starting up IE 7 and navigating to Google :-) , one of the first things I was wondering about was a funny whiteish blob, saying “Google”, in the upper left corner. As large as the funny combined tool-/menubar, but more imposing because of the white background colour, I was wondering what that might be.

Well, now I know: it’s the tabs that IE 7 supports at long last, in the rendition created by the new Aero theme. Wow, who would have thought that this feature would have that ugly a visual representation when it finally came along?

Next Page »

Powered by WordPress
© Copyright 2005-2008 Oliver Sturm