I'm going to be writing some articles on Code Access Security (CAS). CAS is there to prevent a program from doing more than it should. The program is supposed to demand permission to perform the tasks it needs to do. For instance, if a program needs to access the registry, it should demand rights to do so. If it needs network access, it should demand rights to do so. A freecell game should not need to access the network, so it should not demand those rights. My example program for this will be MyCardGame (A .NET application).
Given these demands, the systems administrator can grant specific rights to those programs. For instance, using a "Deny All, Allow Some" security methodology, a systems administrator will deny all rights for that program, except for the ones it needs. For the example program, MyCardGame, the systems administrator will allow GUI usage, as well as Keyboard/Mouse. (S)he will then deny everything else.
Then when the user runs this program, MyCardGame, the OS will then allow it to do any GUI work it needs to do, as well as any keyboard/mouse work. It will deny everything else. Normal operation, that is just fine.
Now, suppose a malicious hacker changes the code in MyCardGame to do 'evil' tasks, such as reading the registry, the OS will deny it. That's wonderful, exactly as we expected.
Take another sample application, MyManagementApp, which requires registry access. The systems administrator knows that this program needs registry access, so it allows it. All is good, until the malicious hacker changes the code in MyManagementApp, to make it clobber values in the registry. Not good.
So how do we prevent this? The key is, the systems administrator needs to be assured that MyManagementApp is really MyManagementApp, and not some hacked version. Strong names prevent this.
A strong name is a 1024 bit RSA public/private key pair. Once you attach a strong name to an assembly, you cannot change it (without breaking the strong name). If you try changing code, without removing the strong name from the assembly, it will not let you run the app.
Note, that it is still possible to change the code. All you have to do is remove the strong name. So how does this help us? This is exactly what we're trying to prevent. With CAS, we're actually trying to prevent malicious code from doing what its not supposed to do.
When the systems administrator allows MyManagementApp to access the registry, (s)he really is allowing the strong name access to the registry. If the malicious hacker changes the code, (s)he has to remove the strong name. As soon as (s)he does this, it is no longer MyManagementApp, and therefore is not allowed to access the registry. Mission successful.
So how do we attach a strong name to our assembly? It's actually pretty easy. First, create your assembly. Once complete, go to your project settings (Right click on your project, go to Properties). In the "Signing" tab, near the bottom, there is a check box called "Sign the Assembly". Select this. Then, from the drop down box, choose "
That's it. Your assembly now has a strong name, and it will continue to do so. Since you maintain control of the private key, no one else can make assemblies with this strong name. Your end-users now have a guarentee that if a project has your strong name, then it is, without a doubt, the program you say it is. They can elevate with confidence.
Monday, August 27, 2007
CAS and Strong Names
Posted by
Mike Christiansen
at
10:31 PM
0
comments
Labels: C#, CAS, Code Access Security, Elevation, Private Key, Public Key, RSA, Strong Names
Sunday, August 26, 2007
Friends don't let friends program as administrator
It's been a while since I wrote anything, but I came across a little gem. Michael Stiefel wrote an article about Code Access Security, or CAS. At the end of the article, he states "Friends don't let friends program as administrator." Why is that, you may ask? Well, here is a scenario. I work with a network containing thousands of users. They're all managed with a domain. Now, of course, we don't want to give administrative rights to every single user. We limit the administrators to 1-5 per unit. These administrators have two accounts. They have a user account (for using the internet) and an administrative account. For security reasons, the administrative account is blocked from all HTTP, FTP, etc.
Over the months that I've been here, I've become a remote administration buff. I hate getting out of my chair. Previously, when I was back in the states, I was logged in as an account that had administrative access to my entire unit. Now, I am forced to be on a non-administrator account, and use the "Run As..." function to perform tasks. Works all fine and great - until you run into something that you can't use "Run As..." for.
The point is that you cannot guarentee that a user will have the same rights as you do when you create the program. Jeff Atwood, in The Programmer's Bill of Rights, states that all programmers should have a fast PC, for development. However, the comments below state that programmers should not only have a fast PC, but a median PC, something equivalent to what average users would have.
A good programmer wears two hats. The first hat, is the developer. The developer writes the code, makes the magic happen. However, every developer must know their roots. Every developer started off as a user. Developers have a job because of one thing - the user. If a program doesn't have a single user - it doesn't need to exist.
That said, every programmer needs to swap between these two hats. They develop in the developer's hat... Then all testing should be done in the user hat. This ensures that you, as the developer, experience every single issue that the user would experience, including lack of administrative rights.
You cannot assume that a user has any administrative rights. When you do need administrative rights for your program, you should use CAS. CAS will let the administrators know what rights you need.
Friends don't let friends program as administrator.
Posted by
Mike Christiansen
at
11:15 PM
2
comments
Labels: .NET, Administrator, CAS, Code Access Security, Hats
Wednesday, August 22, 2007
Converting persisted data using XMLSerializer and implicit operators
public class Timestamp
{
private static DateTime EPOCH = new DateTime(1970, 1, 1);
private UInt64 m_Value;
public UInt64 Value
{
get { return m_Value; }
set { m_Value = value; }
}
public Timestamp(UInt64 seconds)
{ Value = seconds; }
public Timestamp(DateTime datetime)
{ Value = (UInt64)datetime.Subtract(EPOCH).TotalSeconds; }
public Timestamp(Timestamp timestamp)
{ Value = timestamp.Value; }
public Timestamp(double seconds)
{ Value = (UInt64)seconds; }
public static implicit operator Timestamp(UInt64 seconds)
{ return new Timestamp(seconds); }
public static implicit operator Timestamp(DateTime datetime)
{ return new Timestamp(datetime); }
public static implicit operator Timestamp(double seconds)
{ return new Timestamp(seconds); }
public static implicit operator UInt64(Timestamp timestamp)
{ return timestamp.Value; }
public static implicit operator DateTime(Timestamp timestamp)
{ return EPOCH.AddSeconds(timestamp); }
public static implicit operator double(Timestamp timestamp)
{ return (double)timestamp.Value; }
}
Posted by
Mike Christiansen
at
1:20 PM
0
comments
Labels: A better way, C#, conversion, epoch, implicit, implicit operator, timestamp, xml, XmlSerializer
Friday, August 17, 2007
Code Blog Formatter Update
I've updated the code blog formatter slightly, to allow for turning off the line numbers and region formatting. I'll probably post code from here on out without line numbers, so people can more easily copy-paste code.
Updated links and change-list is available in the original post here.
Posted by
Guard
at
2:00 PM
0
comments
Monday, August 13, 2007
Easier managing of INotifyPropertyChanged
INotifyPropertyChanged is the core of WPF Data Binding. One thing that always pissed me off about INotifyPropertyChanged is that it would require me to pass the name of the property to PropertyChanged(). Well, in VS 2005, refactoring is made very simple. So simple, that if you change the name of the property, and then use the context menu to apply the changes to the entire project - it's done flawlessly. However, some complex data binding can cause you to call PropertyChanged for one property, when you set a completely different property! In those instances, you might 'lose track' of a property name change... What happens if the property name passed to PropertyChanged doesn't match that of the property itself? Data binding breaks!
The solution I came up with? Well, we need to write a helper function to get the name of the current property. To do this, we need to examine how properties work. If I have the property named 'MyProperty', it gets converted to accessors when I compile. 'public int MyProperty' becomes two methods, 'public int get_MyProperty()' and 'public void set_MyProperty(int value)'.
The System.Diagnostics.StackTrace class can be used to get the name of the calling method. So, what I did, was devise a function, that when called, obtains the name of the calling method, ensures that it is, in fact, a property (by testing for leading get_ or set_).
Now, I verify that it really IS a property (and not a method pretending to be a property by being named get_ or set_) by using Reflection. First, we get the type of the class by using this.GetType(). Then we get the property with the name we found earlier. If that property is equal to null, then it is NOT a property. Once I've verified that this thing really is a property, then I call PropertyChanged with the appropriate property name.
Then I wrap all of this up into a class, with static methods, for easier reusability. Code is below.
Note that when using reflection to verify that it is actually a property, there are some caveats. For instance, if you have two properties with the same name, one static, one instanced, you will raise an exception. Read the MSDN article for more information. If you cannot deal with those caveats, you could simply take out the call to IsProperty
1public class PropertyChanger
2{
3 public static void PropChanged(object callerobject, PropertyChangedEventHandler PropertyChanged)
4 {
5 string propertyname = new StackTrace().GetFrame(1).GetMethod().Name;
6 string accessor = propertyname.Substring(0, 4);
7 propertyname = propertyname.Substring(4);
8 if (((accessor == "set_") (accessor == "get_")) && (propertyname.Length > 0))
9 {
10 if (IsProperty(callerobject, propertyname))
11 PropertyChanged(callerobject, new PropertyChangedEventArgs(propertyname));
12 else
13 throw new Exception(propertyname + " is not a property.");
14 }
15 else
16 throw new Exception("Calling method is not a get or set accessor.");
17 }
18 private static bool IsProperty(object callerobject, string propertyname)
19 {
20 return callerobject.GetType().GetProperty(propertyname) != null;
21 }
22 }
23}
And to use this class, just call like this:
PropertyChanger.PropChanged(this, PropertyChanged);
where PropertyChanged is the name of your PropertyChanged is the name of your PropertyChanged event handler.
Posted by
Mike Christiansen
at
10:20 PM
1 comments
Labels: C#, Diagnostics, INotifyPropertyChanged, Properties, Reflection, StackTrace
Example: Message Window
Requirements:
Fade-in and fade-out based on time requested (If the user wants automatic timing based on the length of the string, it's easy to make a function to do this)
Automatic resizing based on the length of the string.
Create and forget: Closes itself (thus freeing memory) after it's alloted time.
Since the naming is close to MessageBox, we should have a similiar way of using it.
Design:
As you can see in the picture above, I wanted my message to be in a rectangle, with rounded edges and a drop shadow effect. I did all this through Microsoft Expression Blend, but it's simple to do in the XAML:
<Window.BitmapEffect>
<DropShadowBitmapEffect/>
</Window.BitmapEffect>
<Grid Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle Fill="#FF191919" Stroke="#FF000000" StrokeThickness="1" RadiusX="20" RadiusY="20" Margin="8,8,8,8"/>
<Label Margin="0,0,0,0" x:Name="Message" Width="Auto" Height="25" Content="Label" Foreground="#FFFFFFFF" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Arial" FontSize="12" FontWeight="Normal"/>
</Grid>
RadiusX and RadiusY in Rectangle control the rounded corners. Here I've also placed the label which will hold the message.
Sizing The MessageWindow
The user is going to pass a String into the MessageWindow constructor, and based on how long that is, we need to resize. Luckily, in WPF, you can set a Label width to Auto, which will fix this problem. I want to take the ActualWidth of the Label after we put our String in, and adjust the Window's width and position based on that.
I want the Bottom and Right to be 20 away from the bottom right corner of the "Work Area" (The area above the taskbar). With a little math, here is our constructor:
1public MessageWindow(String message, double duration)
2{
3 InitializeComponent();
4
5 //Message to be displayed in the window
6 Message.Content = message;
7
8 //Begin closing the window after the specified duration has elapsed.
9 Timer closeTimer = new System.Timers.Timer(duration);
10 closeTimer.Elapsed += new System.Timers.ElapsedEventHandler(closeTimer_Elapsed);
11 closeTimer.Start();
12
13 //This cannot be in the constructor directly, because the ActualWidth of items
14 //does not get set until AFTER the constructor. Since I couldn't get the Initialize
15 //event to fire, this method seems to work good.
16 this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidDelegate(delegate
17 {
18 this.Width = Message.ActualWidth + 50;
19
20 //Set the default placement to the bottom right corner, above the Taskbar.
21 this.Left = System.Windows.SystemParameters.WorkArea.Right - this.Width - 20;
22 this.Top = System.Windows.SystemParameters.WorkArea.Bottom - this.Height - 20;
23 }));
24}
I'm also creating a timer here, because after the duration elapses, I want to start to fade out our message, and then close it.
Fading In And Out
I created two storyboards in XAML (Using Blend), one that will fade our window in when the box is shown, and another that we can use to fade out.
<Storyboard x:Key="OnLoaded1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="{x:Null}" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:01" Value=".7"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="FadeAway">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="{x:Null}" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:01" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
In here, the OnLoaded1 event will fade in the window, going from 0 to .7 transparency, leaving the window slightly transparent when it's fully shown. Then when fading out, it'll go from the current value back to 0.
Using this, I set the Fading in event (OnLoaded1 was the default name for it) to trigger when the Window loads:
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
</EventTrigger>
</Window.Triggers>
Now all that's left is to fade the window out, and close. This takes a little code, since we want to wait until our timer elapses before we do it:
1void closeTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
2{
3 ((Timer)sender).Stop();
4
5 //We must begin the storyboard on the main window thread.
6 this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidDelegate(delegate
7 {
8 Storyboard story = (Storyboard)this.FindResource("FadeAway");
9 story.Completed += new EventHandler(story_Completed);
10 this.BeginStoryboard(story);
11 }));
12}
13
14/// <summary>
15/// Closes the window after we're done fading out.
16/// </summary>
17void story_Completed(object sender, EventArgs e)
18{
19 this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidDelegate(Close));
20}
Here you can see once the Window fades away, the storyboard will say it's completed, which will cause the Window to close, with no work needed from the user.
Looking like a MessageBox - A Problem
Like the MessageBox class, I wanted a Show method similiar to MessageBox so I can create and display a MessageBox in 1 line of code. That was a simple add:
1public static void Show(String message, double duration)
2{
3 MessageWindow w = new MessageWindow(message, duration);
4 w.Show();
5}
6
7public static void Show(String message, double duration, Window parent)
8{
9 MessageWindow w = new MessageWindow(message, duration);
10 w.Show();
11 parent.Focus();
12}
Here's the problem I had: I wanted to automatically return the focus to the parent, because theres no reason this Window ever needs focus.
One solution is the one displayed above, where the parent must pass themselves in to recieve focus back.
The other option I saw was to do this.Owner.Focus() on the window. However, this relies on the Owner to actually set itself as the Owner before it shows the MessageWindow, which is a problem, especially with this Show() approach.
For now, the method I've shown works fine. I've asked around and never got a good alternative, so if you have a good alternate method for giving the parent focus again, let me know.
Finished MesssageWindow
And now you have a finished MessageWindow. You can call MessageWindow.Show(...) to show a MessageWindow, or if you want more control, you can create an instance of the Window yourself, then manually position it or do whatever you want.
Source (Executable is included inside)
Posted by
Guard
at
2:20 PM
2
comments
Labels: C#, fading, invoke, MessageWindow, wpf
Data Bound Currency Converter
In my previous article, Data Binding with Value Converters, I discussed using Value Converters (implementing IValueConverter) to assist in converting values for data binding. While a simple Value Converter is good for things like converting degrees to radians, you need something slightly more complex to allow things like currency exchange.
Currency Exchange Basics:
Currency exchanges are actually pretty simple. You have an amount of money in currency A. You want to know how much that is worth in currency B. The first thing you do, is get the currency exchange rate, from a bank, or some other source (I use http://www.xe.com/). Multiply your current value (in Currency A) by this rate, and you arrive at an equivalent value of Currency B.
For example, I have $24.00 (US) in my pocket. Well, I'm currently in Iraq (Iraqi Dinars). The conversion rate from United States Dollars (USD) to Iraqi Dinars (IQD) is 1238.50. That means, 24 USD is equal to 29,724.00 Iraqi Dinars.
Implementing the Interface:
Implementing the interface is exactly like we did with Degrees and Radians, with one small change. This time, we utilize the parameter named 'parameter.' This parameter allows us to pass a value along to the IValueConverter. In this case, we will pass the exchange rate. See my sample code below. Please note that although the comments are talking about USD to IQD, this could, in theory, be used for ANY currency.
1public class Converter : IValueConverter
2{
3 //Convert from USD to IQD using the exchange rate in the parameter
4 //Exchange rate is USD -> IQD.
5 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
6 {
7 if ((string)value == "") return 0.0;
8 double dollars = System.Convert.ToDouble(value);
9 double rate = System.Convert.ToDouble(parameter);
10 double dinar = dollars * rate;
11 return dinar;
12 }
13
14 //Convert from IQD to USD using the exchange rate in the parameter.
15 //Exchange rate is USD -> IQD.
16 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
17 {
18 if ((string)value == "") return 0.0;
19 double dinar = System.Convert.ToDouble(value);
20 double rate = System.Convert.ToDouble(parameter);
21 rate = 1 / rate; //Account for the reverse conversion.
22 double dollars = dinar * rate;
23 return dollars;
24 }
25}
26
Data Binding with Parameters:
This part is easy. The framework is simply the same stuff you have been doing. I'm not going to go through the basics on Data binding with a Value Converter, you can see my other post for help doing that. The only thing we need to do, is add a parameter to the Binding statement. That parameter is named 'ConverterParameter' (How fitting). The below code demonstrates. Note, that the parameter we pass is a static value, making this good only for USD <-> IQD, however, this value can be obtained from anywhere (databound from another text box, database, file, internet).
<TextBox x:Name="txtTo"
Text="{Binding ElementName=txtFrom,
Path=Text, ConverterParameter=1238.50,
Converter={StaticResource Converter}}" />
That's it! Its not that hard at all. Now, if you actually want to implement a currency converter, you would want to obtain rates from somewhere other than this hard coded value... But you see how it works. Pretty easy!
Posted by
Mike Christiansen
at
10:26 AM
0
comments
Labels: C#, Currency, Data Binding, DataBind, DataBinding, IValueConverter, Value Converter, ValueConverter, wpf, XAML
Friday, August 10, 2007
Data Binding with Value Converters
So, today at work, I was working with some data binding, and I wanted the user to be able to input an angle in degrees or radians, whichever they are comfortable with. I also wanted to display the value in both degrees or radians, regardless of which they choose to enter it in. I looked around on the internet, and I found lots of examples of how to use Value Converters, and lots of examples on how to do Data binding. But none that really showed what I wanted to do. So here's how I did it.
Theres four essential steps to making this work. They are:
1.) Write a converter class that implements IValueConverter
2.) Include the namespace into your XAML document.
3.) Data Bind the controls.
4.) Convert the value
Step 1: Write the Converter Class.
This part is pretty simple. The class itself should be self explanatory. Remember to use System.Windows.Data (IValueConverter)
The Convert Function is to convert from Degrees to Radians. As you can see, I take the value parameter, cast it to double (for maths!), perform my calculation, and return the new value. The if statement at the beginning is to fix a 'bug' where the program throws an exception if nothing is in the text box. This just returns 0.
The ConvertBack function is to convert from Radians, back to Degrees. The exact same thing, just doing the calculation in reverse.
1public class DegRads : IValueConverter
2{
3 //Converts from Degrees (double) to Radians (double)
4 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
5 {
6 if (((string)value) == "") return 0.0;
7 double degrees = System.Convert.ToDouble(value);
8 double radians = radians = degrees * (Math.PI / 180);
9 return radians;
10 }
11
12 //Convert back to Degrees (double) from Radians (double)
13 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
14 {
15 if (((string)value) == "") return 0.0;
16 double radians = System.Convert.ToDouble(value);
17 double degrees = degrees = radians * (180 / Math.PI);
18 return degrees;
19 }
20}
Step 2: Including the Namespace in the XAML
This part is really easy. In your Window tag, just declare the namespace as shown. Substitute your own namespace name in for ValueConverterDemo. Note, that the namespace name is the namespace that the converter class is in. Also note, the myns is an alias for that namespace, to refer to it in the rest of the XAML document.
I originally had some problems with this step, and it seems they all stemmed from me changing the name of the namespace. I guess VS2005's refactoring doesn't do XAML, and if you manually change it, it can cause some issues... I remade the project. Might be easier ways to fix this.
<Window x:Class="ValueConverterDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ValueConverterDemo" Height="78" Width="193"
xmlns:myns="clr-namespace:ValueConverterDemo"
>
Step 3: Data Bind
Again, this is really easy. What we want to do here, is set ElementName to the name of the control we're pulling data from, and set Path to the property that we're changing. Note, that we only need to data bind ONE of the text boxes. A side effect from that, is whenever I change the degrees, the radians change instantly. However, when I am changing the radians, I move focus away from the radians text box in order for the degrees text box to update. Now, I haven't don enough testing to see if we'd get some sort of cyclic error (stack overflow?) if we data bound both... Maybe WPF is smart enough to fix it?
<Grid>
<Label Grid.Row="0" Grid.Column="0">Degrees:</Label>
<TextBox Grid.Row="0" Grid.Column="1" x:Name="txtDegrees">0</TextBox>
<Label Grid.Row="1" Grid.Column="0">Radians:</Label>
<TextBox Grid.Row="1" Grid.Column="1" x:Name="txtRadians" Margin="0,0,0,1" Text="{Binding ElementName=txtDegrees, Path=Text, Converter={StaticResource DegRadsConverter}}" />
</Grid>
Step 4: Convert
Now, we have a type that will convert a value. We have a value. Sounds good, right? Wrong. The type itself cannot convert, we need an instance of that type. The XAML document knows about the type (it knows about the namespace from step 2, therefore it knows about its children). To create an instance, we need to go to a Resources section. I used Window.Resources in this case. Looking at the code below, you can see I used the namespace alias I created in step 2, and the name of the class. I also assigned a name to the object (key property). This is equivalent to the following: myns.DegRads DegRadsConverter;
<Grid.Resources>
<myns:DegRads x:Key="DegRadsConverter" />
</Grid.Resources>
Now that we have an instance in our Resources section, we need to actually convert. This is real easy. Just go to our Data bound control, and add the Converter property. Notice the StaticResource part. This tells the document to use the instance found in the resources section.
<TextBox Grid.Row="1" Grid.Column="1" x:Name="txtRadians" Margin="0,0,0,1"
Text="{Binding ElementName=txtDegrees, Path=Text,
Converter={StaticResource DegRadsConverter}}" />
That's it!
Data binding with calculations. There are tons of applications for this. Currency exchange, converting numbers to words, localization, etc. One thing I would like to learn more about in regards to IValueConverter, is there a way to use two inputs to make one output? Perhaps a universal currency converter, where I use information from two text boxes, Input Value, Exchange Rate, to generate an Output Value? Any ideas?
Posted by
Mike Christiansen
at
9:46 AM
4
comments
Labels: C#, DataBind, IValueConverter, ValueConverter, wpf, XAML
Code Blog Formatter

