在Windows窗体应用程序窗体中嵌入文件资源管理器实例

时间:2023-01-17 08:35:35

My (C#, .NET 3.5) application generates files and, in addition to raising events that can be caught and reacted to, I want to display the target folder to the user in a form. The file-list is being shown within the same form as other information.

我的(C#,.NET 3.5)应用程序生成文件,除了引发可以捕获和响应的事件之外,我还想在表单中向用户显示目标文件夹。文件列表显示在与其他信息相同的表单中。

I'm using an instance of the WebBrowser control (System.Windows.Forms.WebBrowser), then navigating to the folder. This shows some default view of the explorer window, with the file summary panel on the left and the files in the 'Tiles' (large icon and text) view.

我正在使用WebBrowser控件的一个实例(System.Windows.Forms.WebBrowser),然后导航到该文件夹​​。这将显示资源管理器窗口的一些默认视图,左侧是文件摘要面板,“Tiles”(大图标和文本)视图中的文件。

For example,

wb.Navigate(@"c:\path\to\folder\");

I'd like to suppress the panel and to view the file list in the Details view. The user can get to this via a right-click, context menu, but I'd like it to come up automatically.

我想压缩面板并在详细信息视图中查看文件列表。用户可以通过右键单击上下文菜单来实现此目的,但我希望它能自动生成。

I'd rather not have to build my own TreeView, DataGridView or whatever; the WebBrowser control does all the updating and re-sorting and whatnot 'for free'.

我宁愿不必构建自己的TreeView,DataGridView或其他任何东西; WebBrowser控件执行所有更新和重新排序,以及“免费”。

Is there a better way? A different control to use or some additional arguments to pass to the control?

有没有更好的办法?使用不同的控件或传递给控件的其他参数?

And if I could trap events (for example, files being selected/renamed/double-clicked, etc.) then all the better!

如果我可以捕获事件(例如,文件被选中/重命名/双击等),那就更好了!

8 个解决方案

#1


In order to handle renaming, deleting and make other customization you need to write your own file explorer. WebBrowser control is not suitable for your needs. It's just a wrapper over ActiveX component.
You should check this codeproject article. It contains an implementation of file explorer. There are few more samples of file browser:
one
two

为了处理重命名,删除和进行其他自定义,您需要编写自己的文件资源管理器。 WebBrowser控件不适合您的需要。它只是ActiveX组件的包装器。您应该检查此代码项目文章。它包含文件资源管理器的实现。文件浏览器的样本数量较少:一两个

#2


WARNING: Long post with lots of code.

警告:包含大量代码的长帖子。

When you navigate the web browser control to a file system folder the web browser control hosts a shell view window that in turn hosts the explorer list view. In fact this is exactly the same thing that the Explorer process does as well as the file dialogs and Internet Explorer. This shell window is not a control so there are no methods that can be called on it or events that can be subscribed to but it can receive windows messages and it can be sub-classed.

将Web浏览器控件导航到文件系统文件夹时,Web浏览器控件将承载一个shell视图窗口,该窗口依次托管资源管理器列表视图。实际上,这与Explorer进程以及文件对话框和Internet Explorer完全相同。这个shell窗口不是一个控件,因此没有可以在其上调用的方法或可以订阅的事件,但是它可以接收Windows消息,并且可以是子类。

It turns out that the part of your question dealing with setting the view to Details automatically is actually quite easy. In your web browser control's Navigated event simply find the handle to the shell view window and send it a WM_COMMAND message with a particular shell constant (SHVIEW_REPORT). This is an undocumented command but it is supported on all Windows platforms up to and including Windows 2008 and almost certainly will be on Windows 7. Some code to add to your web browser's form demonstrates this:

事实证明,你的问题中涉及将视图自动设置为详细信息的部分实际上非常简单。在Web浏览器控件的Navigated事件中,只需找到shell视图窗口的句柄,并向其发送带有特定shell常量(SHVIEW_REPORT)的WM_COMMAND消息。这是一个未记录的命令,但它在所有Windows平台上都受支持,包括Windows 2008,几乎肯定会在Windows 7上。有些代码要添加到Web浏览器的表单中,这表明:

    private delegate int EnumChildProc(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
        IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern int EnumChildWindows(IntPtr hWndParent,
        EnumChildProc lpEnumFunc, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName,
        int nMaxCount);

    private const int WM_COMMAND = 0x0111;
    private const int SHVIEW_REPORT = 0x702C;
    private const string SHELLVIEW_CLASS = "SHELLDLL_DefView";

    private IntPtr m_ShellView;

    void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
        m_ShellView = IntPtr.Zero;
        EnumChildWindows(webBrowser1.Handle, EnumChildren, IntPtr.Zero);
        if (m_ShellView != IntPtr.Zero)
        {
            SendMessage(m_ShellView, WM_COMMAND, (IntPtr)SHVIEW_REPORT, (IntPtr)0);
        }
    }

    private int EnumChildren(IntPtr hwnd, IntPtr lParam)
    {
        int retval = 1;

        StringBuilder sb = new StringBuilder(SHELLVIEW_CLASS.Length + 1);
        int numChars = GetClassName(hwnd, sb, sb.Capacity);
        if (numChars == SHELLVIEW_CLASS.Length)
        {
            if (sb.ToString(0, numChars) == SHELLVIEW_CLASS)
            {
                m_ShellView = hwnd;
                retval = 0;
            }
        }

        return retval;
    }

Every time the web browser navigates to a new window (including when a folder is opened from within the explorer view) a new shell view window is created so the message must be re-sent to the new window in every Navigated event.

每次Web浏览器导航到新窗口时(包括从资源管理器视图中打开文件夹时),都会创建一个新的shell视图窗口,因此必须在每个Navigated事件中将消息重新发送到新窗口。

For the second part of your question you would like to receive events from the explorer list view. This is quite a bit more difficult than the first part. To do this you would need to sub-class the list view window and then monitor the windows messages for ones that interest you (such as WM_LBUTTONDBLCLK). In order to sub-class a window you would need to create your own class derived from the NativeWindow class and assign it the handle of the window that you need to monitor. You can then override its Window procedure and handle the various messages as you wish. Below is an example of creating a double click event - it is relatively simple but to get extensive access to the explorer list view may involve a lot more work than you are willing to do.

对于问题的第二部分,您希望从资源管理器列表视图中接收事件。这比第一部分困难得多。为此,您需要对列表视图窗口进行子类化,然后监视Windows消息以查找您感兴趣的消息(例如WM_LBUTTONDBLCLK)。为了对窗口进行子类化,您需要创建从NativeWindow类派生的自己的类,并为其分配需要监视的窗口的句柄。然后,您可以覆盖其Window过程并根据需要处理各种消息。下面是创建双击事件的示例 - 它相对简单但是要获得对资源管理器列表视图的广泛访问可能涉及比您愿意做的更多的工作。

Add this to your form:

将其添加到您的表单:

    private ExplorerListView m_Explorer;

    void OnExplorerItemExecuted(object sender, ExecuteEventArgs e)
    {
        string msg = string.Format("Item to be executed: {0}{0}{1}", 
            Environment.NewLine, e.SelectedItem);
        e.Cancel = (MessageBox.Show(msg, "", MessageBoxButtons.OKCancel) 
            == DialogResult.Cancel);
    }

and these two lines to the Navigated event handler (right after the SendMessage):

这两行到Navigated事件处理程序(在SendMessage之后):

    m_Explorer = new ExplorerListView(m_ShellView);
    m_Explorer.ItemExecuted += OnExplorerItemExecuted;

Then add the following classes:

然后添加以下类:

class ExplorerListView : NativeWindow
{

    public event EventHandler<ExecuteEventArgs> ItemExecuted;

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
        IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern IntPtr FindWindowEx(IntPtr hwndParent,
        IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    private const int WM_LBUTTONDBLCLK = 0x0203;

    private const int LVM_GETNEXTITEM = 0x100C;
    private const int LVM_GETITEMTEXT = 0x1073;

    private const int LVNI_SELECTED = 0x0002;

    private const string EXPLORER_LISTVIEW_CLASS = "SysListView32";

    public ExplorerListView(IntPtr shellViewHandle)
    {
        base.AssignHandle(FindWindowEx(shellViewHandle, IntPtr.Zero, 
            EXPLORER_LISTVIEW_CLASS, null));
        if (base.Handle == IntPtr.Zero)
        {
            throw new ArgumentException("Window supplied does not encapsulate an explorer window.");
        }
    }


    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_LBUTTONDBLCLK:
                if (OnItemExecution() != 0) return;
                break;
            default:
                break;
        }
        base.WndProc(ref m);
    }

    private int OnItemExecution()
    {
        int cancel = 0;
        ExecuteEventArgs args = new ExecuteEventArgs(GetSelectedItem());
        EventHandler<ExecuteEventArgs> temp = ItemExecuted;
        if (temp != null)
        {
            temp(this, args);
            if (args.Cancel) cancel = 1;
        }
        return cancel;
    }

    private string GetSelectedItem()
    {
        string item = null;

        IntPtr pStringBuffer = Marshal.AllocHGlobal(2048);
        IntPtr pItemBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LVITEM)));

        int selectedItemIndex = SendMessage(base.Handle, LVM_GETNEXTITEM, (IntPtr)(-1), (IntPtr)LVNI_SELECTED).ToInt32();
        if (selectedItemIndex > -1)
        {
            LVITEM lvi = new LVITEM();
            lvi.cchTextMax = 1024;
            lvi.pszText = pStringBuffer;
            Marshal.StructureToPtr(lvi, pItemBuffer, false);
            int numChars = SendMessage(base.Handle, LVM_GETITEMTEXT, (IntPtr)selectedItemIndex, pItemBuffer).ToInt32();
            if (numChars > 0)
            {
                item = Marshal.PtrToStringUni(lvi.pszText, numChars);
            }
        }

        Marshal.FreeHGlobal(pStringBuffer);
        Marshal.FreeHGlobal(pItemBuffer);

        return item;
    }

    struct LVITEM
    {
        public int mask;
        public int iItem;
        public int iSubItem;
        public int state;
        public int stateMask;
        public IntPtr pszText;
        public int cchTextMax;
        public int iImage;
        public IntPtr lParam;
        public int iIndent;
        public int iGroupId;
        int cColumns; // tile view columns
        public IntPtr puColumns;
        public IntPtr piColFmt;
        public int iGroup;

    }
}

