Lubo Blagoev's Blog

My thoughts on software and technology

Visual Studio 2008 released. Too early?


There is a buzz around the web these days. The long awaited Visual Studio 2008 is out. As usual the echo chamber is on going. Man there is so much noise about it that it will kill the sound of the fanfare. A quick search on blogs.msdn.com with the phrase "Visual Studio 2008 RTM" reveals more than 3000 post found.

I thought maybe wait until all this settles down and then post, but I was provoked. It seems to me that nobody ever subjects the releases coming from Microsoft. At least nobody is trying to see what's underneath the bits that have RTMed. So I downloaded Visual Studio 2008 readme file and start looking for clues. And I found some. If you look at the TOC of the file there is nothing more than system requirements and a big "Known Issues" chapter that hold various "little" issues. Some of them have workarounds and some of them don't. So let me pick up one or two.

2.1.2 If the computer goes into sleep mode or hibernation mode during Visual Studio installation,

Setup might hang when the computer returns from sleep mode or hibernation mode

Resolution: Just kill your install and start again. Please!

 

2.1.9. Installing Visual Studio 2008 on the same computer as Visual Studio 2005 causes Visual Studio 2005 repair of .NET Framework 2.0 to fail.

Fair enough for the side by side installation or whatever they called it.

 

2.1.12. Windows Automatic Update notification appears during Visual Studio installation on Windows Vista

Please restart your windows... But wait I am not finished yet... Never mind I want you to restart the machine for the changes to take effect...

 

Wait if you managed to install it now you are all alone since there are some issues on uninstall also. But the "Product Issues" are what strikes me more.

2.3.7.1. WcfTestClient may throw an exception if Biztalk Service SDK is installed. System.NullReferenceException: Object reference not set to an instance of an object.

2.3.3.1. Compiler displays an error message a lambda is passed to a doubly-nested latebound method call.

 

2.3.7.6. Managed C++ code generated by using the Service Model Metadata Utility tool (Svcutil.exe) may not compile.

2.3.8.2. Code Refactoring does not change XAML files.

2.3.8.3. Making changes to XAML will not refactor code files.

2.3.8.5. Using the Property Browser during debugging may cause Visual Studio to crash.

2.3.8.6. Visual Studio hangs or crashes when a XAML file that contains a ControlTemplate in a ResourceDictionary is being edited.

2.3.8.7. Visual Studio may hang when you bind to long ObjectDataProvider method calls. .....

 

Now what this means. If you look closely these errors represent critical issues with the product that require more time to fix than to be described as known issues and move along. This means that the developers needed more time to fix it but management stuff doesn't understood and preferred to ship now. From where comes the pressure I don't know, but I know that the official launch is scheduled for late January 2008. I guess the dev teams would have used that time to fix some of these issues especially the deployment related ones. But no "The Suits" have the final word. That's why I totally agree with Brian Harry (Blog)

We are also already planning Service Pack 1.  No, that does not mean that we shipped a ton of bugs - 
2008 was probably the highest quality release I've seen.  It means that we've turned another new leaf 
and committed to shipping a service pack within 6 to 12 months after every major release.  
There are always things you'll find that you want fixed.  And there are always new releases of 
other products for which we have to do work to support. 

 

I believe that VS2008 is the most stable release by now. I have worked on it since beta 2 now and we have a product almost finished using this beta. I am totally confident of the quality. Its just OK if you have used it like me, in a isolated VM environment and a pile of pain killers :). No really it is solid stable enough that's why beta 2 goes with go live license.

Constantly on Beta

