Wednesday, December 22, 2010

Things I wish the Windows Phone would have

- An easy way to share contacts between 2 Windows Phones

Unbelievable, but there is no easy way to just send a contact info from my phone directly to my wife's phone. It is possible, but the solution I found is too complicated, requires computer use and having Office installed: from my mail account on Exchange (where my contacts are saved), send a mail to my wife's accout on Hotmail and attach the contact's info. On a computer, install Outlook with Outlook Hotmail Connector, then follow the steps in Importing contacts from PC article to copy the contact info in the Hotmail contacts of the other account. The phone will sync it from here automatically. There is also a caveat, that Office wants to store by default the contacts in the "Last, First" name format, so if you want them appearing on the phone correctly you'd have to make sure they are saved in the "First Last" format....

- An easy way to publish/share a video recorded with the phone


For pictures, the phone knows how to upload the pictures automatically on SkyDrive or Facebook. However, for videos there isn't a similar way. Why?!?
There is also a Youtube application from Microsoft, but this also doesn't seem to allow uploading a video I just recorded...
Now if I understand correctly, I can import the video on the PC after I'll install the Zune software (which btw, doesn't install on Windows 2008 R2 Server), and I can share it from there, but why do I have to use a PC and install software for this simple task?

If these things will annoy me too much I may end up writing an application to solve the problem (or some other developers may beat me to it).

But I'm hoping the version 2 of the Windows Phone software that will come early next year will help solve these simple tasks. This is functionality that should be directly supported by the phone, and should not require installing 3rd party applications, using a computer or install other software there (paid or free) :-(

Tuesday, December 14, 2010

Enabling Aero Glass or Windows 7 Basic theme in Remote Desktop Connection to a Windows Server 2008

By default, remote desktop connections to a Windows Server 2008 get Windows Classic theme. Enabling Aero or Windows 7 Basic theme requires a couple of steps, and here are the relevant settings (for next time I'll have to do this again)

On server:
1) Add the Desktop Experience feature from the Server Manager.

2) Set the Themes service to autostart, and start the Themes service.
3) Enable the “Allow desktop composition for remote desktop sessions” policy from gpedit.
The policy path is “ComputerConfiguration\AdministrativeTemplates\WindowsComponents\Remote Desktop Services\Remote Desktop Session Host\Remote Session Environment”
4) Enable 32bpp for RDP connections - In Server Manager, go to “Remote Desktop Session Host Configuration” under “Remote Desktop Services” role, right-click on the connection to bring up “RDP-Tcp Properties”, uncheck “Limit Maximum Color Depth” from “Remote Desktop Session Host Configuration.”

More details on the steps above here: http://blogs.msdn.com/b/rds/archive/2009/06/23/aero-glass-remoting-in-windows-server-2008-r2.aspx

5) Since the defaul theme is Classic and can't be changed from Display Properties while connecting through RD, you need to force Aero as a default theme. Again use gpedit, under User Configuration\Administrative Templates\Control Panel\Personalization\Force a specific visual style or force Windows Classic, set it to Enabled and type in the Path to Theme file "%windir%\Resources\Themes\Aero\aero.msstyles".

More details on this here: http://windows7themes.net/windows-7-theme-group-policy.html

On the client machine:
1)  In Mstsc's options, the color depth of the remote session must be set to 32-bit
2) “Desktop composition” must be enabled on the Experience tab
(If the above are not set, the Windows 7 Basic theme will be used instead of Aero)

Saturday, December 11, 2010

Easily recording video of an application behavior

At times, when you encounter a bug in an application and want to report it to the manufacturer (e.g. when reporting bugs to Microsoft on Connect), it may help to attach a video demonstrating the problem when you reproduce it.

An easy and free way to capture such video is to use Office Labs Community Clips recorder. The video recorder can be downloaded directly from http://go.microsoft.com/fwlink/?LinkId=117503&project=Community Clips

When installed and started, the Community Clips application displays an icon in the system tray where recording can be started/stopped.

After stopping the recording, the captured video can be re-played, saved locally as wmv file,  or sent via email.

Wednesday, August 11, 2010