I've released a quick GUI version of the code formatter I mentioned in the first blog post on here. If you use Blogger, another blog that doesn't screw with your tags, or just regular HTML, this will generate the code you need to color all your code, and allow overflow.
It seems that IE6 doesn't allow for the overflow: auto; style, but IE7, Firefox, Opera, and the rest should all be fine with it. (IE6 will just do word wrap.)
Best thing about this, it's a small, stand-alone executable (60KB). This means no installation, and completely portable. However, it does require .NET 2.0.
Downloads:
- Executable
- Source Code
Edit: Changed the file hoster to Microsoft SkyDrive.
Versions:
V1.1 - Fixed issue with Ctrl+A in the HTML box, added a scroll bar. You can now toggle line numbers and region formatting on or off before converting.
V1.0 - Initial Version
Posted by
Guard
at
7:35 AM
2
comments
Wednesday, August 8, 2007
Switching Resource Dictionaries in Code
One of the nice features about WPF is how easily skin-able it makes your applications. You can store information about colors or control styles within a resource dictionary, and load these at the start of your program, or at runtime.
Here is an example of how to unload the resource dictionary you're currently using, and load a new one on the fly to change the look of your application:
1void Window4_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
2{
3 String source = null;
4
5 if (e.Key == System.Windows.Input.Key.F5)
6 {
7 source = "Dictionary1.xaml";
8 }
9 else if (e.Key == System.Windows.Input.Key.F6)
10 {
11 source = "Dictionary2.xaml";
12 }
13 else if (e.Key == System.Windows.Input.Key.F7)
14 {
15 source = "Dictionary3.xaml";
16 }
17
18 if (source != null)
19 {
20 ResourceDictionary dict = new ResourceDictionary();
21 dict.Source = new Uri(source, UriKind.Relative);
22
23 Application.Current.Resources.MergedDictionaries.Clear();
24 Application.Current.Resources.MergedDictionaries.Add(dict);
25 }
26}
Note that I've made the assumption here that you are loading your resources at the application level, and thus these changes will affect your entire application. If you wanted to effect it at a Window level, you can just as easily get the Resources of the Window and do the same exact thing.
In this example, the user can push F5-F7 and get a different look to their program. You may want to add something to check the selected dictionary against the chosen one, but here is my result of changing resource dictionaries in this way:


