ACHTUNG: Lange Post mit viel Code.
Wenn Sie im Webbrowser-Steuerelement zu einem Dateisystemordner navigieren, enthält das Webbrowser-Steuerelement ein Shell-Ansichtsfenster, das wiederum die Explorer-Listenansicht enthält. In der Tat ist dies genau das Gleiche, was der Explorer-Prozess genauso macht wie die Dateidialoge und der Internet Explorer. Dieses Shell-Fenster ist kein Steuerelement, daher gibt es keine Methoden, die darauf aufgerufen werden können, oder Ereignisse, die abonniert werden können, aber es kann Windows-Nachrichten empfangen und es kann unterklassifiziert werden.
Es stellt sich heraus, dass der Teil Ihrer Frage, der sich auf das automatische Einstellen der Ansicht auf Details bezieht, tatsächlich ziemlich einfach ist. Suchen Sie im Navigated-Ereignis Ihres Webbrowser-Steuerelements einfach das Handle für das Shell-Ansichtsfenster und senden Sie ihm eine WM_COMMAND-Nachricht mit einer bestimmten Shell-Konstante (SHVIEW_REPORT). Dies ist ein nicht dokumentierter Befehl, der jedoch auf allen Windows-Plattformen bis einschließlich Windows 2008 unterstützt wird und fast sicher unter Windows 7 ausgeführt wird.Einige Code hinzufügen zeigen, um Ihr Web-Browser-Form folgt aus:
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;
}
Jedes Mal, wenn der Web-Browser auf ein neues Fenster navigiert (einschließlich, wenn ein Ordner aus der Explorer-Ansicht geöffnet ist) ein neues Shell Sichtfenster so wird erstellt Die Nachricht muss in jedem navigierten Ereignis erneut an das neue Fenster gesendet werden.
Für den zweiten Teil Ihrer Frage möchten Sie Ereignisse aus der Explorer-Listenansicht erhalten. Das ist ein bisschen schwieriger als der erste Teil. Um dies zu tun, müssten Sie das Listenansichtsfenster unterteilen und dann die Windows-Nachrichten auf diejenigen überwachen, die Sie interessieren (wie WM_LBUTTONDBLCLK). Um ein Fenster unterzuordnen, müssen Sie eine eigene Klasse erstellen, die von der NativeWindow-Klasse abgeleitet ist, und ihr das Handle des Fensters zuweisen, das Sie überwachen müssen. Sie können dann die Fensterprozedur überschreiben und die verschiedenen Nachrichten wie gewünscht bearbeiten. Im Folgenden finden Sie ein Beispiel für das Erstellen eines Doppelklickereignisses - es ist relativ einfach, aber um umfassenden Zugriff auf die Explorer-Listenansicht zu erhalten, kann viel mehr Arbeit erforderlich sein, als Sie bereit sind.
Fügen Sie dieses Formular:
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);
}
und diese beiden Zeilen in die navigierte Event-Handler (direkt nach dem Sendmessage):
m_Explorer = new ExplorerListView(m_ShellView);
m_Explorer.ItemExecuted += OnExplorerItemExecuted;
Dann fügen Sie die folgenden Klassen:
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;
}
}
Dies sollte Ihnen eine Vorstellung davon geben, was Sie tun müssten. Wenn Sie mehr als nur einfache Ereignisse möchten, sollten Sie nach einer alternativen Steuerung suchen, obwohl es nach dem, was ich in den kostenlosen und kostengünstigen Bereichen gesehen habe, einige recht ordentliche Kontrollen gibt, aber alle haben ein paar Macken und keinen nahtlosen Explorer Erfahrung.
Denken Sie daran, dass dieser Code ziemlich schnell ohne Fehlerbehandlung oder Kommentare zusammengestellt wurde und mehrere Probleme wie mehrere ausgewählte Elemente ignoriert. Verwenden Sie ihn daher als Richtlinie und auf eigenes Risiko.
Was ich nützlich fand, ist die (kommerzielle) [ShellBrowser-Komponente] (http://www.jam-software.com/shellbrowser_net/?language=EN). –