Microsoft Language Portal -

Have you ever wanted to create a program localized in other language but were not quite sure what's the usual translation of a computer-related word or phrase?
E.g. have you ever wondered how to say "recycle bin" in French?

Well, now it's easily possible. Microsoft has made searchable the translations used in their programs.
Just search the words of interest on Microsoft Language Portal and your program can have the same familiar feel as other localized Microsoft programs!

Also there are available for download Style Guides for the languages, describing when to use capitalizations, or whether nouns/verbs should be preferred for buttons and menu items, etc.

Monday, July 19, 2010

Windows 7 Jump Lists and Visual Studio 2010

 

The jumplists in Visual Studio 2010 should display in the Recent Items list the most recently used projects and solutions. The list should be similar with the MRU list displayed on the StartPage, and with the project list in Files/RecentProjectsAndSolution menu.

Projects and Solutions are automatically added to the list by Windows on behalf of Visual Studio when projects are double-clicked in Windows Explorer, or when are opened using the standard File/Open/Project dialog. The items also end up in this list when Visual Studio calls explicitly SHAddToRecentDocs() with the file name.

We had reports that Recent items list in jump lists don’t display all the projects and solutions displayed by the other lists (as demonstrated below), without the user doing anything special like explicitly removing the items from Windows’ jump list.

Jumplists1

It may be possible at times that Visual Studio 2010 jump lists don’t show any projects and solutions, as shown in this picture:

JumplistMissing

 

There may be a couple of explanations to this:

1) In Windows, the display of Recent Items and the number of items in the list are controlled by a couple of settings accessible in Taskbar properties. These settings may be modified by mistake or may be mismatched with the Visual Studio settings for the number of recent items.

Right click the taskbar, choose Properties, then in  StartMenu tab look for “Store and display recently opened items in the Start menu and the taskbar” checkbox. Make sure the checkbox is checked.

JumplistTaskbar1

The number of recent items in the jumplist is controlled by a different setting. Right click the taskbar, choose Properties, then in  StartMenu tab click the Customize button. In the dialog that opens, look for the “Number of recent items to display in Jump lists”. Make sure the number of items is not set to 0 (zero) by mistake. The default value is 10.

JumplistTaskbar2

The Visual Studio similar setting for the number of items to show in MRU lists (e.g. the recent projects list from the StartPage) can be accessed via Tools/Options dialog, under Environment/General category. The default is also 10 items shown in recently used lists.

Jumplist3

 

2) The projects shown in Visual Studio recent projects lists may have been created in temporary locations.

By design, Windows 7 jump lists don’t show recent items that are created in temporary folders. This makes sense - no items in temp folders are ever added to Jump Lists or the Recent Items Folder, because Jump Lists and Recent Items are about getting back to important items, and by definition a temporary file is not something that users want to get back to.

The recent projects lists in Visual Studio’s StartPage and File menu don’t have the same restriction. You can easily see if the projects missing from jumplists are in temporary folder by hovering over the items in the StartPage and looking at the tooltips.

JumplistsTemp


3) You’re running multiple Visual Studio instances, under different registry hives and their jump lists clash.

This may happen if you’re creating projects extending Visual Studio and have installed Visual Studio SDK.

Here you see I’m running 2 instances of Visual Studio, one of them started under Experimental Hive. The instances have different MRU settings (stored in registry under different hives), colors, etc. but they share the same icon in Windows taskbar and they share the jump list.

JumplistClash

This is a VS10 bug we need to fix for next version of Visual Studio. VS started under the experimental hive needs to use a different AppUserModelID to have a different icon and have a separate jump list.

4) You’ve created your own shortcuts to devenv.exe and are starting Visual Studio using those shortcuts.

Visual Studio uses a custom AppUserModelID (e.g. for VS Pro and Ultimate this is “VisualStudio.10.0”), and for jump lists to work correctly this model id needs to be set on all User Interface elements of the application (windows, shortcuts, etc). The shortcut created when Visual Studio was installed has the correct property (System.AppUserModel.ID) set. However, any new shortcuts you create won’t have the property, and Windows may or may not display correctly the jumplists when starting Visual Studio using one of those shortcuts.

