301 lines
8.2 KiB
C++
301 lines
8.2 KiB
C++
// Page.cpp: implementation of the TaskPage class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "Page.h"
|
|
|
|
|
|
////////////////////////////////////////////////////////
|
|
// ActiveX Host Element
|
|
|
|
class AxHost : public HWNDHost
|
|
{
|
|
public:
|
|
static HRESULT Create(Element**) { return E_NOTIMPL; } // Required for ClassInfo
|
|
static HRESULT Create(OUT AxHost** ppElement) { return Create(0, AE_MouseAndKeyboard, ppElement); }
|
|
static HRESULT Create(UINT nCreate, UINT nActive, OUT AxHost** ppElement);
|
|
|
|
~AxHost() { ATOMICRELEASE(_pOleObject); }
|
|
|
|
// Initialization
|
|
HRESULT AttachControl(IUnknown* punkObject);
|
|
|
|
// Rendering
|
|
virtual SIZE GetContentSize(int dConstW, int dConstH, Surface* psrf);
|
|
|
|
// ClassInfo accessors (static and virtual instance-based)
|
|
static IClassInfo* Class;
|
|
virtual IClassInfo* GetClassInfo() { return Class; }
|
|
|
|
protected:
|
|
AxHost() : _pOleObject(NULL) {}
|
|
|
|
virtual HWND CreateHWND(HWND hwndParent)
|
|
{
|
|
return CreateWindowEx(0,
|
|
CAxWindow::GetWndClassName(),
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE,
|
|
0, 0, 0, 0,
|
|
hwndParent,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
|
|
private:
|
|
IOleObject* _pOleObject;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////
|
|
// AxHost Initialization
|
|
|
|
HRESULT AxHost::Create(UINT nCreate, UINT nActive, OUT AxHost** ppElement)
|
|
{
|
|
if (!ppElement)
|
|
return E_POINTER;
|
|
|
|
*ppElement = NULL;
|
|
|
|
AxHost* pe = new AxHost;
|
|
if (!pe)
|
|
return E_OUTOFMEMORY;
|
|
|
|
HRESULT hr = pe->Initialize(nCreate, nActive);
|
|
if (FAILED(hr))
|
|
{
|
|
pe->Destroy();
|
|
}
|
|
else
|
|
{
|
|
*ppElement = pe;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT AxHost::AttachControl(IUnknown* punkObject)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == GetHWND())
|
|
return E_UNEXPECTED;
|
|
|
|
if (NULL == punkObject)
|
|
return E_INVALIDARG;
|
|
|
|
ATOMICRELEASE(_pOleObject);
|
|
|
|
hr = punkObject->QueryInterface(IID_IOleObject, (void**)&_pOleObject);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComPtr<IUnknown> spUnk;
|
|
hr = AtlAxGetHost(GetHWND(), &spUnk);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComPtr<IAxWinHostWindow> spAxHostWindow;
|
|
hr = spUnk->QueryInterface(&spAxHostWindow);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = spAxHostWindow->AttachControl(punkObject, GetHWND());
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// AxHost Rendering
|
|
|
|
SIZE AxHost::GetContentSize(int dConstW, int dConstH, Surface* psrf)
|
|
{
|
|
SIZE size = { 0, 0 };
|
|
|
|
// Ask the attached ActiveX control for its preferred size
|
|
if (NULL != _pOleObject)
|
|
{
|
|
SIZEL sizeT;
|
|
if (SUCCEEDED(_pOleObject->GetExtent(DVASPECT_CONTENT, &sizeT)))
|
|
{
|
|
int dpiX;
|
|
int dpiY;
|
|
|
|
switch (psrf->GetType())
|
|
{
|
|
case Surface::stDC:
|
|
{
|
|
HDC hDC = CastHDC(psrf);
|
|
dpiX = GetDeviceCaps(hDC, LOGPIXELSX);
|
|
dpiY = GetDeviceCaps(hDC, LOGPIXELSX);
|
|
}
|
|
break;
|
|
|
|
#ifdef GADGET_ENABLE_GDIPLUS
|
|
case Surface::stGdiPlus:
|
|
{
|
|
Gdiplus::Graphics * pgpgr = CastGraphics(psrf);
|
|
dpiX = (int)pgpgr->GetDpiX();
|
|
dpiY = (int)pgpgr->GetDpiY();
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
dpiX = dpiY = 96;
|
|
break;
|
|
}
|
|
|
|
// Convert from HIMETRIC to pixels
|
|
size.cx = (MAXLONG == sizeT.cx) ? MAXLONG : MulDiv(sizeT.cx, dpiX, 2540);
|
|
size.cy = (MAXLONG == sizeT.cy) ? MAXLONG : MulDiv(sizeT.cy, dpiY, 2540);
|
|
|
|
if (-1 != dConstW && size.cx > dConstW) size.cx = dConstW;
|
|
if (-1 != dConstH && size.cy > dConstH) size.cy = dConstH;
|
|
}
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Property definitions
|
|
|
|
/** Property template (replace !!!), also update private PropertyInfo* parray and class header (element.h)
|
|
// !!! property
|
|
static int vv!!![] = { DUIV_INT, -1 }; StaticValue(svDefault!!!, DUIV_INT, 0);
|
|
static PropertyInfo imp!!!Prop = { L"!!!", PF_Normal, 0, vv!!!, (Value*)&svDefault!!! };
|
|
PropertyInfo* Element::!!!Prop = &imp!!!Prop;
|
|
**/
|
|
|
|
////////////////////////////////////////////////////////
|
|
// ClassInfo (must appear after property definitions)
|
|
|
|
// Class properties
|
|
//static PropertyInfo* _aPI[] = {;};
|
|
|
|
// Define class info with type and base type, set static class pointer
|
|
static ClassInfo<AxHost,HWNDHost> _ciAxHost(L"AxHost", NULL, 0);
|
|
//static ClassInfo<AxHost,HWNDHost> _ciAxHost(L"AxHost", _aPI, sizeof(_aPI) / sizeof(PropertyInfo*));
|
|
IClassInfo* AxHost::Class = &_ciAxHost;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT TaskPage::Create(REFCLSID rclsidPage, HWND hParent, OUT TaskPage** ppElement)
|
|
{
|
|
if (!ppElement)
|
|
return E_POINTER;
|
|
|
|
*ppElement = NULL;
|
|
|
|
TaskPage* pe = new TaskPage(rclsidPage);
|
|
if (!pe)
|
|
return E_OUTOFMEMORY;
|
|
|
|
HRESULT hr = pe->Initialize(hParent, /*double-buffer*/ true, 0);
|
|
if (FAILED(hr))
|
|
{
|
|
pe->Destroy();
|
|
}
|
|
else
|
|
{
|
|
*ppElement = pe;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT TaskPage::CreateContent(ITaskPage* pPage)
|
|
{
|
|
HRESULT hr;
|
|
UINT nPane;
|
|
|
|
if (NULL != _pTaskPage)
|
|
return E_UNEXPECTED;
|
|
|
|
if (NULL == _hWnd)
|
|
return E_FAIL;
|
|
|
|
if (NULL == pPage)
|
|
return E_INVALIDARG;
|
|
|
|
_pTaskPage = pPage;
|
|
_pTaskPage->AddRef();
|
|
|
|
for (nPane = 0; ; nPane++)
|
|
{
|
|
// Panes are sequentially numbered, starting at 0, with id names
|
|
// "Pane0", "Pane1", etc.
|
|
WCHAR szPane[16] = L"Pane";
|
|
_ultow(nPane, &szPane[4], 10);
|
|
|
|
// Don't use StrToID here since it asserts success
|
|
// but we expect it to fail.
|
|
ATOM atomID = FindAtomW(szPane);
|
|
if (INVALID_ATOM == atomID)
|
|
{
|
|
// No more panes
|
|
break;
|
|
}
|
|
|
|
Element *pePane = FindDescendent(atomID);
|
|
if (NULL != pePane)
|
|
{
|
|
// How many objects are in this pane?
|
|
UINT cObjects = 0;
|
|
hr = _pTaskPage->GetObjectCount(nPane, &cObjects);
|
|
if (SUCCEEDED(hr) && 0 != cObjects)
|
|
{
|
|
UINT nObject;
|
|
for (nObject = 0; nObject < cObjects; nObject++)
|
|
{
|
|
// Create the object
|
|
CComPtr<IUnknown> spObject;
|
|
hr = _pTaskPage->CreateObject(nPane, nObject, IID_IUnknown, (void**)&spObject);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AxHost* pAxHost;
|
|
|
|
// Create an AxHost container for the object
|
|
hr = AxHost::Create(&pAxHost);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Add the element to the heirarchy
|
|
// Note: this is where AxHost::CreateHWND() is called
|
|
hr = pePane->Add(pAxHost);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Must have an HWND for this to work, so do
|
|
// this after pePane->Add.
|
|
hr = pAxHost->AttachControl(spObject);
|
|
if (FAILED(hr))
|
|
{
|
|
pePane->Remove(pAxHost);
|
|
delete pAxHost; //::DestroyWindow(pAxHost->GetHWND());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Turn on WS_VISIBLE
|
|
SetVisible(true);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT TaskPage::Reinitialize()
|
|
{
|
|
if (NULL == _pTaskPage)
|
|
return E_UNEXPECTED;
|
|
|
|
return _pTaskPage->Reinitialize(0);
|
|
}
|