1/* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18#include "StdAfx.h" 19 20#include "comutil.h" 21#include "ShObjIdl.h" 22 23#include "DebugServices.h" 24 25#include "Resource.h" 26 27#include "ExplorerBar.h" 28 29#include "About.h" 30// MFC Debugging 31 32#ifdef _DEBUG 33#define new DEBUG_NEW 34#undef THIS_FILE 35static char THIS_FILE[] = __FILE__; 36#endif 37 38//=========================================================================================================================== 39// Constants 40//=========================================================================================================================== 41#define LENGTHOF(a) (sizeof(a) == sizeof(&*a)) ? 0 : (sizeof(a) / sizeof(*a)) 42#define MIN_SIZE_X 10 43#define MIN_SIZE_Y 10 44 45//=========================================================================================================================== 46// ExplorerBar 47//=========================================================================================================================== 48 49ExplorerBar::ExplorerBar( void ) 50{ 51 ++gDLLRefCount; 52 53 mRefCount = 1; 54 mSite = NULL; 55 mWebBrowser = NULL; 56 mParentWindow = NULL; 57 mFocus = FALSE; 58 mViewMode = 0; 59 mBandID = 0; 60} 61 62//=========================================================================================================================== 63// ~ExplorerBar 64//=========================================================================================================================== 65 66ExplorerBar::~ExplorerBar( void ) 67{ 68 if( mWebBrowser ) 69 { 70 mWebBrowser->Release(); 71 mWebBrowser = NULL; 72 } 73 if( mSite ) 74 { 75 mSite->Release(); 76 mSite = NULL; 77 } 78 79 --gDLLRefCount; 80} 81 82#if 0 83#pragma mark - 84#pragma mark == IUnknown implementation == 85#endif 86 87//=========================================================================================================================== 88// QueryInterface 89//=========================================================================================================================== 90 91STDMETHODIMP ExplorerBar::QueryInterface( REFIID inID, LPVOID *outResult ) 92{ 93 HRESULT err; 94 95 if( IsEqualIID( inID, IID_IUnknown ) ) // IUnknown 96 { 97 *outResult = this; 98 } 99 else if( IsEqualIID( inID, IID_IOleWindow ) ) // IOleWindow 100 { 101 *outResult = (IOleWindow *) this; 102 } 103 else if( IsEqualIID( inID, IID_IDockingWindow ) ) // IDockingWindow 104 { 105 *outResult = (IDockingWindow *) this; 106 } 107 else if( IsEqualIID( inID, IID_IDeskBand ) ) // IDeskBand 108 { 109 *outResult = (IDeskBand *) this; 110 } 111 else if( IsEqualIID( inID, IID_IInputObject ) ) // IInputObject 112 { 113 *outResult = (IInputObject *) this; 114 } 115 else if( IsEqualIID( inID, IID_IObjectWithSite ) ) // IObjectWithSite 116 { 117 *outResult = (IObjectWithSite *) this; 118 } 119 else if( IsEqualIID( inID, IID_IPersistStream ) ) // IPersistStream 120 { 121 *outResult = (IPersistStream *) this; 122 } 123 else if( IsEqualIID( inID, IID_IContextMenu ) ) // IContextMenu 124 { 125 *outResult = (IContextMenu *) this; 126 } 127 else 128 { 129 *outResult = NULL; 130 err = E_NOINTERFACE; 131 goto exit; 132 } 133 134 ( *( (LPUNKNOWN *) outResult ) )->AddRef(); 135 err = S_OK; 136 137exit: 138 return( err ); 139} 140 141//=========================================================================================================================== 142// AddRef 143//=========================================================================================================================== 144 145STDMETHODIMP_( DWORD ) ExplorerBar::AddRef( void ) 146{ 147 return( ++mRefCount ); 148} 149 150//=========================================================================================================================== 151// Release 152//=========================================================================================================================== 153 154STDMETHODIMP_( DWORD ) ExplorerBar::Release( void ) 155{ 156 DWORD count; 157 158 count = --mRefCount; 159 if( count == 0 ) 160 { 161 delete this; 162 } 163 return( count ); 164} 165 166#if 0 167#pragma mark - 168#pragma mark == IOleWindow implementation == 169#endif 170 171//=========================================================================================================================== 172// GetWindow 173//=========================================================================================================================== 174 175STDMETHODIMP ExplorerBar::GetWindow( HWND *outWindow ) 176{ 177 *outWindow = mWindow.GetSafeHwnd(); 178 return( S_OK ); 179} 180 181//=========================================================================================================================== 182// ContextSensitiveHelp 183//=========================================================================================================================== 184 185STDMETHODIMP ExplorerBar::ContextSensitiveHelp( BOOL inEnterMode ) 186{ 187 DEBUG_UNUSED( inEnterMode ); 188 189 return( E_NOTIMPL ); 190} 191 192#if 0 193#pragma mark - 194#pragma mark == IDockingWindow implementation == 195#endif 196 197//=========================================================================================================================== 198// ShowDW 199//=========================================================================================================================== 200 201STDMETHODIMP ExplorerBar::ShowDW( BOOL inShow ) 202{ 203 if( mWindow.GetSafeHwnd() ) 204 { 205 mWindow.ShowWindow( inShow ? SW_SHOW : SW_HIDE ); 206 } 207 return( S_OK ); 208} 209 210//=========================================================================================================================== 211// CloseDW 212//=========================================================================================================================== 213 214STDMETHODIMP ExplorerBar::CloseDW( DWORD inReserved ) 215{ 216 DEBUG_UNUSED( inReserved ); 217 218 ShowDW( FALSE ); 219 if( mWindow.GetSafeHwnd() ) 220 { 221 mWindow.SendMessage( WM_CLOSE ); 222 } 223 return( S_OK ); 224} 225 226//=========================================================================================================================== 227// ResizeBorderDW 228//=========================================================================================================================== 229 230STDMETHODIMP ExplorerBar::ResizeBorderDW( LPCRECT inBorder, IUnknown *inPunkSite, BOOL inReserved ) 231{ 232 DEBUG_UNUSED( inBorder ); 233 DEBUG_UNUSED( inPunkSite ); 234 DEBUG_UNUSED( inReserved ); 235 236 return( E_NOTIMPL ); 237} 238 239#if 0 240#pragma mark - 241#pragma mark == IDeskBand implementation == 242#endif 243 244//=========================================================================================================================== 245// GetBandInfo 246//=========================================================================================================================== 247 248STDMETHODIMP ExplorerBar::GetBandInfo( DWORD inBandID, DWORD inViewMode, DESKBANDINFO *outInfo ) 249{ 250 HRESULT err; 251 252 require_action( outInfo, exit, err = E_INVALIDARG ); 253 254 mBandID = inBandID; 255 mViewMode = inViewMode; 256 257 if( outInfo->dwMask & DBIM_MINSIZE ) 258 { 259 outInfo->ptMinSize.x = 100; 260 outInfo->ptMinSize.y = 100; 261 } 262 if( outInfo->dwMask & DBIM_MAXSIZE ) 263 { 264 // Unlimited max size. 265 266 outInfo->ptMaxSize.x = -1; 267 outInfo->ptMaxSize.y = -1; 268 } 269 if( outInfo->dwMask & DBIM_INTEGRAL ) 270 { 271 outInfo->ptIntegral.x = 1; 272 outInfo->ptIntegral.y = 1; 273 } 274 if( outInfo->dwMask & DBIM_ACTUAL ) 275 { 276 outInfo->ptActual.x = 0; 277 outInfo->ptActual.y = 0; 278 } 279 if( outInfo->dwMask & DBIM_TITLE ) 280 { 281 CString s; 282 BOOL ok; 283 284 ok = s.LoadString( IDS_NAME ); 285 require_action( ok, exit, err = kNoResourcesErr ); 286 287 #ifdef UNICODE 288 lstrcpyn( outInfo->wszTitle, s, sizeof_array( outInfo->wszTitle ) ); 289 #else 290 DWORD nChars; 291 292 nChars = MultiByteToWideChar( CP_ACP, 0, s, -1, outInfo->wszTitle, sizeof_array( outInfo->wszTitle ) ); 293 err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr ); 294 require_noerr( err, exit ); 295 #endif 296 } 297 if( outInfo->dwMask & DBIM_MODEFLAGS ) 298 { 299 outInfo->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT; 300 } 301 302 // Force the default background color. 303 304 outInfo->dwMask &= ~DBIM_BKCOLOR; 305 err = S_OK; 306 307exit: 308 return( err ); 309} 310 311#if 0 312#pragma mark - 313#pragma mark == IInputObject implementation == 314#endif 315 316//=========================================================================================================================== 317// UIActivateIO 318//=========================================================================================================================== 319 320STDMETHODIMP ExplorerBar::UIActivateIO( BOOL inActivate, LPMSG inMsg ) 321{ 322 DEBUG_UNUSED( inMsg ); 323 324 if( inActivate ) 325 { 326 mWindow.SetFocus(); 327 } 328 return( S_OK ); 329} 330 331//=========================================================================================================================== 332// HasFocusIO 333//=========================================================================================================================== 334 335STDMETHODIMP ExplorerBar::HasFocusIO( void ) 336{ 337 if( mWindow.GetFocus()->GetSafeHwnd() == mWindow.GetSafeHwnd() ) 338 { 339 return( S_OK ); 340 } 341 return( S_FALSE ); 342} 343 344//=========================================================================================================================== 345// TranslateAcceleratorIO 346//=========================================================================================================================== 347 348STDMETHODIMP ExplorerBar::TranslateAcceleratorIO( LPMSG inMsg ) 349{ 350 DEBUG_UNUSED( inMsg ); 351 352 return( S_FALSE ); 353} 354 355#if 0 356#pragma mark - 357#pragma mark == IObjectWithSite implementation == 358#endif 359 360//=========================================================================================================================== 361// SetSite 362//=========================================================================================================================== 363 364STDMETHODIMP ExplorerBar::SetSite( IUnknown *inPunkSite ) 365{ 366 AFX_MANAGE_STATE( AfxGetStaticModuleState() ); 367 368 HRESULT err; 369 370 // Release the old interfaces. 371 372 if( mWebBrowser ) 373 { 374 mWebBrowser->Release(); 375 mWebBrowser = NULL; 376 } 377 if( mSite ) 378 { 379 mSite->Release(); 380 mSite = NULL; 381 } 382 383 // A non-NULL site means we're setting the site. Otherwise, the site is being released (done above). 384 385 if( !inPunkSite ) 386 { 387 err = S_OK; 388 goto exit; 389 } 390 391 // Get the parent window. 392 393 IOleWindow * oleWindow; 394 395 mParentWindow = NULL; 396 err = inPunkSite->QueryInterface( IID_IOleWindow, (LPVOID *) &oleWindow ); 397 require( SUCCEEDED( err ), exit ); 398 399 err = oleWindow->GetWindow( &mParentWindow ); 400 oleWindow->Release(); 401 require_noerr( err, exit ); 402 require_action( mParentWindow, exit, err = E_FAIL ); 403 404 // Get the IInputObject interface. 405 406 err = inPunkSite->QueryInterface( IID_IInputObjectSite, (LPVOID *) &mSite ); 407 require( SUCCEEDED( err ), exit ); 408 check( mSite ); 409 410 // Get the IWebBrowser2 interface. 411 412 IOleCommandTarget * oleCommandTarget; 413 414 err = inPunkSite->QueryInterface( IID_IOleCommandTarget, (LPVOID *) &oleCommandTarget ); 415 require( SUCCEEDED( err ), exit ); 416 417 IServiceProvider * serviceProvider; 418 419 err = oleCommandTarget->QueryInterface( IID_IServiceProvider, (LPVOID *) &serviceProvider ); 420 oleCommandTarget->Release(); 421 require( SUCCEEDED( err ), exit ); 422 423 err = serviceProvider->QueryService( SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID *) &mWebBrowser ); 424 serviceProvider->Release(); 425 require( SUCCEEDED( err ), exit ); 426 427 // Create the main window. 428 429 err = SetupWindow(); 430 require_noerr( err, exit ); 431 432exit: 433 return( err ); 434} 435 436//=========================================================================================================================== 437// GetSite 438//=========================================================================================================================== 439 440STDMETHODIMP ExplorerBar::GetSite( REFIID inID, LPVOID *outResult ) 441{ 442 HRESULT err; 443 444 *outResult = NULL; 445 require_action( mSite, exit, err = E_FAIL ); 446 447 err = mSite->QueryInterface( inID, outResult ); 448 449exit: 450 return( err ); 451} 452 453#if 0 454#pragma mark - 455#pragma mark == IPersistStream implementation == 456#endif 457 458// 459// IPersistStream implementation 460// 461// This is only supported to allow the desk band to be dropped on the desktop and to prevent multiple instances of 462// the desk band from showing up in the context menu. This desk band doesn't actually persist any data. 463// 464 465//=========================================================================================================================== 466// GetClassID 467//=========================================================================================================================== 468 469STDMETHODIMP ExplorerBar::GetClassID( LPCLSID outClassID ) 470{ 471 *outClassID = CLSID_ExplorerBar; 472 return( S_OK ); 473} 474 475//=========================================================================================================================== 476// IsDirty 477//=========================================================================================================================== 478 479STDMETHODIMP ExplorerBar::IsDirty( void ) 480{ 481 return( S_FALSE ); 482} 483 484//=========================================================================================================================== 485// Load 486//=========================================================================================================================== 487 488STDMETHODIMP ExplorerBar::Load( LPSTREAM inStream ) 489{ 490 DEBUG_UNUSED( inStream ); 491 492 return( S_OK ); 493} 494 495//=========================================================================================================================== 496// Save 497//=========================================================================================================================== 498 499STDMETHODIMP ExplorerBar::Save( LPSTREAM inStream, BOOL inClearDirty ) 500{ 501 DEBUG_UNUSED( inStream ); 502 DEBUG_UNUSED( inClearDirty ); 503 504 return( S_OK ); 505} 506 507//=========================================================================================================================== 508// GetSizeMax 509//=========================================================================================================================== 510 511STDMETHODIMP ExplorerBar::GetSizeMax( ULARGE_INTEGER *outSizeMax ) 512{ 513 DEBUG_UNUSED( outSizeMax ); 514 515 return( E_NOTIMPL ); 516} 517 518 519//=========================================================================================================================== 520// QueryContextMenu 521//=========================================================================================================================== 522 523STDMETHODIMP ExplorerBar::QueryContextMenu(HMENU hShellContextMenu, UINT iContextMenuFirstItem, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) 524{ 525 DEBUG_UNUSED( idCmdLast ); 526 DEBUG_UNUSED( uFlags ); 527 528 CMenu menubar; 529 530 menubar.LoadMenu(IDR_CONTEXT_MENU); 531 CMenu * menu = menubar.GetSubMenu(0); 532 533 CMenu shellmenu; 534 535 shellmenu.Attach(hShellContextMenu); 536 537 UINT iShellItem = iContextMenuFirstItem; //! remove plus one 538 UINT idShellCmd = idCmdFirst; 539 540 int n = menu->GetMenuItemCount(); 541 542 for (int i=0; i<n; ++i) 543 { 544 MENUITEMINFO mii; 545 TCHAR sz[128] = {0}; 546 547 ZeroMemory(&mii, sizeof(mii)); 548 mii.fMask = MIIM_TYPE | MIIM_ID; 549 mii.fType = MFT_STRING; 550 mii.cbSize = sizeof(mii); 551 mii.cch = LENGTHOF(sz); 552 mii.dwTypeData = sz; 553 554 menu->GetMenuItemInfo(i, &mii, TRUE); 555 556 mii.wID = idShellCmd++; 557 558 shellmenu.InsertMenuItem(iShellItem++, &mii, TRUE); 559 } 560 561 shellmenu.Detach(); 562 563 return n; 564} 565 566 567//=========================================================================================================================== 568// GetCommandString 569//=========================================================================================================================== 570 571// Not called for explorer bars 572STDMETHODIMP ExplorerBar::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax) 573{ 574 DEBUG_UNUSED( idCmd ); 575 DEBUG_UNUSED( uType ); 576 DEBUG_UNUSED( pwReserved ); 577 DEBUG_UNUSED( pszName ); 578 DEBUG_UNUSED( cchMax ); 579 580 return E_NOTIMPL; 581} 582 583//=========================================================================================================================== 584// InvokeCommand 585//=========================================================================================================================== 586 587// The shell sends either strings or indexes 588// IE never sends strings 589// The indexes are into an array of my commands 590// So the verb for the first command I added to the menu is always 0x0000 591// Here - because I don't have any submenus - 592// I can treat the 'verb' as an menu item position 593STDMETHODIMP ExplorerBar::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) 594{ 595 // IE doesn't send string commands 596 if (HIWORD(lpici->lpVerb) != 0) return 0; 597 598 CAbout dlg; 599 600 dlg.DoModal(); 601 602 return S_OK; 603} 604 605#if 0 606#pragma mark - 607#pragma mark == Other == 608#endif 609 610//=========================================================================================================================== 611// SetupWindow 612//=========================================================================================================================== 613 614OSStatus ExplorerBar::SetupWindow( void ) 615{ 616 OSStatus err; 617 CWnd * window; 618 CRect rect; 619 CString s; 620 BOOL ok; 621 622 window = CWnd::FromHandle( mParentWindow ); 623 check( window ); 624 window->GetClientRect( rect ); 625 626 ok = s.LoadString( IDS_NAME ); 627 require_action( ok, exit, err = kNoResourcesErr ); 628 629 ok = mWindow.Create( NULL, s, WS_CHILD | WS_VISIBLE, rect, window, 100 ) != 0; 630 require_action( ok, exit, err = kNoResourcesErr ); 631 632 mWindow.SetOwner( this ); 633 err = kNoErr; 634 635exit: 636 return( err ); 637} 638 639//=========================================================================================================================== 640// GoToURL 641//=========================================================================================================================== 642 643OSStatus ExplorerBar::GoToURL( const CString &inURL ) 644{ 645 OSStatus err; 646 BSTR s; 647 VARIANT empty; 648 649 s = inURL.AllocSysString(); 650 require_action( s, exit, err = kNoMemoryErr ); 651 652 VariantInit( &empty ); 653 err = mWebBrowser->Navigate( s, &empty, &empty, &empty, &empty ); 654 SysFreeString( s ); 655 require_noerr( err, exit ); 656 657exit: 658 return( err ); 659} 660