public class ExecuteEventArgs : EventArgs
{
    public string SelectedItem { get; private set; }
    public bool Cancel { get; set; }

    internal ExecuteEventArgs(string selectedItem)
    {
        SelectedItem = selectedItem;
    }
}

This should give you an idea of what you would need to do. If you want more than fairly simple events you may want to look for a alternative control, though from what I have seen in the free and low cost areas there are some pretty decent controls but they all have some quirks and will not give a seamless explorer experience.

这应该可以让您了解您需要做什么。如果你想要的不只是相当简单的事件,你可能想要寻找一个替代控件,虽然从我在免费和低成本领域看到的有一些相当不错的控件,但他们都有一些怪癖,不会给无缝的探险家经验。

Remember this code was put together fairly quickly without error handling or comments and ignoring several issues such as multiple selected items, so use it as a guideline and at your own risk.

请记住,此代码在没有错误处理或注释的情况下相当快速地放在一起,并忽略了多个选定项目等问题,因此请将其用作指南,风险自负。

#3


LogicNP Software has two controls (FileView and ShComboBox) that do what your looking for: http://www.ssware.com/fldrview.htm

LogicNP软件有两个控件(FileView和ShComboBox)可以满足您的需求:http://www.asware.com/fldrview.htm

You can download a trial from their page, however it's ~130$ for the license.

