<?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/"
	>

<channel>
	<title>steverands.com &#187; c#</title>
	<atom:link href="http://www.steverands.com/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.steverands.com</link>
	<description>Contain your excitement</description>
	<lastBuildDate>Tue, 08 Sep 2009 22:08:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using a custom WndProc in WPF apps</title>
		<link>http://www.steverands.com/2009/03/19/custom-wndproc-wpf-apps/</link>
		<comments>http://www.steverands.com/2009/03/19/custom-wndproc-wpf-apps/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 00:21:55 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[wpf]]></category>

		<guid isPermaLink="false">http://www.steverands.com/?p=128</guid>
		<description><![CDATA[A current project at work needs to be able to respond to USB &#8216;thumb&#8217; drives being inserted and removed. In Windows, such notifications are handled by processing the WM_DEVICECHANGE message. Using Windows Forms this is reasonably straightforward: the Form class has a protected WndProc method that can be overridden, like so:
protected override void WndProc(ref Message m)
{
    [...]]]></description>
			<content:encoded><![CDATA[<p>A current project at work needs to be able to respond to USB &#8216;thumb&#8217; drives being inserted and removed. In Windows, such notifications are handled by processing the <a href="http://msdn.microsoft.com/en-us/library/aa363480(VS.85).aspx" target="_blank"><code>WM_DEVICECHANGE</code></a> message. Using Windows Forms this is reasonably straightforward: the <code>Form</code> class has a protected <code>WndProc</code> method that can be overridden, like so:</p>
<pre class="brush: csharp; gutter: false">protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_DEVICECHANGE)
    {
        // Handle WM_DEVICECHANGE...
    }

    base.WndProc(ref m);
}</pre>
<p>Unfortunately the same technique cannot be used in WPF applications. The spiritual equivalent of the <code>Form</code> class in WPF is <code>Window</code>, which has no <code>WndProc</code> method to override. So what to do?</p>
<p><span id="more-128"></span>Turns out that there is a helper class in the <code>System.Windows.Interop</code> namespace called <code>HwndSource</code> that can be used to hook into the window procedure (amongst other things). From the <a href="http://msdn.microsoft.com/en-us/library/system.windows.interop.hwndsource.aspx" target="_blank">MSDN documentation</a>:</p>
<blockquote><p>The HwndSource class implements its own window procedure.  This window procedure is used to process important window messages, such as those related to layout, rendering, and input.  However, you can also hook the window procedure for your own use.  You can specify your own hook during construction by setting the HwndSourceParameters.HwndSourceHook property, or you can also use AddHook and RemoveHook to add and remove hooks after the window has been created.</p></blockquote>
<p>First we need a <code>HwndSource</code> instance, so that we can call its <code>AddHook</code> method. <code>HwndSource</code> is derived from <code>PresentationSource</code>; using the static <code>PresentationSource.FromVisual</code> method we can obtain a <code>PresentationSource</code> from a specified WPF <code>Window</code>, and cast it as follows:</p>
<pre class="brush: csharp; gutter: false">HwndSource source = PresentationSource.FromVisual(window) as HwndSource;
// &#039;window&#039; is a reference to a WPF Window instance</pre>
<p>Now we have a <code>HwndSource</code> instance, we can call its <code>AddHook</code> method. This takes a single parameter, a <code>HwndSourceHook</code> delegate, the signature for which is:</p>
<pre class="brush: csharp; gutter: false">public delegate IntPtr HwndSourceHook(
    IntPtr hwnd,
    int msg,
    IntPtr wParam,
    IntPtr lParam,
    ref bool handled)</pre>
<p>Putting this all together, we end-up with the following:</p>
<pre class="brush: csharp; gutter: false">using System;
using System.Windows;
using System.Windows.Interop;

namespace WpfApplication1
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
            source.AddHook(WndProc);
        }

        IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // Handle messages...

            return IntPtr.Zero;
        }
    }
}
</pre>
<p>Here we have a derived <code>Window</code> class called <em><code>Window1</code></em>. We&#8217;ve overridden the <code>OnSourceInitialized</code> method to create our <code>HWndSource</code> object and call its <code>AddHook</code> method (it&#8217;s not possible to do this in the constructor as the window&#8217;s handle has not been created at that point, hence there will be no <code>HwndSource</code>).</p>
<p>Our window procedure method is called <code>WndProc</code> (no points for originality), and matches the <code>HwndSourceHook</code> delegate signature, meaning that we can just pass that method name to <code>AddHook</code>.</p>
<p>At this point, we&#8217;ve implemented the WPF equivalent of overriding a <code>Form</code>&#8217;s <code>WndProc</code> method. All that&#8217;s left to do now is to handle the relevant Windows messages as per our application&#8217;s requirements. In a future post I&#8217;ll detail how to implement those USB drive notifications that were mentioned at the beginning of this article.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.steverands.com/2009/03/19/custom-wndproc-wpf-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