If you need more shortcuts to devenv.exe it is recommended to copy the shortcut created when Visual Studio was installed on the computer.

5) Mysterious jump lists disappearance/appearance.

We also had reports of jump lists mysteriously disappearing or reappearing (usually when upgrading the Visual Studio build from one daily build to another, or when upgrading say from beta or the RC build to the RTM version of Visual Studio 2010). Often times it just starts working, usually when opening a file from Windows Explorer by double clicking it, or by rebooting the machine.

So far we do not have a consistent repro, and we are only suspecting a Windows bug that Windows doesn’t correctly calculate the app user model ID associated with the running application calling SHAddToRecentDocs for a specific file extension (like *.sln).

Should this be indeed the case, you will be able to workaround it by declaring an explicit AppUserModelID for the ProgID used by the VisualStudio files.

E.g. for Visual Studio Professional / Premium / Ultimate, save the section below as a *.reg file and import it into registry.

  

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\VisualStudio.sln.10.0]
"AppUserModelID"="VisualStudio.10.0"

[HKEY_CLASSES_ROOT\VisualStudio.csproj.10.0]
"AppUserModelID"="VisualStudio.10.0"

[HKEY_CLASSES_ROOT\VisualStudio.vbproj.10.0]
"AppUserModelID"="VisualStudio.10.0"

[HKEY_CLASSES_ROOT\VisualStudio.vcproj.10.0]
"AppUserModelID"="VisualStudio.10.0"

[HKEY_CLASSES_ROOT\VisualStudio.vcxproj.10.0]
"AppUserModelID"="VisualStudio.10.0"

[HKEY_CLASSES_ROOT\VisualStudio.dbproj.10.0]
"AppUserModelID"="VisualStudio.10.0"

[HKEY_CLASSES_ROOT\VisualStudio.vdproj.10.0]
"AppUserModelID"="VisualStudio.10.0"

[HKEY_CLASSES_ROOT\VisualStudio.fsproj.10.0]
"AppUserModelID"="VisualStudio.10.0"

For Visual Studio Express SKUs you’ll need entries like the ones below (the example is for C# Express)

 

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\VCSExpress.sln.10.0]
"AppUserModelID"="VCSExpress.10.0"

[HKEY_CLASSES_ROOT\VCSExpress.csproj.10.0]
"AppUserModelID"="VCSExpress.10.0"

You may need to replace the application names to match the Express SKU type you have installed, and the project files extensions used by that Express SKU.

E.g.

Microsoft Visual C# 2010 Express: “VCSExpress” name, “csproj” file extension.

Microsoft Visual Basic 2010 Express: “VBExpress” name, “vbproj” file extension.

Microsoft Visual C++ 2010 Express: “VCExpress” name, “vcproj” and “vcxproj” file extensions.

Microsoft Visual Web Developer 2010 Express: “VWDExpress” name, “csproj” and “vbproj” file extensions.

Friday, May 7, 2010

Windows Update error 8024402C

Today I decided to check the Windows Update status on my laptop, and to my surprise, I was getting an error code 8024402C. Pressing the “Try again” button didn’t help, I was getting the same error over and over again.

WSUS2

And I clicked the “Get help with this error” link, which indicated a lot of possible causes that lead to this error message. This set me on the right track - while my computer is not “usually connected to a network at work”, I did connect once to the work network and I joined the domain there. (It was more than a month ago, before leaving in vacation, and I didn’t even remembered I did that; it was also the last time updates were installed on the laptop).

And so, when I joined the domain, the domain administrators have set my computer to be managed by Windows Server Update Services (WSUS) , as (not verily clearly) indicated by the message “You receive updates: Managed by your system administrator” near the bottom of the page. (I knew that joining the domain would be bad juju sooner or later, but I had to do it so I can access the TFS servers for source control and bug tracking.)

I started searching for policies that were set on my machine and I came upon this Technet page describing  how to  manage the WSUS automatic updates with Group Policy. Indeed searching in Windows7 for “Group Policy”, launching the policy editor and looking at Computer Configuration/Administrative Templates/Windows Components/ Windows Update I found out I had one policy set, for “Specify intranet Microsoft update service location”