Posted by
Guard
at
10:46 AM
0
comments
Labels: resource dictionary, resources, skinning, wpf
Friday, August 3, 2007
Anonymous Functions and Invoking in WPF
At first, I had a little bit of trouble going from multi-threaded WinForms to WPF. The reason is that Invoke changed quite a bit between the two. Here's how to do Invoke in WPF:
First off, for those who don't know, invoke is required when you want to change something for a control or window that is on a different thread than your current one. For example, if you want to Close your window after a timer elapses, you need to send that command back to the Window's thread.
Here's the easy way to do Invoke in your Window, along with the code for the example I just gave:
1delegate void VoidDelegate();
2
3void invokeAndDoAnything()
4{
5 this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidDelegate(delegate()
6 {
7 //Do anything you want to the window in here!
8 }));
9}
10
11void timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
12{
13 ((System.Timers.Timer)sender).Stop();
14 //Close the window after this timer is done.
15 //We can just use the Window's close function in the
16 // VoidDelegate, because it happens to take no parameters
17 // and return void.
18 this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidDelegate(Close));
19}
Pretty simple overall, you just need to know the correct syntax to do it. This way you can do multi-threading without worrying about those annoying cross-threaded operation errors, and with anonymous functions, you don't need to clutter up your code for small operations.
Posted by
Guard
at
1:27 PM
1 comments
Thursday, August 2, 2007
WPF: Virtual Keyboard

