【发布时间】:2011-12-03 15:47:58
【问题描述】:
我在我的 Win32 应用程序中“嵌入 Windows 资源管理器”。 (从技术上讲,我在我的应用程序中托管了一个文件夹的 ShellView,这是 Windows 资源管理器所做的)。
问题是视图从不调用 IShellBrowser.BrowseObject。 shell 视图不是要求 me 导航到新位置(通过 BrowseObject 事件),而是启动 Windows Explorer 的副本来查看文件夹。
我希望默认的 shell 视图(俗称 DefView)是可浏览的。
示例代码教程
首先,我们需要为我想要显示的某个文件夹获取IShellFolder。最简单的文件夹是 Desktop 文件夹,因为它有一个 SHGetDesktopFolder API:
folder: IShellFolder;
SHGetDesktopFolder({out} folder);
接下来我们要求桌面文件夹hand我们它的IShellView:
view: IShellView;
folder.CreateViewObject(Self.Handle, IID_IShellView, {out}view);
现在我们有了文件夹的 IShellView(而不是 IContextMenu 或 IExtractIcon),我们现在想要显示 shell拨打IShellView.CreateViewWindow查看:
hostRect: TRect; //where the view is to display itself
folderSettings: TFolderSettings; //display settings for the view
hwndView: HWND; //the newly created view's window handle
folderSettings.ViewMode := FVM_DETAILS; //details mode please, rather than icon/list/etc
folderSettings.fFlags := 0;
hostRect := Rect(20, 20, 660, 500); //the view can position itself there
view.CreateViewWindow(nil, folderSettings, shellBrowser, {var}hostRect, {out}hView);
view.UIActivate(SVUIA_ACTIVATE_NOFOCUS);
瞧,可识别的 shell 列表视图,显示我的桌面:
包含上下文菜单处理程序:
除了当我单击打开时,它不会通过我提供的IShellBrowser 接口向我发送BrowseObject 事件,而是打开一个新窗口:
当我双击时也会发生同样的情况。
如何让微软的 DefView 可以浏览?
更新 ShellBrowser 实现
创建IShellView 时,您必须给它一个实现IShellBrowser 的对象。这个ShellBrowser 对象是视图与宿主容器通信的方式。
这15种方法中,我只仔细看了四种——其余的都可以返回E_NOTIMPL(这当然可能是问题所在):
{IShellBrowser}
-
BrowseObject(PCUIDLIST_RELATIVE pidl, UINT wFlags);//Informs Windows Explorer to browse to another folder. //This is the notification i want! Result := BrowseToAnotherFolder(pidl, wFlags); -
GetControlWindow(UINT id, HWND *lphwnd);//Gets the window handle to a browser control. //Since i don't have a toolbar, tree, status or progress windows, return 0 lphwnd := 0; Result := S_OK; -
SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret);//Sends control messages to either the toolbar or the status bar in a Windows //From MSDN: Notes to Implementers // If your Windows Explorer does not have these controls, you can return E_NOTIMPL. Result := E_NOTIMPL; -
GetViewStateStream(DWORD grfMode, IStream **ppStrm);//Gets an IStream interface that can be used for storage of view-specific state information. Result := E_NOTIMPL; //i'm don't have a stream to give you -
TranslateAcceleratorSB(LPMSG lpmsg, WORD wID);//Translates accelerator keystrokes intended for the browser's frame // while the view is active. Result := E_NOTIMPL; //i won't be doing any translating -
OnViewWindowActive(IShellView *ppshv);//Called by the Shell view when the view window or one of its child // windows gets the focus or becomes active. Result := S_OK; //i got the notification, thanks -
QueryActiveShellView(IShellView **ppshv);//Retrieves the currently active (displayed) Shell view object. ppshv := view; Result := S_OK; //i would never view another, you know that -
EnableModelessSB(BOOL fEnable);//Tells Windows Explorer to enable or disable its modeless dialog boxes. Result := S_OK; //You want to enable modeless dialog boxes? Interesting. -
InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);//Allows the container to insert its menu groups into the composite // menu that is displayed when an extended namespace is being viewed or used. Result := E_NOTIMPL; //i no has menus -
RemoveMenusSB(HMENU hmenuShared);//Permits the container to remove any of its menu elements // from the in-place composite menu and to free all associated resources. Result := E_NOTIMPL; //i no has menus -
SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject);//Installs the composite menu in the view window. Result := E_NOTIMPL; //i no has menus -
SetStatusTextSB//Sets and displays status text about the in-place object //in the container's frame-window status bar. Result := E_NOTIMPL; //i no has status bar -
SetToolbarItems(LPTBBUTTONSB lpButtons, UINT nButtons, UINT uFlags);//Adds toolbar items to Windows Explorer's toolbar. Result := E_NOTIMPL; //i no has toolbar
然后是祖先IOleWindow:
-
GetWindow([out] HWND *phwnd);//Retrieves a handle to one of the windows participating in // in-place activation (frame, document, parent, or in-place object window). phwnd := Self.Handle; //here's the handle, again, of your parent Result := S_OK; -
`ContextSensitiveHelp([in] BOOL fEnterMode);
//Determines whether context-sensitive help mode should be entered //during an in-place activation session. Result := S_OK; //Ok, thanks, i'll make a note of it
IServiceProvider
function TShellBrowser.QueryService(const rsid, iid: TGuid; out Obj): HResult;
var
sb: IShellBrowser;
s: string;
const
SID_SInPlaceBrowser: TGUID = '{1D2AE02B-3655-46CC-B63A-285988153BCA}';
SID_IShellBrowser: TGUID = '{000214E2-0000-0000-C000-000000000046}';
begin
{
This code is executed when you double click a folder.
It's needed to implement inline browsing.
If you double click a folder the default action of IShellBrowser is to open a new Windows Explorer.
To open the folder in the current window you must implement IServiceProvider.
http://blogs.msdn.com/b/ieinternals/archive/2009/12/30/windows-7-web-browser-control-will-not-browse-file-system.aspx
}
Result := E_NOINTERFACE; //Return $E_NOINTERFACE
OutputDebugString(PChar('TShellBrowser.QueryService: '+IIDToString(rsid)));
{
Make a small change to your application to enable the filesystem object to navigate in-place within the WebOC
when running on Windows 7.
To do so, your hosting application will implement the IServiceProvider interface,
and hand back the WebBrowser control’s SID_SShellBrowser when asked for SID_SInPlaceBrowser
}
if IsEqualGUID(rsid, SID_SInPlaceBrowser) then
begin
sb := Self as IShellBrowser;
Pointer(Obj) := Pointer(sb);
sb._AddRef;
Result := S_OK;
end;
end;
阅读奖励
- ex-MSFT Eric Law documents this behavior as an instantional change in Windows 7, and how to work around it。 archive(除非它不起作用)
- fogbit having the same problem
- more talk on how to implement IServiceProvider to respond to SID_SInPlaceBrowser
另见
【问题讨论】:
-
SDK shell 示例有几个嵌入资源管理器的示例。我会快速浏览一遍。
-
如果您可以依赖 Windows Vista,
IExplorerBrowser接口可以让这变得容易很多。 -
@Ian 你的人生圆满了!
-
@DavidHeffernan 我找不到嵌入
IShellView的示例,无论是标准视图还是命名空间扩展。你能指出相同的文件名/文件夹吗?需要注意的是,我不是在创建命名空间扩展,而是充当 Windows 资源管理器的一部分,或者是一个通用文件对话框(即 实现IShellBrowser,而不是 talking i> 给它)。 -
@DavidHeffernan 是的,我以为你会喜欢的。奖金喋喋不休:我知道我做到了。
标签: windows winapi windows-explorer windows-shell