WSUS3 WSUS1

Unfortunately, setting it back to “Not configured” and rebooting the computer, didn’t help.

I then found out the WSUS Client Diagnostics Tool, and when I run it it indicated WSUS was still enabled on my machine, and still using the server name I had cleared out in policies. So the settings must have been preserved somewhere else…  Searching for WSUS configuration settings location I found out a page describing how to use WSUS without Active Directory, and I learned that Windows Update settings are stored in registry under HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate.

I used RegEdit to change the following registry setting, disabling the use of WSUS server.

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU]
"UseWUServer"=dword:00000000

I tried again Windows Update and the error code this time changed from 8024402C into 80070057. This stands for ERROR_INVALID_PARAMETER, but indicated I was on the right track.

I stopped and restarted the Windows Update Service (I run in an elevated command prompt these commands)

net stop wuauserv
net start wuauserv

which saved me another reboot, and next time I tried Windows Update things were started working!

I guess next time I’ll connect the laptop to the work network the WSUS server will be re-configured and I’ll have to clear it up again, so here I’m writing this article to remind myself how to do it…

Saturday, March 6, 2010

Network shares on Smb server could not be accessed - again

For a couple of days my server was down due to a hardware failure.  After I fixed the problem and I put the server back online I noticed a problem with the workstations: after login Windows popped up a balloon warning that “Could not reconnect all network drives”

NetworkDrives

All the drives I had mapped to Samba shares on my Infrant ReadyNAS system were now inaccessible, and they were showing disconnected in Windows Explorer.

NetworkDrives2

Double clicking the shares in Windows Explorer was displaying a logon prompt with the following error “The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you”.

MapError

Typing correct credentials was useless. The dialog just came back. Canceling the dialog was going through 2 more logon prompts and displaying a message listing all personal certificates on the machine. Needless to say, those were certificates for another domain and logon eventually failed.

I deleted the disconnected mapped drives and I was able to recreate them without problems and everything was fine again. Until the first reboot, that is. And then again, network drives were disconnected and “The system detected a possible attempt to compromise security” was back. :-(

Initially I thought Windows may have installed some update in the last week that strengthened the security settings and breaking network shares to old Linux boxes  (It wouldn’t have been the first time). But that wasn’t the case.

I checked access to the domain controller server. It was fine, I could ping it by its Wins name (SOL), by its fully qualified domain name (sol.constantin.comcast.net), by it’s IP address (192.168.0.2), I could access the network shares on the server, etc. So, server being inaccessible didn’t seem to be the problem.

I looked then in the System Event Log to see if any problems were logged. There were lots of errors like these:

  • Time-Service event ID 129: “NtpClient was unable to set a domain peer to use as a time source because of discovery error. NtpClient will try again in 3473457 minutes and double the reattempt interval thereafter. The error was: The entry is not found. (0x800706E1)”
  • GroupPolicy event ID 1129 “The processing of Group Policy failed because of lack of network connectivity to a domain controller. This may be a transient condition. A success message would be generated once the machine gets connected to the domain controller and Group Policy has successfully processed. If you do not see a success message for several hours, then contact your administrator”. with error code 1222 - "The network is not present or not started."
  • Netlogon 5719: “ This computer was not able to set up a secure session with a domain controller in domain CONSTANTIN due to the following: There are currently no logon servers available to service the logon request. This may lead to authentication problems. Make sure that this computer is connected to the network. If the problem persists, please contact your domain administrator.”
I searched the net for more information them, but none of the solutions proposed or diagnostics like this seemed to lead anywhere in my case.

Eventually I rebooted the computer once more, and this time I got two different event types:

  • GroupPolicy event ID 1055: “The processing of Group Policy failed. Windows could not resolve the computer name. This could be caused by one of more of the following:
    a) Name Resolution failure on the current domain controller.
    b) Active Directory Replication Latency (an account created on another domain controller has not replicated to the current domain controller).”

    (and a similar event 1053 for “The processing of Group Policy failed. Windows could not resolve the user name”)

