<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Random thoughts</title><link>http://www.penov.org:80/</link><description>Random thoughts</description><item><title>Graffiti and Windows Live Writer</title><link>http://www.penov.org:80/graffiti-and-windows-live-writer</link><description>&lt;p&gt;I've been trying WLW on and off for some time now, but I've never actually got to use it regularly. I guess I just couldn't get into it given I wasn't blogging quite often. However, since I have a brand new blog :-), it just seems natural to give WLW another try.&lt;/p&gt;
&lt;p&gt;After couple of test posts, I noticed couple of small things, but nothing too annoying:&lt;/p&gt;
&lt;p&gt;- I am still not sure how WLW will work with Graffiti's hierarchical categories. I guess for now I'll just have to create new categories from Graffiti. Just in case.&amp;nbsp; &lt;br /&gt; - Trying to post the draft and edit online opens a new post in Graffiti, not the draft you just uploaded.&amp;nbsp; &lt;br /&gt; - WLW keywords get translated to Graffiti tags by changing the space to a dash.&lt;/p&gt;
&lt;p&gt;Overall, everything worked just fine, so I guess I'll be using WLW a bit more from now on. Now, anyone knows where can I find a WLW plugin for source code highlighting?&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 04:10:47 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/graffiti-and-windows-live-writer</guid></item><item><title>A new home and a new engine</title><link>http://www.penov.org:80/new-home</link><description>&lt;p&gt;Penov.org has a new home - &lt;a href="http://aws.amazon.com/ec2/" title="Amazon EC2"&gt;Amazon EC2&lt;/a&gt;, and is running on a new engine - &lt;a href="http://orchardproject.net/" title="Orchard CMS"&gt;Orchard CMS&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 04:06:45 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/new-home</guid></item><item><title>Get rid of the webpage stickers</title><link>http://www.penov.org:80/get-rid-of-the-webpage-stickers</link><description>&lt;p&gt;I was wondering lately why are web sties still adding the (X)HTML/CSS-valid buttons? These seem to be the equivalent of the PC stickers for the web pages - something that had its role back in the days, but is now nothing more than just a visual noise.&lt;/p&gt;
&lt;p&gt;Yes, validating your website for (X)HTML and CSS standards compliance is important, there's no arguing about that. It ensures your users will get the most consistent experience in various browsers. However, the validation results are actionable only for you, as the owner of the website; there's nothing your users can (or should) do if that validation fails.&lt;/p&gt;
&lt;p&gt;Besides, most of the people out on the web care not about how well your site validates. They care what their experience is and how relevant is the content you publish for them. Yes, a non-validating (X)HTML may affect their experience; however, even a site that adheres to the newest HTML5 drafts out there may still offer a horrific experience.&lt;/p&gt;
&lt;p&gt;Here's my call for action to all webmasters: As one of your users, I implore of you - get rid of the webpage stickers.&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 03:54:06 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/get-rid-of-the-webpage-stickers</guid></item><item><title>Different ways to use Live Sync</title><link>http://www.penov.org:80/different-ways-to-use-live-sync</link><description>&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:35373587-35b1-440f-9388-ce8c5125fed5" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a rel="tag" href="http://technorati.com/tags/cloud"&gt;cloud&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/live+sync"&gt;live sync&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;ve been using Live Sync for the almost four years, from before Microsoft bought Foldershare. It&amp;rsquo;s been slowly creeping into my everyday life more and more, until today I realized that I am so used to the personal cloud I&amp;rsquo;ve built with it that I can&amp;rsquo;t even remember what the life before it was. Well, almost :-)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve decided to enumerate here the things I am using Live Sync for. If you have other ideas, shout out to francip at Twitter.&lt;/p&gt;
&lt;h3&gt;1. Live Sync of documents&lt;/h3&gt;
&lt;p&gt;The first thing I use Live Sync for is the classic one - I am sharing the Documents folder. The interesting part is that I am sharing that folder between four computers running four different OSes (well, more like versions and SKUs) &amp;ndash; XP, Vista, Win7 x86 and Win7 x64. Since two of these computers are always on, it&amp;rsquo;s like having my documents up in the cloud. They are always there wherever I am.&lt;/p&gt;
&lt;p&gt;An interesting side effect of this is that my Visual Studio settings are consistent on all machines. NOTE: There is a drawback to this, however. Visual Studio keeps something tied to the machine in its settings file, so every time you open Visual Studio after you&amp;rsquo;ve used it another machine, it takes a bit to initialize this piece of data. A bit annoying, if you ask me. Also, keeping VS open on one machine and starting it on another will result in two separate settings files. From there on you lose the settings synchronization until you resolve the conflict. Not a big deal for me either.&lt;/p&gt;
&lt;p&gt;Another interesting side effect is that my Live Writer drafts are also synchronized. This allows me to work on any posts from any machine I am currently sitting on, before I publish it.&lt;/p&gt;
&lt;h3&gt;2. Live Sync for sharing&lt;/h3&gt;
&lt;p&gt;The second thing I use Live Sync for is for sharing pictures with my family back in Bulgaria. My mom and my brother both have Live Sync installed and syncing the same library. This creates a small cloud for the three of us. My mom loves it, as whenever there are new pictures of the grandkids, they instantly show on her computer. It did take some training to teach her to copy the pictures in a different folder, to avoid hitting the limit of number of files in a library. But it wasn&amp;rsquo;t hard and was totally worth it.&lt;/p&gt;
&lt;h3&gt;3. Live Sync and SVN&lt;/h3&gt;
&lt;p&gt;The third thing I use Live Sync has to do with a personal SVN repository where I keep some personal projects. I am doing two things with Live Sync:&lt;/p&gt;
&lt;p&gt;- repository replication - Syncing the repository over Live Sync gives me continuous backup. Of course, it&amp;rsquo;s not the same as a proper backup &amp;ndash; any problems with the repository would be replicated as well. However, it does protect me from hard drive failure and losing everything at once.&lt;/p&gt;
&lt;p&gt;- checkout replication &amp;ndash; I am also syncing the checkout folders for my projects. This means that any change I make on any of the computers is replicated automatically on any other, thus giving me a workplace in the cloud. It also allows me to update and/or commit from any of my machines.&lt;/p&gt;
&lt;h3&gt;4. Live Sync and OneNote&lt;/h3&gt;
&lt;p&gt;The fourth thing is replicating OneNote notebooks. I don&amp;rsquo;t have a separate library for this, I get it for free from syncing the Documents folder. However, I wanted to mention this separately, as it is really a marvel on its own. If you are OneNote user, I strongly recommend setting at least OneNote notebook replication. You get instant access to all your notes everywhere you are, even if OneNote is opened on any of the computer.&lt;/p&gt;
&lt;p&gt;NOTE: There is a drawback if you sync OneNote Mobile from the same device on two computers. Active Sync gets confused and creates separate section for each computer you sync your device on. I&amp;rsquo;ve solved this problem by syncing my phone on one machine only.&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 03:54:05 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/different-ways-to-use-live-sync</guid></item><item><title>Markets In Everything</title><link>http://www.penov.org:80/markets-in-everything</link><description>&lt;p&gt;One of my favorite economic blogs is &lt;a href="http://www.marginalrevolution.com/" target="_blank"&gt;Marginal Revolution&lt;/a&gt; written by Tyler Cowen and Alex Tabarrok. The whole blog is worth reading, but my favorite part of it is the series of Markets In Everything posts.&lt;/p&gt;  &lt;p&gt;Today I discovered the &lt;a href="http://marketsineverything.com/" target="_blank"&gt;Markets In Everything index page&lt;/a&gt; maintained by Michael Cleverly. This is really neat ideas, as you can go and read all the posts in the series dating from the very first one back in September 2003. It’s definitely worth it.&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 03:54:03 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/markets-in-everything</guid></item><item><title>Smart objects</title><link>http://www.penov.org:80/smart-objects</link><description>&lt;p&gt;I was watching yesterday the &lt;a target="_blank" href="http://bit.ly/8e38A"&gt;Microsoft Office Labs 2019 Vision&lt;/a&gt;. The common theme throughout both videos was the ubiquity of the smart objects. For an example, take a look at 2:20 in the second video, where the actor looks at a PDA-like object and then detaches the top half of it to get two separate devices that interact, one as a main display and one as a secondary display offering auxiliary function (in that particular case it looked like a location based service).&lt;/p&gt;
&lt;p&gt;This really reminded me of the &lt;a target="_blank" href="http://siftables.com/"&gt;Siftables&lt;/a&gt; scenario. Except that Siftables targets kids. Than again, in ten years the kids that play today with Siftables will be in their teen age and smart objects will be something they grew up with. (On a side note, after I posted this on Facebook, I got comments from couple of people my age that were skeptic about how useful and feasible that scenario is. Maybe it is not only a technology, but also an age problem&amp;hellip; :-))&lt;/p&gt;
&lt;p&gt;One interesting detail about the smart objects in that video (and I still don&amp;rsquo;t know if it is a side effect of the rendering or intentional effect) was the lack of border on al the smart objects in the video. All the different devices throughout the video were rendering the UI all the way to the edge. This allows for composition of two smart objects to form one whole bigger object visually. Something Siftables does not offer yet.&lt;/p&gt;
&lt;p&gt;It is also interesting to figure out the software platform these smart objects would run on. Granted, this is Microsoft vision, so the underlying assumption is that all of these devices run on some form of Windows. :-) Still, to enable such seamless integration, either all the objects have to run the same platform and be able to transform software agents between each other, or they all should be running smart software agents that talk the same protocol for negotiating the composite UI and data processing.&lt;/p&gt;
&lt;p&gt;Or maybe the actual processing is done by a big machine and the &amp;ldquo;smart&amp;rdquo; objects are just dumb terminals that render the UI and use short-range radio (Bluetooth or wi-fi) to connect. Even though I don&amp;rsquo;t like this scenario, that might be the practical approach.&lt;/p&gt;
&lt;p&gt;Anyway, it would be interesting to watch that space in the next few years.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d like to talk more about this, ping me on &lt;a target="_blank" href="http://twitter.com/francip"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 03:54:01 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/smart-objects</guid></item><item><title>Moving feeds</title><link>http://www.penov.org:80/moving-feeds</link><description>&lt;p&gt;Penov.org is using FeedBurner for its feeds. I am currently in process of migrating all feeds over to the Penov.org domain. Unfortunately, this happens at the same time as my hoster is migrating the site to different servers as well. Thus, the DNS entries will be somewhat flaky in the next few days. As a result, the new feeds might be unavailable.&lt;/p&gt;
&lt;p&gt;I will do my best to make the transition as smooth as possible. Let's hope everything works out properly.&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:59 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/moving-feeds</guid></item><item><title>Healthy Sleeping Habits, Happy Child</title><link>http://www.penov.org:80/healthy-sleeping-habits-happy-child</link><description>&lt;p&gt;(Full disclaimer: if you buy anything from Amazon through the links in this post, I get a kickback)&lt;/p&gt;
&lt;p&gt;One of the books that helped us tremendously is &lt;a href="http://www.amazon.com/gp/product/0345486455?ie=UTF8&amp;amp;tag=penovorg-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0345486455"&gt;Healthy Sleep Habits, Happy Child&lt;/a&gt;&lt;img style="border-right: medium none; border-top: medium none; margin: 0px; border-left: medium none; border-bottom: medium none" height="1" alt="" width="1" border="0" src="http://www.assoc-amazon.com/e/ir?t=penovorg-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0345486455" /&gt; by Marc Weissbluth. The book gives a lot of info and practical steps on how to ensure your baby has a healthy sleep and boy does that make her happy. :-) We've been trying to follow the book's advice for a while now and the results are really good. Our daughter is going to bed around 7:30pm - 8pm and is sleeping through the whole night with the occasional break aroun 2am for a quick snack, but not too often. Not only is she less cranky, getting more sleep definitely helps mom and dad's mood as well.&lt;/p&gt;
&lt;p&gt;If you have to buy only one baby book, buy this one. If you don't want to spend the money, check your local library or borrow it from a friend. But definitely find a copy and read it at least once.&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:57 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/healthy-sleeping-habits-happy-child</guid></item><item><title>New blog home</title><link>http://www.penov.org:80/new-blog-home</link><description>&lt;p&gt;After several years of occasional blogging on &lt;a target="_blank" href="http://blogs.msdn.com/francip"&gt;MSDN&lt;/a&gt; and &lt;a target="_blank" href="http://lapsusdigitae.spaces.live.com"&gt;Spaces&lt;/a&gt;, I decided it's about time for me to merge my professional and personal blogs under a new roof. Aside from increasing the chances that I'll post a bit more often now that I have to manage only one blog, hosting my own content gives me a lot more flexibility and control over the format and the structure of what I publish.&lt;/p&gt;
&lt;p&gt;Welcome to my new blog! :-)&lt;/p&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:55 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/new-blog-home</guid></item><item><title>Sky's the limit...</title><link>http://www.penov.org:80/sky-s-the-limit</link><description>&lt;P&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #365f91; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;...or rather, 5GB is the limit on SkyDrive. :-) Plus, it's now available in 38 markets.&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #365f91; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&amp;nbsp;Oh, and I should probably mention it's not a Beta anymore.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #365f91; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;For more details, head on the the &lt;A class="" title="SkyDrive team blog" href="http://skydriveteam.spaces.live.com/blog/cns!977F793E846B3C96!1697.entry" mce_href="http://skydriveteam.spaces.live.com/blog/cns!977F793E846B3C96!1697.entry"&gt;SkyDrive team blog&lt;/A&gt;.&lt;/SPAN&gt;&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:54 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/sky-s-the-limit</guid></item><item><title>IServiceProvider vs. IServiceProvider</title><link>http://www.penov.org:80/iserviceprovider-vs.-iserviceprovider</link><description>&lt;P&gt;I've been using the&amp;nbsp;COM &lt;A class="" title=IServiceProvider href="http://msdn.microsoft.com/en-us/library/aa770042(VS.85).aspx#wbc_svcprov" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/aa770042(VS.85).aspx#wbc_svcprov"&gt;IServiceProvider interface&lt;/A&gt; for a while now, mostly through extensions to the ATL's IServiceProviderImpl and BEGIN_SERVICE_MAP. Last week, I've been writing some managed code where I wanted to use the same pattern based on the &lt;A class="" title=System.IServiceProvider href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.aspx"&gt;System.IServiceProvider&lt;/A&gt; interface. Unfortunately, it turned out that it's not exactly the same interface.&lt;/P&gt;
&lt;P&gt;On the first glance, the two interfaces look sufficiently similar. Both interfaces have only one method - QueryService() (QS) in the unmanaged version and GetService() (GS) in the managed version (I do prefer the QS name), that takes a service identifier and returns an object that implements this service, the actual contract and behavior of the two method is quite different. QueryService() takes two in parameters - a service identifier (SID) and an interface identifier (IID), while GetService() takes only on parameter - Type.&lt;/P&gt;
&lt;P&gt;Since a SID is just a GUID, QS() offers the ability to have an implementation-agnostic service identification in the client code. The actual service implementation can be changed completely while the SID used to discover the service can stay the same. Moreover, this allows the service provider implementation to be the one that maps SIDs and services.&lt;/P&gt;
&lt;P&gt;The Type parameter in GS() on the other hand implies that the service discovery should be done based on the actual type of the implementation. This prevents services polimorphism, as any new implementation needs to be discovered through it's type, thus cannot replace previous implementation. It also requires more tight coupling between the IServiceProvider client and the services, as it forces the client to know the types that implement particular service. And at service implementation level, it makes it impossible to have aggregated services that consist of two or more objects that implement different facets, unless the service itself has a facet discovery mechanism. (Though, since a service is usually treated as a logical entity, it could be argued that the facet management is a function of the service itself, not the service provider)&lt;/P&gt;
&lt;P&gt;Of course, it is possible to have an&amp;nbsp;GS() implementation that treats the Type parameter as a random string identifier, thus mimicing the QS() behavior.&amp;nbsp;However, while it does solve the two big limitations of the managed IServiceProvider, I find this approach undesireable - intentionally violating an interface contract is guaranteed to cause problems down the road.&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:53 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/iserviceprovider-vs.-iserviceprovider</guid></item><item><title>IObjectWithBrowserSiteImpl - base template for IE BHO or toolbars</title><link>http://www.penov.org:80/iobjectwithbrowsersiteimpl---base-template-for-ie-bho-or-toolbars</link><description>&lt;P&gt;If you want to &lt;A class="" title="Building Browser Helper Objects with Visual Studio 2005" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/cols/dnexpie/expie_hello_bho.asp" target=_blank mce_href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/cols/dnexpie/expie_hello_bho.asp"&gt;extend IE with a browser helper object&lt;/A&gt; or a &lt;A class="" title="Creating Custom Explorer Bars, Tool Bands, and Desk Bands" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_adv/bands.asp" mce_href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_adv/bands.asp"&gt;toolbar&lt;/A&gt;, you need to implement IObjectWithSite interface. ATL has a basic IObjectWithSiteImpl&amp;lt;&amp;gt; template that helps a bit.&amp;nbsp;&amp;nbsp;Most BHOs and toolbars also subscribe to the browser events. ATL has a helper template for that as well - IDispEventImpl&amp;lt;&amp;gt;. Thus, pretty much any IE extension implemented with ATL inherits both templates. So, I've decided to implement a new template - IObjectWithBrowserSite&amp;lt;&amp;gt;, that besides storing the site pointer as IUnknown, also stores a pointer to IWebBrowser2 and subscribes to the browser events.&lt;/P&gt;
&lt;P&gt;The new template declaration looks like this:&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;template&lt;/FONT&gt;&lt;FONT size=2&gt; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; T, UINT nID&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; ATL_NO_VTABLE IObjectWithBrowserSiteImpl :&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; IObjectWithSiteImpl&amp;lt;T&amp;gt;,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; IDispEventImpl&amp;lt;nID, T, &amp;amp;DIID_DWebBrowserEvents2, &amp;amp;LIBID_SHDocVw, 1, 1&amp;gt;&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt;:&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // IObjectWithSite&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT size=2&gt;IFACEMETHOD(SetSite)(IUnknown *pUnkSite)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr = S_OK;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// Silently ignore any failure from CleanupSite&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;CleanupSite();&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// Store the IUnknown pointer to the new site&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;hr = IObjectWithSiteImpl&amp;lt;T&amp;gt;::SetSite(pUnkSite);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (SUCCEEDED(hr))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SetupSite();&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (FAILED(hr))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// Our setup logic failed; the real failure that caused&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// us to clean up here is more important, so propagate this one to the site&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// Silently ignore any failure from CleanupSite;&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;CleanupSite();&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; hr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// DWebBrowserEvents2&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;STDMETHOD(OnQuit)()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; DetachBrowserEvents();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt;:&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// Setup and cleanup on site change&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;STDMETHOD(SetupSite)()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr = S_OK;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (m_spUnkSite)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// We have a site; get the new browser pointer&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;m_pWebBrowser = m_spUnkSite;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (m_pWebBrowser == NULL)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = E_INVALIDARG;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// We have a site, but it's not a browser; get the new browser pointer from the site's IServiceProvider&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;CComQIPtr&amp;lt;IServiceProvider&amp;gt; pServiceProvider = m_spUnkSite;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (pServiceProvider != NULL)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pServiceProvider-&amp;gt;QueryService(SID_SInternetExplorer, IID_IWebBrowser2, (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt;**)&amp;amp;m_pWebBrowser);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (m_pWebBrowser != NULL)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// Attach to the new browser events&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;hr = AttachBrowserEvents();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; hr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; STDMETHOD(CleanupSite)()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (m_pWebBrowser != NULL)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// Detach from the current site events&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;HRESULT hr = DetachBrowserEvents();&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// IE7 disconnects our connection points _before_ calling us &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;with SetSite(NULL)&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// so DispUnadvise() returns CONNECT_E_NOCONNECTION (0x80040200)&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (hr == CONNECT_E_NOCONNECTION)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = S_OK;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// Release the pointer to the current hosting web browser&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;m_pWebBrowser.Release();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// We are done with the current site&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; IObjectWithSiteImpl&amp;lt;T&amp;gt;::SetSite(NULL);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// Browser event connection methods&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;STDMETHOD(AttachBrowserEvents)()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// ATL's event cookie is 0xFEFEFEFE, when the sink is not advised&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (m_dwEventCookie != 0xFEFEFEFE)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; S_OK;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; DispEventAdvise(m_pWebBrowser, &amp;amp;DIID_DWebBrowserEvents2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; STDMETHOD(DetachBrowserEvents)()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// ATL's event cookie is 0xFEFEFEFE, when the sink is not advised&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (m_dwEventCookie == 0xFEFEFEFE)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; S_OK;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; DispEventUnadvise(m_pWebBrowser, &amp;amp;DIID_DWebBrowserEvents2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// Hosting browser&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;CComQIPtr&amp;lt;IWebBrowser2&amp;gt; m_pWebBrowser;&lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;Here's how you would use that template as a base of your CBho class. The magic numebr 1 in the template instantiation below is the ID of the browser control, by which we will reference its events in the sink map. If your class subscribes to events from other objects, like ActiveX controls, you need to make sure the browser control ID is unique an d does not collide with another one.&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; CBho;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;#define&lt;/FONT&gt;&lt;FONT size=2&gt; IDC_BROWSER 1&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;typedef&lt;/FONT&gt;&lt;FONT size=2&gt; IObjectWithBrowserSiteImpl&amp;lt;CBho, IDC_BROWSER&amp;gt; CBhoBaseBrowserSiteImpl;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; ATL_NO_VTABLE CBho :&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; CComObjectRootEx&amp;lt;CComSingleThreadModel&amp;gt;,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; CComCoClass&amp;lt;CBho, &amp;amp;CLSID_Bho&amp;gt;,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; CBhoBaseBrowserSiteImpl&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;The typedef of CBhoBaseBrowserSiteImpl is not really necessary, but it does make the your code more readable when you need to call the methods of IObjectWithBrowserSiteImpl&amp;lt;&amp;gt;.&lt;/P&gt;
&lt;P&gt;There are couple more things you need to do to get this working. First, you need to add IObjectWithSite to your interface map, so IUnknown::QueryInterface() implementation will return proper pointer.&amp;nbsp;Second, you need to add sink map for your events. Unfortunately, ATL sink macros don't support chaining, so the whole DWebBrowserEvents2 sink map needs to be in your class. This means that while the IObjectWithBrowserSiteImpl&amp;lt;&amp;gt; template defines standard OnQuit() handler, it's not hooked by default to the DWebBrowserEvents2::OnQuit event. You need to do that yourself in order to get yourself detached from the browser events. (Note: Although IE7 will take care of that, your code should not rely on that and should behave well; plus you might be hosted in IE6 or another host)&amp;nbsp;There are two options - you can hook your own method and call OnQuit() explicitly, or you can hook OnQuit() and optionally override it (not forgetting to call the base implementation yourself :-)).&lt;/P&gt;
&lt;P&gt;Here are the bare minimum sink and interface maps you need to have. Note the magin number 1 in the &lt;/P&gt;&lt;FONT size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;BEGIN_SINK_MAP(CBho)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SINK_ENTRY_EX(IDC_BROWSER, DIID_DWebBrowserEvents2, DISPID_ONQUIT, OnQuit)&lt;BR&gt;END_SINK_MAP()&lt;/P&gt;
&lt;P&gt;BEGIN_COM_MAP(CBho)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; COM_INTERFACE_ENTRY(IObjectWithSite)&lt;BR&gt;END_COM_MAP()&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;You don't need to implement SetSite() itself; you can see that I've split it into two separate methods - SetupSite() and CleanupSite() which you can override.&amp;nbsp;Of course, you still have the choice to override the provided SetSite implementation and do whatever you need. I find this structure somewhat cleaner as the setup and the cleanup logic are strictly separated; plus, now on setup failure the code does automatic cleanup.&lt;/P&gt;
&lt;P&gt;If you implement an IE toolbar instead of a BHO, the pointer you get on SetSite() is not a pointer to the browser control. You can still use the above template as a base IObjectWithSite class, though. The SetupSite() implementation will take care of getting the browser pointer through the toolbar site's IServiceProvider interface.&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:52 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/iobjectwithbrowsersiteimpl---base-template-for-ie-bho-or-toolbars</guid></item><item><title>Yahoo! Mail Web Service - interesting business model</title><link>http://www.penov.org:80/yahoo-mail-web-service---interesting-business-model</link><description>&lt;P&gt;Dare&amp;nbsp;posted &lt;A class="" title="Some Thoughts on the Yahoo! Mail Web Service" href="http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=14a729f2-f534-4e62-91f5-9f0ebc848f4c" mce_href="http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=14a729f2-f534-4e62-91f5-9f0ebc848f4c"&gt;some thoughts&lt;/A&gt; on the limitations of the new &lt;A class="" title="Yahoo! Mail Web Service" href="http://developer.yahoo.com/mail/" mce_href="http://developer.yahoo.com/mail/"&gt;Yahoo! Mail Web Service&lt;/A&gt;. One thing he missed to mention though, is how that Web Service ties into Yahoo! Mail subscription model:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;"Yahoo! Mail offers an incentive for developers to build applications using the full functionality available for premium Yahoo! Mail accounts. Specifically, Yahoo! Mail provides a commission of $10.00 for every new Yahoo! Mail Plus account referred by developers."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;It would be interesting to see how many developers would see this as an incentive to build an application around the Yahoo! Mail Web Service. It would be even more interesting to see the conversion rates overall and per application.&lt;/P&gt;
&lt;P&gt;On more practical side, maybe I could find couple of hours this weekend and throw in together some WPF/WCF app to check my Yahoo! email. :-)&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:51 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/yahoo-mail-web-service---interesting-business-model</guid></item><item><title>Enablilng dragging in Canvas, v3.5 edition</title><link>http://www.penov.org:80/enablilng-dragging-in-canvas-v3.5-edition</link><description>&lt;P&gt;About a year ago I &lt;A class="" title="Enabling dragging inCanvas, Part 2" href="http://blogs.msdn.com/francip/archive/2007/02/28/enabling-dragging-in-canvas-part-2.aspx" mce_href="/francip/archive/2007/02/28/enabling-dragging-in-canvas-part-2.aspx"&gt;posted&lt;/A&gt; a class implemented couple of dependency properties you could attach to a Canvas and it's children and allowed dragging. The DPs were working quite well with any visual element inside the Canvas, including the standard controls like Button.&lt;/P&gt;
&lt;P&gt;Unfortunately, with .Net v3.5 the attached behavior was broken due to new behavior of some of the controls. For example, the Button control now supports three different OnClick behaviors - on hover, on press and on release. My DP code depends on the MouseLeftButtonDown event being fired; however, the new Button behavior was suppressing this event.&lt;/P&gt;
&lt;P&gt;Fortunately, the fix for this is quite easy. Instead of hooking the MouseLeftButtonDown, MouseLeftButtonUp and MouseMove events, I now hook the PreviewMouseLeftButtonDown, PreviewMouseLeftButtonUp and PreviewMouseMove events. This allows my code to enable dragging on Buttons, without modifying their behavior.&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:50 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/enablilng-dragging-in-canvas-v3.5-edition</guid></item><item><title>Enabling dragging in canvas</title><link>http://www.penov.org:80/enabling-dragging-in-canvas</link><description>&lt;P&gt;When developing UI, most of the time we want the controls nicely&amp;nbsp;sized, ordered and aligned automatically.&amp;nbsp;But sometimes it's just fun to put them free floating and be able to push them around. The Canvas panel allows for absolute positioning of the controls on it; however, there's nothing in WPF that would allow us to interact with the control position on it.&lt;/P&gt;
&lt;P&gt;Since the Canvas layout is using absolute positioning and we only want to allow changing of the position of, there is no need to implement new panel. We could implement the drag behavior and just attach it to the Canvas&amp;nbsp;using the&amp;nbsp;&lt;A class="" title="Ramora DP" href="http://blogs.msdn.com/bencon/archive/2006/07/26/679321.aspx" mce_href="/bencon/archive/2006/07/26/679321.aspx"&gt;Ramora DP&lt;/A&gt;&amp;nbsp;pattern. This can be done by creating a new class CanvasDragHelper, that will extend Canvas instances behavior.&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; CanvasDragHelper : DependencyObject&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected&lt;/FONT&gt;&lt;FONT size=2&gt; Canvas owner;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;We'll start by defining three dependency properties. We need one&amp;nbsp;DP to attach the helper object to the canvas, one to attach to the elements we want to support being dragged around and one that we will set on the Canvas in our XAML in order to enable the behavior:&lt;/P&gt;&lt;FONT size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; Property used to cache the drag helper instance. It also removes the necessity of additional storage&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; to hold the drag helper instances&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;readonly&lt;/FONT&gt;&lt;FONT size=2&gt; DependencyPropertyKey CanvasDragHelperPropertyKey = DependencyProperty.RegisterAttachedReadOnly(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;"CanvasDragHelper"&lt;/FONT&gt;&lt;FONT size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(CanvasDragHelper), &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(CanvasDragHelper), &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; FrameworkPropertyMetadata(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;));&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;readonly&lt;/FONT&gt;&lt;FONT size=2&gt; DependencyProperty CanvasDragHelperProperty = CanvasDragHelperPropertyKey.DependencyProperty;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; CanvasDragHelper GetCanvasDragHelper(DependencyObject obj)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/FONT&gt;&lt;FONT size=2&gt; (CanvasDragHelper)obj.GetValue(CanvasDragHelperProperty);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; SetCanvasDragHelper(DependencyObject obj, CanvasDragHelper value)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; obj.SetValue(CanvasDragHelperPropertyKey, value);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; This is property that specifies if a framework element is draggable&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;readonly&lt;/FONT&gt;&lt;FONT size=2&gt; DependencyProperty IsDraggableProperty = DependencyProperty.RegisterAttached(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;"IsDraggable"&lt;/FONT&gt;&lt;FONT size=2&gt;,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt;), &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(CanvasDragHelper), &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; FrameworkPropertyMetadata(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;));&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt; GetIsDraggable(DependencyObject obj)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt;)obj.GetValue(IsDraggableProperty);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; SetIsDraggable(DependencyObject obj, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt; value)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; obj.SetValue(IsDraggableProperty, value);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; This is the main property that activates the drag helper. Set this property to true on the canvas to enable the behavior.&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;readonly&lt;/FONT&gt;&lt;FONT size=2&gt; DependencyProperty AllowChildrenDragProperty = DependencyProperty.RegisterAttached(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;"AllowChildrenDrag"&lt;/FONT&gt;&lt;FONT size=2&gt;,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt;), &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(CanvasDragHelper), &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; FrameworkPropertyMetadata(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;, OnAllowChildrenDragChanged));&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt; GetAllowChildrenDrag(DependencyObject obj)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt;)obj.GetValue(AllowChildrenDragProperty);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; SetAllowChildrenDrag(DependencyObject obj, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt; value)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; obj.SetValue(AllowChildrenDragProperty, value);&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The first two DP are really straightforward - they only hold data in them. The third DP on the other hand has some logic. In it's Changed event handler we need to create the CanvasDragHelper instance and attach it to the Canvas.&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; Handler for when AllowChildrenDrag changes.&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; If AllowChildrenDrag is set to true, attach a CanvasDragHelper instance&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; (if there's one already, don't do anything)&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;param name="target"&amp;gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;CanvasDragHelper target. Must be Canvas.&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/param&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;param name="e"&amp;gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;Event args&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/param&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; OnAllowChildrenDragChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Canvas element = target &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; Canvas;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Debug.Assert(element != &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;"Can only use CanvasDragHelper with a Canvas"&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Is there a drag helper instance attached?&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT size=2&gt;CanvasDragHelper dragHelper = (CanvasDragHelper)GetCanvasDragHelper(element);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/FONT&gt;&lt;FONT size=2&gt; ((&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt;)e.NewValue == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (dragHelper != &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000 size=2&gt;// Yes, let's detach it from the canvas events&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;dragHelper.Detach();&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// ...and remove the instance from the canvas&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;SetCanvasDragHelper(element, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/FONT&gt;&lt;FONT size=2&gt; (dragHelper != &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;)&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;{&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// Yes, we already have a helper attached, so do noting&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// No, create new drag helper instance and attach it to the canvas events&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;dragHelper = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; CanvasDragHelper(element);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// ...and attach the instance to the canvas&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;SetCanvasDragHelper(element, dragHelper);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;The handler logic creates a new instance and passes the Canvas element to it's constructor. In the constructor we'll subscribe to the Canvas events we are interested. We also need a method to detach from them, if the AllowChildrenDrag property on the Canvas is set to false. And to make GC's life easier, we will actually set that property to false on the Canvas' OnUnloaded event. :-)&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; CanvasDragHelper(Canvas owner)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner = owner;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Attach();&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; Attach()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.AddHandler(Thumb.DragStartedEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; DragStartedEventHandler(OnDragStarted));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.AddHandler(Thumb.DragDeltaEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; DragDeltaEventHandler(OnDragDelta));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.AddHandler(Thumb.DragCompletedEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; DragCompletedEventHandler(OnDragCompleted));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.AddHandler(Canvas.MouseLeftButtonDownEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; MouseButtonEventHandler(OnMouseLeftButtonDown));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.AddHandler(Canvas.MouseLeftButtonUpEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; MouseButtonEventHandler(OnMouseLeftButtonUp));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.AddHandler(Canvas.MouseMoveEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; MouseEventHandler(OnMouseMove));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.AddHandler(FrameworkElement.UnloadedEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; RoutedEventHandler(OnUnloaded));&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; Detach()&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.RemoveHandler(Thumb.DragStartedEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; DragStartedEventHandler(OnDragStarted));&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.RemoveHandler(Thumb.DragDeltaEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; DragDeltaEventHandler(OnDragDelta));&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.RemoveHandler(Thumb.DragCompletedEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; DragCompletedEventHandler(OnDragCompleted));&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.RemoveHandler(Canvas.MouseLeftButtonDownEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; MouseButtonEventHandler(OnMouseLeftButtonDown));&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.RemoveHandler(Canvas.MouseLeftButtonUpEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; MouseButtonEventHandler(OnMouseLeftButtonUp));&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.RemoveHandler(Canvas.MouseMoveEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; MouseEventHandler(OnMouseMove));&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.RemoveHandler(FrameworkElement.UnloadedEvent, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; RoutedEventHandler(OnUnloaded));&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; OnUnloaded(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, RoutedEventArgs e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetAllowChildrenDrag(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;Now the only thing left is the actual dragging logic, which as you can guess from the above code will be done on the mouse LeftButton and Move events. That code will come in the next post.&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:47 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/enabling-dragging-in-canvas</guid></item><item><title>Incoming posts</title><link>http://www.penov.org:80/incoming-posts</link><description>&lt;P&gt;Here's short list of topics I am planning to write about in the next month after I finsh the CanvasDragHelper (and if I can find the time). I am going to use this post as a simple survey to see what people would like to see first. Of course, I might not get to some of these.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;1. (COM/CLR/WPF) Scriptable WPF application - a sample WPF aplication that exposes automation objects and runs as a local COM server.&lt;BR&gt;2. (COM/IE) IObjectWithBrowserSiteAndDispEventImpl - an&amp;nbsp;ATL-like template that implements IObjectWithSite (by using IObjectWithSiteImpl), queries the site for IWebBrowser and subscribes to DWebBrowserEvents2. Can be used as a base class for IE BHOs and Toolbars.&lt;BR&gt;3. (WPF) Pile panel - a Canvas based panel that add rotation property to it's children.&lt;BR&gt;4. (WPF) Adding Adorners using a simple Ramora DP.&lt;BR&gt;5. (WPF) Sample WPF app that draws in the non-client area. Well, it doesn't actualy draw in the NC area, but it simulates it quite well even under Vista (with all the DWM goodies)&lt;BR&gt;6. (COM) ATL CAxWindow, WM_CREATE and CoInitialize/CoUnitialize balancing issue.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;If you are interested in any of these topic, post&amp;nbsp;a comment. (And yes, I'll be using this post also as a rude form of feedback on how many people still read me after nearly two years of silence)&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:46 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/incoming-posts</guid></item><item><title>Enabling dragging in Canvas, part 2</title><link>http://www.penov.org:80/enabling-dragging-in-canvas-part-2</link><description>&lt;P&gt;&lt;STRONG&gt;Update:&lt;/STRONG&gt; There were some bugs in the code, which caused funny behavior with elements that have a&amp;nbsp;render transform&amp;nbsp;applied to them. I've updated the code below to fix these.&lt;/P&gt;
&lt;P&gt;In &lt;A class="" title="Enabling dragging in Canvas" href="http://blogs.msdn.com/francip/archive/2007/02/22/Enabling-dragging-in-canvas.aspx" mce_href="/francip/archive/2007/02/22/Enabling-dragging-in-canvas.aspx"&gt;part 1&lt;/A&gt; we covered how the dragging behavior will be attached to the Canvas object. Let's take a look now at the actual dragging code.&lt;/P&gt;
&lt;P&gt;Before we get to the actual code, we'll need some data members to keep some state between the events. These are mostly self explanatory, with the exception of _canvasLeft and _canvasTop. We'll use these to keep the original position of the element that we drag around in case we cancel the drag.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Canvas&lt;/FONT&gt;&lt;FONT size=2&gt; owner;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Point&lt;/FONT&gt;&lt;FONT size=2&gt; _lastLeftDown;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;double&lt;/FONT&gt;&lt;FONT size=2&gt; _canvasLeft;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;double&lt;/FONT&gt;&lt;FONT size=2&gt; _canvasTop;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt; _isDragging = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;The code that support the dragging is split into two groups - first is the logic that determines that we are dragging something and how far away and the second is how we apply this to the actual Canvas children. Let's first look into how we determine we&amp;nbsp;are dragging someting. We start on mouse left button down event. We check that the element generating the event belongs to the Canvas and that it has the IsDraggable property set on it. Then we save the original position of the element and capture the mouse. There's an additional check that this lbutton event is not a double click event.&lt;/P&gt;&lt;FONT size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; OnMouseLeftButtonDown(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;MouseButtonEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt; dragElement = e.Source &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/FONT&gt;&lt;FONT size=2&gt; ((dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;) || (dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (!GetIsDraggable(dragElement))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// Track mouse click position for offsetting the drag element position&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;_lastLeftDown = e.GetPosition(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner);&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; ((e.ClickCount == 1) &amp;amp;&amp;amp; (!_isDragging))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000 size=2&gt;// Capture mouse only on the left button down for a single click&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// We want to avoid dragging on double click&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;dragElement.CaptureMouse();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;else&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// Cancel any pending drag&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;StopDragging(dragElement, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Mouse&lt;/FONT&gt;&lt;FONT size=2&gt;.GetPosition(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner), &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;Obviously, on mouse left button up we need to stop dragging as well.&lt;/P&gt;&lt;FONT size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; OnMouseLeftButtonUp(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;MouseButtonEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt; dragElement = e.Source &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#2b91af&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; ((dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;) || (dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner))&lt;BR&gt;&lt;FONT color=#2b91af&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#2b91af&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;StopDragging(dragElement, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Mouse&lt;/FONT&gt;&lt;FONT size=2&gt;.GetPosition(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner), &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;The actual stop logic is also very simple. All it does is release the mouse capture and raise the DragCompletedEvent with the point to which we've dragged the element and whether the drag was canceled.&lt;/P&gt;&lt;FONT size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; Stop dragging, raise the drag completed event is necessary and release the mouse capture&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;param name="point"&amp;gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;Device coodinates for the drag completed event&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/param&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;///&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;param name="canceled"&amp;gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;True if drag was canceled&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;/param&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; StopDragging(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt; dragElement, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Point&lt;/FONT&gt;&lt;FONT size=2&gt; point, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt; canceled)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _isDragging = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Mouse&lt;/FONT&gt;&lt;FONT size=2&gt;.Captured == dragElement)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// We still have the mouse capture, release it&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;dragElement.ReleaseMouseCapture();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;// Signal end dragging&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;dragElement.RaiseEvent(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;DragCompletedEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt;(point.X - _lastLeftDown.X, point.Y - _lastLeftDown.Y, canceled));&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;Most of the actual drag logic is in the mouse move event. In this code we determnie two things - have we actually started a drag and how far have we dragged, if so. The first one is determined by checking if the mouse has moved more than an arbitrary number of pixels in any direction (and obviously you can tweak how precise that logic is) and if so, we actually flag a drag start and raise the DragStart event on the drag element. The second is based on whether we have detected a drag start already and whether it's still the same element that initially was dragged (to deal with the mouse moving outside of the Canvas or the window and other odd situations) and raising the DragDelta event on the drag element.&lt;/P&gt;&lt;FONT size=2&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; OnMouseMove(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;MouseEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt; dragElement = e.Source &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; ((dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;) || (dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;Point&lt;/FONT&gt;&lt;FONT size=2&gt; point = &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Mouse&lt;/FONT&gt;&lt;FONT size=2&gt;.GetPosition(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (_isDragging &amp;amp;&amp;amp; ((&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Mouse&lt;/FONT&gt;&lt;FONT size=2&gt;.Captured != dragElement) || (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Mouse&lt;/FONT&gt;&lt;FONT size=2&gt;.LeftButton != &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;MouseButtonState&lt;/FONT&gt;&lt;FONT size=2&gt;.Pressed)))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StopDragging(dragElement, point, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;else&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (!_isDragging &amp;amp;&amp;amp; (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Mouse&lt;/FONT&gt;&lt;FONT size=2&gt;.Captured == dragElement))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (!AreReallyClose(point, _lastLeftDown&lt;/FONT&gt;&lt;FONT size=2&gt;))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// we are now officially dragging, raise drag start&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;_isDragging = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dragElement.RaiseEvent(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;DragStartedEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt;(point.X - _lastLeftDown.X, point.Y - _lastLeftDown.Y));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT size=2&gt;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (_isDragging)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;// Raise the drag delta&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;dragElement.RaiseEvent(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;DragDeltaEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt;(point.X - _lastLeftDown.X, point.Y - _lastLeftDown.Y));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;static&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;bool&lt;/FONT&gt;&lt;FONT size=2&gt; AreReallyClose(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Point&lt;/FONT&gt;&lt;FONT size=2&gt; p1, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Point&lt;/FONT&gt;&lt;FONT size=2&gt; p2)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Math&lt;/FONT&gt;&lt;FONT size=2&gt;.Abs(p1.X - p2.X) &amp;lt; .001 &amp;amp;&amp;amp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Math&lt;/FONT&gt;&lt;FONT size=2&gt;.Abs(p1.Y - p2.Y) &amp;lt; .001);&lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;Now comes the second part of the drag logic. We have the drag events raised on the canvas child we are dragging. This enables us to let the element deal with the fact that it's being dragged around before the canvas gets those events. If the element does not do anything, the events are bubbled up. A normal Canvas panel doesn't handle these events, normally they would bubble up to the canvas parent. However, our drag helper has attached itself to the events on the canvas and can update the dragged element position. This approach gives us the flexibility to later one attach the helper to a more advanced Canvas descendant that knows how to deal with drag events and can choose to react to them or let them go to our handler.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; OnDragStarted(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;DragStartedEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt; dragElement = e.Source &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; ((dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;) || (dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _canvasLeft = &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Canvas&lt;/FONT&gt;&lt;FONT size=2&gt;.GetLeft(dragElement);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Double&lt;/FONT&gt;&lt;FONT size=2&gt;.IsNaN(_canvasLeft))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _canvasLeft = 0.0;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _canvasTop = &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Canvas&lt;/FONT&gt;&lt;FONT size=2&gt;.GetTop(dragElement);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Double&lt;/FONT&gt;&lt;FONT size=2&gt;.IsNaN(_canvasTop))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _canvasTop = 0.0;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; e.Handled = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; OnDragDelta(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;DragDeltaEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt; dragElement = e.Source &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; ((dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;) || (dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#2b91af size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Canvas&lt;/FONT&gt;&lt;FONT size=2&gt;.SetLeft(dragElement, _canvasLeft + e.HorizontalChange);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Canvas&lt;/FONT&gt;&lt;FONT size=2&gt;.SetTop(dragElement, _canvasTop + e.VerticalChange);&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.UpdateLayout();&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; e.Handled = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; OnDragCompleted(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;object&lt;/FONT&gt;&lt;FONT size=2&gt; sender, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;DragCompletedEventArgs&lt;/FONT&gt;&lt;FONT size=2&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt; dragElement = e.Source &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;FrameworkElement&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; ((dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;) || (dragElement == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (e.Canceled)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Canvas&lt;/FONT&gt;&lt;FONT size=2&gt;.SetLeft(dragElement, _canvasLeft);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;Canvas&lt;/FONT&gt;&lt;FONT size=2&gt;.SetTop(dragElement, _canvasTop);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.owner.UpdateLayout();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; e.Handled = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;Of course, there are some improvements that could be done here, like handling keyboard modifiers to the dragging or constraining the drag position of the element in the visible portion of the Canvas. However, these can be easily added to the existing logic.&lt;/P&gt;
&lt;P&gt;I've attached the full class code to this post, so you don't have to assemble it yourself from the pieces in the two posts.&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:45 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/enabling-dragging-in-canvas-part-2</guid></item><item><title>ASP.NET Ajax 1.0 RTW</title><link>http://www.penov.org:80/asp.net-ajax-1.0-rtw</link><description>ASP.NET Ajax 1.0 (formerly "Atlas") has been released to the web. You can read more about the framework and the control toolkit at &lt;A href="http://ajax.asp.net/"&gt;http://ajax.asp.net&lt;/A&gt; (including some really nice viedeo demos), or grab the bits from &lt;A class="" title="ASP.NET Ajax 1.0" href="http://www.microsoft.com/downloads/thankyou.aspx?familyId=ca9d90fa-e8c9-42e3-aa19-08e2c027f5d6&amp;amp;displayLang=en" mce_href="http://www.microsoft.com/downloads/thankyou.aspx?familyId=ca9d90fa-e8c9-42e3-aa19-08e2c027f5d6&amp;amp;displayLang=en"&gt;here&lt;/A&gt; and the toolkit from &lt;A class="" title="ASP.NET Ajax Control Toolkit" href="http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=AtlasControlToolkit" mce_href="http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=AtlasControlToolkit"&gt;here&lt;/A&gt;.</description><pubDate>Sat, 06 Aug 2011 03:53:44 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/asp.net-ajax-1.0-rtw</guid></item><item><title>Windows Live Toolbar build 130</title><link>http://www.penov.org:80/windows-live-toolbar-build-130</link><description>&lt;P&gt;We just released the latest build of Windows Live Toolbar. There are no new features in this release, it's fucosed mostly on stability and performance improvements. If you use the toolbar, I'd suggest you upgrade. And if you're not using WLT, well, be a chap and give it a test drive, would you? :-)&lt;/P&gt;
&lt;P&gt;You can grab the bits from the &lt;A class="" title="Windows Live Toolbar" href="http://toolbar.live.com/" target=_blank mce_href="http://toolbar.live.com"&gt;WLT web page&lt;/A&gt;. After the install, you should be running version 03.01.0000.0130. You can check your toolbar version on the General page of the Settings dialog.&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:42 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/windows-live-toolbar-build-130</guid></item><item><title>Goodbye, Indigo! Hello, Max!</title><link>http://www.penov.org:80/goodbye-indigo-hello-max</link><description>&lt;P&gt;The three years I worked on WCF were a fun ride, but it's time for me to move on to other challenges. Starting tomorrow I am leaving the Indigo team and moving on to the &lt;A href="http://www.microsoft.com/max"&gt;Max&lt;/A&gt; team as a dev.&lt;/P&gt;</description><pubDate>Sat, 06 Aug 2011 03:53:41 GMT</pubDate><guid isPermaLink="true">http://www.penov.org:80/goodbye-indigo-hello-max</guid></item></channel></rss>
