I became intrigued by the problem of finding the color at any point of a rectangle that has been filled with a LinearGradientBrush. There is are techniques for doing this by essentially sampling the pixel at a rendered point but I wanted to approach the problem algorithmically.
I developed the following method which receives a rectangle object that has been filled with a LinearGradientBrush and a point relative to the upper left corner of the rectangle and returns the calculated color at that point. There are no restrictions on the Start/Stop Points or the number of GradientStops. The ColorInterpolationMode can be either SRgbLinearInterpolation (default) or ScRgbLinearInterpolation. The GradientSpreadMethod is required to be the default (Pad).
There are two methods below:
Color GetColorAtPoint(Rectangle r, Point p) – finds the color at any point of a LinearGradientBrush filled rectangle.
private Double dist(Point px, Point po, Point pf) – helper method for GetColorAtPoint.
To use, copy both methods to your class and call GetColorAtPoint() with a rectangle and point.
The method works by projecting the input point onto the vector that is described by the LinearGradientBrush Start/Stop points. There are special cases for horizontal and vertical lines. The width of the line is calculated as well as the relative distance of the projected point from the StartPoint (using the dist() method). The GradientStops are ordered and two stops are found that are the closest the projected point. The color channel values are interpolated based on the relative position of the projected point and these two stops. The values are assembled into a color and returned.
You can download a demo of this method here.
A common question on the MSDN C# Express forum is how do I generate reports? That is, how does one get a printout of data? The Standard and higher editions of Visual Studio have reporting services that allow reports to be easily designed in a WYSIWYG way. But Express users must either buy a third party application (à la Crystal Reports–about $300 USD) or programmatically create the report using C# and GDI+ Classes.
Now with Visual C# 2008 Express Edition, there is a new option. Windows Presentation Foundation (WPF) provides a set of classes for converting markup (XAML) to Microsoft’s XML Page Specification (XPS). XPS documents can then be printed directly from your application or saved an viewed and printed by other applications and platforms.
With this system, there are a couple of options: First, you can specify the report document directly in C# code much like you would using GDI+. That is, you could place a textBlock or graphic at a specific x,y coordinate on a page using the properties of these elements. The second option is almost as good as having a report designer like in the higher Visual Studio editions. You can use the designer in Visual Studio to layout your report in a WPF grid so you can see exactly how your report should look when it is rendered. Then it is a very simple matter to pass the name of this grid to XPS generating classes for printing or saving.
Printing and XPS in WPF are covered thoroughly in Chapter 15 of Sells & Griffiths, Programming WPF, O”Reilly.
The following example shows the routine for saving a grid1 (and all that it contains) to an XPS file.
This routine requires adding a couple of references to the solution: ReachFramework and System.Printing. You will need to also add some namespace references:
The code for printing directly is not much more complex and is described in the book.
With WPF one should be able to quickly and easily create a rich looking data report that can be printed or saved.
Visual C# Express 2008 does not come with a project template for creating custom controls (.dll files). You can create your own template by following these steps:
- 1. Open Visual C# Express 2008.
- 2. Create New WPF Application with name: MyLibrary
- 3. Project > Add User Control
- 4. In Solution Explorer, Delete Window1.xaml and App.xaml (the corresponding .cs files should be deleted by this step)
- 5. Project > MyLibrary Properties > Application > Output Type = Class Library
- 6. Build Solution. There should be no errors and the bin/Release folder should have a MyLibrary.dll file
- 7. File > Export Template
- 8. Select Project Template then Next
- 9. Under Template Options change name to: WPF Control Library and Description: Create WPF Control .dll
The next time you open VS, you will find your newly created template ready to use.
I needed a color picker for WPF and found a simple design by Lee Brimelow here.
I used a bitmap image of a pallet from the Windows Forms ColorPicker dialog.
The problem is that it is not a complete color picker. The missing variable is luminosity.
I found complete ColorPicker here.
The frustrating thing about the WPF Designer in VS2008 (a.k.a. “Cider”) is that it does not support drag and drop placement of items for every control. The first three that I encountered were menus, toolbars and laying out controls on a tab page. The IDE does have some capability to facilitate the design of these items that don’t require exclusive XAML coding. You just have to know the techniques to use them.
While you can add MenuItem to the toolbox, you can not drag it to the content portion of a Menu control in the designer. The easy way to create Menus is as follows:
1. Drag a Menu control from the toolbox onto the window.
2. Select the Menu control and find the Items property in the Property window. Click on the (…) icon. This will bring up the Collection Editor dialog.
3. Use it to add MenuItems. You can edit the properties of each item (like the Header property) as well as add sub-items by clicking on the Items property of the MenuItem. For the sub-items, you can also add a separator.
Items in a ToolBar can only be added with the XAML editor. Once added, you can edit and move them using the Collection Editor for the ToolBar.
You cannot layout controls directly on a TabItem for a TabControl. There are two tricks that are required: use a Grid panel and using the SelectedIndex to put each page in view for layout.
1. Drag a TabControl from the toolbox onto the window.
2. Using the Items propery in the Property window, add your TabItems and enter the Header properties for each one.
3. In the XAML editor, add a Grid to each TabItem like this:
4. Select the TabControl and locate the SelectedIndex property. Change the index to the page you want to layout.
5. Drag and drop items from the toolbox onto the Grid of the TabItem.
Apparently, .Net does not provide a good set of classes to create icons programmatically. In helping someone on a forum, I ran across a free tool for image processing that does a great job.
Here are the steps:
1. Download the FreeImage .dll from here.
2. Copy the .dll into the bin/Debug and/or bin/Release folder in your project
3. Add an Enum and FreeImage Class to your project (shown in the example below).
4. Use three calls to the functions in FreeImage: load the bitmap file, save in icon format, release the resource.
The following example loads a .bmp into FreeImage and saves it back as a .ico file. It includes the required Enum and FreeImage Class. (Requires using System.Runtime.InteropServices; )