Searching the net for this one proved to be successful. I found this Microsoft support page, which indicated to look for an additional error code in Event Details tab. In my case the error code was 1355 “The specified domain either does not exist or could not be contacted.”. The support page instructed further to “Use nslookup to confirm you can resolve addresses of the domain controllers in the user domain.”

Sure enough, the DNS server was not able to resolve the name of the domain server computer…

Nslookup1

And then it hit me what was wrong. The DNS server I was using was the Wi-Fi router (192.168.0.1), a Netgear/Linux box. This was not able to provide DNS entries correctly for the local network computers, despite them being configured with static addresses. :-( It was my fault, too – I had set the router as preferred DNS when the DC server was down due to the hardware failure…

Solution

So, I went to Control Panel\Network and Sharing Center, clicked on LocalAreaConnection, Properties, selected “Internet Protocol Version 4”, clicked Properties, and switched the Preferred/Alternate DNS Severs to use the domain controller (192.168.0.2) as the Preferred DNS server.

Now I was able to resolve correctly the name of the Domain Controller, and I was able to access the network shares without problem again…

Nslookup2

If you reached this point and you’re asking why I told you all this, it’s because 12 months from now when I may hit again the same problem with the network shares it’s likely I won’t remember it may be due to an innocent switch of the DNS servers. Having it documented in the blog will help me remember. I hope if you searched and reached this article, it might help you too….

Tuesday, March 2, 2010

Implementing disabled WPF toolbar buttons for Visual Studio 2010

 

If you’ve ever wanted to implement a toolbar in WPF you may have come upon this limitation: you can easily set images for the toolbar buttons, but there is no default way of making these images appear grayed when the toolbar buttons are disabled.

To implement the toolbar buttons and menu items, Visual Studio 2010 uses a custom algorithm to create gray images from the original picture. This is publicly available  for consumption via a converter Microsoft.VisualStudio.PlatformUI.GrayscaleImageConverter, implemented in Microsoft.VisualStudio.Shell.10.0 assembly. The converter takes as input an ImageSource and converts to an Image element that uses for source the grayed out version of the image.

If you need to implement toolbars for your package/dialogs you should strongly consider using shell-implemented toolbars (defined by your application via *.vsct files) and used through IVsToolWindowToolbar/IVsToolWindowToolbarHost interfaces. That guarantees a consistent look of all the buttons, separators or split-buttons in your toolbar with the rest of the shell.

For instance, to display a shell-owned toolbar in a WPF dialog you can use IVsUIShell4.CreateToolbarTray() interface to obtain an IVsToolbarTrayHost, then call AddToolbar() on this object to add the toolbar using the guid of your package and the resource Id of the toolbar in vsct, then get the UIElement representing the toolbar using IVsToolbarTrayHost.GetToolbarTray() and position the element to your liking in the dialog.

 

However, there may be situations when you’ll want to implement your own WPF toolbar buttons. To maintain a consistent grayed out look of disabled buttons you may choose to reuse the GrayscaleImageConverter implemented by the shell. Below I describe a way to do this:

1)  Implement a ToolbarButtonImage class having a Source dependency property. You’ll use this to set the button’s image in the “normal” state.

2) The style of the ToolbarButtonImage class will use a trigger to switch the template of the button’s content when the button gets enabled/disabled between a control template (ToolbarButtonImage_Normal) containing the image in the normal state and a control template (ToolbarButtonImage_Disabled) containing the grayed out image produced by the  GrayscaleImageConverter.

3) Add the buttons to the toolbars as follows:

<ToolBar>
    <Button IsEnabled="{Binding ……….}">
       <local:ToolbarButtonImage Source="Resources\ButtonNormalImage.png"/>
    </Button>
</ToolBar>

Below is the sample code for the ToolbarButtonImage and its style:

----------------------------------------------
ToolbarButtonImage.cs
----------------------------------------------

using
System;

using
System.Windows;

using
System.Windows.Controls;

using
System.Windows.Data;

using
System.Windows.Media;

using
System.Windows.Media.Imaging;


