//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 1994 - 1998 Microsoft Corporation. All Rights Reserved.
//
// PROGRAM: FVINIT.CPP
//
// PURPOSE: All initialization functions and some miscellany for the CFileViewer implementation.
//
// PLATFORMS: Windows 95
//
// FUNCTIONS:
//
//
// SPECIAL INSTRUCTIONS: N/A
//
#include "fileview.h"
//
// FUNCTION: CFileViewer::Init
//
// PURPOSE: Performs any intiailization of a CFileViewer that's prone to
// failure that we also use internally before exposing the object
// outside.
//
// RETURN VALUE:
// HRESULT NOERROR if successful, error code otherwise.
//
HRESULT CFileViewer::Init(void)
{
LPUNKNOWN pIUnknown=(LPUNKNOWN)this;
WNDCLASS wc;
HRESULT hr;
HDC hDC;
//Default error code
hr=ResultFromScode(E_OUTOFMEMORY);
// Make pIUnknown point to outer unknown if we get one.
// The interfaces allocated below are always given an IUnknown
// to which they delegate at all times. This will be either
// the CFileViewer object's IUnknown itself or the outer
// unknown if this object is aggregated. The interfaces
// need not know which case is being used.
if (NULL!=m_pUnkOuter)
pIUnknown=m_pUnkOuter;
//Allocate contained interfaces.
m_pIPersistFile=new CImpIPersistFile(this, pIUnknown);
if (NULL==m_pIPersistFile)
return hr;
m_pIFileViewer=new CImpIFileViewer(this, pIUnknown);
if (NULL==m_pIFileViewer)
return hr;
m_pST=new CStringTable(m_hInst);
if (NULL==m_pST)
return hr;
// Go load the strings we need in CFileViewer::String.
if (!m_pST->FInit(IDS_MIN, IDS_MAX, CCHSTRINGMAX))
return hr;
//Register window classes that we'll need to display the file
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = FileViewerFrameProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = CBWNDEXTRAFRAME;
wc.hInstance = m_hInst;
wc.hIcon = LoadIcon(m_hInst, "Icon");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.lpszClassName = String(IDS_CLASSFRAME);
if (!RegisterClass(&wc))
return hr;
// MODIFY: This is the viewport window that does the work
// of displaying the data. Modify it to your needs.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = ViewportWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = CBWNDEXTRAVIEWPORT;
wc.hInstance = m_hInst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.lpszClassName = String(IDS_CLASSVIEWPORT);
if (!RegisterClass(&wc))
return hr;
m_fClassReg=TRUE;
// Create a default fixed pitch font for the Viewport. We
// use Courier New here instead of say, SYSTEM_FIXED_FONT
// because we want the font sizing buttons to work normally
// when this window appears, and the system fonts do not
// scale, but Courier New does. Default is 10 point calculated
// from 10*PIXELSPERINCH/72.
hDC=GetDC(NULL);
m_cyPPI=GetDeviceCaps(hDC, LOGPIXELSY);
ReleaseDC(NULL, hDC);
m_hFont=CreateFont(MulDiv(-10, m_cyPPI, 72)
, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE
, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "Courier New");
return NOERROR;
}
//
// FUNCTION: CFileViewer::FInitFrameControls
//
// PURPOSE: Creates and initializes the toolbar and status bar for the frame window.
//
// PARAMETERS:
//
// RETURN VALUE:
// BOOL TRUE if the function worked, FALSE otherwise.
//
BOOL CFileViewer::FInitFrameControls(void)
{
BOOL fRet;
RECT rc;
TBBUTTON rgtb[CTBBUTTONS];
// Initialize the toolbar button array. This uses the TOOLS.BMP
// resource which has three buttons and one separator. The
// buttons are tied to File/Open As and Increase/Decrease Font
// size.
rgtb[0].iBitmap=IDBT_OPENAS;
rgtb[0].idCommand=IDM_FILEOPENAS;
rgtb[0].fsState=TBSTATE_ENABLED;
rgtb[0].fsStyle=TBSTYLE_BUTTON;
rgtb[0].dwData=0L;
rgtb[0].iString=0;
rgtb[1].iBitmap=0;
rgtb[1].idCommand=0;
rgtb[1].fsState=TBSTATE_ENABLED;
rgtb[1].fsStyle=TBSTYLE_SEP;
rgtb[1].dwData=0L;
rgtb[1].iString=0;
rgtb[2].iBitmap=IDBT_FONTSIZEINCREASE;
rgtb[2].idCommand=IDM_VIEWFONTINCREASE;
rgtb[2].fsState=TBSTATE_ENABLED;
rgtb[2].fsStyle=TBSTYLE_BUTTON;
rgtb[2].dwData=0L;
rgtb[2].iString=0;
rgtb[3].iBitmap=IDBT_FONTSIZEDECREASE;
rgtb[3].idCommand=IDM_VIEWFONTDECREASE;
rgtb[3].fsState=TBSTATE_ENABLED;
rgtb[3].fsStyle=TBSTYLE_BUTTON;
rgtb[3].dwData=0L;
rgtb[3].iString=0;
// BUGBUG: Open as button: call SHGetIconOfFile to retrieve
// the image, then overwrite it in the toolbar bitmap we send
// to CreateToolbarEx. If SHGetIconOfFile fails, then just
// use the one in the toolbar bitmap already.
//
m_hWndToolbar=CreateToolbarEx(m_hWnd, TBSTYLE_TOOLTIPS
| WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, ID_TOOLBAR
, CTBBITMAPS, m_hInst, IDB_TOOLS, rgtb, CTBBUTTONS
, 0, 0, 0, 0, sizeof(TBBUTTON));
if (NULL==m_hWndToolbar)
{
ODS("CFileViewer::FInitFrameTools failed to create toolbar");
return FALSE;
}
// Remember the height for resizing this and the viewport.
// Use window rectangles for toolbars.
GetWindowRect(m_hWndToolbar, &rc);
m_cyTools=rc.bottom-rc.top;
// Status line
m_hWndStatus=CreateStatusWindow(WS_CHILD | WS_VISIBLE
, String(IDS_MSGREADY), m_hWnd, ID_STATUSBAR);
if (NULL==m_hWndStatus)
{
ODS("CFileViewer::FInitFrameTools failed to create status bar");
return FALSE;
}
// Remember the height for resizing this and the viewport.
// Use client rectangle for status lines.
GetClientRect(m_hWndStatus, &rc);
m_cyStatus=rc.bottom-rc.top;
// Create a status bar helper and tell it what messages
// to use. This object will be called from WM_MENUSELECT
// in FileViewerFrameProc in FVPROC.CPP.
m_pSH=new CStatusHelper(m_hWndStatus, m_hInst);
if (NULL==m_pSH)
return FALSE;
fRet=m_pSH->MessageMap(m_hWnd, IDR_STATMESSAGEMAP, IDS_STATUSMSGMIN
, IDS_STATUSMSGMAX, CCHSTATUSMSGMAX, ID_MENUFILE, ID_MENUHELP
, ID_MSGREADY, ID_MSGEMPTY, ID_MENUSYS);
return fRet;
}
//
// FUNCTION: CFileViewer::String
//
// PURPOSE: string lookup function for access to stringtable.
//
LPSTR CFileViewer::String(UINT uID)
{
return (*m_pST)[uID];
}
//
// FUNCTION: CFileViewer::MemAlloc
//
// PURPOSE:Central allocation function using IMalloc.
//
LPVOID CFileViewer::MemAlloc(ULONG cb)
{
LPMALLOC pIMalloc;
LPVOID pv;
HRESULT hr;
if (FAILED(hr = CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
{
ODSu("CFileViewer::MemAlloc CoGetMalloc failed %ld", hr);
if (hr == CO_E_NOTINITIALIZED)
{
if ((FAILED(hr=CoInitialize(NULL))) ||
FAILED(hr=CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
{
ODSu("CFileViewer::MemAlloc CoInitialize/CoGetMalloc failed %x", hr);
return NULL;
}
}
else
return NULL;
}
pv=pIMalloc->Alloc(cb);
pIMalloc->Release();
return pv;
}
//
// FUNCTION:CFileViewer::MemFree
//
// PURPOSE: Central free function using IMalloc.
//
void CFileViewer::MemFree(LPVOID pv)
{
LPMALLOC pIMalloc;
if (NULL==pv)
{
ODS("CFileViewer::MemFree passed NULL pointer");
return;
}
if (FAILED(CoGetMalloc(MEMCTX_SHARED, &pIMalloc)))
{
ODS("CFileViewer::MemFree CoGetMalloc failed");
return;
}
pIMalloc->Free(pv);
pIMalloc->Release();
return;
}
//
// FUNCTION: CFileViewer::QueryInterface
//
STDMETHODIMP CFileViewer::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
//The only calls for IUnknown are either in a nonaggregated
// case or when created in an aggregation, so in either case
// always return our IUnknown for IID_IUnknown.
if (IsEqualIID(riid, IID_IUnknown))
*ppv=(LPVOID)this;
//IPersist is base of IPersistFile
if (IsEqualIID(riid, IID_IPersist)
|| IsEqualIID(riid, IID_IPersistFile))
*ppv=(LPVOID)m_pIPersistFile;
if (IsEqualIID(riid, IID_IFileViewer))
*ppv=(LPVOID)m_pIFileViewer;
//AddRef any interface we'll return.
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
//
// FUNCTION: CFileViewer::AddRef
//
STDMETHODIMP_(ULONG) CFileViewer::AddRef(void)
{
return ++m_cRef;
}
//
// FUNCTION: CFileViewer::Release
//
STDMETHODIMP_(ULONG) CFileViewer::Release(void)
{
ULONG cRefT;
cRefT=--m_cRef;
ODSu("CFileViewer::Release Count=%d", cRefT);
if (0L==m_cRef)
{
// Tell the server that an object is going away
// so it can shut down if appropriate. (See FILEVIEW.CPP
// for the ObjectDestroyed function).
if (NULL!=m_pfnDestroy)
(*m_pfnDestroy)();
delete this;
}
return cRefT;
}