2022-05-23 00:16:32 +04:00

141 lines
4.8 KiB
Python

# A sample of using Vista's IExplorerBrowser interfaces...
# Currently doesn't quite work:
# * CPU sits at 100% while running.
import sys
import pythoncom
from win32com.shell import shell, shellcon
import win32gui, win32con, win32api
from win32com.server.util import wrap, unwrap
# event handler for the browser.
IExplorerBrowserEvents_Methods = """OnNavigationComplete OnNavigationFailed
OnNavigationPending OnViewCreated""".split()
class EventHandler:
_com_interfaces_ = [shell.IID_IExplorerBrowserEvents]
_public_methods_ = IExplorerBrowserEvents_Methods
def OnNavigationComplete(self, pidl):
print("OnNavComplete", pidl)
def OnNavigationFailed(self, pidl):
print("OnNavigationFailed", pidl)
def OnNavigationPending(self, pidl):
print("OnNavigationPending", pidl)
def OnViewCreated(self, view):
print("OnViewCreated", view)
# And if our demo view has been registered, it may well
# be that view!
try:
pyview = unwrap(view)
print("and look - its a Python implemented view!", pyview)
except ValueError:
pass
class MainWindow:
def __init__(self):
message_map = {
win32con.WM_DESTROY: self.OnDestroy,
win32con.WM_COMMAND: self.OnCommand,
win32con.WM_SIZE: self.OnSize,
}
# Register the Window class.
wc = win32gui.WNDCLASS()
hinst = wc.hInstance = win32api.GetModuleHandle(None)
wc.lpszClassName = "test_explorer_browser"
wc.lpfnWndProc = message_map # could also specify a wndproc.
classAtom = win32gui.RegisterClass(wc)
# Create the Window.
style = win32con.WS_OVERLAPPEDWINDOW | win32con.WS_VISIBLE
self.hwnd = win32gui.CreateWindow(
classAtom,
"Python IExplorerBrowser demo",
style,
0,
0,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
0,
0,
hinst,
None,
)
eb = pythoncom.CoCreateInstance(
shellcon.CLSID_ExplorerBrowser,
None,
pythoncom.CLSCTX_ALL,
shell.IID_IExplorerBrowser,
)
# as per MSDN docs, hook up events early
self.event_cookie = eb.Advise(wrap(EventHandler()))
eb.SetOptions(shellcon.EBO_SHOWFRAMES)
rect = win32gui.GetClientRect(self.hwnd)
# Set the flags such that the folders autoarrange and non web view is presented
flags = (shellcon.FVM_LIST, shellcon.FWF_AUTOARRANGE | shellcon.FWF_NOWEBVIEW)
eb.Initialize(self.hwnd, rect, (0, shellcon.FVM_DETAILS))
if len(sys.argv) == 2:
# If an arg was specified, ask the desktop parse it.
# You can pass anything explorer accepts as its '/e' argument -
# eg, "::{guid}\::{guid}" etc.
# "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" is "My Computer"
pidl = shell.SHGetDesktopFolder().ParseDisplayName(0, None, sys.argv[1])[1]
else:
# And start browsing at the root of the namespace.
pidl = []
eb.BrowseToIDList(pidl, shellcon.SBSP_ABSOLUTE)
# and for some reason the "Folder" view in the navigator pane doesn't
# magically synchronize itself - so let's do that ourself.
# Get the tree control.
sp = eb.QueryInterface(pythoncom.IID_IServiceProvider)
try:
tree = sp.QueryService(
shell.IID_INameSpaceTreeControl, shell.IID_INameSpaceTreeControl
)
except pythoncom.com_error as exc:
# this should really only fail if no "nav" frame exists...
print(
"Strange - failed to get the tree control even though "
"we asked for a EBO_SHOWFRAMES"
)
print(exc)
else:
# get the IShellItem for the selection.
si = shell.SHCreateItemFromIDList(pidl, shell.IID_IShellItem)
# set it to selected.
tree.SetItemState(si, shellcon.NSTCIS_SELECTED, shellcon.NSTCIS_SELECTED)
# eb.FillFromObject(None, shellcon.EBF_NODROPTARGET);
# eb.SetEmptyText("No known folders yet...");
self.eb = eb
def OnCommand(self, hwnd, msg, wparam, lparam):
pass
def OnDestroy(self, hwnd, msg, wparam, lparam):
print("tearing down ExplorerBrowser...")
self.eb.Unadvise(self.event_cookie)
self.eb.Destroy()
self.eb = None
print("shutting down app...")
win32gui.PostQuitMessage(0)
def OnSize(self, hwnd, msg, wparam, lparam):
x = win32api.LOWORD(lparam)
y = win32api.HIWORD(lparam)
self.eb.SetRect(None, (0, 0, x, y))
def main():
w = MainWindow()
win32gui.PumpMessages()
if __name__ == "__main__":
main()