Click here to Skip to main content
15,896,727 members
Articles / Programming Languages / C#

Full implementation of IShellBrowser

Rate me:
Please Sign up or sign in to vote.
4.86/5 (29 votes)
5 May 2009CPOL4 min read 160.3K   3.2K   113   51
A VS-like open and save file dialog implementation.

FileDialogs.png

Introduction

This library contains a full implementation of the IShellBrowser interface. The implementation is used in a VS-like OpenFileDialog and SaveFileDialog implementation. The components can be used the same way the System.Windows.Forms.OpenFileDialog and System.Windows.Forms.SaveFileDialog are used. The library also contains the SelectFolderDialog component which can be used as a replacement to the System.Windows.Forms.FolderBrowserDialog.

Background

Ever since I first read the article, Implementing IShellBrowser to host IShellView, I wanted to implement the same thing using C#, but after several unsuccessful tries, I had to put it aside. But, when I really needed a customized implementation of the Open and Save file dialogs in one of my applications, and using templates wasn't sufficient, I had to retry one more time. So, after re-declaring my shell interfaces a couple of times, I finally succeeded. I decided to create this library and write this article to demonstrate the IShellBrowser interface.

Using the Code

OpenFileDialog and SaveFileDialog are very similar to and contain almost the same properties as System.Windows.Forms.OpenFileDialog and System.Windows.Forms.SaveFileDialog respectively. This means that they can be used in almost the same way. The SelectFolderDialog however doesn't look and act as the System.Windows.Forms.FolderBrowserDialog but can still be used in a similar way.

All three components share the following two properties:

  • Options
  • Places

The Options property controls the drop-down items of the OK split button. You can either add the strings using the Designer or by using code, see the following example:

C#
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Options.Add("Open");
openFileDialog1.Options.Add("Open As Read Only");

You can then access the selected option through the SelectedOptionIndex property:

C#
if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{
    if (openFileDialog.SelectedOptionIndex == 1)
        MessageBox.Show(this, "Open as read only selected");
}

The Places property contains the collection of items shown in the places bar. By default it contains the Desktop, My Documents and My Computer. You can eiter change the items using the Designer or by code. It is very easy to customize the places bar using the Places Editor.

Places Editor

Or if you want to change the places bar programatically, see the following example:

C#
openFileDialog1.Places.Add(new FileDialogPlace(SpecialFolder.Desktop));
openFileDialog1.Places.Add(new FileDialogPlace(SpecialFolder.MyDocuments));
openFileDialog1.Places.Add(new FileDialogPlace(SpecialFolder.MyComputer));
CustomFileDialogPlace customPlace1 = new CustomFileDialogPlace(
    "C:\Documents and Settings\[User]\My Documents\Visual Studio 2005\Projects");
customPlace1.Text = "My Projects";
openFileDialog1.Places.Add(customPlace1);

Registry Support

The registry is used to store window position and file name MRU, but the code is wrapped in #if blocks. If you want to store the information in the registry, add the following code to the top of FileDialog.cs: #define REGISTRY_SUPPORT.

How to Implement IShellBrowser

I'm now going to explain how to implement the IShellBrowser in your own dialog. Start by including NativeMethods.cs (which is included in the source code) into your project, and perhaps change the namespace. Then, add the following attributes and inheritance to your form.

C#
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public partial class Form1: Form, NativeMethods.IShellBrowser, 
                            NativeMethods.IServiceProvider
{
    ...
}

The IShellBrowser interface is used to host the IShellView, and if we don't inherit IServiceProvider, the IShellView will open a new Explorer window every time we browse to a new folder.

Now, add the following member fields:

C#
private NativeMethods.IShellView m_shellView;          // The current IShellView
private IntPtr m_hWndListView;                         // The handle of the listview
private NativeMethods.IShellFolder m_desktopFolder;    // The desktop IShellFolder
private NativeMethods.IShellFolder m_currentFolder;    // The current IShellFolder

private IntPtr m_pidlAbsCurrent;                       // The current absolute pidl
private IntPtr m_desktopPidl;                          // The desktop pidl

private NativeMethods.FOLDERVIEWMODE m_viewMode = NativeMethods.FOLDERVIEWMODE.FVM_LIST;
private NativeMethods.FOLDERFLAGS m_flags = (NativeMethods.FOLDERFLAGS.FWF_SHOWSELALWAYS |
                                             NativeMethods.FOLDERFLAGS.FWF_SINGLESEL |
                                             NativeMethods.FOLDERFLAGS.FWF_NOWEBVIEW);

In the constructor, initialize the desktop PIDL and IShellFolder.

C#
public Form1()
{
    InitializeComponent();

    NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, 
                  (int)SpecialFolder.Desktop, out m_desktopPidl);
    IntPtr desktopFolderPtr;
    NativeMethods.Shell32.SHGetDesktopFolder(out desktopFolderPtr);
    m_desktopFolder = (NativeMethods.IShellFolder)
                       Marshal.GetObjectForIUnknown(desktopFolderPtr);
}

Now, it's time to implement the IShellBrowser interface.

C#
// Return the window handle.
int NativeMethods.IShellBrowser.GetWindow(out IntPtr hwnd)
{
    hwnd = Handle;
    return NativeMethods.S_OK;
}

int NativeMethods.IShellBrowser.ContextSensitiveHelp(int fEnterMode)
{
    return NativeMethods.E_NOTIMPL;
}

// Allows the container to insert its menu groups into the composite menu
// that is displayed when an extended namespace is being viewed or used.
int NativeMethods.IShellBrowser.InsertMenusSB(IntPtr hmenuShared, 
                                              IntPtr lpMenuWidths)
{
    return NativeMethods.E_NOTIMPL;
}

// Installs the composite menu in the view window.
int NativeMethods.IShellBrowser.SetMenuSB(IntPtr hmenuShared, 
    IntPtr holemenuRes, IntPtr hwndActiveObject)
{
    return NativeMethods.E_NOTIMPL;
}

// Permits the container to remove any of its menu elements from the
// in-place composite menu and to free all associated resources.
int NativeMethods.IShellBrowser.RemoveMenusSB(IntPtr hmenuShared)
{
    return NativeMethods.E_NOTIMPL;
}