I think that we are facing one strange pattern. We are using more and more tools that are in CTPs/Betas/RCs phases and when these tools are just  released we move on to switch to the other CTPs/Betas that are coming out. It is a requirement that we should obey if we want to stay on the verge of technologies. Or do we? Right now while every body are celebrating the new Visual Studio 2008 release there is a separate download for the next version Visual Studio Code Name Rosario (http://msdn2.microsoft.com/en-us/teamsystem/bb725993.aspx).  Yeah! Go grab it. Fire up a virtual machine and use it. Lets leave the Orcas RTM in the past.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

November 20, 2007 18:17 by lubo
Tags:
Categories: Visual Studio | Software Development

Taking screenshots including the mouse pointer programmatically.


Recently I needed to take some screenshots of my screen that include the mouse pointer. While there are many programs out there that do just that I failed to find anything that is simple and easy enough and most importantly is free. There are some screen capture utilities that have free versions but non of them have the ability to include the mouse pointer or if they does this is included in the commercial version of the program.

After couple of hours evaluating I found the most promising solution -  Cropper by Brian Scott (http://www.codeplex.com/cropper). It is not only free but it is open source C# application. Unfortunately it can't capture the mouse pointer. At first I though it is difficult to do that since most of the tools include this in the commercial version. After some time investigating I saw one article from Zarko Gajic in Delphi About (http://delphi.about.com/od/graphics/l/aa021004a.htm). I used to read him a lot when I was doing Delphi development.

I had what I needed so I guess the next step was obvious. I modified the excellent Cropper tool to include the mouse pointer. The truth is that the tool is designed to be extensible enough and it is not much of a code so the task went very easy. I will post here the method that does the cursor capturing. The rest I intend to send to Brian Scott to include it in the next version of the tool. Here it is

The NativeMethods.cs contains additions for the needed interop signatures.

[StructLayout(LayoutKind.Sequential)]
public struct CURSORINFO
{
    public Int32 cbSize;
    public Int32 flags;
    public IntPtr hCursor;
    public POINT ptScreenPos;
}

[DllImport("user32.dll")]
public static extern bool GetCursorInfo(out CURSORINFO pci);

public const Int32 CURSOR_SHOWING = 0x00000001;

[DllImport("user32.dll")]
public static extern IconHandle CopyIcon(IntPtr hIcon);

[StructLayout(LayoutKind.Sequential)]
public struct ICONINFO
{
    public bool fIcon;
    public Int32 xHotspot;
    public Int32 yHotspot;
    public IntPtr hbmMask;
    public IntPtr hbmColor;
}

[DllImport("user32.dll")]
public static extern bool GetIconInfo(IconHandle hIcon, out ICONINFO piconinfo);

[SuppressUnmanagedCodeSecurity, SecurityCritical,
DllImport("user32.dll", EntryPoint = "DestroyIcon", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool DestroyIcon(IntPtr hIcon);

[SecurityCritical, SuppressUnmanagedCodeSecurity,
DllImport("gdi32.dll", EntryPoint = "DeleteObject", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DeleteObject(IntPtr hObject);


[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
public class IconHandle : SafeHandle
{
    [SecurityCritical, SecurityTreatAsSafe]
    public IconHandle()
        : base(IntPtr.Zero, true)
    {
    }

    [SecurityCritical]
    protected override bool ReleaseHandle()
    {
        return DestroyIcon(base.handle);
    }

    public override bool IsInvalid
    {
        [SecurityCritical, SecurityTreatAsSafe]
        get
        {
            return (base.handle == IntPtr.Zero);
        }
    }
}

And the additional method added to Fusion8.Cropper.Core.ImageCapture class.

private void AddCursor(Image image, Rectangle capturedRectangle)
{
    using (Graphics graphics = Graphics.FromImage(image))
    {
        NativeMethods.CURSORINFO cursorInfo;
        cursorInfo.cbSize = Marshal.SizeOf(typeof(NativeMethods.CURSORINFO));
        if (NativeMethods.GetCursorInfo(out cursorInfo))
        {
            if (cursorInfo.flags == NativeMethods.CURSOR_SHOWING)
            {
                using (NativeMethods.IconHandle handle = NativeMethods.CopyIcon(cursorInfo.hCursor))
                {
                    NativeMethods.ICONINFO iconInfo;
                    if (NativeMethods.GetIconInfo(handle, out iconInfo))
                    {
                        try
                        {
                            using (Icon icon = Icon.FromHandle(handle.DangerousGetHandle()))
                            {
                                int targetX = cursorInfo.ptScreenPos.X - capturedRectangle.X - iconInfo.xHotspot;
                                int targetY = cursorInfo.ptScreenPos.Y - capturedRectangle.Y - iconInfo.yHotspot;
                                graphics.DrawIcon(icon, targetX, targetY);
                            }
                        }
                        finally
                        {
                            NativeMethods.DeleteObject(iconInfo.hbmColor);
                            NativeMethods.DeleteObject(iconInfo.hbmMask);
                        }
                    }
                }
            }
        }
        else
        {
            Debug.WriteLine(Marshal.GetLastWin32Error());
        }
    }
}

Note the DeleteObject calls in the finally statement. I found couple of articles on the web that do not free these objects. You should avoid this mistake.

Here is the final result

 screenshot

Although I found the code quality not very good I think this is a great tool with all the functionality and the plug-ins. It does a wonderful job and is very user friendly. I will send my changes to Brian and hope you will like it. After all the biggest support you can give for an open source project is to use it.

Have fun!
Lubo

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Building a WPF LinkLabel control


Currently there is no LinkLabel control for WPF and that's why I decided to build one. First I will show what is currently available in WPF.

If you want to simulate LinkLabel you can use inline Hyperlink in a TextBlock.

 
<TextBlock>
    <Hyperlink>
        <Run Text="Test link"/>
    </Hyperlink>
</TextBlock>
 
You can use Label control and inline there a hyperlink but I think TextBlock is better since you can edit the properties of all the child elements from InlineCollection directly in Expression Blend UI.

 

  WPF LinkLabel 1

While this approach have benefits I don't like it much so I though why not write a better LinkLabel control similar to the one in Windows Forms. And so I did. First let me show you what the control looks like.

 A WPF LinkLabel

The first one is a default LinkLabel control, the second one have its  LinkLabelBehavior set to HoverUnderline and the third is using custom colors for Foreground and HoverForeground properties.

The LinkLabel control supports

  • Foreground and HoverForeground properties
    • Allows setting custom properties of both foreground and hoverforeground properties
  • LinkLabelBehavior property
    • Allows setting the underline behavior when cursor hovers or not the LinkLabel
  • Custom HyperlinkStyle property
    • You can use this property to set specific custom defined style for the internal hyperlink of the LinkLabel. If set override custom  foreground and hoverforeground colors
  • Url - the navigation target property.
  • All other properties are inherited from the standard System.Windows.Controls.Label control

Settings these properties is easy using Blend or xaml code.  

<ThemedControlLibrary:LinkLabel Content="Link Label" FontSize="22"/>
<ThemedControlLibrary:LinkLabel Content="Link Label" LinkLabelBehavour="HoverUnderline" />
<ThemedControlLibrary:LinkLabel Foreground="#FF847901" HoverForeground="#FF06C8F2" Content="Link Label" LinkLabelBehavour="NeverUnderline"/>

 

WPF LinkLabel

Here is how this control can be used in a window. Just add namespace to the xaml and use the control.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="DemoApplication.Window1"
    Title="DemoApplication" Height="300" Width="300"
    xmlns:ThemedControlsLibrary="clr-namespace:ThemedControlsLibrary;assembly=ThemedControlsLibrary"
    >
    <Grid>
        <ThemedControlsLibrary:LinkLabel HorizontalAlignment="Left" VerticalAlignment="Top" Content="LinkLabel"/>
    </Grid>
</Window>

 

The whole code of the control as simple as it can be. It just defines the desired properties and the appropriate category attributes that control where these properties are shown in Blend Designer.

public class LinkLabel : Label
{
    private const string _linkLabel = "LinkLabel";

    public static readonly DependencyProperty UrlProperty = DependencyProperty.Register("Url", typeof(Uri), typeof(LinkLabel));

    [Category("Common Properties"), Bindable(true)]
    public Uri Url
    {
        get { return GetValue(UrlProperty) as Uri; }
        set { SetValue(UrlProperty, value); }
    }

    public static readonly DependencyProperty HyperlinkStyleProperty = DependencyProperty.Register("HyperlinkStyle", typeof(Style),
            typeof(LinkLabel));

    public Style HyperlinkStyle
    {
        get { return GetValue(HyperlinkStyleProperty) as Style; }
        set { SetValue(HyperlinkStyleProperty, value); }
    }

    public static readonly DependencyProperty HoverForegroundProperty = DependencyProperty.Register("HoverForeground", typeof(Brush),
            typeof(LinkLabel));

    [Category("Brushes"), Bindable(true)]
    public Brush HoverForeground
    {
        get { return GetValue(HoverForegroundProperty) as Brush; }
        set { SetValue(HoverForegroundProperty, value); }
    }

    public static readonly DependencyProperty LinkLabelBehavourProperty = DependencyProperty.Register("LinkLabelBehavour",
            typeof(LinkLabelBehaviour),
            typeof(LinkLabel));

    [Category("Common Properties"), Bindable(true)]
    public LinkLabelBehaviour LinkLabelBehavour
    {
        get { return (LinkLabelBehaviour)GetValue(LinkLabelBehavourProperty); }
        set { SetValue(LinkLabelBehavourProperty, value); }
    }

    static LinkLabel()
    {
        FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(
            typeof(LinkLabel),
            new FrameworkPropertyMetadata(typeof(LinkLabel)));
    }
}

 

In order for the Content to be bindable I used the BindableRun implemented by Filipe Fortes here. I added this BindableRun object to the control template like so:

<local:BindableRun BoundText="{Binding RelativeSource= {RelativeSource TemplatedParent}, Path=Content}"/>	
 
In order to have theme support  for any control you should have a Themes folder in the project that contains the Styles of your control. The LinkLabel defines only one such file Generic.xaml since the hyperlink style is the same no matter what is the current system theme. I will not include the control template of the LinkLabel but it consist of a inline Hyperlink in a TextBlock just like you may have done it with out the LinkLabel control. Check it in the attached project.
That's all about it. Simple and beautiful. Download and use it.
 
[Update 25.11.2007] Fixed the RequestEvent and ClickEvent registration and firing.
[Update 10.11.2007] I have updated the control to include WPF commands support and fixed IsEnabled property behavior.
 

Download the source code Themed Controls Library.zip or just the compiled assembly ThemedControlsLibrary.dll

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

November 10, 2007 17:29 by lubo
Tags: , ,
Categories: Software Development