您可以从他们的页面下载试用版,但是许可证大约为130美元。

#4


I have written a library that might be able to help you. You can find it at: http://gong-shell.sourceforge.net/

我写了一个可以帮助你的图书馆。你可以在http://gong-shell.sourceforge.net/找到它。

The control you're looking for is the ShellView. There's tutorials there on how to create a simple Windows Explorer clone in only a few lines too.

您正在寻找的控件是ShellView。那里有关于如何仅在几行中创建一个简单的Windows资源管理器克隆的教程。

Note for .NET 4.0 users: Gong-shell is currently broken for 4.0. The framework introduced changes in Interop and it will build just fine but cause different issues when interfacing with shell32 (notably the shellicon api, leading to an unmanaged null pointer dereference).

注意.NET 4.0用户:Gong-shell目前已破4.0。该框架引入了Interop中的更改,它将构建得很好但在与shell32接口时会导致不同的问题(特别是shellicon api,导致非托管空指针取消引用)。

#5


Check out this article here, it shows how to do this in .NET and WinForms. Doing it this way gives full-control over what the user sees.

在这里查看这篇文章,它展示了如何在.NET和WinForms中执行此操作。这样做可以完全控制用户看到的内容。

I've used it in one of my applications and it works really well. You can show icon/details/list view and it stops the user moving to other directories (which is often the problem of showing the standard file/directory dialogs.