namespace
YourApplicationNamespace 
{ 
    public class ToolbarButtonImage : UserControl
 
    { 
        static ToolbarButtonImage()
        {
              DefaultStyleKeyProperty.OverrideMetadata(
typeof(ToolbarButtonImage),

                                new FrameworkPropertyMetadata(typeof(ToolbarButtonImage)));
        } 

        public
static readonly DependencyProperty SourceProperty = DependencyProperty.Register

                               ("Source", typeof(BitmapSource), typeof(ToolbarButtonImage)); 

        public
BitmapSource
Source
        {
            get
            {
                 return (BitmapSource)GetValue(SourceProperty);
            }
            set

            {
                SetValue(SourceProperty,
value);
            }
        }
    }
}

----------------------------------------------
ToolbarButtonImageStyle.xaml
----------------------------------------------

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:YourApplicationNamespace"

    xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.10.0">


<ui:GrayscaleImageConverter x:Key="GrayscaleImageConverter"/>


<ControlTemplate x:Key="ToolbarButtonImage_Normal" TargetType="{x:Type local:ToolbarButtonImage}">

     <Image Width="16" Height="16" Source="{TemplateBinding Property=Source}"/>

</ControlTemplate>


<ControlTemplate x:Key="ToolbarButtonImage_Disabled" TargetType="{x:Type local:ToolbarButtonImage}">

     <ContentPresenter Width="16" Height="16" Content="{TemplateBinding Property=Source, Converter={StaticResource GrayscaleImageConverter}}"/>

</ControlTemplate>


<Style x:Key="{x:Type local:ToolbarButtonImage}" TargetType="{x:Type local:ToolbarButtonImage}">
 
    <Setter Property="Template" Value="{StaticResource ToolbarButtonImage_Normal}"/>

    <Style.Triggers>

        <DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}}" Value="False">

            <Setter Property="Template" Value="{StaticResource ToolbarButtonImage_Disabled}"/>

        </DataTrigger>

    </Style.Triggers>

</Style>

</ResourceDictionary>

Thursday, February 4, 2010

Drag and drop in Visual Studio 2010

 

Let me explain first how drag and drop works in a WPF application:

1) the Win32 window hosting the WPF controls needs to be registered as a drop target with Windows by calling RegisterDragDrop. When some object is dragged, Windows selects the “closest” Win32 window registered for drag drop under the mouse, and then it calls functions like DragEnter/Drop/etc on the IDropTarget interface provided at registration. WPF does this registration for HwndSource windows, and when an object is dragged over a WPF window, WPF will be called.

2) the WPF control that wants to intercept the drop needs to specify UIElement.AllowDrop=true. When called by Windows, WPF will select the innermost WPF control under the mouse that allows drop and will route to it WPF-style drag and drop events (e.g. PreviewDragEnter events will be tunneled to that control, then DragEnter events will bubble up). The controls and its parents have a chance of intercepting these events.

3) the control or one of the parents needs to recognize one of the formats of the data being dragged, and allow the drop. If no control recognizes the format, the DropEffect will be None and the drop will not be possible.

Now back to Visual Studio.

Visual Studio 2010 and later are WPF applications. The main window and floating windows (toolwindows or documents) are HwndSource, thus are registered for drag and drop by WPF. The shell sets AllowDrop=true on the root WPF elements in these windows, and since this is an inherited property, all child controls (e.g. the toolwindows contents) will automatically allow drop as well.

If the toolwindows host WPF content but they don’t intercept the drag & drop events, the shell will eventually intercept the bubbling WPF events, and will attempt to extract from the dropped data file names to be opened either as solutions/project or in editor windows. Similarly, if the toolwindows host Win32 elements but don’t register them as droptargets with Windows, Windows will pick the shell’s main window as drop target and again the shell will check the dropped data if it contains filenames that can be opened in editor.

A) Drag and drop over Shell-owned elements

The shell owns some elements in the Visual Studio UI, e.g. the frames of the toolwindows and document windows, document tabs in the document well, the main window’s background area, main window’s toolbars, toolbars in toolwindows hosted by the shell, etc., thus it controls dragging and dropping over these elements.