// Sets and displays status text about the in-place object in the
// container's frame-window status bar.
int NativeMethods.IShellBrowser.SetStatusTextSB(IntPtr pszStatusText)
{
    return NativeMethods.E_NOTIMPL;
}

// Tells Microsoft Windows Explorer
// to enable or disable its modeless dialog boxes.
int NativeMethods.IShellBrowser.EnableModelessSB(bool fEnable)
{
    return NativeMethods.E_NOTIMPL;
}

// Translates accelerator keystrokes intended
// for the browser's frame while the view is active.
int NativeMethods.IShellBrowser.TranslateAcceleratorSB(IntPtr pmsg, short wID)
{
    return NativeMethods.S_OK;
}

// Informs Microsoft Windows Explorer to browse to another folder.
int NativeMethods.IShellBrowser.BrowseObject(IntPtr pidl, uint wFlags)
{
    int hr;
    IntPtr folderTmpPtr;
    NativeMethods.IShellFolder folderTmp;
    IntPtr pidlTmp;

    if (NativeMethods.Shell32.ILIsEqual(pidl, m_desktopPidl))
    {
        // pidl is desktop folder
        pidlTmp = m_desktopPidl;
        folderTmp = m_desktopFolder;
    }
    else if ((wFlags & NativeMethods.SBSP_RELATIVE) != 0)
    {
        // SBSP_RELATIVE - pidl is relative from the current folder
        if ((hr = m_currentFolder.BindToObject(pidl, IntPtr.Zero, 
            ref NativeMethods.IID_IShellFolder,
            out folderTmpPtr)) != NativeMethods.S_OK)
            return hr;
        pidlTmp = NativeMethods.Shell32.ILCombine(m_pidlAbsCurrent, pidl);
        folderTmp = (NativeMethods.IShellFolder)
                     Marshal.GetObjectForIUnknown(folderTmpPtr);
    }
    else
    {
        // SBSP_ABSOLUTE - pidl is an absolute pidl (relative from desktop)
        pidlTmp = NativeMethods.Shell32.ILClone(pidl);
        if ((hr = m_desktopFolder.BindToObject(pidlTmp, IntPtr.Zero, 
            ref NativeMethods.IID_IShellFolder,
            out folderTmpPtr)) != NativeMethods.S_OK)
            return hr;
        folderTmp = (NativeMethods.IShellFolder)
                     Marshal.GetObjectForIUnknown(folderTmpPtr);
    }

    if (folderTmp == null)
    {
        NativeMethods.Shell32.ILFree(pidlTmp);
        return NativeMethods.E_FAIL;
    }

    // Check that we have a new pidl
    if (NativeMethods.Shell32.ILIsEqual(pidlTmp, m_pidlAbsCurrent))
    {
        Marshal.ReleaseComObject(folderTmp);
        NativeMethods.Shell32.ILFree(pidlTmp);
        return NativeMethods.S_OK;
    }

    m_currentFolder = folderTmp;

    NativeMethods.FOLDERSETTINGS fs = new NativeMethods.FOLDERSETTINGS();
    NativeMethods.IShellView lastIShellView = m_shellView;

    if (lastIShellView != null)
        lastIShellView.GetCurrentInfo(ref fs);
        // Copy the old folder settings
    else
    {
        fs = new NativeMethods.FOLDERSETTINGS();
        fs.fFlags = (uint)m_flags;
        fs.ViewMode = (uint)m_viewMode;
    }

    // Create the IShellView
    IntPtr iShellViewPtr;
    hr = folderTmp.CreateViewObject(Handle, 
         ref NativeMethods.IID_IShellView, out iShellViewPtr);
    if (hr == NativeMethods.S_OK)
    {
        m_shellView = (NativeMethods.IShellView)
                       Marshal.GetObjectForIUnknown(iShellViewPtr);

        m_hWndListView = IntPtr.Zero;
        NativeMethods.RECT rc =
            new NativeMethods.RECT(8, 8,
           ClientSize.Width - 8,
           ClientSize.Height - 8);

        int res;

        try
        {
            // Create the actual list view
            res = m_shellView.CreateViewWindow(lastIShellView, ref fs, 
                  this, ref rc, ref m_hWndListView);
        }
        catch (COMException)
        {
            return NativeMethods.E_FAIL;
        }

        if (res < 0)
            return NativeMethods.E_FAIL;

        // Release the old IShellView
        if (lastIShellView != null)
        {
            lastIShellView.GetCurrentInfo(ref fs);
            lastIShellView.UIActivate((uint)
                NativeMethods.SVUIA_STATUS.SVUIA_DEACTIVATE);
            lastIShellView.DestroyViewWindow();
            Marshal.ReleaseComObject(lastIShellView);
        }

        // Set focus to the IShellView
        m_shellView.UIActivate((uint)
          NativeMethods.SVUIA_STATUS.SVUIA_ACTIVATE_FOCUS);
        m_pidlAbsCurrent = pidlTmp;
    }

    return NativeMethods.S_OK;
}

// This method is used to save and restore the persistent state for a view
// (the icon positions, the column widths,
//  and the current scroll position, for example). 
int NativeMethods.IShellBrowser.GetViewStateStream(uint grfMode, IntPtr ppStrm)
{
    return NativeMethods.E_NOTIMPL;
}

// GetControlWindow is used so views
// can directly manipulate the browser's controls.
int NativeMethods.IShellBrowser.GetControlWindow(uint id, out IntPtr phwnd)
{
    phwnd = IntPtr.Zero;
    return NativeMethods.S_FALSE;
}

// Sends control messages to either the toolbar or the status bar
// in a Microsoft Windows Explorer window.
int NativeMethods.IShellBrowser.SendControlMsg(uint id, uint uMsg, 
                  uint wParam, uint lParam, IntPtr pret)
{
    return NativeMethods.E_NOTIMPL;
}

// Retrieves the currently active (displayed) Shell view object.
int NativeMethods.IShellBrowser.QueryActiveShellView(
                  ref NativeMethods.IShellView ppshv)
{
    Marshal.AddRef(Marshal.GetIUnknownForObject(m_shellView));
    ppshv = m_shellView;
    return NativeMethods.S_OK;
}

