blob: 644515fe464cf444b2f16f60a6db87b639e25dee [file] [log] [blame]
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "StdAfx.h"
#include "comutil.h"
#include "ShObjIdl.h"
#include "DebugServices.h"
#include "Resource.h"
#include "ExplorerBar.h"
#include "About.h"
// MFC Debugging
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//===========================================================================================================================
// Constants
//===========================================================================================================================
#define LENGTHOF(a) (sizeof(a) == sizeof(&*a)) ? 0 : (sizeof(a) / sizeof(*a))
#define MIN_SIZE_X 10
#define MIN_SIZE_Y 10
//===========================================================================================================================
// ExplorerBar
//===========================================================================================================================
ExplorerBar::ExplorerBar( void )
{
++gDLLRefCount;
mRefCount = 1;
mSite = NULL;
mWebBrowser = NULL;
mParentWindow = NULL;
mFocus = FALSE;
mViewMode = 0;
mBandID = 0;
}
//===========================================================================================================================
// ~ExplorerBar
//===========================================================================================================================
ExplorerBar::~ExplorerBar( void )
{
if( mWebBrowser )
{
mWebBrowser->Release();
mWebBrowser = NULL;
}
if( mSite )
{
mSite->Release();
mSite = NULL;
}
--gDLLRefCount;
}
#if 0
#pragma mark -
#pragma mark == IUnknown implementation ==
#endif
//===========================================================================================================================
// QueryInterface
//===========================================================================================================================
STDMETHODIMP ExplorerBar::QueryInterface( REFIID inID, LPVOID *outResult )
{
HRESULT err;
if( IsEqualIID( inID, IID_IUnknown ) ) // IUnknown
{
*outResult = this;
}
else if( IsEqualIID( inID, IID_IOleWindow ) ) // IOleWindow
{
*outResult = (IOleWindow *) this;
}
else if( IsEqualIID( inID, IID_IDockingWindow ) ) // IDockingWindow
{
*outResult = (IDockingWindow *) this;
}
else if( IsEqualIID( inID, IID_IDeskBand ) ) // IDeskBand
{
*outResult = (IDeskBand *) this;
}
else if( IsEqualIID( inID, IID_IInputObject ) ) // IInputObject
{
*outResult = (IInputObject *) this;
}
else if( IsEqualIID( inID, IID_IObjectWithSite ) ) // IObjectWithSite
{
*outResult = (IObjectWithSite *) this;
}
else if( IsEqualIID( inID, IID_IPersistStream ) ) // IPersistStream
{
*outResult = (IPersistStream *) this;
}
else if( IsEqualIID( inID, IID_IContextMenu ) ) // IContextMenu
{
*outResult = (IContextMenu *) this;
}
else
{
*outResult = NULL;
err = E_NOINTERFACE;
goto exit;
}
( *( (LPUNKNOWN *) outResult ) )->AddRef();
err = S_OK;
exit:
return( err );
}
//===========================================================================================================================
// AddRef
//===========================================================================================================================
STDMETHODIMP_( DWORD ) ExplorerBar::AddRef( void )
{
return( ++mRefCount );
}
//===========================================================================================================================
// Release
//===========================================================================================================================
STDMETHODIMP_( DWORD ) ExplorerBar::Release( void )
{
DWORD count;
count = --mRefCount;
if( count == 0 )
{
delete this;
}
return( count );
}
#if 0
#pragma mark -
#pragma mark == IOleWindow implementation ==
#endif
//===========================================================================================================================
// GetWindow
//===========================================================================================================================
STDMETHODIMP ExplorerBar::GetWindow( HWND *outWindow )
{
*outWindow = mWindow.GetSafeHwnd();
return( S_OK );
}
//===========================================================================================================================
// ContextSensitiveHelp
//===========================================================================================================================
STDMETHODIMP ExplorerBar::ContextSensitiveHelp( BOOL inEnterMode )
{
DEBUG_UNUSED( inEnterMode );
return( E_NOTIMPL );
}
#if 0
#pragma mark -
#pragma mark == IDockingWindow implementation ==
#endif
//===========================================================================================================================
// ShowDW
//===========================================================================================================================
STDMETHODIMP ExplorerBar::ShowDW( BOOL inShow )
{
if( mWindow.GetSafeHwnd() )
{
mWindow.ShowWindow( inShow ? SW_SHOW : SW_HIDE );
}
return( S_OK );
}
//===========================================================================================================================
// CloseDW
//===========================================================================================================================
STDMETHODIMP ExplorerBar::CloseDW( DWORD inReserved )
{
DEBUG_UNUSED( inReserved );
ShowDW( FALSE );
if( mWindow.GetSafeHwnd() )
{
mWindow.SendMessage( WM_CLOSE );
}
return( S_OK );
}
//===========================================================================================================================
// ResizeBorderDW
//===========================================================================================================================
STDMETHODIMP ExplorerBar::ResizeBorderDW( LPCRECT inBorder, IUnknown *inPunkSite, BOOL inReserved )
{
DEBUG_UNUSED( inBorder );
DEBUG_UNUSED( inPunkSite );
DEBUG_UNUSED( inReserved );
return( E_NOTIMPL );
}
#if 0
#pragma mark -
#pragma mark == IDeskBand implementation ==
#endif
//===========================================================================================================================
// GetBandInfo
//===========================================================================================================================
STDMETHODIMP ExplorerBar::GetBandInfo( DWORD inBandID, DWORD inViewMode, DESKBANDINFO *outInfo )
{
HRESULT err;
require_action( outInfo, exit, err = E_INVALIDARG );
mBandID = inBandID;
mViewMode = inViewMode;
if( outInfo->dwMask & DBIM_MINSIZE )
{
outInfo->ptMinSize.x = 100;
outInfo->ptMinSize.y = 100;
}
if( outInfo->dwMask & DBIM_MAXSIZE )
{
// Unlimited max size.
outInfo->ptMaxSize.x = -1;
outInfo->ptMaxSize.y = -1;
}
if( outInfo->dwMask & DBIM_INTEGRAL )
{
outInfo->ptIntegral.x = 1;
outInfo->ptIntegral.y = 1;
}
if( outInfo->dwMask & DBIM_ACTUAL )
{
outInfo->ptActual.x = 0;
outInfo->ptActual.y = 0;
}
if( outInfo->dwMask & DBIM_TITLE )
{
CString s;
BOOL ok;
ok = s.LoadString( IDS_NAME );
require_action( ok, exit, err = kNoResourcesErr );
#ifdef UNICODE
lstrcpyn( outInfo->wszTitle, s, sizeof_array( outInfo->wszTitle ) );
#else
DWORD nChars;
nChars = MultiByteToWideChar( CP_ACP, 0, s, -1, outInfo->wszTitle, sizeof_array( outInfo->wszTitle ) );
err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
require_noerr( err, exit );
#endif
}
if( outInfo->dwMask & DBIM_MODEFLAGS )
{
outInfo->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
}
// Force the default background color.
outInfo->dwMask &= ~DBIM_BKCOLOR;
err = S_OK;
exit:
return( err );
}
#if 0
#pragma mark -
#pragma mark == IInputObject implementation ==
#endif
//===========================================================================================================================
// UIActivateIO
//===========================================================================================================================
STDMETHODIMP ExplorerBar::UIActivateIO( BOOL inActivate, LPMSG inMsg )
{
DEBUG_UNUSED( inMsg );
if( inActivate )
{
mWindow.SetFocus();
}
return( S_OK );
}
//===========================================================================================================================
// HasFocusIO
//===========================================================================================================================
STDMETHODIMP ExplorerBar::HasFocusIO( void )
{
if( mWindow.GetFocus()->GetSafeHwnd() == mWindow.GetSafeHwnd() )
{
return( S_OK );
}
return( S_FALSE );
}
//===========================================================================================================================
// TranslateAcceleratorIO
//===========================================================================================================================
STDMETHODIMP ExplorerBar::TranslateAcceleratorIO( LPMSG inMsg )
{
DEBUG_UNUSED( inMsg );
return( S_FALSE );
}
#if 0
#pragma mark -
#pragma mark == IObjectWithSite implementation ==
#endif
//===========================================================================================================================
// SetSite
//===========================================================================================================================
STDMETHODIMP ExplorerBar::SetSite( IUnknown *inPunkSite )
{
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
HRESULT err;
// Release the old interfaces.
if( mWebBrowser )
{
mWebBrowser->Release();
mWebBrowser = NULL;
}
if( mSite )
{
mSite->Release();
mSite = NULL;
}
// A non-NULL site means we're setting the site. Otherwise, the site is being released (done above).
if( !inPunkSite )
{
err = S_OK;
goto exit;
}
// Get the parent window.
IOleWindow * oleWindow;
mParentWindow = NULL;
err = inPunkSite->QueryInterface( IID_IOleWindow, (LPVOID *) &oleWindow );
require( SUCCEEDED( err ), exit );
err = oleWindow->GetWindow( &mParentWindow );
oleWindow->Release();
require_noerr( err, exit );
require_action( mParentWindow, exit, err = E_FAIL );
// Get the IInputObject interface.
err = inPunkSite->QueryInterface( IID_IInputObjectSite, (LPVOID *) &mSite );
require( SUCCEEDED( err ), exit );
check( mSite );
// Get the IWebBrowser2 interface.
IOleCommandTarget * oleCommandTarget;
err = inPunkSite->QueryInterface( IID_IOleCommandTarget, (LPVOID *) &oleCommandTarget );
require( SUCCEEDED( err ), exit );
IServiceProvider * serviceProvider;
err = oleCommandTarget->QueryInterface( IID_IServiceProvider, (LPVOID *) &serviceProvider );
oleCommandTarget->Release();
require( SUCCEEDED( err ), exit );
err = serviceProvider->QueryService( SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID *) &mWebBrowser );
serviceProvider->Release();
require( SUCCEEDED( err ), exit );
// Create the main window.
err = SetupWindow();
require_noerr( err, exit );
exit:
return( err );
}
//===========================================================================================================================
// GetSite
//===========================================================================================================================
STDMETHODIMP ExplorerBar::GetSite( REFIID inID, LPVOID *outResult )
{
HRESULT err;
*outResult = NULL;
require_action( mSite, exit, err = E_FAIL );
err = mSite->QueryInterface( inID, outResult );
exit:
return( err );
}
#if 0
#pragma mark -
#pragma mark == IPersistStream implementation ==
#endif
//
// IPersistStream implementation
//
// This is only supported to allow the desk band to be dropped on the desktop and to prevent multiple instances of
// the desk band from showing up in the context menu. This desk band doesn't actually persist any data.
//
//===========================================================================================================================
// GetClassID
//===========================================================================================================================
STDMETHODIMP ExplorerBar::GetClassID( LPCLSID outClassID )
{
*outClassID = CLSID_ExplorerBar;
return( S_OK );
}
//===========================================================================================================================
// IsDirty
//===========================================================================================================================
STDMETHODIMP ExplorerBar::IsDirty( void )
{
return( S_FALSE );
}
//===========================================================================================================================
// Load
//===========================================================================================================================
STDMETHODIMP ExplorerBar::Load( LPSTREAM inStream )
{
DEBUG_UNUSED( inStream );
return( S_OK );
}
//===========================================================================================================================
// Save
//===========================================================================================================================
STDMETHODIMP ExplorerBar::Save( LPSTREAM inStream, BOOL inClearDirty )
{
DEBUG_UNUSED( inStream );
DEBUG_UNUSED( inClearDirty );
return( S_OK );
}
//===========================================================================================================================
// GetSizeMax
//===========================================================================================================================
STDMETHODIMP ExplorerBar::GetSizeMax( ULARGE_INTEGER *outSizeMax )
{
DEBUG_UNUSED( outSizeMax );
return( E_NOTIMPL );
}
//===========================================================================================================================
// QueryContextMenu
//===========================================================================================================================
STDMETHODIMP ExplorerBar::QueryContextMenu(HMENU hShellContextMenu, UINT iContextMenuFirstItem, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
DEBUG_UNUSED( idCmdLast );
DEBUG_UNUSED( uFlags );
CMenu menubar;
menubar.LoadMenu(IDR_CONTEXT_MENU);
CMenu * menu = menubar.GetSubMenu(0);
CMenu shellmenu;
shellmenu.Attach(hShellContextMenu);
UINT iShellItem = iContextMenuFirstItem; //! remove plus one
UINT idShellCmd = idCmdFirst;
int n = menu->GetMenuItemCount();
for (int i=0; i<n; ++i)
{
MENUITEMINFO mii;
TCHAR sz[128] = {0};
ZeroMemory(&mii, sizeof(mii));
mii.fMask = MIIM_TYPE | MIIM_ID;
mii.fType = MFT_STRING;
mii.cbSize = sizeof(mii);
mii.cch = LENGTHOF(sz);
mii.dwTypeData = sz;
menu->GetMenuItemInfo(i, &mii, TRUE);
mii.wID = idShellCmd++;
shellmenu.InsertMenuItem(iShellItem++, &mii, TRUE);
}
shellmenu.Detach();
return n;
}
//===========================================================================================================================
// GetCommandString
//===========================================================================================================================
// Not called for explorer bars
STDMETHODIMP ExplorerBar::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax)
{
DEBUG_UNUSED( idCmd );
DEBUG_UNUSED( uType );
DEBUG_UNUSED( pwReserved );
DEBUG_UNUSED( pszName );
DEBUG_UNUSED( cchMax );
return E_NOTIMPL;
}
//===========================================================================================================================
// InvokeCommand
//===========================================================================================================================
// The shell sends either strings or indexes
// IE never sends strings
// The indexes are into an array of my commands
// So the verb for the first command I added to the menu is always 0x0000
// Here - because I don't have any submenus -
// I can treat the 'verb' as an menu item position
STDMETHODIMP ExplorerBar::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
{
// IE doesn't send string commands
if (HIWORD(lpici->lpVerb) != 0) return 0;
CAbout dlg;
dlg.DoModal();
return S_OK;
}
#if 0
#pragma mark -
#pragma mark == Other ==
#endif
//===========================================================================================================================
// SetupWindow
//===========================================================================================================================
OSStatus ExplorerBar::SetupWindow( void )
{
OSStatus err;
CWnd * window;
CRect rect;
CString s;
BOOL ok;
window = CWnd::FromHandle( mParentWindow );
check( window );
window->GetClientRect( rect );
ok = s.LoadString( IDS_NAME );
require_action( ok, exit, err = kNoResourcesErr );
ok = mWindow.Create( NULL, s, WS_CHILD | WS_VISIBLE, rect, window, 100 ) != 0;
require_action( ok, exit, err = kNoResourcesErr );
mWindow.SetOwner( this );
err = kNoErr;
exit:
return( err );
}
//===========================================================================================================================
// GoToURL
//===========================================================================================================================
OSStatus ExplorerBar::GoToURL( const CString &inURL )
{
OSStatus err;
BSTR s;
VARIANT empty;
s = inURL.AllocSysString();
require_action( s, exit, err = kNoMemoryErr );
VariantInit( &empty );
err = mWebBrowser->Navigate( s, &empty, &empty, &empty, &empty );
SysFreeString( s );
require_noerr( err, exit );
exit:
return( err );
}