我已经在我的一个应用程序中使用它,它的效果非常好。您可以显示图标/详细信息/列表视图,它会阻止用户移动到其他目录(这通常是显示标准文件/目录对话框的问题。

I use it to show the screen like the one below below http://img7.imageshack.us/img7/7647/screenshotbaf.png:

我用它来显示如下面的屏幕http://img7.imageshack.us/img7/7647/screenshotbaf.png:

#6


You may want to look at the ExplorerBrowser object.

您可能想要查看ExplorerBrowser对象。

See http://blogs.msdn.com/ieinternals/archive/2009/12/30/Windows-7-Web-Browser-Control-will-not-browse-file-system.aspx for more details.

有关详细信息,请参阅http://blogs.msdn.com/ieinternals/archive/2009/12/30/Windows-7-Web-Browser-Control-will-not-browse-file-system.aspx。

#7


If you are happy being Windows Vista only and wrapping a COM control, IExplorerBrowser might be acceptable for you needs.

如果您很高兴只使用Windows Vista并包装COM控件,IExplorerBrowser可能是您可以接受的。

This The Code Project article shows its use within an MFC program but at least one other person seems to have got it to work in C# after some effort.

这段代码项目文章显示了它在MFC程序中的使用,但至少有一个人似乎已经在C#中使用了一些努力。

The newer API exposes considerably more programmability than simply intercepting messages, but it is (obviously) useless for older platforms.

较新的API暴露出比简单拦截消息更多的可编程性,但它(显然)对于旧平台来说是无用的。

#8


If you want to open a different window to display the target folder's content you can use System.Windows.Forms.OpenFileDialog, or SaveFileDialog, or inherit from FileDialog and extend it.

如果要打开另一个窗口以显示目标文件夹的内容,可以使用System.Windows.Forms.OpenFileDialog或SaveFileDialog,或从FileDialog继承并扩展它。

To allow the user to select a folder you can use FolderBrowserDialog, though as a user I don't like that control.

要允许用户选择文件夹,您可以使用FolderBrowserDialog,但作为用户我不喜欢该控件。

Does this help or you absolutely have to embed a control in your form?

这有用吗,或者你必须在表单中嵌入一个控件?

Asaf

#1


In order to handle renaming, deleting and make other customization you need to write your own file explorer. WebBrowser control is not suitable for your needs. It's just a wrapper over ActiveX component.
You should check this codeproject article. It contains an implementation of file explorer. There are few more samples of file browser:
one
two

为了处理重命名,删除和进行其他自定义,您需要编写自己的文件资源管理器。 WebBrowser控件不适合您的需要。它只是ActiveX组件的包装器。您应该检查此代码项目文章。它包含文件资源管理器的实现。文件浏览器的样本数量较少:一两个

#2


WARNING: Long post with lots of code.

警告:包含大量代码的长帖子。

When you navigate the web browser control to a file system folder the web browser control hosts a shell view window that in turn hosts the explorer list view. In fact this is exactly the same thing that the Explorer process does as well as the file dialogs and Internet Explorer. This shell window is not a control so there are no methods that can be called on it or events that can be subscribed to but it can receive windows messages and it can be sub-classed.

将Web浏览器控件导航到文件系统文件夹时,Web浏览器控件将承载一个shell视图窗口,该窗口依次托管资源管理器列表视图。实际上,这与Explorer进程以及文件对话框和Internet Explorer完全相同。这个shell窗口不是一个控件,因此没有可以在其上调用的方法或可以订阅的事件,但是它可以接收Windows消息,并且可以是子类。

It turns out that the part of your question dealing with setting the view to Details automatically is actually quite easy. In your web browser control's Navigated event simply find the handle to the shell view window and send it a WM_COMMAND message with a particular shell constant (SHVIEW_REPORT). This is an undocumented command but it is supported on all Windows platforms up to and including Windows 2008 and almost certainly will be on Windows 7. Some code to add to your web browser's form demonstrates this:

事实证明,你的问题中涉及将视图自动设置为详细信息的部分实际上非常简单。在Web浏览器控件的Navigated事件中,只需找到shell视图窗口的句柄,并向其发送带有特定shell常量(SHVIEW_REPORT)的WM_COMMAND消息。这是一个未记录的命令,但它在所有Windows平台上都受支持,包括Windows 2008,几乎肯定会在Windows 7上。有些代码要添加到Web浏览器的表单中,这表明:

    private delegate int EnumChildProc(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
        IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern int EnumChildWindows(IntPtr hWndParent,
        EnumChildProc lpEnumFunc, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName,
        int nMaxCount);

    private const int WM_COMMAND = 0x0111;
    private const int SHVIEW_REPORT = 0x702C;
    private const string SHELLVIEW_CLASS = "SHELLDLL_DefView";

    private IntPtr m_ShellView;

    void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
        m_ShellView = IntPtr.Zero;
        EnumChildWindows(webBrowser1.Handle, EnumChildren, IntPtr.Zero);
        if (m_ShellView != IntPtr.Zero)
        {
            SendMessage(m_ShellView, WM_COMMAND, (IntPtr)SHVIEW_REPORT, (IntPtr)0);
        }
    }

    private int EnumChildren(IntPtr hwnd, IntPtr lParam)
    {
        int retval = 1;

        StringBuilder sb = new StringBuilder(SHELLVIEW_CLASS.Length + 1);
        int numChars = GetClassName(hwnd, sb, sb.Capacity);
        if (numChars == SHELLVIEW_CLASS.Length)
        {
            if (sb.ToString(0, numChars) == SHELLVIEW_CLASS)
            {
                m_ShellView = hwnd;
                retval = 0;
            }
        }

        return retval;
    }

Every time the web browser navigates to a new window (including when a folder is opened from within the explorer view) a new shell view window is created so the message must be re-sent to the new window in every Navigated event.

每次Web浏览器导航到新窗口时(包括从资源管理器视图中打开文件夹时),都会创建一个新的shell视图窗口,因此必须在每个Navigated事件中将消息重新发送到新窗口。

For the second part of your question you would like to receive events from the explorer list view. This is quite a bit more difficult than the first part. To do this you would need to sub-class the list view window and then monitor the windows messages for ones that interest you (such as WM_LBUTTONDBLCLK). In order to sub-class a window you would need to create your own class derived from the NativeWindow class and assign it the handle of the window that you need to monitor. You can then override its Window procedure and handle the various messages as you wish. Below is an example of creating a double click event - it is relatively simple but to get extensive access to the explorer list view may involve a lot more work than you are willing to do.

对于问题的第二部分,您希望从资源管理器列表视图中接收事件。这比第一部分困难得多。为此,您需要对列表视图窗口进行子类化,然后监视Windows消息以查找您感兴趣的消息(例如WM_LBUTTONDBLCLK)。为了对窗口进行子类化,您需要创建从NativeWindow类派生的自己的类,并为其分配需要监视的窗口的句柄。然后,您可以覆盖其Window过程并根据需要处理各种消息。下面是创建双击事件的示例 - 它相对简单但是要获得对资源管理器列表视图的广泛访问可能涉及比您愿意做的更多的工作。

Add this to your form:

将其添加到您的表单:

    private ExplorerListView m_Explorer;

    void OnExplorerItemExecuted(object sender, ExecuteEventArgs e)
    {
        string msg = string.Format("Item to be executed: {0}{0}{1}", 
            Environment.NewLine, e.SelectedItem);
        e.Cancel = (MessageBox.Show(msg, "", MessageBoxButtons.OKCancel) 
            == DialogResult.Cancel);
    }

and these two lines to the Navigated event handler (right after the SendMessage):

这两行到Navigated事件处理程序(在SendMessage之后):

    m_Explorer = new ExplorerListView(m_ShellView);
    m_Explorer.ItemExecuted += OnExplorerItemExecuted;

Then add the following classes:

然后添加以下类:

class ExplorerListView : NativeWindow
{

    public event EventHandler<ExecuteEventArgs> ItemExecuted;

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
        IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern IntPtr FindWindowEx(IntPtr hwndParent,
        IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    private const int WM_LBUTTONDBLCLK = 0x0203;

    private const int LVM_GETNEXTITEM = 0x100C;
    private const int LVM_GETITEMTEXT = 0x1073;

    private const int LVNI_SELECTED = 0x0002;

    private const string EXPLORER_LISTVIEW_CLASS = "SysListView32";

    public ExplorerListView(IntPtr shellViewHandle)
    {
        base.AssignHandle(FindWindowEx(shellViewHandle, IntPtr.Zero, 
            EXPLORER_LISTVIEW_CLASS, null));
        if (base.Handle == IntPtr.Zero)
        {
            throw new ArgumentException("Window supplied does not encapsulate an explorer window.");
        }
    }


    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_LBUTTONDBLCLK:
                if (OnItemExecution() != 0) return;
                break;
            default:
                break;
        }
        base.WndProc(ref m);
    }

    private int OnItemExecution()
    {
        int cancel = 0;
        ExecuteEventArgs args = new ExecuteEventArgs(GetSelectedItem());
        EventHandler<ExecuteEventArgs> temp = ItemExecuted;
        if (temp != null)
        {
            temp(this, args);
            if (args.Cancel) cancel = 1;
        }
        return cancel;
    }

    private string GetSelectedItem()
    {
        string item = null;

        IntPtr pStringBuffer = Marshal.AllocHGlobal(2048);
        IntPtr pItemBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LVITEM)));

        int selectedItemIndex = SendMessage(base.Handle, LVM_GETNEXTITEM, (IntPtr)(-1), (IntPtr)LVNI_SELECTED).ToInt32();
        if (selectedItemIndex > -1)
        {
            LVITEM lvi = new LVITEM();
            lvi.cchTextMax = 1024;
            lvi.pszText = pStringBuffer;
            Marshal.StructureToPtr(lvi, pItemBuffer, false);
            int numChars = SendMessage(base.Handle, LVM_GETITEMTEXT, (IntPtr)selectedItemIndex, pItemBuffer).ToInt32();
            if (numChars > 0)
            {
                item = Marshal.PtrToStringUni(lvi.pszText, numChars);
            }
        }

        Marshal.FreeHGlobal(pStringBuffer);
        Marshal.FreeHGlobal(pItemBuffer);

        return item;
    }

    struct LVITEM
    {
        public int mask;
        public int iItem;
        public int iSubItem;
        public int state;
        public int stateMask;
        public IntPtr pszText;
        public int cchTextMax;
        public int iImage;
        public IntPtr lParam;
        public int iIndent;
        public int iGroupId;
        int cColumns; // tile view columns
        public IntPtr puColumns;
        public IntPtr piColFmt;
        public int iGroup;

    }
}