// This method informs the browser that the view is getting the focus
// (when the mouse is clicked on the view, for example).
int NativeMethods.IShellBrowser.OnViewWindowActive(NativeMethods.IShellView pshv)
{
    return NativeMethods.E_NOTIMPL;
}

// Adds toolbar items to Microsoft Windows Explorer's toolbar.
int NativeMethods.IShellBrowser.SetToolbarItems(IntPtr lpButtons, 
                                uint nButtons, uint uFlags)
{
    return NativeMethods.E_NOTIMPL;
}

The only important methods in this simple implementation is GetWindow, BrowseObject, and QueryActiveShellView. All the methods aren't necessary; also, note that the BrowseObject method just contains the basic functionality. In the demo, the BrowseObject contains more functionality such as go to parent.

Let's continue by implementing the IServiceProvider interface.

C#
int NativeMethods.IServiceProvider.QueryService(ref Guid guidService, 
                  ref Guid riid, out NativeMethods.IShellBrowser ppvObject)
{
    if (riid == NativeMethods.IID_IShellBrowser)
    {
        ppvObject = this;
        return NativeMethods.S_OK;
    }

    ppvObject = null;
    return NativeMethods.E_NOINTERFACE;
}

When you double-click on a folder, the IShellView first calls IServiceProvier::QueryService() for an IShellBrowser interface, and it finds that the IShellBrowser::BrowseObject() is invoked with the PIDL of the new folder and does nothing (i.e., waits for you to open the new folder). If you don't implement IServiceProvider (or don't return an IShellBrowser from QueryService), IShellView just launches a whole new Windows Explorer to display the new folder.

Now, the only thing that remains is the startup and cleanup.

C#
protected override void OnHandleCreated(EventArgs e)
{
    base.OnHandleCreated(e);

    ((NativeMethods.IShellBrowser)this).BrowseObject(m_desktopPidl, 
                                        NativeMethods.SBSP_ABSOLUTE);
}

protected override void OnHandleDestroyed(EventArgs e)
{
    m_pidlAbsCurrent = IntPtr.Zero;

    // Release the IShellView
    if (m_shellView != null)
    {
        m_shellView.UIActivate((uint)NativeMethods.SVUIA_STATUS.SVUIA_DEACTIVATE);
        m_shellView.DestroyViewWindow();
        Marshal.ReleaseComObject(m_shellView);
        m_shellView = null;
    }

    base.OnHandleDestroyed(e);
}

Points of Interest

One of the hardest things was to figure out which interfaces should be used and how they should be declared. I had to manually handle many things such as keyboard input and filtering. During the development, I found out the following:

  • The IShellBrowser.BrowseObject method isn't called for 'My Documents'.
  • The WM_GETISHELLBROWSER message is never sent.

History

  • 30 Aug 2008

    Initial posting.

  • 24 Sep 2008
    • Fixed some issues concerning the OK and Cancel buttons, when the Enter key was pressed.
    • Fixed a simple bug causing the overwrite prompt to show twice.
    • Fixed a problem with the auto-complete when using absolute paths.
    • Added the SelectFolderDialog component which can be used as a more advanced FolderBrowserDialog.
  • 10 Oct 2008
    • Updated article image.
    • Fixed a problem when creating a new folder the traditional way.
    • Fixed an issue in the BrowseObject method causing desktop pidl to be freed.
    • After comparing with Windows and the VS open file dialog, I removed the part in the BrowseObject method where i was checking if I had a new pidl.
    • Fixed an issue with some keys (Enter, Escape, Delete, Left, Up, Right, Down) when renaming an item.
  • 5 May 2009
    • Added support for shortcuts.
    • Fixed some small bugs when saving.
    • Fixed issue concerning the Enter key.
    • Replaced the OK Button with a SplitButton control.
    • Disabled the selection of special folders in the SelectFolderDialog.
    • Added the ability to customize the places in the places bar through a dialog.
    • Removed properties CheckFileExists and CheckPathExists because neihter of them affects the behavior of the FileDialog.
    • Changed the behavior of the FileName property.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer IDesignIT Kungsbacka
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralError - help needed Pin
Gilvinit3-Feb-09 2:37
Gilvinit3-Feb-09 2:37 
AnswerRe: Error - help needed Pin
Frohmen3-Feb-09 7:53
Frohmen3-Feb-09 7:53 
GeneralRe: Error - help needed Pin
Gilvinit3-Feb-09 9:01
Gilvinit3-Feb-09 9:01 
GeneralSmall bug ! Pin
Rumio7-Dec-08 17:41
Rumio7-Dec-08 17:41 
GeneralRe: Small bug ! Pin
Gee.21-Jan-09 10:59
Gee.21-Jan-09 10:59 
QuestionI want to dont display contextmenu in listview Pin
zahra nessri3-Nov-08 19:39
zahra nessri3-Nov-08 19:39 
GeneralThank you! and some modifications PinPopular
SlingBlade20-Oct-08 15:21
SlingBlade20-Oct-08 15:21 
GeneralRe: Thank you! and some modifications Pin
SlingBlade20-Oct-08 15:54
SlingBlade20-Oct-08 15:54 
SpecialFolder new item:
MyNetwork = 0x12,

FileDialog design Changes:

FileDialog.MinimumSize = new Size(600, 420);

FileDialog member changes:
// 10/20/2008: Changes for new features
// Changed from read only to change size for DesktopOnly feature.
private static Padding FileViewPadding = new Padding(96, 28, 5, 53);

// My Property mebers
private bool m_DesktopOnly;
private bool m_FolderSelect;
private bool m_HideSpecialFolders;
// Special folders to use for placesBar and hiding.
private IntPtr m_myNetPidl;
private string m_myNetPath;
private string m_myNetName;
private IntPtr m_recentPidl;
private string m_recentPath;
private string m_recentName;
// End 10/20/2008 changes.

