<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"
>

<channel>
	<title>JMSoftware &#187; .net</title>
	<atom:link href="http://www.jmsoftware.co.uk/blog/category/programming/net-programming/feed" rel="self" type="application/rss+xml" />
	<link>http://www.jmsoftware.co.uk</link>
	<description>Software Development</description>
	<lastBuildDate>Sat, 19 Jun 2010 14:02:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
		<item>
		<title>Setting the order of properties in an ExpandableObjectConverter</title>
		<link>http://www.jmsoftware.co.uk/blog/setting-the-order-of-properties-in-an-expandableobjectconverter</link>
		<comments>http://www.jmsoftware.co.uk/blog/setting-the-order-of-properties-in-an-expandableobjectconverter#comments</comments>
		<pubDate>Sat, 19 Jun 2010 13:29:40 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ExpandableObjectConverter]]></category>
		<category><![CDATA[GetProperties]]></category>
		<category><![CDATA[PropertyDescriptorCollection]]></category>
		<category><![CDATA[sort]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/?p=217</guid>
		<description><![CDATA[When inheriting from an ExpandableObjectConverter to display custom properties in a PropertyGrid, you will often want to set the order of the properties instead of having them in alphabetical order. To do this you just need to override the GetProperties &#8230; <a href="http://www.jmsoftware.co.uk/blog/setting-the-order-of-properties-in-an-expandableobjectconverter">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When inheriting from an ExpandableObjectConverter to display custom properties in a PropertyGrid, you will often want to set the order of the properties instead of having them in alphabetical order.</p>
<p>To do this you just need to override the <em>GetProperties</em> method. Call the Sort function on the PropertyDescriptorCollection object returned by the base function, passing an array of strings with the property names in the order that you desire.</p>
<p>For example:</p>
<pre class="prettyprint"><code>public override PropertyDescriptorCollection
      GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
    return base.GetProperties(context, value, attributes)
                            .Sort(new string[] { "Name", "Street", "City", "Country" });
}</code></pre>
<p>Any properties not in the string array will be added on afterwards in alphabetical order.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/setting-the-order-of-properties-in-an-expandableobjectconverter/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>C# Snippet for Accessing Bitmap Data with Unsafe Code</title>
		<link>http://www.jmsoftware.co.uk/blog/c-snippet-for-accessing-bitmap-data-with-unsafe-code</link>
		<comments>http://www.jmsoftware.co.uk/blog/c-snippet-for-accessing-bitmap-data-with-unsafe-code#comments</comments>
		<pubDate>Mon, 30 Mar 2009 17:37:55 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[pixel]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[unsafe]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/?p=175</guid>
		<description><![CDATA[Since GetPixel is slow and I keep having to access bitmap data with unsafe code, I thought it would be a nice thing to make into a snippet. Paste the following code into a text file, and save it as &#8230; <a href="http://www.jmsoftware.co.uk/blog/c-snippet-for-accessing-bitmap-data-with-unsafe-code">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Since GetPixel is slow and I keep having to access bitmap data with unsafe code, I thought it would be a nice thing to make into a snippet.<span id="more-175"></span></p>
<p>Paste the following code into a text file, and save it as &#8220;usbmp.snippet&#8221;. In Visual Studio go to &#8220;Tools/Code Snippets Manager&#8230;&#8221; and import the file.</p>
<hr />
<pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;CodeSnippets
    xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&gt;
  &lt;CodeSnippet Format="1.0.0"&gt;
    &lt;Header&gt;
      &lt;Title&gt;Unsafe Bitmap Processing&lt;/Title&gt;
      &lt;Shortcut&gt;usbmp&lt;/Shortcut&gt;
      &lt;Description&gt;Code for accessing a bitmaps pixel data with unsafe code&lt;/Description&gt;
      &lt;Author&gt;Jonathan Mathews Software&lt;/Author&gt;
    &lt;/Header&gt;
    &lt;Snippet&gt;
      &lt;Declarations&gt;
        &lt;Object&gt;
          &lt;ID&gt;bitmap&lt;/ID&gt;
          &lt;Type&gt;System.Drawing.Bitmap&lt;/Type&gt;
          &lt;ToolTip&gt;Replace with a bitmap in your application.&lt;/ToolTip&gt;
          &lt;Default&gt;bitmap&lt;/Default&gt;
        &lt;/Object&gt;
      &lt;/Declarations&gt;
      &lt;Code Language="CSharp"&gt;
        &lt;![CDATA[unsafe
                {
                    BitmapData data = $bitmap$.LockBits(
                                                    new Rectangle(new Point(0, 0), $bitmap$.Size), 
                                                    ImageLockMode.ReadOnly, 
                                                    PixelFormat.Format24bppRgb);

                    byte* pointer = (byte*)data.Scan0;

                    int padding = data.Stride - ($bitmap$.Width * 3);

                    for (int y = 0; y &lt; $bitmap$.Height; y++)
                    {
                        for (int x = 0; x &lt; $bitmap$.Width; x++)
                        {
                            // pointer[2]; // R
                            // pointer[1]; // G
                            // pointer[0]; // B
                            $end$

                            pointer += 3;
                        }

                        pointer += padding;
                    }

                    $bitmap$.UnlockBits(data);
                }]]&gt;
      &lt;/Code&gt;
    &lt;/Snippet&gt;
  &lt;/CodeSnippet&gt;
&lt;/CodeSnippets&gt;</code></pre>
<hr />
<p>Notes:</p>
<ul>
<li>Use it by entering &#8220;usbmp&#8221; in your code, and pressing tab twice. Edit the bitmap name to your bitmap.</li>
<li>You&#8217;ll need to add <code>using System.Drawing.Imaging;</code> if it&#8217;s not there already.</li>
<li>If you want to edit the pixels instead of just reading them, change &#8220;ImageLockMode.ReadOnly&#8221;.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/c-snippet-for-accessing-bitmap-data-with-unsafe-code/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Image.Clone does not unlock the file</title>
		<link>http://www.jmsoftware.co.uk/blog/imageclone-does-not-unlock-the-file</link>
		<comments>http://www.jmsoftware.co.uk/blog/imageclone-does-not-unlock-the-file#comments</comments>
		<pubDate>Thu, 05 Feb 2009 15:12:12 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Clone]]></category>
		<category><![CDATA[delete]]></category>
		<category><![CDATA[Image]]></category>
		<category><![CDATA[lock]]></category>
		<category><![CDATA[unlock]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/?p=171</guid>
		<description><![CDATA[Turns out, copying an image using Clone really does make an exact copy. You can&#8217;t just open an image, clone it, then safely close it as you might expect, because it also copies the file lock. Instead, copy the image &#8230; <a href="http://www.jmsoftware.co.uk/blog/imageclone-does-not-unlock-the-file">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Turns out, copying an image using Clone really does make an exact copy. You can&#8217;t just open an image, clone it, then safely close it as you might expect, because it also copies the file lock.</p>
<p>Instead, copy the image in memory using <code>Image copy = new Image(source)</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/imageclone-does-not-unlock-the-file/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Automatically Fill a ComboBox with an Enum</title>
		<link>http://www.jmsoftware.co.uk/blog/automatically-fill-a-combobox-with-an-enum</link>
		<comments>http://www.jmsoftware.co.uk/blog/automatically-fill-a-combobox-with-an-enum#comments</comments>
		<pubDate>Mon, 26 Jan 2009 14:31:42 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ComboBox]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[enum]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/?p=161</guid>
		<description><![CDATA[This is a really nice little feature. If we have an enumerator, say: public enum MyEnumerator { Oranges, Apples, Hedgehogs, Laptops, Budgies, Other } Having a form with a ComboBox called comboBox1, put this in the constructor/form load etc: this.comboBox1.DataSource &#8230; <a href="http://www.jmsoftware.co.uk/blog/automatically-fill-a-combobox-with-an-enum">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is a really nice little feature.</p>
<p>If we have an enumerator, say:</p>
<p><code>public enum MyEnumerator { Oranges, Apples, Hedgehogs, Laptops, Budgies, Other }</code></p>
<p>Having a form with a ComboBox called comboBox1, put this in the constructor/form load etc:<br />
<code>this.comboBox1.DataSource = Enum.GetValues(typeof(MyEnumerator));</code></p>
<p>This fills the combobox with the values. To convert the current combobox value back into the enumerator&#8217;s value:<br />
<code>MyEnumerator selected = (MyEnumerator)this.comboBox1.SelectedValue;</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/automatically-fill-a-combobox-with-an-enum/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Things I can&#8217;t code without in Visual Studio</title>
		<link>http://www.jmsoftware.co.uk/blog/things-i-cant-code-without-in-visual-studio</link>
		<comments>http://www.jmsoftware.co.uk/blog/things-i-cant-code-without-in-visual-studio#comments</comments>
		<pubDate>Sun, 11 Jan 2009 11:53:22 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[fxcop]]></category>
		<category><![CDATA[ghostdoc]]></category>
		<category><![CDATA[regionerate]]></category>
		<category><![CDATA[stylecop]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/?p=130</guid>
		<description><![CDATA[Here&#8217;s a quick list of essential plug-ins and tools for Visual Studio. All of them are free, and this is mainly so the next time I reinstall windows I won&#8217;t spend ages trying to remember what that thing I use &#8230; <a href="http://www.jmsoftware.co.uk/blog/things-i-cant-code-without-in-visual-studio">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a quick list of essential plug-ins and tools for Visual Studio. All of them are free, and this is mainly so the next time I reinstall windows I won&#8217;t spend ages trying to remember what that thing I use was called.</p>
<p><strong>Microsoft StyleCop</strong>: <a href="http://code.msdn.microsoft.com/sourceanalysis">http://code.msdn.microsoft.com/sourceanalysis</a><br />
This is the source analysis tool from and used by Microsoft programmers, and helps to &#8220;enforce a common set of best practices for layout, readability, maintainability, and documentation of C# source code&#8221;. It can also be integrated it into the build process to help keep you honest.</p>
<p>Once you learn and get used to its strict rules, they are easy to live by (I&#8217;ve even grown used to using <em>this.variable</em> rather then <em>_Variable</em> ).</p>
<p><strong>GhostDoc</strong>: <a href="http://www.roland-weigelt.de/ghostdoc/">http://www.roland-weigelt.de/ghostdoc/</a><br />
With just a keypress this adds in XML comments for the current type, often magically filling in the values from base types, other comments, or who knows where. Saves a lot of time, and it&#8217;s perfect for all those StyleCop &#8220;must have a documentation header&#8221; warnings.</p>
<p><strong>Regionerate </strong><a href="http://www.rauchy.net/regionerate/">http://www.rauchy.net/regionerate/</a><br />
Great little plugin that automatically arranges your code based on layout rules. Produce neat and friendly code without any effort. Check out this post in their forum for a StyleCop layout: <a href="http://www.rauchy.net/regionerate/forums/viewtopic.php?f=4&#038;t=189">http://www.rauchy.net/regionerate/forums/viewtopic.php?f=4&#038;t=189</a>. The only issue is that it uses tabs instead of spaces, but you just have to remember to select all (Ctrl-A), then format it (Ctrl-K-F).</p>
<p><strong>Microsoft FxCop</strong>: <a href="http://code.msdn.microsoft.com/codeanalysis">http://code.msdn.microsoft.com/codeanalysis</a><br />
Microsoft code analysis tool. It looks at the compiled code and produces a list of possible problems based on Microsoft&#8217;s design guidelines.</p>
<p><strong>Proggy Fonts</strong>: <a href="http://www.proggyfonts.com/index.php?menu=download">http://www.proggyfonts.com/index.php?menu=download</a><br />
A collection of small, neat, and easy to read fonts. They&#8217;re all good, but I tend to stick with Proggy Square.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/things-i-cant-code-without-in-visual-studio/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>The DirectSound Capture Buffer</title>
		<link>http://www.jmsoftware.co.uk/blog/the-directsound-capture-buffer</link>
		<comments>http://www.jmsoftware.co.uk/blog/the-directsound-capture-buffer#comments</comments>
		<pubDate>Fri, 09 Jan 2009 16:58:23 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[DirectSound]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[buffer]]></category>
		<category><![CDATA[capture]]></category>
		<category><![CDATA[capturebuffer]]></category>
		<category><![CDATA[directx]]></category>
		<category><![CDATA[notify]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/?p=123</guid>
		<description><![CDATA[A CaptureBuffer is a buffer of a specified length that reads audio from a Capture object which represents the capture (or input) device, into a one-dimensional array of bytes with a specified WaveFormat. The capture buffer can be used in &#8230; <a href="http://www.jmsoftware.co.uk/blog/the-directsound-capture-buffer">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A <strong>CaptureBuffer</strong> is a buffer of a specified length that reads audio from a <strong>Capture</strong> object which represents the capture (or input) device, into a one-dimensional array of bytes with a specified <strong>WaveFormat</strong>.</p>
<p><span id="more-123"></span>The capture buffer can be used in two ways. As a <em>static buffer</em>, which stops when the buffer is full, or a <em>streaming buffer</em>, where once the buffer is full it returns to the start and begins overwriting the samples. You obviously need to read and do something with the data before this happens.</p>
<p>One method is to set up a <strong>Notify</strong> object, giving it an array of <strong>BufferPositionNotify</strong> objects. These contain the handle for an event, and the buffer offset at which to fire that event. This is usually an <strong>AutoResetEvent</strong>, monitored by a separate thread which then reads a section of the buffer, and processes that data. One problem is that they can be unreliable if another program is also using DirectSound notifications at the same time. You may start receiving those as well, or even have yours go missing.</p>
<p>The other option is to monitor it yourself, periodically checking the write position of the capture buffer through its <strong>GetCurrentPosition</strong> function. When you see that it has moved past a certain point (i.e. an offset position) you can then process that chunk of data as before.</p>
<p>To make a CaptureBuffer, first instantiate a new <strong>Capture</strong> object. Use no parameters or a <strong>Guid.Empty</strong> for the default device, or give it the Guid or an IntPtr to the device you want to use. The available devices can be discovered by creating a <strong>CaptureDevicesCollection</strong> object.</p>
<p>Then use this Capture object to a create a new <strong>CaptureBuffer</strong>, along with a WaveFormat, and the length of the buffer you want.</p>
<p>Reading the buffer is accomplished by simply calling the Read function with the start position, number of bytes to read, and a <strong>LockFlag</strong> to say if you want to prevent the data from being overwritten while you read it. Finally, cast the resultant <strong>Array</strong> to an array of bytes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/the-directsound-capture-buffer/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>An Explanation of Output Buffers in DirectSound</title>
		<link>http://www.jmsoftware.co.uk/blog/an-explanation-of-output-buffers-in-directsound</link>
		<comments>http://www.jmsoftware.co.uk/blog/an-explanation-of-output-buffers-in-directsound#comments</comments>
		<pubDate>Tue, 06 Jan 2009 02:07:57 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[DirectSound]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[buffer]]></category>
		<category><![CDATA[directx]]></category>
		<category><![CDATA[primary]]></category>
		<category><![CDATA[secondary]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/?p=65</guid>
		<description><![CDATA[A DirectSound Buffer is a one-dimensional array of bytes which represent sound waves in a digital form. The data is laid out in a specified Microsoft.DirectX.DirectSound.WaveFormat which specifies the format type, number of channels, number of samples per second and &#8230; <a href="http://www.jmsoftware.co.uk/blog/an-explanation-of-output-buffers-in-directsound">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A DirectSound Buffer is a one-dimensional array of bytes which represent sound waves in a digital form. The data is laid out in a specified <em>Microsoft.DirectX.DirectSound.WaveFormat</em> which specifies the format type, number of channels, number of samples per second and so on.<sup>1</sup></p>
<p>Each byte is a part of a <em>sample</em>, and a sample represents the average amplitude of the sound waves position at that point in time.<sup>2</sup></p>
<p>There are two types of buffers used for output: Primary and Secondary. These both send data to an output device, represented by a <em>Microsoft.DirectX.DirectSound.Device</em> object.<br />
<span id="more-65"></span><br />
<hr />
<p><b>Primary Buffer</b></p>
<p>There is only one Primary Buffer for a device, and the data it contains is exactly what will come out of that device.</p>
<p>Accessing and changing the primary buffer is possible, but usually unnecessary. It&#8217;s better to let DirectX handle the mixing, or you will have to take responsibility for outputting the buffer in real-time. You also lose the ability to use secondary buffers, and it prevents other applications from using buffers.</p>
<p>To access the primary buffer, create a <em>Microsoft.DirectX.DirectSound.Buffer</em> object using a DirectSound Device with its cooperative level set to <em>CooperativeLevel.WritePrimary</em>.</p>
<hr />
<p><b>Secondary Buffer</b></p>
<p>The secondary buffer is a buffer of a specified size, and contains sound data ready to be output. An application can have as many secondary buffers as it wants, within memory limits.</p>
<p>When you call a buffer&#8217;s Play function the content is mixed into the primary buffer and output by DirectX.</p>
<p>If called with the <em>BufferPlayFlags.Looping</em> flag set, it will play the buffer from start to finish over and over again until stopped. By continually writing new data into the buffer just ahead of the current play position it is possible to output audio that would not have fitted into memory, or that did not even exist when you started the buffer. This is known as <em>streaming</em>.</p>
<p>You can either use a <em>Microsoft.DirectX.DirectSound.Buffer</em>, or a <em>Microsoft.DirectX.DirectSound.SecondaryBuffer</em> which inherits the previous and adds support for effects such as distortion, compression, reverb, and more.</p>
<hr />
<ol class="footnotes"><li id="footnote_0_65" class="footnote">Only data which matches that format can be loaded into the an output buffer. Sound data with different formats can be played at the same time by using separate secondary buffers for each.</li><li id="footnote_1_65" class="footnote">Remember that sound is a waveform, and the buffer contains the actual wave data. Filling it with just one value will produce silence as the speaker cones will not move. To produce a tone programatically you need to fill the buffer with a waveform, such as a Sine Wave, a Square Wave, a Triangle Wave, or a Sawtooth Wave.</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/an-explanation-of-output-buffers-in-directsound/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>TextRenderer is slow, DrawString is wrong</title>
		<link>http://www.jmsoftware.co.uk/blog/textrenderer-is-slow-drawstring-is-wrong</link>
		<comments>http://www.jmsoftware.co.uk/blog/textrenderer-is-slow-drawstring-is-wrong#comments</comments>
		<pubDate>Thu, 30 Aug 2007 22:42:38 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[api_functions]]></category>
		<category><![CDATA[drawing]]></category>
		<category><![CDATA[DrawString]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[string_array]]></category>
		<category><![CDATA[TextRenderer]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/blog/textrenderer-is-slow-drawstring-is-wrong</guid>
		<description><![CDATA[After struggling with WinAPI code and hacks in .NET 1.0 I was really looking forward to the TextRenderer class when I first heard about it. But as it turns out, not only is TextRenderer horrible at measuring character size it &#8230; <a href="http://www.jmsoftware.co.uk/blog/textrenderer-is-slow-drawstring-is-wrong">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After struggling with WinAPI code and hacks in .NET 1.0 I was really looking forward to the <a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.textrenderer.aspx">TextRenderer</a> class when I first heard about it. But as it turns out, not only is TextRenderer horrible at measuring character size it is also monumentally slow at <em>rendering text</em>.<span id="more-18"></span></p>
<p>All I needed to do was to draw a series of characters onto an image, each one having a different Color value. Easy right? Straightforward code, plug it in to the Ascgen and&#8230; wait&#8230; we get the output required. After a quick profile of the application, it was clear that the problem was with the external function and there was nothing that could be done to speed things up to an acceptable level.</p>
<p>Before digging into api functions, I decided to look back to the older method of drawing strings: <a href="http://msdn2.microsoft.com/en-us/library/system.drawing.graphics.drawstring.aspx">Graphics.DrawString</a>.</p>
<p>The code is less straightforward, but, despite having to create a new SolidBrush object for every Color, it works quickly. An image that took around 10 seconds with TextRenderer takes milliseconds with DrawString. The only obvious problem was that DrawString shifted the text right a fraction, but a quick google leads to a solution: using StringFormat.GenericTypographic in the call.</p>
<p>Now, the next obvious step was to use DrawString to improve the speed of drawing text all in one Color, and that&#8217;s where it all goes wrong: DrawString adds extra space between characters, and there doesn&#8217;t seem to be a way to stop it.</p>
<p>Applying the same code as before and printing each character separately (after first having to split it into a string array) gives the text spaced correctly. However it&#8217;s actually marginally slower then calling TextRenderer once on the whole string, and far more complicated.</p>
<p>Ideally I&#8217;d like to put the two together, so I need to either find a way to speed up TextRenderer or a way to fix the spacing in DrawString.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/textrenderer-is-slow-drawstring-is-wrong/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Dragging and dropping onto a RichTextBox</title>
		<link>http://www.jmsoftware.co.uk/blog/dragging-and-dropping-onto-a-richtextbox</link>
		<comments>http://www.jmsoftware.co.uk/blog/dragging-and-dropping-onto-a-richtextbox#comments</comments>
		<pubDate>Tue, 24 Jul 2007 12:38:36 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[drag_drop]]></category>
		<category><![CDATA[drop_operations]]></category>
		<category><![CDATA[filenames]]></category>
		<category><![CDATA[intellisense]]></category>
		<category><![CDATA[net_framework]]></category>
		<category><![CDATA[Practical]]></category>
		<category><![CDATA[RichTextBox]]></category>
		<category><![CDATA[richtextbox_control]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/blog/dragging-and-dropping-onto-a-richtextbox</guid>
		<description><![CDATA[One of many flaws with the RichTextBox control is its lack of support for drag/drop operations. Luckily it&#8217;s simple to add. In fact, it&#8217;s so simple you&#8217;ll wonder why they didn&#8217;t just support it out of the box. Let&#8217;s assume &#8230; <a href="http://www.jmsoftware.co.uk/blog/dragging-and-dropping-onto-a-richtextbox">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of many flaws with the RichTextBox control is its lack of support for drag/drop operations. Luckily it&#8217;s simple to add. In fact, it&#8217;s so simple you&#8217;ll wonder why they didn&#8217;t just support it out of the box.<span id="more-16"></span></p>
<p>Let&#8217;s assume that you&#8217;ve created a form and added a RichTextBox called richTextBox1. Rather then going to the properties window to add the events, you&#8217;ll need to do it yourself.</p>
<p>Add the following in the constructor of the form:</p>
<pre><code>richTextBox1.AllowDrop = true;
richTextBox1.DragDrop += new DragEventHandler(richTextBox1_DragDrop);
richTextBox1.DragEnter += new DragEventHandler(richTextBox1_DragEnter);</code></pre>
<p>Type in the &#8220;+=&#8221; and press tab to automatically complete the line, then press tab again to create the function. Or just add the handler functions manually:</p>
<pre><code>public void richTextBox1_DragEnter(object sender, DragEventArgs e) {
	if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
		e.Effect = DragDropEffects.Copy;
	}
	else {
		e.Effect = DragDropEffects.None;
	}
}

public void richTextBox1_DragDrop(object sender, DragEventArgs e) {
	string[] filenames = (string[])e.Data.GetData(DataFormats.FileDrop);

	foreach (string filename in filenames) {
		// code to process a filename
	}
}</code></pre>
<p>You can also implement DragOver and DragLeave in the same way, although those are there to &#8220;support the .NET Framework infrastructure&#8221; and are &#8220;not intended to be used directly from your code&#8221;. Intellisense doesn&#8217;t even show those events, but you can type them in and compile without problems. Also note that DragLeave is an EventHandler rather then a DragEventHandler.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/dragging-and-dropping-onto-a-richtextbox/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Making sure a number is between 0 and 255</title>
		<link>http://www.jmsoftware.co.uk/blog/making-sure-a-number-is-between-0-and-255</link>
		<comments>http://www.jmsoftware.co.uk/blog/making-sure-a-number-is-between-0-and-255#comments</comments>
		<pubDate>Tue, 10 Jul 2007 13:21:47 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[between]]></category>
		<category><![CDATA[bitwise_operations]]></category>
		<category><![CDATA[byte]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[limit]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[max]]></category>
		<category><![CDATA[min]]></category>
		<category><![CDATA[number]]></category>
		<category><![CDATA[pixel]]></category>
		<category><![CDATA[Theory]]></category>

		<guid isPermaLink="false">http://www.jmsoftware.co.uk/blog/making-sure-a-number-is-between-0-and-255</guid>
		<description><![CDATA[Recently while reworking the code for the Ascgen dotNET I needed to make sure that a variable is between 0 and 255 before converting it to a byte, and I needed it to be as fast as possible since it &#8230; <a href="http://www.jmsoftware.co.uk/blog/making-sure-a-number-is-between-0-and-255">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently while reworking the code for the <a href="/software/ascgen">Ascgen dotNET</a> I needed to make sure that a variable is between 0 and 255 before converting it to a byte, and I needed it to be as fast as possible since it can get called several million times a second.<span id="more-9"></span></p>
<p>After realising that there really wasn&#8217;t a built in function like:</p>
<p><code>Result[x, y] = Math.Between(0, 255, pixel);</code></p>
<p>I initially used the minimum and maximum functions:</p>
<p><code>Result[x, y] = Math.Max(0, Math.Min(255, pixel));</code></p>
<p>This works, and is a pretty neat little piece of code. However, after profiling the application it quickly became obvious that it was slowing things down. A look at the compiled code shows that even when built for release, Min and Max are left as function calls instead of being inlined.</p>
<p>Looking into bitwise operations, we see that using a bitwise AND with 255 will trim the value to be between 0 and 255. Unfortunately it loops around, so that isn&#8217;t what we need:</p>
<pre>
  100101100   300
&#038; 011111111   255
= 000101100   044
</pre>
<p>The next option was to just check it manually:</p>
<pre><code>if (pixel &amp;gt; 255) {
	Result[x, y] = 255;
}
else if (pixel &amp;lt; 0) {
	Result[x, y] = 0;
}
else {
	Result[x, y] = (byte)pixel;
}</code></pre>
<p>Which is better, or:</p>
<pre><code>Result[x, y] = (byte)(pixel &gt; 255 ? 255 : (pixel &lt; 0 ? 0 : pixel));</code></pre>
<p>Which is silly and harder to maintain.</p>
<p>Either way a new problem is that most of the pixel values are between 0 and 255, therefore two checks will usually be required. Thanks to a great suggestion by biznatchio, we can instead do it in one comparison.</p>
<p>We saw earlier that &#8220;value &#038;= 255&#8243; will trim the value to be between 0 and 255. So, if we just compare the value to the trimmed value we will know if it is in range:</p>
<pre><code>if ((pixel &amp; 255) == pixel) {
	Result[x, y] = (byte)pixel;
}
else if (pixel &amp;gt; 255) {
	Result[x, y] = 255;
}
else {
	Result[x, y] = 0;
}</code></pre>
<p>This will be slower then before if the value is &lt;0 or &gt;255. As our values will be in range most of the time, this method is the best.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jmsoftware.co.uk/blog/making-sure-a-number-is-between-0-and-255/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license>
	</item>
	</channel>
</rss>
