Random thoughts

  • Some thoughts on Windows RT

    After close to three years of laptop free, iPad-driven couch experience at home, I was recently put into the position to look for a new machine that can be used by my wife both at home and in her practice. And since my wife is used to Windows, and wants something she can run some dental software, and wants a keyboard, and doesn't want to spend too much money... Continue reading...

  • Get rid of the webpage stickers

    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. Continue reading...

  • Smart objects

    I was watching yesterday the Microsoft Office Labs 2019 Vision. 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). Continue reading...

  • Markets In Everything

    One of my favorite economic blogs is Marginal Revolution 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. Continue reading...

  • Different ways to use Live Sync

    I’ve been using Live Sync for the almost four years, from before Microsoft bought Foldershare. It’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’ve built with it that I can’t even remember what the life before it was. Well, almost :-) Continue reading...

  • Moving feeds

    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. Continue reading...

  • Graffiti and Windows Live Writer

    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. Continue reading...

  • New blog home

    After several years of occasional blogging on MSDN and Spaces, 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. Continue reading...

  • IServiceProvider vs. IServiceProvider

    I've been using the COM IServiceProvider interface 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 System.IServiceProvider interface. Unfortunately, it turned out that it's not exactly the same interface. 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. 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. 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 … Continue reading...

  • Sky's the limit...

    ...or rather, 5GB is the limit on SkyDrive. :-) Plus, it's now available in 38 markets. Oh, and I should probably mention it's not a Beta anymore. For more details, head on the the SkyDrive team blog. Continue reading...

  • Enablilng dragging in Canvas, v3.5 edition

    About a year ago I posted 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. 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. 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. Continue reading...

  • Yahoo! Mail Web Service - interesting business model

    Dare posted some thoughts on the limitations of the new Yahoo! Mail Web Service. One thing he missed to mention though, is how that Web Service ties into Yahoo! Mail subscription model: "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." 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. 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. :-) Continue reading...

  • IObjectWithBrowserSiteImpl - base template for IE BHO or toolbars

    If you want to extend IE with a browser helper object or a toolbar, you need to implement IObjectWithSite interface. ATL has a basic IObjectWithSiteImpl<> template that helps a bit.  Most BHOs and toolbars also subscribe to the browser events. ATL has a helper template for that as well - IDispEventImpl<>. Thus, pretty much any IE extension implemented with ATL inherits both templates. So, I've decided to implement a new template - IObjectWithBrowserSite<>, that besides storing the site pointer as IUnknown, also stores a pointer to IWebBrowser2 and subscribes to the browser events. The new template declaration looks like this: template <class T, UINT nID>class ATL_NO_VTABLE IObjectWithBrowserSiteImpl :    public IObjectWithSiteImpl<T>,    public IDispEventImpl<nID, T, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>{public:    // IObjectWithSite    IFACEMETHOD(SetSite)(IUnknown *pUnkSite)    {        HRESULT hr = S_OK;         // Silently ignore any failure from CleanupSite        CleanupSite();         // Store the IUnknown pointer to the new site        hr = IObjectWithSiteImpl<T>::SetSite(pUnkSite);         if (SUCCEEDED(hr))            hr = SetupSite();         if (FAILED(hr))            // Our setup logic failed; the real failure that caused            // us to clean up here is more important, so propagate this one to the site            // Silently ignore any failure … Continue reading...

  • Enabling dragging in Canvas, part 2

    Update: There were some bugs in the code, which caused funny behavior with elements that have a render transform applied to them. I've updated the code below to fix these. In part 1 we covered how the dragging behavior will be attached to the Canvas object. Let's take a look now at the actual dragging code. 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. protected Canvas owner;protected Point _lastLeftDown;protected double _canvasLeft;protected double _canvasTop;protected bool _isDragging = false; 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 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. public void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e){    FrameworkElement dragElement = e.Source as FrameworkElement;     if ((dragElement == null) || (dragElement == this.owner))        return;     if (!GetIsDraggable(dragElement))        return;     // Track mouse click position for offsetting the drag element position    _lastLeftDown = e.GetPosition(this.owner);     if ((e.ClickCount == 1) && (!_isDragging))    {  & … Continue reading...

  • Incoming posts

    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. 1. (COM/CLR/WPF) Scriptable WPF application - a sample WPF aplication that exposes automation objects and runs as a local COM server.2. (COM/IE) IObjectWithBrowserSiteAndDispEventImpl - an 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.3. (WPF) Pile panel - a Canvas based panel that add rotation property to it's children.4. (WPF) Adding Adorners using a simple Ramora DP.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)6. (COM) ATL CAxWindow, WM_CREATE and CoInitialize/CoUnitialize balancing issue. If you are interested in any of these topic, post 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) Continue reading...

  • Enabling dragging in canvas

    When developing UI, most of the time we want the controls nicely sized, ordered and aligned automatically. 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. 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 using the Ramora DP pattern. This can be done by creating a new class CanvasDragHelper, that will extend Canvas instances behavior. public class CanvasDragHelper : DependencyObject{    protected Canvas owner;} We'll start by defining three dependency properties. We need one 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: /// <summary>/// Property used to cache the drag helper instance. It also removes the necessity of additional storage/// to hold the drag helper instances/// </summary>protected static readonly DependencyPropertyKey CanvasDragHelperPropertyKey = DependencyProperty.RegisterAttachedReadOnly("CanvasDragHelper",    typeof(CanvasDragHelper), typeof(CanvasDragHelper), new FrameworkPropertyMetadata(null)); public static readonly DependencyProperty CanvasDragHelperProperty = CanvasDragHelperPropertyKey.DependencyProperty; public static CanvasDragHelper GetCanvasDragHelper(DependencyObject obj){    return (CanvasDragHelper)obj.GetValue(CanvasDragHelperProperty);} protected static void SetCanvasDragHelper(DependencyObject obj, CanvasDragHelper value){    obj.SetValue(CanvasDragHelperPropertyKey, value);} /// <summary>/// This is … Continue reading...

  • Windows Live Toolbar build 130

    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? :-) You can grab the bits from the WLT web page. 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. Continue reading...