Ian*_*oyd 9 windows winapi windows-explorer windows-shell
我在我的Win32应用程序中"嵌入Windows资源管理器".(从技术上讲,我在我的应用程序中托管了一个文件夹的ShellView,这是Windows资源管理器所做的).
问题是视图永远不会调用IShellBrowser.BrowseObject.shell视图不是要求我导航到新位置(通过BrowseObject事件),而是启动Windows资源管理器的副本以查看该文件夹.
我希望默认的shell视图(通俗地称为DefView)是可浏览的.
首先,我们需要获取IShellFolder我想要显示的文件夹.要获取的最简单的文件夹是Desktop文件夹,因为SHGetDesktopFolder API它有一个for:
folder: IShellFolder;
SHGetDesktopFolder({out} folder);
Run Code Online (Sandbox Code Playgroud)
接下来我们要求桌面文件夹将其IShellView 交给我们:
view: IShellView;
folder.CreateViewObject(Self.Handle, IID_IShellView, {out}view);
Run Code Online (Sandbox Code Playgroud)
现在我们有文件夹的IShellView(而不是IContextMenu或IExtractIcon),我们现在想通过调用IShellView.CreateViewWindow来显示shell视图:
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);
Run Code Online (Sandbox Code Playgroud)
et voila,可识别的shell listview,显示我的桌面:
完成上下文菜单处理程序:

除非我点击Open,而不是BrowseObject通过IShellBrowser我提供的界面向我发送事件,它会打开一个新窗口:
双击时也会发生同样的情况.
我怎样才能让微软的DefView可以浏览?
创建时,IShellView必须为其提供实现的对象IShellBrowser.该ShellBrowser对象是视图如何与主机容器通信.
在15种方法中,我只仔细看四 - 其余的可以返回E_NOTIMPL(当然可能是问题):
{IShellBrowser}
Run Code Online (Sandbox Code Playgroud)
BrowseObject(PCUIDLIST_RELATIVE pidl, UINT wFlags);
//Informs Windows Explorer to browse to another folder.
//This is the notification i want!
Result := BrowseToAnotherFolder(pidl, wFlags);
Run Code Online (Sandbox Code Playgroud)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;
Run Code Online (Sandbox Code Playgroud)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;
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)QueryActiveShellView(IShellView **ppshv);
//Retrieves the currently active (displayed) Shell view object.
ppshv := view;
Result := S_OK; //i would never view another, you know that
Run Code Online (Sandbox Code Playgroud)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.
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject);
//Installs the composite menu in the view window.
Result := E_NOTIMPL; //i no has menus
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)SetToolbarItems(LPTBBUTTONSB lpButtons, UINT nButtons, UINT uFlags);
//Adds toolbar items to Windows Explorer's toolbar.
Result := E_NOTIMPL; //i no has toolbar
Run Code Online (Sandbox Code Playgroud)那就是祖先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;
Run Code Online (Sandbox Code Playgroud)`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
Run Code Online (Sandbox Code Playgroud)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;
Run Code Online (Sandbox Code Playgroud)
在 Vista 或更高版本上,您可以切换到托管 ExplorerBrowser,从中您可以 QI IObjectWithSite 并传递一个使用 SID_SShellBrowser 或 SID_SInPlaceBrowser 等服务实现 IServiceProvier 的对象。
在 XP 上,您可能需要处理源自您的进程的 DDE 消息,因为当时默认的文件夹关联是 DDE。
| 归档时间: |
|
| 查看次数: |
3643 次 |
| 最近记录: |