FileDialog method changes:
FileDialog.Init() changes:
// 10/20/2008: Changed to initialize more special folders.
private void Init()
{
    NativeMethods.SHFILEINFO info;

    // My Computer
    info = new NativeMethods.SHFILEINFO();
    NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.MyComputer,
                                                     out m_myCompPidl);
    NativeMethods.Shell32.SHGetFileInfo(m_myCompPidl, 0, ref info, NativeMethods.cbFileInfo,
                                        NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
    m_myCompName = info.szDisplayName;

    // My Network
    info = new NativeMethods.SHFILEINFO();
    NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.MyNetwork,
                                                     out m_myNetPidl);
    NativeMethods.Shell32.SHGetFileInfo(m_myNetPidl, 0, ref info, NativeMethods.cbFileInfo,
                                        NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
    m_myNetName = info.szDisplayName;

    // Recent Documents
    info = new NativeMethods.SHFILEINFO();
    NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.Recent,
                                                     out m_recentPidl);
    NativeMethods.Shell32.SHGetFileInfo(m_recentPidl, 0, ref info, NativeMethods.cbFileInfo,
                                        NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
    m_recentName = info.szDisplayName;

    // Desktop
    NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.Desktop, out m_desktopPidl);
    IntPtr desktopFolderPtr;
    NativeMethods.Shell32.SHGetDesktopFolder(out desktopFolderPtr);
    m_desktopFolder = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(desktopFolderPtr);
    m_desktopPath = GetDisplayName(m_desktopFolder, m_desktopPidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
    m_currentFolder = m_desktopFolder;

    // My Documents
    NativeMethods.SHGFAO pdwAttributes = 0;
    m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, NativeMethods.CLSID_MyDocuments, IntPtr.Zero,
                                     out m_myDocsPidl, pdwAttributes);
    info = new NativeMethods.SHFILEINFO();
    NativeMethods.Shell32.SHGetFileInfo(m_myDocsPidl, 0, ref info, NativeMethods.cbFileInfo,
                                        NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
    m_myDocsName = info.szDisplayName;
    m_myDocsPath = GetDisplayName(m_desktopFolder, m_myDocsPidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
    m_myNetPath = GetDisplayName(m_desktopFolder, m_myNetPidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
    m_recentPath = GetDisplayName(m_desktopFolder, m_recentPidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
}

FileDialog.InitPlacesBar() changes:
// Initialize the places bar
// 10/20/2008: Changed to add My Recent Documents and My Network Places.
private void InitPlacesBar()
{
    int lineLimit = 13;
    // Recent Documents
    ToolStripButton recentDocumentsButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.Recent));
    recentDocumentsButton.Tag = m_recentPidl;
    recentDocumentsButton.Text = this.InsertLineBreaks(m_recentName, lineLimit);
    placesBar.Items.Add(recentDocumentsButton);

    // Desktop
    ToolStripButton desktopButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.Desktop));
    desktopButton.Tag = m_desktopPidl;
    desktopButton.Text = this.InsertLineBreaks(GetDisplayName(m_desktopFolder, m_desktopPidl, NativeMethods.SHGNO.SHGDN_INFOLDER), lineLimit);
    placesBar.Items.Add(desktopButton);

    // My Documents
    ToolStripButton myDocsButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.MyDocuments));
    myDocsButton.Tag = m_myDocsPidl;
    myDocsButton.Text = this.InsertLineBreaks(m_myDocsName, lineLimit);
    placesBar.Items.Add(myDocsButton);

    // My Computer
    ToolStripButton myCompButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.MyComputer));
    myCompButton.Tag = m_myCompPidl;
    myCompButton.Text = this.InsertLineBreaks(m_myCompName, lineLimit);
    placesBar.Items.Add(myCompButton);

    // My Network Places
    ToolStripButton myNetButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.MyNetwork));
    myNetButton.Tag = m_myNetPidl;
    myNetButton.Text = this.InsertLineBreaks(m_myNetName, lineLimit);
    placesBar.Items.Add(myNetButton);

    // TODO: Uncomment the following if you wan't to add more places

    //IntPtr pidl;
    //m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, @"C:\Inetpub\wwwroot", IntPtr.Zero, out pidl, 0);

    //placesBar.Items.Add(GetDisplayName(m_desktopFolder, pidl), ShellImageList.GetImage(pidl));
    //placesBar.Items[3].Tag = pidl;

    foreach (ToolStripItem placeItem in placesBar.Items)
    {
        placeItem.Margin = new Padding(1, 0, 0, 0);
        placeItem.Padding = new Padding(0, 8, 0, 8);
        placeItem.ImageAlign = ContentAlignment.BottomCenter;
        placeItem.TextImageRelation = TextImageRelation.ImageAboveText;
    }
}

// 10/20/2008: New method because ToolStripButtons don't wrap on there own.
private string InsertLineBreaks(string text, int lineLimit)
{
    string[] splitText = text.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
    text = "";
    int charactersOnCurrentLine = 0;
    for (int wordIndex = 0; wordIndex < splitText.Length; wordIndex++)
    {
        string word = splitText[wordIndex];
        if (word.Length + charactersOnCurrentLine + 1 <= lineLimit)
        {
            if (charactersOnCurrentLine != 0)
                text += " ";
            text += word;
            charactersOnCurrentLine += word.Length + 1;
        }
        else
        {
            text += "\r\n" + word;
            charactersOnCurrentLine = word.Length;
        }
    }
    return text;
}