public class ExecuteEventArgs : EventArgs
{
    public string SelectedItem { get; private set; }
    public bool Cancel { get; set; }

    internal ExecuteEventArgs(string selectedItem)
    {
        SelectedItem = selectedItem;
    }
}

This should give you an idea of what you would need to do. If you want more than fairly simple events you may want to look for a alternative control, though from what I have seen in the free and low cost areas there are some pretty decent controls but they all have some quirks and will not give a seamless explorer experience.

这应该可以让您了解您需要做什么。如果你想要的不只是相当简单的事件,你可能想要寻找一个替代控件,虽然从我在免费和低成本领域看到的有一些相当不错的控件,但他们都有一些怪癖,不会给无缝的探险家经验。

Remember this code was put together fairly quickly without error handling or comments and ignoring several issues such as multiple selected items, so use it as a guideline and at your own risk.

请记住,此代码在没有错误处理或注释的情况下相当快速地放在一起,并忽略了多个选定项目等问题,因此请将其用作指南,风险自负。

#3


LogicNP Software has two controls (FileView and ShComboBox) that do what your looking for: http://www.ssware.com/fldrview.htm

LogicNP软件有两个控件(FileView和ShComboBox)可以满足您的需求:http://www.asware.com/fldrview.htm

You can download a trial from their page, however it's ~130$ for the license.