Creating a virtual keyboard in WPF can be quite an obstacle. As far as I can tell, WPF does not directly support simulating keyboard strokes. As a result, you have two options:
- Import the SendInput function from a C++ DLL (User32.dll i believe it is)
- Manually write the output in the cases you want to.
The 2nd option isn't too bad to handle. This way also prevents you from having to handle each button separately, but I'm sure you could work around that in a way similar to what I've done here.
Basically, create your keyboard layout within it's own panel or grid, with each key being a button. Once you've done this, you can do a foreach loop on each button, where if it's a letter (usually the Button.Content.Length == 1), send it to one event handler, otherwise, send the button to a special event handler. Also, make sure every button is not focusable (Button.IsFocusable = false).
1foreach (Button b in KeyboardPanel.Children)
2{
3 b.Focusable = false;
4
5 if (b.Content.ToString().Length <= 1)
6 {
7 b.Click += new RoutedEventHandler(keyboardButton_Click);
8 }
9 else
10 {
11 b.Click += new RoutedEventHandler(keyboardButtonSpecial_Click);
12 }
13}
Once you've done this, the implementation is similiar to this:
662
663
664
665 void keyboardButtonSpecial_Click(object sender, RoutedEventArgs e)
666 {
669 switch (((Button)sender).Content.ToString())
670 {
671 case "Space":
672 if (System.Windows.Input.Keyboard.FocusedElement.GetType() == typeof(TextBox))
673 {
674 TextBox box = ((TextBox)System.Windows.Input.Keyboard.FocusedElement);
675 int newIndex = box.CaretIndex + 1;
676 box.Text = box.Text.Insert(box.CaretIndex, " ");
677 box.CaretIndex = newIndex;
678 }
679 break;
680 case "Shift":
681 if (isKeyboardUppercase())
682 setKeyboardUppercase(false);
683 else
684 setKeyboardUppercase(true);
685 break;
686 case "Tab":
687 ((UIElement)System.Windows.Input.Keyboard.FocusedElement).MoveFocus(new System.Windows.Input.TraversalRequest(System.Windows.Input.FocusNavigationDirection.Next));
688 break;
689
