In Sample |
Interface |
Function |
Description |
|
IShellFolder |
SetNameOf |
Sets a new display name for the object. |
|
IShellFolder |
ParseDisplayName |
Converts from a string to a PIDL. |
IShellFolder |
EnumObjects |
Creates an enumeration object to list all the items present. |
|
|
IShellFolder |
BindToObject |
Handles the subfolders, if any. |
|
IShellFolder |
BindToStorage |
Not supported. |
|
IShellFolder |
CompareIDs |
Provides a way to sort the various items. |
|
IShellFolder |
GetAttributesOf |
Retrieves the attributes of the specified objects. |
IShellFolder |
CreateViewObject |
Creates the view object. |
|
|
IShellFolder |
GetUIObjectOf |
Associates special extensions such as context menus or icon handlers. |
|
IShellFolder |
GetDisplayNameOf |
Converts from a PIDL to a string. |
IPersistFolder |
Initialize |
Called when initializing the folder object. |
|
IPersistFolder |
GetClassID |
Returns the CLSID. |
Figure 6 IEnumIDList and IshellView
In Sample |
Interface |
Function |
Description |
|
IEnumIDList |
Next |
Returns the next given number of elements in the item list. |
|
IEnumIDList |
Skip |
Jumps over the specified number of elements in the list. |
|
IEnumIDList |
Clone |
Duplicates the enumeration object mantaining its current state. |
|
IEnumIDList |
Reset |
Rewinds the enumeration object and makes it point to the first item in the list. |
IShellView |
CreateViewWindow |
Creates the view. Usually, it is a child dialog but it may be any window. |
|
IShellView |
DestroyViewWindow |
Destroys the current view. |
|
IShellView |
Refresh |
Refreshes the current view. Usually, it occurs when the user hits the F5 key. |
|
|
IShellView |
SaveViewState |
Saves the current state of the view. |
|
IShellView |
TranslateAccelerator |
Handles menu accelerator keys. |
|
IShellView |
GetCurrentInfo |
Returns information about the current folder settings. |
|
IShellView |
UIActivate |
Called when the activation state of the window changes. |
|
IShellView |
AddPropertySheetPages |
Allows adding property pages to the Explorer's Options dialog. |
|
IShellView |
EnableModeless |
Enables and disables all modeless windows, if any. |
|
IShellView |
SelectItem |
Changes the selection state for a given set of items. |
|
IShellView |
GetItemObject |
Allows you to get the selected items from the view. |
Figure 7 Creating a View
/*-------------------------------------------------------------------*/
// Procedure....: CreateViewWindow()
// Description..: Sets up the folder's content and view
/*-------------------------------------------------------------------*/
STDMETHODIMP CHtmlView::CreateViewWindow( IShellView *lpPrevView,
LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, LPRECT prcView, HWND *phWnd )
{
*phWnd = NULL;
m_pShellBrowser = psb;
// Gets the main window handle from the shell browser.
psb->GetWindow( &m_hwndMain );
// Creates the window to show the contents of the HTML file.
m_hwndView = CreateDialog( g_hInstance, MAKEINTRESOURCE(IDD_HTMLVIEW),
m_hwndMain, (DLGPROC) View_DlgProc );
*phWnd = m_hwndView;
// Resizes the view. (Since it will contains some controls
// you should resize them in WM_INITDIALOG).
SetWindowPos( m_hwndView, NULL, prcView->left, prcView->top,
prcView->right-prcView->left, prcView->bottom-prcView->top,
SWP_NOZORDER|SWP_SHOWWINDOW );
// Sets up toolbar and menu.
SetMenu();
SetToolbar();
// Filling out the view.
HWND hwndTree = GetDlgItem( m_hwndView, IDC_TREEVIEW );
m_pHtmlTree = new CHtmlTree( hwndTree, m_pShellBrowser );
m_pHtmlTree->Load( m_szFile );
g_pHtmlTree = m_pHtmlTree;
// This is necessary because initializing MSHTML.dll
// (needed for accessing the HTML document object) might be
// time-consuming. To avoid unexpected crashes I add menu and toolbar
// items in a disabled state, so now it's time to unlock them...
// The CDynHtml::Load() method terminates only when
// the MSHTML server is ready for use.
EnableUI();
return NOERROR;
}
/*-------------------------------------------------------------------*/
// Procedure....: DestroyViewWindow()
// Description..: Destroys the view objects
/*-------------------------------------------------------------------*/
STDMETHODIMP CHtmlView::DestroyViewWindow()
{
if( !m_hwndView )
return E_UNEXPECTED;
if( m_pHtmlTree )
delete m_pHtmlTree;
DestroyWindow( m_hwndView );
return NOERROR;
}
/*-------------------------------------------------------------------*/
// Procedure....: Refresh()
// Description..: Update the view.
/*-------------------------------------------------------------------*/
STDMETHODIMP CHtmlView::Refresh( VOID )
{
m_pHtmlTree->Unload();
m_pHtmlTree->Load( m_szFile );
return NOERROR;
}
/*-------------------------------------------------------------------*/
// Procedure....: SetToolbar()
// Description..: Set up the folder's toolbar
/*-------------------------------------------------------------------*/
STDMETHODIMP CHtmlView::SetToolbar()
{
TBADDBITMAP tbab;
LONG lNewIndex;
// Declare an array of initially grayed buttons.
TBBUTTON tbb[] = {
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0},
{0,IDM_FILE_RUN,0,TBSTYLE_BUTTON,0,0},
{1,IDM_VIEW_SOURCE,0,TBSTYLE_BUTTON,0,0}
};
// Add new bitmaps to the Explorer toolbar.
tbab.hInst = g_hInstance;
tbab.nID = IDB_TOOLBAR;
m_pShellBrowser->SendControlMsg( FCW_TOOLBAR, TB_ADDBITMAP,
2, (LPARAM) &tbab, &lNewIndex );
// The folder's toolbar holds a variety of bitmaps. We need
// to know where are our most recent bitmaps.
// lNewIndex has been filled out with the index of the first
// image we added with the previous instruction.
tbb[1].iBitmap = lNewIndex;
tbb[2].iBitmap = lNewIndex+1;
// Now just adds the new buttons.
m_pShellBrowser->SendControlMsg( FCW_TOOLBAR, TB_ADDBUTTONS,
3, (LPARAM) &tbb, NULL );
return NOERROR;
}
/*-------------------------------------------------------------------*/
// Procedure....: SetMenu()
// Description..: Sets up the folder's menu
/*-------------------------------------------------------------------*/
STDMETHODIMP CHtmlView::SetMenu()
{
OLEMENUGROUPWIDTHS mgw = { {0, 0, 0, 0, 0, 0} };
if( m_hMenu ) DestroyMenu( m_hMenu );
// Create a new menu to insert into the shell browser.
m_hMenu = CreateMenu();
m_pShellBrowser->InsertMenusSB( m_hMenu, &mgw );
MENUITEMINFO mii;
ZeroMemory( &mii, sizeof(MENUITEMINFO) );
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_SUBMENU;
// modify menus: File
GetMenuItemInfo( m_hMenu, FCIDM_MENU_FILE, FALSE, &mii );
HMENU hmnuFile = mii.hSubMenu;
InsertMenu( hmnuFile, 0, MF_BYPOSITION|MF_SEPARATOR, 0, NULL );
InsertMenu( hmnuFile, 0, MF_BYPOSITION|MF_STRING|MF_GRAYED,
IDM_FILE_RUN, "Run..." );
InsertMenu( hmnuFile, 1, MF_BYPOSITION|MF_STRING|MF_GRAYED,
IDM_FILE_SETASDEFAULT, "Set as default" );
// modify menus: View
GetMenuItemInfo( m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii );
HMENU hmnuView = mii.hSubMenu;
AppendMenu( hmnuView, MF_SEPARATOR, 0, NULL );
AppendMenu( hmnuView, MF_STRING|MF_GRAYED, IDM_VIEW_SOURCE, "Source" );
// modify menus: Help
GetMenuItemInfo( m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii );
HMENU hmnuHelp = mii.hSubMenu;
DeleteMenu( hmnuHelp, 0, MF_BYPOSITION );
AppendMenu( hmnuHelp, MF_STRING, IDM_HELP_ABOUT, "About..." );
// remove Edit menu
DeleteMenu( m_hMenu, FCIDM_MENU_EDIT, MF_BYCOMMAND );
// save changes
m_pShellBrowser->SetMenuSB( m_hMenu, NULL, NULL );
return NOERROR;
}
Figure 9 Declaration of CDynHtml
#ifndef _DYNHTML_
#define _DYNHTML_
#include <mshtml.h>
#include <urlmon.h>
#include <objbase.h>
#include <mshtmdid.h>
// callbacks
typedef BOOL (CALLBACK *LPLINKENUMPROC) (IHTMLAnchorElement*, DWORD);
typedef BOOL (CALLBACK *LPIMAGEENUMPROC) (IHTMLImgElement*, DWORD);
typedef BOOL (CALLBACK *LPOBJECTENUMPROC) (IHTMLElement*, DWORD);
typedef BOOL (CALLBACK *LPSCRIPTENUMPROC) (IHTMLElement*, DWORD);
typedef BOOL (CALLBACK *LPAPPLETENUMPROC) (IHTMLElement*, DWORD);
// definitions
#define WM_EX_DOCUMENTREADY (WM_USER+1)
#define ELEM_LINK 0x01
#define ELEM_APPLET 0x02
#define ELEM_SCRIPT 0x03
#define ELEM_OBJECT 0x04
#define ELEM_IMAGE 0x05
// useful macros
#define BSTR_TO_STRING(b,s,n) \
WideCharToMultiByte(CP_ACP,0,b,-1,s,n,NULL,NULL)
#define STRING_TO_BSTR(s,b,n) \
MultiByteToWideChar(CP_ACP,0,s,-1,b,n);
// Define a Dynamic HTML class
class CDynHtml : public IPropertyNotifySink, IDispatch
{
public:
CDynHtml();
~CDynHtml();
// IUnknown methods
STDMETHODIMP QueryInterface( REFIID, LPVOID FAR* );
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IPropertyNotifySink methods
STDMETHODIMP OnChanged( DISPID dispID );
STDMETHODIMP OnRequestEdit( DISPID dispID );
// IDispatch methods
STDMETHODIMP Invoke( DISPID, REFIID, LCID, WORD,
DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT* )
{ return E_NOTIMPL; };
STDMETHODIMP GetTypeInfoCount( UINT* )
{ return E_NOTIMPL; }
STDMETHODIMP GetTypeInfo( UINT, LCID, ITypeInfo** )
{ return E_NOTIMPL; }
STDMETHODIMP GetIDsOfNames( REFIID, LPOLESTR*, UINT, LCID, DISPID* )
{ return E_NOTIMPL; }
// Custom methods
STDMETHODIMP Init( VOID );
STDMETHODIMP Close( VOID );
STDMETHODIMP Load( LPCTSTR pszHtmlFile );
STDMETHODIMP GetTitle( LPTSTR pszBuf, INT iBufSize );
STDMETHODIMP GetNumOf( INT iElemType, LPLONG plBuf );
STDMETHODIMP GetSource( LPTSTR pszBuf, INT iBufSize );
STDMETHODIMP GetSourceSize( LPDWORD pdwSize );
STDMETHODIMP EnumLinks( LPLINKENUMPROC, DWORD );
STDMETHODIMP EnumImages( LPIMAGEENUMPROC, DWORD );
STDMETHODIMP EnumObjects( LPOBJECTENUMPROC, DWORD );
STDMETHODIMP EnumScripts( LPSCRIPTENUMPROC, DWORD );
STDMETHODIMP EnumApplets( LPAPPLETENUMPROC, DWORD );
protected:
IHTMLDocument2* m_pMSHTML;
DWORD m_cRef;
LPCONNECTIONPOINT m_pCP;
TCHAR m_szFile[MAX_PATH];
READYSTATE m_readyState;
DWORD m_dwCookie;
IHTMLElementCollection* m_pLinkColl;
IHTMLElementCollection* m_pImageColl;
IHTMLElementCollection* m_pObjectColl;
IHTMLElementCollection* m_pScriptColl;
IHTMLElementCollection* m_pAppletColl;
STDMETHODIMP GetAllTags( LPCTSTR, IHTMLElementCollection** );
};
#endif
Figure 10 Loading an HTML Document
/*-------------------------------------------------------------------*/
// Procedure....: ::OnRequestEdit()
// Description..: Allow or not the editing of a property
/*-------------------------------------------------------------------*/
STDMETHODIMP CDynHtml::OnRequestEdit( DISPID dispID )
{
return NOERROR;
}
/*-------------------------------------------------------------------*/
// Procedure....: ::OnChanged()
// Description..: The specified property has changed
/*-------------------------------------------------------------------*/
STDMETHODIMP CDynHtml::OnChanged( DISPID dispID )
{
HRESULT hr;
if( m_pMSHTML==NULL )
return E_UNEXPECTED;
if( dispID==DISPID_READYSTATE )
{
VARIANT vResult = {0};
EXCEPINFO ei;
UINT err;
DISPPARAMS dp = {NULL, NULL, 0, 0};
hr = m_pMSHTML->Invoke( DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &dp, &vResult, &ei, &err );
if( SUCCEEDED(hr) )
{
m_readyState = (READYSTATE) V_I4(&vResult);
switch( m_readyState )
{
case READYSTATE_UNINITIALIZED:
case READYSTATE_LOADING:
case READYSTATE_LOADED:
case READYSTATE_INTERACTIVE:
break;
case READYSTATE_COMPLETE:
PostThreadMessage( GetCurrentThreadId(),
WM_EX_DOCUMENTREADY, 0, 0 );
break;
}
VariantClear( &vResult );
}
else
return E_UNEXPECTED;
}
return NOERROR;
}
/*-------------------------------------------------------------------*/
// Procedure....: ::Init()
// Description..: Create an instance of the document object
/*-------------------------------------------------------------------*/
STDMETHODIMP CDynHtml::Init( VOID )
{
HRESULT hr;
LPCONNECTIONPOINTCONTAINER pCPC = NULL;
// OleInitialize()'s been called by the class constructor.
// Create an instance of the MSHTML server.
hr = CoCreateInstance( CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER,
IID_IHTMLDocument2, (LPVOID*) &m_pMSHTML );
if( FAILED(hr) ) return E_UNEXPECTED;
// Set up a hook to detect property change event.
hr = m_pMSHTML->QueryInterface( IID_IConnectionPointContainer, (LPVOID*) &pCPC );
if( FAILED(hr) )
{
pCPC->Release();
return hr;
}
hr = pCPC->FindConnectionPoint( IID_IPropertyNotifySink, &m_pCP );
if (FAILED(hr) )
{
pCPC->Release();
return hr;
}
m_pCP->Advise( (LPUNKNOWN) (IPropertyNotifySink*)this, &m_dwCookie );
pCPC->Release();
return hr;
}
/*-------------------------------------------------------------------*/
// Procedure....: ::Close()
// Description..: Clean up connection point
/*-------------------------------------------------------------------*/
STDMETHODIMP CDynHtml::Close( VOID )
{
HRESULT hr=NOERROR;
if( m_pCP )
{
hr = m_pCP->Unadvise( m_dwCookie );
m_pCP->Release();
}
return hr;
}
/*-------------------------------------------------------------------*/
// Procedure....: ::Load()
// Description..: Load the given HTML file
/*-------------------------------------------------------------------*/
STDMETHODIMP CDynHtml::Load( LPCTSTR pszHtmlFile )
{
HRESULT hr=NOERROR;
OLECHAR wszHtmlFile[MAX_PATH];
if( !pszHtmlFile || !m_pMSHTML )
return E_UNEXPECTED;
// turn the name into wide chars
STRING_TO_BSTR( pszHtmlFile, wszHtmlFile, MAX_PATH );
// Check whether IPersistMoniker or IPersistFile is needed.
if( memcmp( pszHtmlFile, "file:", 5 )==0 ||
memcmp( pszHtmlFile, "http:", 5 )==0 )
{
// Ask the system for a URL Moniker.
IMoniker* pIMoniker;
hr = CreateURLMoniker( NULL, (LPWSTR)wszHtmlFile, &pIMoniker );
if( SUCCEEDED(hr) )
{
// Get the IPersistMoniker interface.
IPersistMoniker* pPMk;
hr = m_pMSHTML->QueryInterface( IID_IPersistMoniker, (LPVOID*)&pPMk );
if( SUCCEEDED(hr) )
{
IBindCtx *pBCtx;
hr = CreateBindCtx(0, &pBCtx);
if( SUCCEEDED(hr) )
{
// Call Load on the IPersistMoniker.
hr = pPMk->Load(FALSE, pIMoniker, pBCtx, STGM_READ);
pBCtx->Release();
}
pPMk->Release();
}
pIMoniker->Release();
}
}
else {
IPersistFile* pPFile;
hr = m_pMSHTML->QueryInterface( IID_IPersistFile, (LPVOID*) &pPFile );
if( SUCCEEDED(hr) )
{
// Call Load on the IPersistFile.
hr = pPFile->Load( (LPWSTR)wszHtmlFile, 0 );
pPFile->Release();
}
}
// Wait for the liberating message before proceeding.
if( SUCCEEDED(hr) || hr==E_PENDING )
{
MSG msg;
while( GetMessage(&msg, NULL, 0, 0) )
{
if( msg.message==WM_EX_DOCUMENTREADY && msg.hwnd==NULL )
break;
else
DispatchMessage( &msg );
}
// Now save the pointers to some useful collections for a later use.
// For images and links we have a built-in collection. In other case
// we need to prepare our own list, extracting elements via tag name.
// links collection
if( m_pLinkColl != NULL )
m_pLinkColl->Release();
m_pMSHTML->get_links( &m_pLinkColl );
// images collection
if( m_pImageColl != NULL )
m_pImageColl->Release();
m_pMSHTML->get_images( &m_pImageColl );
// objects collection
if( m_pObjectColl != NULL )
m_pObjectColl->Release();
GetAllTags( "OBJECT", &m_pObjectColl );
// scripts collection
if( m_pScriptColl != NULL )
m_pScriptColl->Release();
GetAllTags( "SCRIPT", &m_pScriptColl );
// applets collection
if( m_pAppletColl != NULL )
m_pAppletColl->Release();
GetAllTags( "APPLET", &m_pAppletColl );
return hr;
}