The shell understands only the DataFormat.FileDrop (CF_HDROP) format. This format is used for instance when one or more files are dragged from Windows Explorer. When dropped over Visual Studio’s main window, VS will use the dropped file names to open the files in a Visual Studio editor.

This works when dropping over most shell elements, with a couple of exceptions:
- dropping over tabbed toolwindows tabs or document tabs is disallowed: instead this is used to switch the active toolwindow or document in the tab group.
- dropping over comboboxes in toolbars (if editable, these allow drop with Text format)
- dropping over the main window’s title is not possible (this is a WPF issue)


B) Drag and drop over toolwindows’ content

A tool window implementer has the option of using Win32-based content or using a WPF element as content. When using the VsSDK/MPF classes like ToolWindowPane, the content can be exposed using either the Window or Content properties from the base class.

Win32 content

Whenever a Win32 window is returned from ToolWindowPane.Window, from IVsWindowPane.CreatePaneWindow, or indirectly from IVsUIElementPane.CreateUIElementPane via IVsUIWin32Element, that toolwindow will have a Win32 content. To intercept drop operations on the toolwindow content, the toolwindow’s implementer will need to register the Win32 window with Windows by calling RegisterDragDrop, and providing an IDropTarget, then handling the Windows-style drag and drop calls.

An example of such toolwindow is SolutionExplorer, which registers its content to allow D&D of solution and project items between the projects in the tree.

WPF content

Whenever a FrameworkElement is returned from the ToolWindowPane.Content property, from IVsUIElementPane.CreateUIElementPane (or indirectly via IVsUIWpfElement), the shell will host that toolwindow’s content in a pure-WPF hierarchy, without intervening HWnd. WPF-style events will then flow freely up/down the visual tree starting with the main window (or the floating window root, when the toolwindow is floating).  Conditions 1) and 2) are automatically satisfied, and all you need to do is satisfy 3) – intercept the WPF events for the dropped format you understand. Again, if the toolwindow does not intercept the dropped data and mark the WPF events handled, the shell will intercepts  them and will either deny the drop or will open the files in editors (if the data is in the FileDrop format accepted by the shell).

See the sample below for an example.

C) Drag and drop over toolwindows’ toolbars

To use a shell-implemented toolbars (WPF), a toolwindow can host it in two modes:

a) Letting the shell to host the toolbar. E.g. get an IVsToolWindowToolbarHost from the window frame by calling IVsWindowFrame.GetProperty for VSFPROPID_ToolbarHost, call AddToolbar on the toolbar host. The shell will host the toolbar directly in a WPF tree without intervening hwnds. Any drops over the toolbar will be handled by the shell. To intercept drops over the toolbar area, the toolbar has to be added using a different function: instead of using IVsToolWindowToobar.AddToobar, query the IVsToolWindowToolbarHost2 interface from the toolbar host and call AddToolbar2 method. This allows providing an object implementing IDropTarget interface that will be called by the shell when the drop happens over the toolbar area.

b) Hosting the toolbar yourself. E.g. If your toolwindow content is Win32-based, create a Win32 window child of the toolwindow’s content, and an object implementing IVsToolWindowToolbarHost interface, call  IVsUIShell.SetupToolbar to associate the Win32 child with your toolbar host, then call IVsToolWindowToobar.AddToobar to add the toolbar into the host. This way you can place a toolbar anywhere in your toolwindow’s area. If the toolwindow’s content  is already registered as drop target by calling RegisterDragDrop, Windows will select it as the “closest” drop target under mouse when the drop happens under the toolbar area, too, and you’ll receive the Windows-style calls on the drop target interface. You can also register the toolbar host child window as a separate drop target if you so wish.

------------------------------------------------------------------------------------------------------------------------------

The following sample demonstrates drag and drag of a custom data format, and intercepting the drop in a WPF control. It also demonstrate dragging of data in formats understood by editors and VS shell.

http://www.alinconstantin.net/Download/Example.SimpleDragDropInVS.zip

You need VS2010 and VSSDK2010 installed in order to build the sample and run it under the experimental hive. To view the toolwindow, use the View/OtherWindow/DragAndDropToolwindow command, then drag the labels over the indicated areas.

Capture