您可以从他们的页面下载试用版,但是许可证大约为130美元。

#4


I have written a library that might be able to help you. You can find it at: http://gong-shell.sourceforge.net/

我写了一个可以帮助你的图书馆。你可以在http://gong-shell.sourceforge.net/找到它。

The control you're looking for is the ShellView. There's tutorials there on how to create a simple Windows Explorer clone in only a few lines too.

您正在寻找的控件是ShellView。那里有关于如何仅在几行中创建一个简单的Windows资源管理器克隆的教程。

Note for .NET 4.0 users: Gong-shell is currently broken for 4.0. The framework introduced changes in Interop and it will build just fine but cause different issues when interfacing with shell32 (notably the shellicon api, leading to an unmanaged null pointer dereference).

注意.NET 4.0用户:Gong-shell目前已破4.0。该框架引入了Interop中的更改,它将构建得很好但在与shell32接口时会导致不同的问题(特别是shellicon api,导致非托管空指针取消引用)。

#5


Check out this article here, it shows how to do this in .NET and WinForms. Doing it this way gives full-control over what the user sees.

在这里查看这篇文章,它展示了如何在.NET和WinForms中执行此操作。这样做可以完全控制用户看到的内容。

I've used it in one of my applications and it works really well. You can show icon/details/list view and it stops the user moving to other directories (which is often the problem of showing the standard file/directory dialogs.