FileDialog.OnFileOK(object sender, EventArgs e) changes:
// 10/20/2008: Changed to allow folder selection.
 protected virtual void OnFileOK(object sender, EventArgs e)
 {
     if (m_selectedPidls != null && m_selectedPidls.Length > 0)
     {
         // Check if the first item is a folder.
         // It would be better to check against the SFGAO_BROWSABLE attribute, but it is never set.
         // Instead check against the SFGAO_STREAM attribute, to assure that the item isn't a file.
         IntPtr[] pidls = new IntPtr[] { m_selectedPidls[0] };
         NativeMethods.SHGFAO attribs = NativeMethods.SHGFAO.SFGAO_STREAM;
         m_currentFolder.GetAttributesOf(1, pidls, ref attribs);

         // 10/20/2008: Changed to enable setting folder selection with the FolderSelect property.
         if ((attribs & NativeMethods.SHGFAO.SFGAO_STREAM) == 0 && !this.FolderSelect)
         {
             ((NativeMethods.IShellBrowser)this).BrowseObject(m_selectedPidls[0], NativeMethods.SBSP_RELATIVE);
         }
         else
         {
             int index = 0;
             string[] fileNames = new string[m_selectedPidls.Length];
             fileNames[0] =
                 GetDisplayName(m_currentFolder, m_selectedPidls[0], NativeMethods.SHGNO.SHGDN_FORPARSING);

             for (int i = 1; i < m_selectedPidls.Length; i++)
             {
                 pidls = new IntPtr[] { m_selectedPidls[i] };
                 attribs = NativeMethods.SHGFAO.SFGAO_STREAM;
                 m_currentFolder.GetAttributesOf(1, pidls, ref attribs);

                 // 10/20/2008: Changed to enable setting folder selection with the FolderSelect property.
                 if ((attribs & NativeMethods.SHGFAO.SFGAO_STREAM) == NativeMethods.SHGFAO.SFGAO_STREAM || this.FolderSelect)
                 {
                   fileNames[++index] =
                       GetDisplayName(m_currentFolder, m_selectedPidls[i], NativeMethods.SHGNO.SHGDN_FORPARSING);
                 }
             }

             if (fileNames.Length > index + 1)
                 Array.Resize(ref fileNames, index + 1);

             if (!File.Exists(fileNames[0]) || PromptFileOverwrite(Path.GetFileName(fileNames[0])))
             {
                 m_fileNames = fileNames;
                 DialogResult = DialogResult.OK;
             }
         }
     }
     else
     {
         string path = fileNameComboBox.Text, driveName;
         string trimmedPath = path.Trim();
         if (path != trimmedPath)
         {
             m_ignoreFileNameChange = true;

             path = trimmedPath;
             fileNameComboBox.Text = trimmedPath;
         }

         if (string.IsNullOrEmpty(path))
         {
             if (!string.IsNullOrEmpty(m_currentFilePattern) && m_shellView != null)
             {
                 m_currentFilePattern = string.Empty;
                 m_shellView.Refresh(); // Causes the ICommDlgBrowser::IncludeObject to be called
             }

             return;
         }

         bool lastCharIsSeparator = (path[path.Length - 1] == Path.DirectorySeparatorChar);

         UpdateFileNameMRU(path);

         bool isPathRooted = Path.IsPathRooted(path);
         string orgPath = path;
         if (!isPathRooted)
             path =
                 Path.Combine(
                     GetDisplayName(m_desktopFolder, m_pidlAbsCurrent, NativeMethods.SHGNO.SHGDN_FORPARSING),
                     path);

         //string rootedPath = path;
         if (path.Contains(".."))
             path = Path.GetFullPath(path);

         if (Directory.Exists(path))
         {
             //if (!isPathRooted)
             //{
             //    IntPtr pidl;
             //    m_currentFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, orgPath, IntPtr.Zero, out pidl, 0);
             //    ((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_RELATIVE);
             //}
             //else
             //{
             IntPtr pidl;
             m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, path, IntPtr.Zero, out pidl, 0);
             ((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_ABSOLUTE);
             //}

             fileNameComboBox.Text = string.Empty;
             return;
         }
         // If the path root is a drive make sure it's available
         else if (path.Length <= 3 && PathUtils.PathRootIsDrive(path, out driveName))
         {
             DriveInfo di = new DriveInfo(driveName);
             if (di.DriveType == DriveType.CDRom)
             {
                 // The drive is an optical disk drive
                 string message = "The selected disk drive is not in use. Check to make sure a disk is inserted.";
                 while (!di.IsReady)
                 {
                     // Loop until a disk is inserted or cancel is clicked
                     if (
                         MessageBoxWithFocusRestore(message, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) ==
                         DialogResult.Cancel)
                     {
                         fileNameComboBox.SelectAll();
                         return;
                     }
                 }
             }
             else if (di.DriveType == DriveType.NoRootDirectory)
             {
                 // The drive does not have a root directory, e.g. an unconnected network drive
                 string message =
                     string.Format("The drive '{0}' is not valid. Enter a valid drive letter.",
                                   driveName.Substring(0, 2));
                 MessageBoxWithFocusRestore(message, MessageBoxButtons.OK, MessageBoxIcon.Information);
                 fileNameComboBox.SelectAll();
                 return;
             }

             IntPtr pidl;
             m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, driveName, IntPtr.Zero, out pidl, 0);
             ((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_ABSOLUTE);

             fileNameComboBox.Text = string.Empty;
             return;
         }
         else if (lastCharIsSeparator) // TODO: Find out what to do when m_pathMustExist != true
         {
             string message =
                 string.Format(
                     @"The folder '{0}' isn't accessible. The folder may be located in an unavailable location, protected with a password, or the filename contains a / or \.",
                     path);
             MessageBoxWithFocusRestore(message, MessageBoxButtons.OK, MessageBoxIcon.Information);

             fileNameComboBox.SelectAll();
             return;
         }

         string parentPath = Path.GetDirectoryName(path);

         if (File.Exists(path))
         {
             if (PromptFileOverwrite(Path.GetFileName(path)))
             {
                 FileName = path;
                 DialogResult = DialogResult.OK;
                 return;
             }
         }
         else if (Directory.Exists(parentPath))
         {
             string currentPath =
                 GetDisplayName(m_desktopFolder, m_pidlAbsCurrent, NativeMethods.SHGNO.SHGDN_FORPARSING);

             if (!isPathRooted)
             {
                 if (parentPath != currentPath)
                 {
                     IntPtr pidl;
                     m_currentFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, Path.GetDirectoryName(orgPath),
                                                      IntPtr.Zero, out pidl, 0);
                     ((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_RELATIVE);
                     fileNameComboBox.Text = Path.GetFileName(orgPath);
                 }
                 PromptFileCreate();
             }
             else
             {
                 if (parentPath != currentPath)
                 {
                     IntPtr pidl;
                     m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, parentPath, IntPtr.Zero, out pidl,
                                                      0);
                     ((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_ABSOLUTE);
                     fileNameComboBox.Text = Path.GetFileName(path);
                 }
                 PromptFileCreate();
             }
         }
         else // TODO: Find out what to do when m_fileMustExist != false
         {
             if (PromptFileCreate())
             {
                 FileName = path;
                 DialogResult = DialogResult.OK;
                 return;
             }
         }
     }
 }

