home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
msdn_vcb
/
samples
/
vc98
/
sdk
/
com
/
inole2
/
classlib
/
cframe.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-23
|
33KB
|
1,370 lines
/*
* CFRAME.CPP
* Sample Code Class Libraries
*
* Generic CFrame class that manages either SDI or MDI clients as
* well as typical File, Edit, Window, and Help commands.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include <windows.h>
#include <memory.h>
extern "C"
{
#include <commdlg.h>
}
#include "classlib.h"
/*
* CFrame::CFrame
* CFrame::~CFrame
*
* Constructor Parameters:
* hInst HINSTANCE from WinMain
* hInstPrev HINSTANCE from WinMain
* pszCmdLine LPSTR from WinMain
* nCmdShow int from WinMain
*/
CFrame::CFrame(HINSTANCE hInst, HINSTANCE hInstPrev
, LPSTR pszCmdLine, int nCmdShow)
: CWindow(hInst)
{
m_hInstPrev =hInstPrev;
m_nCmdShow =nCmdShow;
#ifdef WIN32
//This gives us the Unicode version if necessary
m_pszCmdLine=GetCommandLine();
#else
m_pszCmdLine=pszCmdLine;
#endif
m_ppszCmdArgs=NULL;
m_cCmdArgs=0;
m_fCmdsParsed=FALSE;
m_fLastEnable=(BOOL)-1; //Uninitialized
m_fLastPaste =(BOOL)-1; //Uninitialized
m_phMenu=NULL;
m_hBmp =NULL;
m_pST =NULL;
m_pTB =NULL;
m_pSL =NULL;
m_pCL =NULL;
return;
}
CFrame::~CFrame(void)
{
m_fClosing=TRUE;
//Accelerators freed automatically.
//Free the toolbar bitmaps
if (NULL!=m_hBmp)
DeleteObject(m_hBmp);
if (NULL!=m_pCL)
delete m_pCL;
if (NULL!=m_pSL)
delete m_pSL;
if (NULL!=m_pTB)
delete m_pTB;
//Free the menu handle array
if (NULL!=m_phMenu)
delete []((UINT *)m_phMenu);
//Free the stringtable.
if (NULL!=m_pST)
delete m_pST;
//Free the command-line argument pointer array
if (NULL!=m_ppszCmdArgs)
delete []m_ppszCmdArgs;
m_fClosing=FALSE;
return;
}
/*
* CFrame::ParseCommandLine
*
* Purpose:
* Before other initialization, parse the command line arguments
* since derived classes may need the arguments before calling
* Init below.
*
* Return Value:
* BOOL TRUE if parsing succeeded, FALSE otherwise.
*/
BOOL CFrame::ParseCommandLine(void)
{
LPTSTR *ppsz=NULL;
LPTSTR psz, pszT;
int cArgs=0;
if (m_fCmdsParsed)
return TRUE;
psz=PszWhiteSpaceScan(m_pszCmdLine, TRUE);
#ifdef WIN32
//Skip the first argument which is the EXE name in Win32
psz=PszWhiteSpaceScan(psz, FALSE);
psz=PszWhiteSpaceScan(psz, TRUE);
#endif
for (pszT=psz; *pszT!=0; )
{
cArgs++;
//Skip to the end of this argument
pszT=PszWhiteSpaceScan(pszT, FALSE);
//Stop if we hit the end of the string
if ((TCHAR)0==*pszT)
break;
//Skip whitespace to the next argument
pszT=PszWhiteSpaceScan(pszT, TRUE);
}
/*
* Now allocate a pointer array to each argument in the
* command line and null terminate each argument.
*/
if (0!=cArgs)
{
int i;
ppsz=new LPTSTR[cArgs];
if (NULL==ppsz)
return FALSE;
for (i=0; i < cArgs; i++)
{
ppsz[i]=psz;
psz=PszWhiteSpaceScan(psz, FALSE);
if ((TCHAR)0!=*psz)
pszT=psz;
psz=PszWhiteSpaceScan(psz, TRUE);
*pszT=(TCHAR)0;
}
}
m_ppszCmdArgs=ppsz;
m_cCmdArgs=cArgs;
m_fCmdsParsed=TRUE;
return TRUE;
}
/*
* CFrame::Init
*
* Purpose:
* Initializer for a CFrame object containing anything prone to
* failure.
*
* Parameters:
* pFI PFRAMEINIT containing initialization parameters.
*
* Return Value:
* BOOL TRUE if initialization succeeded, FALSE
* otherwise. If FALSE is returned, the caller must
* guarantee that the destructor is called promptly
* to insure cleanup.
*/
BOOL CFrame::Init(PFRAMEINIT pFI)
{
RECT rc;
HMENU hMenu;
UINT uTemp;
TOOLDISPLAYDATA tdd;
m_fInit=TRUE;
//1. Create our stringtable
m_pST=new CStringTable(m_hInst);
if (!m_pST->Init(pFI->idsMin, pFI->idsMax))
return FALSE;
/*
* 2. Register the classes we need for this application.
* We have our main (frame) window, document windows (for
* either MDI or SDI, and Polyline windows which are the
* editing controls. This separate virtual function allows
* applications to add additional classes.
*/
if (NULL==m_hInstPrev)
{
if (!RegisterAllClasses())
return FALSE;
}
/*
* 3. Create the main window, the toolbar, and the status line.
*/
m_pCL=NULL;
m_hWnd=CreateWindow(SZCLASSFRAME, PSZ(IDS_CAPTION)
, WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
, pFI->x, pFI->y, pFI->cx, pFI->cy
, NULL, NULL, m_hInst, this);
if (NULL==m_hWnd)
return FALSE;
GetClientRect(m_hWnd, &rc);
UIToolConfigureForDisplay(&tdd);
m_dxB=tdd.cxButton;
m_dyB=tdd.cyButton;
m_cyBar=tdd.cyBar;
m_pTB=new CToolBar(m_hInst);
if (!m_pTB->Init(m_hWnd, ID_GIZMOBAR, m_cyBar))
return FALSE;
m_pSL=new CStatusLine(m_hInst);
if (!m_pSL->Init(m_hWnd, ID_STATSTRIP, CYSTATSTRIP))
return FALSE;
//Initialize the status line for automated WM_MENUSELECT processing
if (!m_pSL->MessageMap(m_hWnd, m_hInst, IDR_STATMESSAGEMAP
, pFI->idsStatMin, pFI->idsStatMax, CCHMESSAGEMAX
, pFI->idStatMenuMin, pFI->idStatMenuMax, ID_MESSAGEREADY
, ID_MESSAGEEMPTY, ID_MENUSYS))
return FALSE;
rc.top+=m_cyBar;
/*
* 4. Create the client window that owns documents. This
* client also creates an advise sink and gives it to
* each document to notify the frame of events.
*
* Also allocate space for the menu handle array and store
* the popup handles. Get the menu handle of the Window
* menu specifically for later processing.
*/
m_pCL=CreateCClient();
hMenu=GetMenu(m_hWnd);
#ifdef MDI
//Save this for UpdateMenus. Stays NULL in SDI
m_hMenuWindow=GetSubMenu(hMenu, pFI->iPosWindowMenu);
#endif
if (!m_pCL->Init(m_hMenuWindow, &rc))
return FALSE;
m_phMenu=new HMENU[pFI->cMenus];
for (uTemp=0; uTemp < pFI->cMenus; uTemp++)
m_phMenu[uTemp]=GetSubMenu(hMenu, uTemp);
/*
* 5. Initialize fancy things like the toolbar. If a derived
* class wants more tool images, they can copy the first
* two in the standard image set and this code will still
* load it. This code just won't reference it.
*/
m_hBmp=LoadBitmap(m_hInst, MAKEINTRESOURCE(tdd.uIDImages));
if (NULL==m_hBmp)
return FALSE;
//Create all the tools, and uninitialize working flags
CreateToolbar();
UpdateToolbar();
m_fLastEnable=(BOOL)-1; //Uninitialized
m_fLastPaste =(BOOL)-1; //Uninitialized
m_hAccel=LoadAccelerators(m_hInst
, MAKEINTRESOURCE(IDR_ACCELERATORS));
if (NULL==m_hAccel)
return FALSE;
/*
* 6. In the default implementation PreShowInit does not do
* anything, but is called here to allow derivations to
* hook the function and modify m_nCmdShow before we
* call ShowWindow. This is one such place where OLE affects
* a derivation, because servers will change m_nCmdShow to
* SW_HIDE if started with -Embedding.
*/
if (!PreShowInit())
return FALSE;
/*
* 7. Handle window visibility appropriately after giving
* PreShowInit a chance to modify it.
*/
ShowWindow(m_hWnd, m_nCmdShow);
UpdateWindow(m_hWnd);
/*
* 8. Parse the command line and take appropriate action. The
* derived class may have called ParseCommandLine earlier, so
* m_fCmdsParsed tells us if we still need to call it.
*/
if (!m_fCmdsParsed)
ParseCommandLine();
OpenInitialFiles();
m_fInit=FALSE;
return TRUE;
}
/*
* CFrame::CreateCClient
*
* Purpose:
* Creates a CClient object for use in this frame. This function
* is overrided by derived classes to create a different type of
* CClient.
*
* Return Value:
* PCClient Pointer to the new CClient object.
*/
PCClient CFrame::CreateCClient(void)
{
return new CClient(m_hInst, this);
}
/*
* CFrame::RegisterAllClasses
*
* Purpose:
* Registers all classes used in this application.
*
* Return Value:
* BOOL TRUE if registration succeeded, FALSE otherwise.
*/
BOOL CFrame::RegisterAllClasses(void)
{
WNDCLASS wc;
//Field that are the same for all windows.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = m_hInst;
wc.cbClsExtra = 0;
//Register the Frame window
wc.lpfnWndProc = FrameWndProc;
wc.cbWndExtra = CBFRAMEWNDEXTRA;
wc.hIcon = LoadIcon(m_hInst, TEXT("Icon"));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.lpszClassName = SZCLASSFRAME;
if (!RegisterClass(&wc))
return FALSE;
#ifndef MDI
wc.lpfnWndProc = SDIClientWndProc;
wc.cbWndExtra = CBCLIENTWNDEXTRA;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = SZCLASSSDICLIENT;
if (!RegisterClass(&wc))
return FALSE;
#endif
wc.lpfnWndProc = DocumentWndProc;
wc.cbWndExtra = CBDOCUMENTWNDEXTRA;
wc.hIcon = LoadIcon(m_hInst
, MAKEINTRESOURCE(IDR_DOCUMENTICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = SZCLASSDOCUMENT;
if (!RegisterClass(&wc))
return FALSE;
return TRUE;
}
/*
* CFrame::PreShowInit
*
* Purpose:
* Called from Init before intially showing the window. We do
* whatever else we want here, modifying nCmdShow as necessary
* which affects ShowWindow in Init.
*
* Return Value:
* BOOL TRUE if this initialization succeeded, FALSE
* otherwise.
*/
BOOL CFrame::PreShowInit(void)
{
return TRUE;
}
/*
* CFrame::OpenInitialFiles
*
* Purpose:
* Opens any files that were present on the command line.
*/
void CFrame::OpenInitialFiles(void)
{
UINT i;
PCDocument pDoc;
//Create a new document if we have nothing specific to open
if (0==m_cCmdArgs)
{
pDoc=m_pCL->NewDocument(TRUE);
if (NULL!=pDoc)
pDoc->Load(TRUE, NULL);
UpdateToolbar();
return;
}
//Iterate over the arguments and see if there's any filenames
for (i=0; i < m_cCmdArgs; i++)
{
LPTSTR psz=m_ppszCmdArgs[i];
if (NULL==psz)
break;
//Skip switches prefixed with / and -
if ((TCHAR)0!=*psz && TEXT('/')!=*psz && TEXT('-')!=*psz)
{
pDoc=m_pCL->NewDocument(TRUE);
if (NULL!=pDoc)
pDoc->Load(TRUE, psz);
}
UpdateToolbar();
}
return;
}
/*
* CFrame::CreateToolbar
*
* Purpose:
* Procedure to create all the necessary toolbar buttons.
*
* Return Value:
* UINT Number of tools added to the bar.
*/
UINT CFrame::CreateToolbar(void)
{
UINT uState=GIZMO_NORMAL;
UINT utCmd =GIZMOTYPE_BUTTONCOMMAND;
UINT utEx =GIZMOTYPE_BUTTONATTRIBUTEEX;
//File New, Open, Close, Save, Import
m_pTB->Add(utCmd, 0, IDM_FILENEW, m_dxB, m_dyB, NULL, NULL
, 3, uState);
m_pTB->Add(utCmd, 1, IDM_FILEOPEN, m_dxB, m_dyB, NULL, NULL
, 4, uState);
m_pTB->Add(utCmd, 2, IDM_FILECLOSE, m_dxB, m_dyB, NULL, m_hBmp
, 0, uState);
m_pTB->Add(utCmd, 3, IDM_FILESAVE, m_dxB, m_dyB, NULL, NULL
, 5, uState);
//Separator
m_pTB->Add(GIZMOTYPE_SEPARATOR, 4, 0, 6, m_dyB, NULL, NULL
, 0, uState);
//Edit Undo, Cut, Copy, Paste
m_pTB->Add(utCmd, 5, IDM_EDITUNDO, m_dxB, m_dyB, NULL, m_hBmp
, 1, uState);
m_pTB->Add(utCmd, 6, IDM_EDITCUT, m_dxB, m_dyB, NULL, NULL
, 0, uState);
m_pTB->Add(utCmd, 7, IDM_EDITCOPY, m_dxB, m_dyB, NULL, NULL
, 1, uState);
m_pTB->Add(utCmd, 8, IDM_EDITPASTE, m_dxB, m_dyB, NULL, NULL
, 2, uState);
return 9;
}
/*
* CFrame::MessageLoop
*
* Purpose:
* Spins in a standard message loop (with accelerators) until
* WM_QUIT is found after which it returns.
*
* Return Value:
* WPARAM Contents of msg.wParam from WM_QUIT.
*/
WPARAM CFrame::MessageLoop(void)
{
MSG msg;
while (GetMessage(&msg, NULL, 0,0 ))
{
if (!m_pCL->TranslateAccelerator(&msg))
{
if (!TranslateAccelerator(m_hWnd, m_hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return msg.wParam;
}
/*
* CFrame::FMessageHook
*
* Purpose:
* Provides a derivation of the base CFrame class to hook all
* messages to the window procedure for special processing.
* WM_COMMAND is NOT sent here as that goes through OnCommand
* instead.
*
* Parameters:
* <WndProc Parameters>
* pLRes LRESULT * in which to store the return value
* for the message.
*
* Return Value:
* BOOL TRUE to prevent further processing, FALSE
* otherwise.
*/
BOOL CFrame::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
, LPARAM lParam, LRESULT *pLRes)
{
*pLRes=0;
return FALSE;
}
/*
* CFrame::OnCommand
*
* Purpose:
* WM_COMMAND handler for the frame window so derivations can
* process their messages and then pass the standard commands (like
* file open and save) on to the base class.
*
* Parameters:
* hWnd HWND of the frame window.
* wParam WPARAM of the message.
* lParam LPARAM of the message.
*
* Return Value:
* LRESULT Return value for the message.
*/
LRESULT CFrame::OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PCDocument pDoc;
TCHAR szFile[CCHPATHMAX];
BOOL fOK;
UINT uTemp;
UINT uType;
PCHourglass pHour;
COMMANDPARAMS(wID, wCode, hWndMsg);
/*
* Don't bother with anything during first initialization,
* skipping many toolbar notifications.
*/
if (m_fInit)
return 0L;
pDoc=m_pCL->ActiveDocument();
switch (wID)
{
case IDM_FILENEW:
if (!m_pCL->SDIVerify())
break;
pHour=new CHourglass;
pDoc=m_pCL->NewDocument(TRUE);
//Insure the document is untitled.
if (NULL!=pDoc)
pDoc->Load(TRUE, NULL);
delete pHour;
break;
case IDM_FILEOPEN:
if (!m_pCL->SDIVerify())
break;
szFile[0]=0;
fOK=SaveOpenDialog(szFile, CCHPATHMAX, IDS_FILEOPEN
, TRUE, &uType);
if (!fOK)
return 0L;
pDoc=m_pCL->NewDocument(FALSE);
if (NULL==pDoc)
return 0L;
pHour=new CHourglass;
uTemp=pDoc->Load(TRUE, szFile);
delete pHour;
pDoc->ErrorMessage(uTemp);
//Close the new doc on failure, show on success.
if (DOCERR_NONE!=uTemp)
m_pCL->CloseDocument(pDoc);
else
m_pCL->ShowDocument(pDoc, TRUE);
return (DOCERR_NONE==uTemp);
case IDM_FILECLOSE:
//Ask if you want to save.
if (!m_pCL->FCleanVerify(pDoc))
return 0L;
m_pCL->CloseDocument(pDoc);
UpdateToolbar();
break;
case IDM_FILESAVE:
//If we get this from the toolbar, we may need Save As
fOK=pDoc->FQuerySave();
if (fOK)
{
//Save using current document name and version
pHour=new CHourglass;
uTemp=pDoc->Save(0, NULL);
delete pHour;
pDoc->ErrorMessage(uTemp);
return (DOCERR_NONE==uTemp);
}
//FALL through to File/Save As for no name documents.
case IDM_FILESAVEAS:
//Go get a filename, then save it.
pDoc->FilenameGet(szFile, CCHPATHMAX);
fOK=SaveOpenDialog(szFile, CCHPATHMAX, IDS_FILESAVEAS
, FALSE, &uType);
if (!fOK)
return 0L;
pHour=new CHourglass;
uTemp=pDoc->Save(uType, szFile);
delete pHour;
pDoc->ErrorMessage(uTemp);
return (DOCERR_NONE==uTemp);
case IDM_FILEEXIT:
PostMessage(hWnd, WM_CLOSE, 0, 0L);
break;
case IDM_EDITCUT:
case IDM_EDITCOPY:
pHour=new CHourglass;
pDoc->Clip(hWnd, (IDM_EDITCUT==wID));
delete pHour;
//Update the toolbar as appropriate.
m_pTB->Enable(IDM_EDITPASTE, pDoc->FQueryPaste());
break;
case IDM_EDITUNDO:
pDoc->Undo();
break;
case IDM_EDITPASTE:
pHour=new CHourglass;
pDoc->Paste(hWnd);
delete pHour;
break;
//These commands don't happen in SDI builds; not on the menu
case IDM_WINDOWCASCADE:
m_pCL->OnWindowCommand(WM_MDICASCADE, 0);
break;
case IDM_WINDOWTILEHORZ:
m_pCL->OnWindowCommand(WM_MDITILE, MDITILE_HORIZONTAL);
break;
case IDM_WINDOWTILEVERT:
m_pCL->OnWindowCommand(WM_MDITILE, MDITILE_VERTICAL);
break;
case IDM_WINDOWICONS:
m_pCL->OnWindowCommand(WM_MDIICONARRANGE, 0);
break;
case IDM_HELPABOUT:
DialogBox(m_hInst, MAKEINTRESOURCE(IDD_ABOUT)
, m_hWnd, (DLGPROC)AboutProc);
break;
default:
return m_pCL->DefaultFrameProc(hWnd, WM_COMMAND, wParam
, lParam);
}
return 0L;
}
/*
* CFrame::OnDocumentDataChange
*
* Purpose:
* Most of the CDocumentAdviseSink notifications we get are fairly
* standard implementations. When data in the document changes,
* however, there's probably more special things we can do, so we
* keep this simple case simple with this hook, not forcing a
* derived class to reimplement CDocumentAdviseSink.
*
* Parameters:
* pDoc PCDocument notifying the sink.
*/
void CFrame::OnDocumentDataChange(PCDocument pDoc)
{
return;
}
/*
* CFrame::OnDocumentActivate
*
* Purpose:
* Most of the CDocumentAdviseSink notifications we get are fairly
* standard implementations. When the current document changes,
* however, there's probably more UI that frame derivations need
* to do, so we allow the hook here.
*
* Parameters:
* pDoc PCDocument notifying the sink.
*/
void CFrame::OnDocumentActivate(PCDocument pDoc)
{
return;
}
/*
* CFrame::SaveOpenDialog
*
* Purpose:
* Invokes the COMMDLG.DLL GetOpenFileName dialog and retrieves
* a filename for saving or opening.
*
* Parameters:
* pszFile LPTSTR buffer to receive the entered filename.
* cchFile UINT length of pszFile
* idsCaption UINT of string to use in the caption bar.
* fOpen BOOL indicating if we want file open or save.
* puType UINT * in which we store the selected type.
* Can be NULL.
*
* Return Value:
* BOOL TRUE if the function retrieved a filename,
* FALSE if the user pressed CANCEL.
*/
BOOL CFrame::SaveOpenDialog(LPTSTR pszFile, UINT cchFile
, UINT idsCaption, BOOL fOpen, UINT *puType)
{
OPENFILENAME ofn;
TCHAR szFilter[80];
UINT cch;
BOOL fRet;
#ifdef DEBUG
DWORD dwErr;
#endif
if (NULL==pszFile)
return FALSE;
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize =sizeof(OPENFILENAME);
ofn.hwndOwner =m_hWnd;
if (fOpen)
lstrcpy(szFilter, PSZ(IDS_FILEOPENFILTER));
else
lstrcpy(szFilter, PSZ(IDS_FILESAVEFILTER));
cch=lstrlen(szFilter);
ReplaceCharWithNull(szFilter, szFilter[cch-1]);
ofn.lpstrFilter =szFilter;
ofn.nFilterIndex =1L;
ofn.lpstrTitle =PSZ(idsCaption);
ofn.lpstrFile =pszFile;
ofn.nMaxFile =cchFile;
ofn.lpstrDefExt =PSZ(IDS_DEFEXT);
if (fOpen)
{
ofn.Flags=OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
fRet=GetOpenFileName(&ofn);
}
else
{
ofn.Flags=OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
fRet=GetSaveFileName(&ofn);
}
if (fRet || NULL!=puType)
*puType=(UINT)ofn.nFilterIndex;
#ifdef DEBUG
dwErr=CommDlgExtendedError();
#endif
return fRet;
}
/*
* CFrame::ReplaceCharWithNull
*
* Purpose:
* Walks a null-terminated string and replaces a given character
* with a zero for use with the SaveOpenDialog member.
*
* Parameters:
* psz LPTSTR to the string to process.
* ch int character to replace.
*
* Return Value:
* int Number of characters replaced. -1 if psz is NULL
*/
UINT CFrame::ReplaceCharWithNull(LPTSTR psz, int ch)
{
UINT cChanged=0;
if (NULL==psz)
return 0;
while ((TCHAR)0!=*psz)
{
if (ch==*psz)
{
*psz=0;
cChanged++;
}
psz++;
}
return cChanged;
}
/*
* CFrame::PszWhiteSpaceScan
*
* Purpose:
* Skips characters in a string until a whitespace or non-whitespace
* character is seen. Whitespace is defined as \n, \r, \t, or ' '.
*
* Parameters:
* psz LPTSTR to string to manipulate
* fSkip BOOL TRUE if we want to skip whitespace.
* FALSE if we want to skip anything but whitespace.
*
* Return Value:
* LPTSTR Pointer to first character in the string that
* either non-whitespace (fSkip=TRUE) or
* whitespace (fSkip=FALSE), which may be the
* null terminator.
*/
LPTSTR CFrame::PszWhiteSpaceScan(LPTSTR psz, BOOL fSkip)
{
TCHAR ch;
BOOL fWhite;
while (ch=*psz)
{
//Not too sure how this localizes...
fWhite=(TEXT('\n')==ch || TEXT('\r')==ch
|| TEXT('\t')==ch || TEXT(' ')==ch);
//Too bad C doesn't have a logical XOR (^^) operator.
if ((fSkip && !fWhite) || (!fSkip && fWhite))
break;
psz++;
}
return psz;
}
//PUBLIC FUNCTIONS
/*
* CFrame::AskAndSave
*
* Purpose:
* If a document is closed and is dirty the client window we own
* will get the document's filename and call us here. We will
* ask the user if they want to save that file and if so, send a
* message to our frame window to execute the Save command.
*
* Parameters:
* pszDoc LPTSTR name of the document. If the first
* character is 0 then we use (Untitled).
*
* Return Value:
* BOOL TRUE if the user saved or didn't; FALSE on
* if the user pressed cancel.
*/
BOOL CFrame::AskAndSave(LPTSTR pszDoc)
{
BOOL fRet=TRUE;
UINT uRet;
TCHAR szTemp[CCHFILENAMEMAX+100];
if (NULL==pszDoc)
return FALSE;
if ((TCHAR)0==*pszDoc)
pszDoc=PSZ(IDS_UNTITLED);
else
{
GetFileTitle(pszDoc, szTemp, CCHFILENAMEMAX);
lstrcpy(pszDoc, szTemp);
}
wsprintf(szTemp, PSZ(IDS_FILEDIRTY), pszDoc);
uRet=MessageBox(m_hWnd, szTemp, PSZ(IDS_CAPTION)
, MB_YESNOCANCEL | MB_ICONEXCLAMATION);
/*
* If the user wants to save, tell the window to execute the
* command.
*/
if (IDYES==uRet)
{
/*
* The following is code taken from IDM_SAVE and IDM_SAVEAS
* cases inside OnCommand above. It's copied here to
* allow processing of the return value from pDoc->Save.
*/
PCDocument pDoc;
TCHAR szFile[CCHPATHMAX];
BOOL fOK;
UINT uTemp;
UINT uType;
PCHourglass pHour;
pDoc=m_pCL->ActiveDocument();
fOK=pDoc->FQuerySave();
if (fOK)
{
//Save using current document name and version
pHour=new CHourglass;
uTemp=pDoc->Save(0, NULL);
delete pHour;
pDoc->ErrorMessage(uTemp);
//This return code is for CFrame::AskAndSave
return (DOCERR_NONE==uTemp);
}
//Go get a filename, then save it.
pDoc->FilenameGet(szFile, CCHPATHMAX);
fOK=SaveOpenDialog(szFile, CCHPATHMAX, IDS_FILESAVEAS
, FALSE, &uType);
if (!fOK)
return 0L;
pHour=new CHourglass;
uTemp=pDoc->Save(uType, szFile);
delete pHour;
pDoc->ErrorMessage(uTemp);
return (DOCERR_NONE==uTemp);
}
//TRUE for No, False for Cancel
return (IDCANCEL!=uRet);
}
/*
* CFrame::UpdateMenus
*
* Purpose:
* Handles the WM_INITMENU message for the frame window. Depending
* on the existence of an active window, menu items are selectively
* enabled and disabled.
*
* Parameters:
* hMenu HMENU of the menu to intialize
* iMenu UINT position of the menu.
*/
void CFrame::UpdateMenus(HMENU hMenu, UINT iMenu)
{
PCDocument pDoc;
BOOL fOK=FALSE;
UINT uTemp;
UINT uTempE;
UINT uTempD;
pDoc=m_pCL->ActiveDocument();
uTempE=MF_ENABLED | MF_BYCOMMAND;
uTempD=MF_DISABLED | MF_GRAYED | MF_BYCOMMAND;
uTemp=((NULL!=pDoc) ? uTempE : uTempD);
/*
* File menu: If there is no current document window, disable
* Close, Save, and Save As. If there is a document but
* it doesn't have a filename, disable save.
*/
if (m_phMenu[0]==hMenu)
{
EnableMenuItem(hMenu, IDM_FILECLOSE, uTemp);
EnableMenuItem(hMenu, IDM_FILESAVE, uTemp);
EnableMenuItem(hMenu, IDM_FILESAVEAS, uTemp);
if (NULL!=pDoc)
fOK=pDoc->FQuerySave();
EnableMenuItem(hMenu, IDM_FILESAVE, (fOK) ? uTempE : uTempD);
}
/*
* Edit menus: If there's no document, disable all of it.
* If there's a document but no clipboard format available,
* disable paste only.
*/
if (m_phMenu[1]==hMenu)
{
EnableMenuItem(hMenu, IDM_EDITUNDO, uTemp);
EnableMenuItem(hMenu, IDM_EDITCOPY, uTemp);
EnableMenuItem(hMenu, IDM_EDITCUT, uTemp);
/*
* Paste has two dependencies; format available and an open
* document
*/
if (NULL!=pDoc)
fOK=pDoc->FQueryPaste();
fOK &=(uTemp==uTempE);
EnableMenuItem(hMenu,IDM_EDITPASTE, (fOK) ? uTempE : uTempD);
}
#ifdef MDI
//Window menu: no document, no commands
if (m_hMenuWindow==hMenu)
{
EnableMenuItem(hMenu, IDM_WINDOWCASCADE, uTemp);
EnableMenuItem(hMenu, IDM_WINDOWTILEHORZ, uTemp);
EnableMenuItem(hMenu, IDM_WINDOWTILEVERT, uTemp);
EnableMenuItem(hMenu, IDM_WINDOWICONS, uTemp);
}
#endif
return;
}
/*
* CFrame::UpdateToolbar
*
* Purpose:
* Enables and disablest toolbar buttons depending on whether we
* have a document or not and depending on clipboard format
* availability.
*/
void CFrame::UpdateToolbar(void)
{
PCDocument pDoc;
BOOL fEnable;
pDoc=m_pCL->ActiveDocument();
fEnable=(NULL!=pDoc);
if (m_fLastEnable!=fEnable)
{
m_fLastEnable=fEnable;
//No document, disable just about everything
m_pTB->Enable(IDM_FILECLOSE, fEnable);
m_pTB->Enable(IDM_FILESAVE, fEnable);
m_pTB->Enable(IDM_EDITUNDO, fEnable);
m_pTB->Enable(IDM_EDITCUT, fEnable);
m_pTB->Enable(IDM_EDITCOPY, fEnable);
}
//Special handling: clipboard format available, enable paste
if (NULL!=pDoc)
fEnable &= pDoc->FQueryPaste();
//Paste is not enabled unless there's a document too
if (m_fLastPaste!=fEnable)
{
m_fLastPaste=fEnable;
m_pTB->Enable(IDM_EDITPASTE, fEnable);
}
return;
}
/*
* CFrame::WindowTitleSet
*
* Purpose:
* Handles changing the caption bar of a document window.
*
* Parameters:
* pDoc PCDocument of the document affected. If NULL,
* then we remove titles.
* fDocTitle BOOL indicating to set the document or the main
* window captions. In MDI we may do either, this
* is ignored in SDI.
*/
void CFrame::WindowTitleSet(PCDocument pDoc, BOOL fDocTitle)
{
TCHAR szTitle[CCHPATHMAX];
TCHAR szFile[CCHPATHMAX];
/*
* Go grab the filename. If we get an emtpy file back, then
* we'll use (Untitled). If we have a NULL document, then we'll
* just set the title of the app back to having no filename.
*/
if (NULL!=pDoc)
{
pDoc->FilenameGet(szTitle, CCHPATHMAX);
if ((TCHAR)0==szTitle[0])
lstrcpy(szFile, PSZ(IDS_UNTITLED));
else
{
GetFileTitle(szTitle, szFile, sizeof(szFile));
#ifndef WIN32
AnsiUpper(szFile);
#endif
}
}
else
szFile[0]=0;
#ifndef MDI
//SDI always titles the application window
fDocTitle=FALSE;
#endif
if (fDocTitle)
{
if (NULL!=pDoc)
SetWindowText(pDoc->Window(), szFile);
}
else
{
if ((TCHAR)0!=szFile[0])
{
wsprintf(szTitle, TEXT("%s - %s"), PSZ(IDS_CAPTION)
, (LPTSTR)szFile);
SetWindowText(m_hWnd, szTitle);
}
else
SetWindowText(m_hWnd, PSZ(IDS_CAPTION));
}
return;
}
/*
* CFrame::StatusLine (inline)
*
* Purpose:
* Returns the status line object pointer to the caller so they can
* display status messages.
*
* Return Value:
* PCStatusLine Pointer to the status line object.
*/
PCStatusLine inline CFrame::StatusLine(void)
{
return m_pSL;
}