/**************************************************************************
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright 1997 Microsoft Corporation. All Rights Reserved.
**************************************************************************/
/**************************************************************************
File: DockWndw.cpp
Description: Implements CDockingWindow
**************************************************************************/
/**************************************************************************
#include statements
**************************************************************************/
#include "DockWndw.h"
#if (_WIN32_IE >= 0x0400)
/**************************************************************************
CDockingWindow::CDockingWindow()
**************************************************************************/
CDockingWindow::CDockingWindow(CShellView *pView, HWND hwndCommand)
{
m_pView = pView;
if(m_pView)
{
m_pView->AddRef();
}
else
{
delete this;
return;
}
m_pSite = NULL;
m_hWnd = NULL;
m_hwndCommand = hwndCommand;
m_bFocus = FALSE;
m_rcDisplay.left = 0;
m_rcDisplay.top = 0;
m_rcDisplay.right = 0;
m_rcDisplay.bottom = 0;
m_ObjRefCount = 1;
g_DllRefCount++;
}
/**************************************************************************
CDockingWindow::~CDockingWindow()
**************************************************************************/
CDockingWindow::~CDockingWindow()
{
if(m_pView)
{
m_pView->Release();
}
g_DllRefCount--;
}
///////////////////////////////////////////////////////////////////////////
//
// IUnknown Implementation
//
/**************************************************************************
CDockingWindow::QueryInterface
**************************************************************************/
STDMETHODIMP CDockingWindow::QueryInterface(REFIID riid, LPVOID *ppReturn)
{
*ppReturn = NULL;
//IUnknown
if(IsEqualIID(riid, IID_IUnknown))
{
*ppReturn = this;
}
//IOleWindow
else if(IsEqualIID(riid, IID_IOleWindow))
{
*ppReturn = (IOleWindow*)this;
}
//IDockingWindow
else if(IsEqualIID(riid, IID_IDockingWindow))
{
*ppReturn = (IDockingWindow*)this;
}
//IInputObject
else if(IsEqualIID(riid, IID_IInputObject))
{
*ppReturn = (IInputObject*)this;
}
//IObjectWithSite
else if(IsEqualIID(riid, IID_IObjectWithSite))
{
*ppReturn = (IObjectWithSite*)this;
}
if(*ppReturn)
{
(*(LPUNKNOWN*)ppReturn)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/**************************************************************************
CDockingWindow::AddRef
**************************************************************************/
STDMETHODIMP_(DWORD) CDockingWindow::AddRef()
{
return ++m_ObjRefCount;
}
/**************************************************************************
CDockingWindow::Release
**************************************************************************/
STDMETHODIMP_(DWORD) CDockingWindow::Release()
{
if(--m_ObjRefCount == 0)
{
delete this;
return 0;
}
return m_ObjRefCount;
}
///////////////////////////////////////////////////////////////////////////
//
// IOleWindow Implementation
//
/**************************************************************************
CDockingWindow::GetWindow()
**************************************************************************/
STDMETHODIMP CDockingWindow::GetWindow(HWND *phWnd)
{
*phWnd = m_hWnd;
return S_OK;
}
/**************************************************************************
CDockingWindow::ContextSensitiveHelp()
**************************************************************************/
STDMETHODIMP CDockingWindow::ContextSensitiveHelp(BOOL fEnterMode)
{
return E_NOTIMPL;
}
///////////////////////////////////////////////////////////////////////////
//
// IDockingWindow Implementation
//
/**************************************************************************
CDockingWindow::ShowDW()
**************************************************************************/
STDMETHODIMP CDockingWindow::ShowDW(BOOL fShow)
{
//if our window doesn't exist yet, create it now
if(!m_hWnd && m_pSite)
{
HRESULT hr;
//if our window class has not been registered, then do so
WNDCLASS wc;
if(!GetClassInfo(g_hInst, SHTB_CLASS_NAME, &wc))
{
ZeroMemory(&wc, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(192, 0, 0));
wc.lpszMenuName = NULL;
wc.lpszClassName = SHTB_CLASS_NAME;
if(!RegisterClass(&wc))
{
//if this fails, CreateWindow will fail, so don't sweat it
}
}
//get our parent window
hr = m_pSite->GetWindow(&m_hwndParent);
if(SUCCEEDED(hr))
{
RECT rc;
GetClientRect(m_hwndParent, &rc);
//create the window - use zero for pos and size - it will get positioned and sized below
CreateWindowEx( WS_EX_CLIENTEDGE,
SHTB_CLASS_NAME,
NULL,
WS_CHILD | WS_CLIPSIBLINGS,
0,
0,
0,
0,
m_hwndParent,
NULL,
g_hInst,
(LPVOID)this);
if(!m_hWnd)
return E_FAIL;
NegotiateBorderSpace(m_pSite);
}
}
if(m_hWnd && m_pSite)
{
BORDERWIDTHS bwRequest = {0, 0, 0, 0};
if(fShow)
{
//position the window - m_rcDisplay was set up in NegotiateBorderSpace
MoveWindow( m_hWnd,
m_rcDisplay.left,
m_rcDisplay.top,
m_rcDisplay.right,
m_rcDisplay.bottom,
TRUE);
//show our window
ShowWindow(m_hWnd, SW_SHOW);
}
else
{
//hide our window
ShowWindow(m_hWnd, SW_HIDE);
//release our border space - bwRequest was initialized above
m_pSite->SetBorderSpaceDW((IDockingWindow*)this, &bwRequest);
}
}
return S_OK;
}
/**************************************************************************
CDockingWindow::CloseDW()
**************************************************************************/
STDMETHODIMP CDockingWindow::CloseDW(DWORD dwReserved)
{
if(m_pSite)
{
ShowDW(FALSE);
if(IsWindow(m_hWnd))
DestroyWindow(m_hWnd);
m_pSite->Release();
m_pSite = NULL;
}
return S_OK;
}
/**************************************************************************
CDockingWindow::ResizeBorderDW()
**************************************************************************/
STDMETHODIMP CDockingWindow::ResizeBorderDW(LPCRECT prcBorder, IUnknown* punkSite, BOOL fReserved)
{
IDockingWindowSite *pSite = NULL;
//if punkSite is not NULL, use it to negotiate our border space
if(punkSite)
{
if(FAILED(punkSite->QueryInterface(IID_IDockingWindowSite, (LPVOID*)&pSite)))
{
return E_FAIL;
}
}
else if(m_pSite)
{
pSite = m_pSite;
pSite->AddRef();
}
if(pSite)
{
HRESULT hr = E_FAIL;
if(NegotiateBorderSpace(pSite, prcBorder))
{
//updated our window's position
ShowDW(TRUE);
hr = S_OK;
}
pSite->Release();
return hr;
}
return E_FAIL;
}
///////////////////////////////////////////////////////////////////////////
//
// IInputObject Implementation
//
/**************************************************************************
CDockingWindow::UIActivateIO()
**************************************************************************/
STDMETHODIMP CDockingWindow::UIActivateIO(BOOL fActivate, LPMSG pMsg)
{
if(fActivate)
SetFocus(m_hWnd);
return S_OK;
}
/**************************************************************************
CDockingWindow::HasFocusIO()
If this window or one of its decendants has the focus, return S_OK. Return
S_FALSE if we don't have the focus.
**************************************************************************/
STDMETHODIMP CDockingWindow::HasFocusIO(void)
{
if(m_bFocus)
return S_OK;
return S_FALSE;
}
/**************************************************************************
CDockingWindow::TranslateAcceleratorIO()
If the accelerator is translated, return S_OK or S_FALSE otherwise.
**************************************************************************/
STDMETHODIMP CDockingWindow::TranslateAcceleratorIO(LPMSG pMsg)
{
return S_FALSE;
}
///////////////////////////////////////////////////////////////////////////
//
// IObjectWithSite implementations
//
/**************************************************************************
CDockingWindow::SetSite()
**************************************************************************/
STDMETHODIMP CDockingWindow::SetSite(IUnknown* punkSite)
{
if(m_pSite)
{
m_pSite->Release();
m_pSite = NULL;
}
//If punkSite is not NULL, we are connecting to the site.
if(punkSite)
{
if(SUCCEEDED(punkSite->QueryInterface(IID_IDockingWindowSite, (LPVOID*)&m_pSite)))
{
return S_OK;
}
}
return S_OK;
}
/**************************************************************************
CDockingWindow::GetSite()
**************************************************************************/
STDMETHODIMP CDockingWindow::GetSite(REFIID riid, LPVOID *ppvReturn)
{
*ppvReturn = NULL;
if(m_pSite)
return m_pSite->QueryInterface(riid, ppvReturn);
return E_FAIL;
}
///////////////////////////////////////////////////////////////////////////
//
// private method implementations
//
/**************************************************************************
CDockingWindow::WndProc()
**************************************************************************/
LRESULT CALLBACK CDockingWindow::WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
CDockingWindow *pThis = (CDockingWindow*)GetWindowLong(hWnd, GWL_USERDATA);
switch (uMessage)
{
case WM_NCCREATE:
{
LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
pThis = (CDockingWindow*)(lpcs->lpCreateParams);
SetWindowLong(hWnd, GWL_USERDATA, (LONG)pThis);
//set the window handle
pThis->m_hWnd = hWnd;
}
break;
case WM_PAINT:
return pThis->OnPaint();
case WM_COMMAND:
return pThis->OnCommand(wParam, lParam);
case WM_SETFOCUS:
return pThis->OnSetFocus();
case WM_KILLFOCUS:
return pThis->OnKillFocus();
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
/**************************************************************************
CDockingWindow::OnPaint()
**************************************************************************/
LRESULT CDockingWindow::OnPaint(void)
{
PAINTSTRUCT ps;
RECT rc;
BeginPaint(m_hWnd, &ps);
GetClientRect(m_hWnd, &rc);
SetTextColor(ps.hdc, RGB(0, 0, 0));
SetBkMode(ps.hdc, TRANSPARENT);
DrawText(ps.hdc, TEXT("IDockingWindow"), -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(m_hWnd, &ps);
return 0;
}
/**************************************************************************
CDockingWindow::OnCommand()
**************************************************************************/
LRESULT CDockingWindow::OnCommand(WPARAM wParam, LPARAM lParam)
{
/*
Since this is a toolbar object, we need to forward all WM_COMMAND messages to
our assigned command window.
*/
return SendMessage(m_hwndCommand, WM_COMMAND, wParam, lParam);
}
/**************************************************************************
CDockingWindow::FocusChange()
**************************************************************************/
void CDockingWindow::FocusChange(BOOL bFocus)
{
m_bFocus = bFocus;
//inform the input object site that the focus has changed
IInputObjectSite *pios;
if(SUCCEEDED(m_pSite->QueryInterface(IID_IInputObjectSite, (LPVOID*)&pios)))
{
pios->OnFocusChangeIS((IDockingWindow*)this, bFocus);
pios->Release();
}
}
/**************************************************************************
CDockingWindow::OnSetFocus()
**************************************************************************/
LRESULT CDockingWindow::OnSetFocus(void)
{
FocusChange(TRUE);
m_pView->OnActivate(SVUIA_ACTIVATE_FOCUS);
return 0;
}
/**************************************************************************
CDockingWindow::OnKillFocus()
**************************************************************************/
LRESULT CDockingWindow::OnKillFocus(void)
{
FocusChange(FALSE);
m_pView->OnDeactivate();
return 0;
}
/**************************************************************************
CDockingWindow::NegotiateBorderSpace()
**************************************************************************/
BOOL CDockingWindow::NegotiateBorderSpace(IDockingWindowSite *pSite, LPCRECT prcBorder)
{
HRESULT hr;
BORDERWIDTHS bwRequest = {0, 0, 0, 0};
bwRequest.top = TOOLBAR_HEIGHT;
hr = pSite->RequestBorderSpaceDW((IDockingWindow*)this, &bwRequest);
if(SUCCEEDED(hr))
{
hr = pSite->SetBorderSpaceDW((IDockingWindow*)this, &bwRequest);
if(SUCCEEDED(hr))
{
RECT rcTemp;
if(!prcBorder)
{
hr = pSite->GetBorderDW((IDockingWindow*)this, &rcTemp);
if(SUCCEEDED(hr))
{
prcBorder = &rcTemp;
}
}
if(prcBorder)
{
//set up our display rectangle
m_rcDisplay.left = prcBorder->left;
m_rcDisplay.top = prcBorder->top;
m_rcDisplay.right = prcBorder->right - prcBorder->left;
m_rcDisplay.bottom = bwRequest.top;
return TRUE;
}
}
}
return FALSE;
}
#endif //(_WIN32_IE >= 0x0400)