FileDialog.NativeMethods.IShellBrowser.BrowseObject(IntPtr pidl, uint wFlags) changes:
// Informs Microsoft Windows Explorer to browse to another folder.
// 10/20/2008: Change to restrict browsing away from the desktop.
int NativeMethods.IShellBrowser.BrowseObject(IntPtr pidl, uint wFlags)
{
    int hr;
    IntPtr folderTmpPtr;
    NativeMethods.IShellFolder folderTmp = null;
    IntPtr pidlTmp = IntPtr.Zero;

    if (NativeMethods.Shell32.ILIsEqual(pidl, m_desktopPidl))
    {
        // pidl is desktop folder
        pidlTmp = NativeMethods.Shell32.ILClone(m_desktopPidl);
        folderTmp = m_desktopFolder;
    }
    else if ((wFlags & NativeMethods.SBSP_RELATIVE) != 0)
    {
        // SBSP_RELATIVE - pidl is relative from the current folder
        if ((hr = m_currentFolder.BindToObject(pidl, IntPtr.Zero, ref NativeMethods.IID_IShellFolder,
                                               out folderTmpPtr)) != NativeMethods.S_OK)
            return hr;
        pidlTmp = NativeMethods.Shell32.ILCombine(m_pidlAbsCurrent, pidl);
        folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr);
    }
    else if ((wFlags & NativeMethods.SBSP_PARENT) != 0)
    {
        // SBSP_PARENT - Browse the parent folder (ignores the pidl)
        pidlTmp = GetParentPidl(m_pidlAbsCurrent);
        string pathTmp = GetDisplayName(m_desktopFolder, pidlTmp, NativeMethods.SHGNO.SHGDN_FORPARSING);
        if (pathTmp.Equals(m_desktopPath))
            folderTmp = m_desktopFolder;
        else
        {
            if ((hr = m_desktopFolder.BindToObject(pidlTmp, IntPtr.Zero, ref NativeMethods.IID_IShellFolder,
                                                   out folderTmpPtr)) != NativeMethods.S_OK)
                return hr;
            folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr);
        }
    }
    else
    {
        // SBSP_ABSOLUTE - pidl is an absolute pidl (relative from desktop)
        pidlTmp = NativeMethods.Shell32.ILClone(pidl);
        if ((hr = m_desktopFolder.BindToObject(pidlTmp, IntPtr.Zero, ref NativeMethods.IID_IShellFolder,
                                               out folderTmpPtr)) != NativeMethods.S_OK)
            return hr;
        folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr);
    }

    if (folderTmp == null)
    {
        NativeMethods.Shell32.ILFree(pidlTmp);
        return NativeMethods.E_FAIL;
    }

    string path = GetDisplayName(m_desktopFolder, pidlTmp, NativeMethods.SHGNO.SHGDN_FORPARSING);

    // FIX: Force the special folder My documents
    if (path == m_myDocsPath && !NativeMethods.Shell32.ILIsEqual(pidlTmp, m_myDocsPidl))
    {
        NativeMethods.Shell32.ILFree(pidlTmp);
        pidlTmp = NativeMethods.Shell32.ILClone(m_myDocsPidl);
    }

    // If the path root is a drive make sure it's available
    string driveName;
    if (PathUtils.PathRootIsDrive(path, out driveName))
    {
        DriveInfo di = new DriveInfo(driveName);
        if (di.DriveType == DriveType.CDRom)
        {
            // The drive is an optical disk drive
            string message = "The selected disk drive is not in use. Check to make sure a disk is inserted.";
            while (!di.IsReady)
            {
                // Loop until a disk is inserted or cancel is clicked
                if (MessageBoxWithFocusRestore(message, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) ==
                    DialogResult.Cancel)
                    return NativeMethods.S_OK;
            }
        }
        else if (di.DriveType == DriveType.NoRootDirectory)
        {
            // The drive does not have a root directory, e.g. an unconnected network drive
            string message =
                string.Format("The drive '{0}' is not valid. Enter a valid drive letter.",
                              driveName.Substring(0, 2));
            MessageBoxWithFocusRestore(message, MessageBoxButtons.OK, MessageBoxIcon.Information);
            return NativeMethods.S_OK;
        }
    }

    // 10/20/2008: Changed to restrict browsing away from the desktop.
    if (!this.DesktopOnly || NativeMethods.Shell32.ILIsEqual(pidl, m_desktopPidl))
    {
        m_currentFolder = folderTmp;

        NativeMethods.FOLDERSETTINGS fs = new NativeMethods.FOLDERSETTINGS();
        NativeMethods.IShellView lastIShellView = m_shellView;

        if (lastIShellView != null)
            lastIShellView.GetCurrentInfo(ref fs); // Copy the old folder settings
        else
        {
            fs = new NativeMethods.FOLDERSETTINGS();
            fs.fFlags = (uint)m_flags;
            fs.ViewMode = (uint)m_viewMode;
        }
        // Create the IShellView
        IntPtr iShellViewPtr;
        hr = folderTmp.CreateViewObject(Handle, ref NativeMethods.IID_IShellView, out iShellViewPtr);
        if (hr == NativeMethods.S_OK)
        {
            m_shellView = (NativeMethods.IShellView)Marshal.GetObjectForIUnknown(iShellViewPtr);

            m_hWndListView = IntPtr.Zero;
            NativeMethods.RECT rc =
                new NativeMethods.RECT(FileViewPadding.Left, FileViewPadding.Top,
                                       ClientSize.Width - FileViewPadding.Right,
                                       ClientSize.Height - FileViewPadding.Bottom);

            int res;
            try
            {
                // Create the list view
                res = m_shellView.CreateViewWindow(lastIShellView, ref fs, this, ref rc, ref m_hWndListView);
            }
            catch (COMException)
            {
                return NativeMethods.E_FAIL;
            }

            if (res < 0)
                return NativeMethods.E_FAIL;

            bool shellViewHasFocus = m_shellViewHasFocus;
            // Release the old IShellView
            if (lastIShellView != null)
            {
                lastIShellView.GetCurrentInfo(ref fs);
                lastIShellView.UIActivate((uint)NativeMethods.SVUIA_STATUS.SVUIA_DEACTIVATE);
                lastIShellView.DestroyViewWindow();
                Marshal.ReleaseComObject(lastIShellView);
            }

            // Give the new IShellView focus if the old one had focus
            m_shellView.UIActivate(shellViewHasFocus
                                       ? (uint)NativeMethods.SVUIA_STATUS.SVUIA_ACTIVATE_FOCUS
                                       : (uint)NativeMethods.SVUIA_STATUS.SVUIA_ACTIVATE_NOFOCUS);
            IntPtr previousPidl = m_pidlAbsCurrent;
            m_pidlAbsCurrent = pidlTmp;
            UpdateUI(previousPidl);

            // Clear the selection
            m_selectedPidls = null;
            OnSelectionChanged();
        }
    }
    // End 10/20/2008 changes.

    return NativeMethods.S_OK;
}