我已经在我的一个应用程序中使用它,它的效果非常好。您可以显示图标/详细信息/列表视图,它会阻止用户移动到其他目录(这通常是显示标准文件/目录对话框的问题。

I use it to show the screen like the one below below http://img7.imageshack.us/img7/7647/screenshotbaf.png:

我用它来显示如下面的屏幕http://img7.imageshack.us/img7/7647/screenshotbaf.png:

#6


You may want to look at the ExplorerBrowser object.

您可能想要查看ExplorerBrowser对象。

See http://blogs.msdn.com/ieinternals/archive/2009/12/30/Windows-7-Web-Browser-Control-will-not-browse-file-system.aspx for more details.

有关详细信息,请参阅http://blogs.msdn.com/ieinternals/archive/2009/12/30/Windows-7-Web-Browser-Control-will-not-browse-file-system.aspx。

#7


If you are happy being Windows Vista only and wrapping a COM control, IExplorerBrowser might be acceptable for you needs.

如果您很高兴只使用Windows Vista并包装COM控件,IExplorerBrowser可能是您可以接受的。

This The Code Project article shows its use within an MFC program but at least one other person seems to have got it to work in C# after some effort.

这段代码项目文章显示了它在MFC程序中的使用,但至少有一个人似乎已经在C#中使用了一些努力。

The newer API exposes considerably more programmability than simply intercepting messages, but it is (obviously) useless for older platforms.

较新的API暴露出比简单拦截消息更多的可编程性,但它(显然)对于旧平台来说是无用的。

#8


If you want to open a different window to display the target folder's content you can use System.Windows.Forms.OpenFileDialog, or SaveFileDialog, or inherit from FileDialog and extend it.

如果要打开另一个窗口以显示目标文件夹的内容,可以使用System.Windows.Forms.OpenFileDialog或SaveFileDialog,或从FileDialog继承并扩展它。

To allow the user to select a folder you can use FolderBrowserDialog, though as a user I don't like that control.

要允许用户选择文件夹,您可以使用FolderBrowserDialog,但作为用户我不喜欢该控件。

Does this help or you absolutely have to embed a control in your form?

这有用吗,或者你必须在表单中嵌入一个控件?

Asaf