FileDialog.OnSelectionChanged() changes:
// 10/20/2008: Changed to display file names in the fileNameComboBox.
protected virtual void OnSelectionChanged()
{
    if (m_selectedPidls == null)
        fileNameComboBox.Text = "";
    else
    {
        if (this.FolderSelect)
        {
            for (int pidlIndex = 0; pidlIndex < this.m_selectedPidls.Length; pidlIndex++)
            {
                m_ignoreFileNameChange = true;
                if (pidlIndex == 0 && m_selectedPidls.Length == 1)
                    fileNameComboBox.Text = GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]);
                else if (pidlIndex == 0)
                    fileNameComboBox.Text = "\"" + GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]) + "\"";
                else
                    fileNameComboBox.Text += " \"" + GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]) + "\"";
            }
        }
        else
        {
            bool firstListed = false;
            bool secondListed = false;

            for (int pidlIndex = 0; pidlIndex < this.m_selectedPidls.Length; pidlIndex++)
            {
                IntPtr[] pidls = new IntPtr[] { m_selectedPidls[pidlIndex] };
                NativeMethods.SHGFAO attribs = NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR |
                                               NativeMethods.SHGFAO.SFGAO_STREAM |
                                               NativeMethods.SHGFAO.SFGAO_NEWCONTENT;
                m_currentFolder.GetAttributesOf(1, pidls, ref attribs);
                bool isFile = ((attribs & NativeMethods.SHGFAO.SFGAO_STREAM) == NativeMethods.SHGFAO.SFGAO_STREAM);

                if (isFile)
                    m_ignoreFileNameChange = true;

                if (m_selectedPidls.Length == 1 && isFile)
                {
                    fileNameComboBox.Text = GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]);
                    firstListed = true;
                }
                else if (!firstListed && isFile)
                {
                    fileNameComboBox.Text = "\"" + GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]) + "\"";
                    firstListed = true;
                }
                else if (isFile)
                {
                    fileNameComboBox.Text += " \"" + GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]) + "\"";
                    secondListed = true;
                }
            }

            if (!firstListed)
            {
                m_ignoreFileNameChange = true;
                fileNameComboBox.Text = "";
            }
            else if (!secondListed && m_selectedPidls.Length > 1)
            {
                m_ignoreFileNameChange = true;
                fileNameComboBox.Text = fileNameComboBox.Text.Replace("\"", "");
            }
        }
    }
}

FileDialog.NativeMethods.ICommDlgBrowser.IncludeObject(IntPtr ppshv, IntPtr pidl) changes:
// Allows the common dialog box to filter objects that the view displays.
// 10/20/2008: Changed to allow hiding of special folders.
int NativeMethods.ICommDlgBrowser.IncludeObject(IntPtr ppshv, IntPtr pidl)
{
    IntPtr strr = Marshal.AllocCoTaskMem(NativeMethods.MAX_PATH * 2 + 4);
    Marshal.WriteInt32(strr, 0, 0);
    StringBuilder buf = new StringBuilder(NativeMethods.MAX_PATH);

    IntPtr[] pidls = new IntPtr[] { pidl };
    NativeMethods.SHGFAO attribs = NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR |
                                   NativeMethods.SHGFAO.SFGAO_STREAM |
                                   NativeMethods.SHGFAO.SFGAO_NEWCONTENT;
    m_currentFolder.GetAttributesOf(1, pidls, ref attribs);
    bool isFile = ((attribs & NativeMethods.SHGFAO.SFGAO_STREAM) == NativeMethods.SHGFAO.SFGAO_STREAM);

    // 10/20/2008: Changed to allow hiding of special folders.
    if (!isFile && this.HideSpecialFolders)
    {
        if (NativeMethods.Shell32.ILIsEqual(pidl, this.m_myDocsPidl)
            || NativeMethods.Shell32.ILIsEqual(pidl, this.m_myCompPidl)
            || NativeMethods.Shell32.ILIsEqual(pidl, this.m_myNetPidl))
            return NativeMethods.S_FALSE;
    }
    // End 10/20/2008 changes.

    if (m_excludeFiles && (isFile || (attribs & NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR) == 0))
        return NativeMethods.S_FALSE;
    else if (!isFile && (attribs & NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR) == 0)
        return NativeMethods.S_FALSE;

    if (m_currentFolder.GetDisplayNameOf(
            pidl,
            NativeMethods.SHGNO.SHGDN_FORPARSING,
            strr) == NativeMethods.S_OK)
    {
        NativeMethods.Shlwapi.StrRetToBuf(strr, pidl, buf, NativeMethods.MAX_PATH);
        string path = buf.ToString();
        string name = path.Substring(path.LastIndexOf('\\') + 1);

        // If the object is a newly created folder browser to that folder
        if (CreateNewFolder(path, pidl))
            return NativeMethods.S_OK;

        if (m_excludeFiles)
            return NativeMethods.S_OK;

        FileType fileType = (FileType)fileTypeComboBox.SelectedItem;
        if (m_currentFilePattern != string.Empty)
        {
            // If the object is a file and the file doesn't math the pattern, don't include the object
            if (isFile && !Regex.IsMatch(name, m_currentFilePattern, RegexOptions.Compiled))
                return NativeMethods.S_FALSE;
        }
        else if (fileType != null)
        {
            if (fileType.IncludeAllFiles)
                return NativeMethods.S_OK;

            // If the object is a file and the file doesn't math the pattern, don't include the object
            if (isFile && !Regex.IsMatch(name, fileType.FilterPattern, RegexOptions.Compiled))
                return NativeMethods.S_FALSE;
        }
    }

    return NativeMethods.S_OK;
}

New FileDialog properties:
/// <summary>
/// Gets or sets a value indicating whether the dialog box
/// does not allow navigation away from the desktop.
/// </summary>
/// <value>
/// true if the dialog boxdoes not allow navigation away
/// from the desktop; otherwise, false. The default value
/// is false.
/// </value>
[Description("Indicates whether the dialog box does not allow navigation away from the desktop.")]
[Category("Behavior")]
[DefaultValue(false)]
public bool DesktopOnly
{
    get { return this.m_DesktopOnly; }
    set
    {
        this.m_DesktopOnly = value;
        if (value)
        {
            this.lookInComboBox.Enabled = false;
            this.lookInLabel.Enabled = false;
            this.placesBar.Visible = false;
            this.fileNameLabel.Location = new Point(5, this.fileNameLabel.Location.Y);
            this.fileTypeLabel.Location = new Point(5, this.fileTypeLabel.Location.Y);
            this.fileTypeComboBox.Location = new Point(81, this.fileTypeComboBox.Location.Y);
            this.fileNameComboBox.Location = new Point(81, this.fileNameComboBox.Location.Y);
            this.fileNameComboBox.Width += 90;
            this.fileTypeComboBox.Width += 90;
            FileViewPadding = new Padding(5, 28, 5, 53);
        }
        else
        {
            this.lookInComboBox.Enabled = true;
            this.lookInLabel.Enabled = true;
            this.placesBar.Visible = true;
            this.fileNameLabel.Location = new Point(95, this.fileNameLabel.Location.Y);
            this.fileTypeLabel.Location = new Point(95, this.fileTypeLabel.Location.Y);
            this.fileTypeComboBox.Location = new Point(171, this.fileTypeComboBox.Location.Y);
            this.fileNameComboBox.Location = new Point(171, this.fileNameComboBox.Location.Y);
            this.fileNameComboBox.Width -= 90;
            this.fileTypeComboBox.Width -= 90;
            FileViewPadding = new Padding(96, 28, 5, 53);
        }
    }
}

/// <summary>
/// Gets or sets a value indicating whether the dialog box
/// allows folders to be selected.
/// </summary>
/// <value>
/// true if the dialog box allows folders to be selected;
/// otherwise, false. The default value is false.
/// </value>
[Description("Indicates whether the dialog box allows folders to be selected.")]
[Category("Behavior")]
[DefaultValue(false)]
public bool FolderSelect
{
    get { return m_FolderSelect; }
    set { m_FolderSelect = value; }
}

/// <summary>
/// Gets or sets a value indicating whether the dialog box
/// hides special folders.
/// </summary>
/// <value>
/// true if the dialog box hides special folders; otherwise,
/// false. The default value is false.
/// </value>
[Description("Indicates whether the dialog box hides special folders.")]
[Category("Behavior")]
[DefaultValue(false)]
public bool HideSpecialFolders
{
    get { return m_HideSpecialFolders; }
    set { m_HideSpecialFolders = value; }
}

/// <summary>
/// Gets or sets the string to display on the title bar of
/// the dialog box.
/// <summary>
[Description("The string to display on the title bar of the dialog box.")]
[Category("Appearance")]
public string Title
{
    get { return this.Text; }
    set { this.Text = value; }
}

GeneralUnable to unzip FileDialogs_src.zip Pin
cp2008042813-Oct-08 10:43
cp2008042813-Oct-08 10:43 
GeneralRe: Unable to unzip FileDialogs_src.zip Pin
Gee.27-Nov-08 23:49
Gee.27-Nov-08 23:49 
GeneralRe: Unable to unzip FileDialogs_src.zip Pin
DaBombNL18-Dec-09 18:34
DaBombNL18-Dec-09 18:34 
GeneralIncorrect FOLDERVIEWMODE Attribute Pin
cp2008042813-Oct-08 10:23
cp2008042813-Oct-08 10:23 
GeneralQueryContextMenu returns a more complex response Pin
cp2008042829-Sep-08 7:08
cp2008042829-Sep-08 7:08 
NewsRe: QueryContextMenu returns a more complex response [modified] Pin
Frohmen3-Oct-08 23:13
Frohmen3-Oct-08 23:13 
GeneralUnhandled exception Pin
Emil - Gabriel24-Sep-08 22:31
Emil - Gabriel24-Sep-08 22:31 
GeneralRe: Unhandled exception Pin
Frohmen25-Sep-08 3:00
Frohmen25-Sep-08 3:00 
AnswerRe: Unhandled exception [modified] Pin
cp2008042829-Sep-08 9:41
cp2008042829-Sep-08 9:41 
AnswerRe: Unhandled exception Pin
cp2008042829-Sep-08 10:03
cp2008042829-Sep-08 10:03 
NewsRe: Unhandled exception Pin
Frohmen3-Oct-08 23:08
Frohmen3-Oct-08 23:08 
QuestionWhat about WPF? Pin
mbelli24-Sep-08 20:37
mbelli24-Sep-08 20:37 
AnswerRe: What about WPF? Pin
Frohmen25-Sep-08 2:18
Frohmen25-Sep-08 2:18 
AnswerRe: What about WPF? Pin
The Cake of Deceit4-May-09 7:27
The Cake of Deceit4-May-09 7:27 
QuestionCan this be used to create a dialog... Pin
Member 375945124-Sep-08 20:29
Member 375945124-Sep-08 20:29 
AnswerRe: Can this be used to create a dialog... Pin
Frohmen25-Sep-08 2:40
Frohmen25-Sep-08 2:40 
QuestionVista compatibly Pin
The Cake of Deceit1-Sep-08 23:51
The Cake of Deceit1-Sep-08 23:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.