Microsoft-3D-Movie-Maker/SRC/STUDIO/PORTF.CPP
2022-05-03 16:31:19 -07:00

1515 lines
45 KiB
C++

/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */
/***************************************************************************
portf.cpp: Portfolio handler
Primary Author: ******
Review Status: peted has reviewed. Final version not yet approved.
***************************************************************************/
#include "studio.h"
#include "commctrl.h"
ASSERTNAME
/***************************************************************************
FPortDisplayWithIds: Display the portfolio to open or save a file. Portfolio
title and filters generated using supplied string ids.
Arguments: fni - Output FNI for file selected
fOpen - fTrue if open portfolio, else save portfolio.
lFilterLabel - id of portfolio filter label
lFilterExt - id of portfolio filter extension
lTitle - id of portfolio title
lpstrDefExt - Ptr to string for default file extension for save if required.
pstnDefFileName - Ptr to default extension stn if required.
pfniInitialDir - Ptr to initial directory fni if required.
grfPrevType - Bits for types of preview required, (eg movie, sound etc) == 0 if no preview
cnoWave - Wave cno for audio when portfolio is invoked
Returns: TRUE - File selected
FALSE - User canceled portfolio.
***************************************************************************/
bool FPortDisplayWithIds(FNI *pfni, bool fOpen, long lFilterLabel, long lFilterExt, long lTitle,
LPTSTR lpstrDefExt, PSTN pstnDefFileName, FNI *pfniInitialDir, ulong grfPrevType, CNO cnoWave)
{
STN stnTitle;
STN stnFilterLabel;
STN stnFilterExt;
int cChLabel, cChExt;
SZ szFilter;
bool fRet;
AssertVarMem(pfni);
AssertNilOrPo(pfniInitialDir, 0);
AssertNilOrPo(pstnDefFileName, 0);
if (!vapp.FGetStnApp(lTitle, &stnTitle))
return fFalse;
// Filter string contain non-terminating null characters, so must
// build up string from separate label and file extension strings.
if (!vapp.FGetStnApp(lFilterLabel, &stnFilterLabel))
return fFalse;
if (!vapp.FGetStnApp(lFilterExt, &stnFilterExt))
return fFalse;
// Kauai does not like internal null chars in an STN. So build
// up the final final string as an SZ.
cChLabel = stnFilterLabel.Cch();
cChExt = stnFilterExt.Cch();
stnFilterLabel.GetSz(szFilter);
stnFilterExt.GetSz(&szFilter[cChLabel + 1]);
szFilter[cChLabel + cChExt + 2] = chNil;
// Now display the open or save portfolio as required
StopAllMovieSounds();
vapp.EnsureInteractive();
vapp.SetFInPortfolio(fTrue);
if(fOpen)
{
fRet = FPortGetFniOpen(pfni, szFilter, stnTitle.Prgch(),
pfniInitialDir, grfPrevType, cnoWave);
}
else
{
fRet = FPortGetFniSave(pfni, szFilter, stnTitle.Prgch(),
lpstrDefExt, pstnDefFileName, grfPrevType, cnoWave);
}
// Make sure no portfolio related audio is still playing.
vpsndm->StopAll(sqnNil, sclNil);
vapp.SetFInPortfolio(fFalse);
// Let the script know what the outcome is.
vpcex->EnqueueCid(cidPortfolioClosed, 0, 0, fRet);
// We must also enqueue a message for the help system here.
// Help doesn't get the above cidPortfolioClosed as it has
// already been filtered.
vpcex->EnqueueCid(cidPortfolioResult, 0, 0, fRet);
return fRet;
}
/***************************************************************************
FPortGetFniOpen: Display the portfolio to open a file.
Arguments: pfni - Output FNI for file selected
lpstrFilter - String containing files types to filter on
lpstrTitle - String containing title of portfolio
pfniInitialDir - Ptr to initial directory fni if required.
grfPrevType - Bits for types of preview required, (eg movie, sound etc) == 0 if no preview
cnoWave - Wave cno for audio when portfolio is invoked
Returns: TRUE - File selected
FALSE - User canceled portfolio.
***************************************************************************/
bool FPortGetFniOpen(FNI *pfni, LPTSTR lpstrFilter, LPTSTR lpstrTitle,
FNI *pfniInitialDir, ulong grfPrevType, CNO cnoWave)
{
SZ szFile;
DLGINFO diPortfolio;
OPENFILENAME ofn;
STN stn;
bool fOKed;
STN stnInitialDir;
SZ szInitialDir;
AssertPo(pfni, 0);
AssertNilOrPo(pfniInitialDir, 0);
ClearPb(&ofn, size(OPENFILENAME));
ClearPb(&diPortfolio, size(DLGINFO));
szFile[0] = 0;
ofn.lStructSize = size(OPENFILENAME);
ofn.hwndOwner = vwig.hwndApp;
ofn.hInstance = vwig.hinst;
ofn.nFilterIndex = 1L;
ofn.lpstrCustomFilter = NULL;
ofn.lpstrFile = szFile;
ofn.nMaxFile = kcchMaxSz;
ofn.lpstrFileTitle = NULL;
ofn.lpfnHook = OpenHookProc;
ofn.lpTemplateName = MAKEINTRESOURCE(dlidPortfolio);
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE;
// lpstrDefExt is used for appended to the user typed filename is
// one is entered without an extension. As the user cannot type
// anything during a portfolio open, we don't use the lpstrDefExt here.
ofn.lpstrDefExt = NULL;
// Initialize internal data for accessing from inside dlg hook proc.
diPortfolio.fIsOpen = fTrue;
diPortfolio.fDrawnBkgnd = fFalse;
diPortfolio.grfPrevType = grfPrevType;
diPortfolio.cnoWave = cnoWave;
ofn.lCustData = (DWORD)&diPortfolio;
ofn.lpstrFilter = lpstrFilter;
ofn.lpstrTitle = lpstrTitle;
// Get the string for the initial directory if required.
if(pfniInitialDir != pvNil)
{
pfniInitialDir->GetStnPath(&stnInitialDir);
stnInitialDir.GetSz(szInitialDir);
ofn.lpstrInitialDir = szInitialDir;
}
else
{
// Initial directory will be current directory.
ofn.lpstrInitialDir = pvNil;
}
// Now display the portfolio.
fOKed = (GetOpenFileName(&ofn) == FALSE ? fFalse : fTrue);
if(!fOKed)
{
// Check if custom common dlg failed to initialize. Don't rely on the returned
// error being CDERR_INITIALIZATION, as who knows what error will be returned
// in future versions.
if(CommDlgExtendedError() != NOERROR)
{
// User never saw portfolio. Therefore attempt to display
// common dlg with no customization.
ofn.Flags &= ~(OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE);
fOKed = (GetOpenFileName(&ofn) == FALSE ? fFalse : fTrue);
}
}
// If the user selected a file, build up the associated fni.
if(fOKed)
{
stn.SetSz(ofn.lpstrFile);
pfni->FBuildFromPath(&stn, 0);
}
// Update the app window to make sure no parts of the portfolio
// window are left on the screen while the file is being opened.
// Calling UpdateMarked() does not have the desired effect here.
UpdateWindow(vwig.hwndApp);
// Report error to user if never displayed the portfolio.
if(CommDlgExtendedError() != NOERROR)
{
PushErc(ercSocPortfolioFailed);
}
// Only return TRUE if the user selected a file.
return(fOKed);
}
/***************************************************************************
pfGetFniSave: Display the save portfolio.
Arguments: pfni - Output FNI for file selected
lpstrFilter - String containing files types to filter on
lpstrTitle - String containing title of portfolio
lpstrDefExt - String containing default extension for filenames
typed by user without an extension.
pstnDefFileName - Ptr to default extension stn if required.
grfPrevType - Bits for types of preview required, (eg movie, sound etc) == 0 if no preview
cnoWave - Wave cno for audio when portfolio is invoked
Returns: TRUE - File selected
FALSE - User canceled portfolio, (or other error).
***************************************************************************/
bool FPortGetFniSave(FNI *pfni, LPTSTR lpstrFilter, LPTSTR lpstrTitle, LPTSTR lpstrDefExt,
PSTN pstnDefFileName, ulong grfPrevType, CNO cnoWave)
{
DLGINFO diPortfolio;
OPENFILENAME ofn;
bool fOKed;
bool tRet;
bool fRedisplayPortfolio = fFalse;
bool fExplorer = fTrue;
STN stnFile, stnErr;
FNI fniUserDir;
STN stnUserDir;
SZ szUserDir;
SZ szDefFileName;
SZ szFileTitle;
AssertPo(pfni, 0);
AssertNilOrPo(pstnDefFileName, 0);
ClearPb(&ofn, size(OPENFILENAME));
ClearPb(&diPortfolio, size(DLGINFO));
szFileTitle[0] = chNil;
ofn.lStructSize = size(OPENFILENAME);
ofn.hwndOwner = vwig.hwndApp;
ofn.hInstance = vwig.hinst;
ofn.nFilterIndex = 1L;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxFile = kcchMaxSz;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = kcchMaxSz;
ofn.lpfnHook = OpenHookProc;
ofn.lpTemplateName = MAKEINTRESOURCE(dlidPortfolio);
// Don't use OFN_OVERWRITEPROMPT here, otherwise we can't intercept
// the btn press on the Save btn to display our own message. Note,
// we don't do that either, because the help topic display mechanism
// was not designed for use within a modal dlg box such as the portfolio.
// Instead query overwrite after the portfolio has closed.
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE;
// Do not allow the save portfolio to change the current directory.
ofn.Flags |= OFN_NOCHANGEDIR;
// Let the initial dir be the user's dir.
vapp.GetFniUser(&fniUserDir);
fniUserDir.GetStnPath(&stnUserDir);
stnUserDir.GetSz(szUserDir);
ofn.lpstrInitialDir = szUserDir;
// Initialize internal data for accessing from inside dlg hook proc.
diPortfolio.fIsOpen = fFalse;
diPortfolio.fDrawnBkgnd = fFalse;
diPortfolio.grfPrevType = grfPrevType;
diPortfolio.cnoWave = cnoWave;
ofn.lCustData = (DWORD)&diPortfolio;
ofn.lpstrFilter = lpstrFilter;
ofn.lpstrTitle = lpstrTitle;
ofn.lpstrDefExt = lpstrDefExt;
// Set the the portfolio default save file name if required.
if(pstnDefFileName != pvNil)
{
pstnDefFileName->GetSz(szDefFileName);
}
else
{
szDefFileName[0] = chNil;
}
ofn.lpstrFile = szDefFileName;
// We may need to display the portfolio multiple times if the user
// selects an existing file, and then says they don't want to overwrite it.
do // Display portfolio
{
fRedisplayPortfolio = fFalse;
// Now display the portfolio.
fOKed = (GetSaveFileName(&ofn) == FALSE ? fFalse : fTrue);
if(!fOKed)
{
DWORD dwRet;
// Check if custom common dlg failed to initialize. Don't rely on the returned
// error being CDERR_INITIALIZATION, as who knows what error will be returned
// in future versions.
if((dwRet = CommDlgExtendedError()) != NOERROR)
{
if (dwRet == FNERR_INVALIDFILENAME ||
dwRet == FNERR_BUFFERTOOSMALL)
{
// Set the the portfolio default save file name if required.
if(pstnDefFileName != pvNil)
{
pstnDefFileName->GetSz(szDefFileName);
}
else
{
szDefFileName[0] = chNil;
}
ofn.lpstrFile = szDefFileName;
PushErc(ercSocInvalidFilename);
fRedisplayPortfolio = fTrue;
}
else if (dwRet == CDERR_INITIALIZATION && fExplorer)
{
// User never saw portfolio. Therefore attempt to display
// common dlg with no customization.
ofn.Flags &= ~(OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE);
fRedisplayPortfolio = fTrue;
fExplorer = fFalse;
}
else
PushErc(ercSocPortfolioFailed);
vapp.DisplayErrors();
continue;
}
}
else
{
// Build stn if user selected a file.
stnFile.SetSz(ofn.lpstrFile);
// Query any attempt to overwrite an existing file now.
if(CchSz(ofn.lpstrFile) != 0)
{
bool tExists;
// We always save the file with the default extension. If the
// user used a different extension, add the default on the end.
if(ofn.Flags & OFN_EXTENSIONDIFFERENT)
{
stnFile.FAppendCh('.');
stnFile.FAppendSz(lpstrDefExt);
}
// Make sure the pfni is built from the appended file name if applicable.
pfni->FBuildFromPath(&stnFile, 0);
if((tExists = pfni->TExists()) != tNo)
{
long cch;
achar *pch;
// File already exists. Query user for overwrite.
// The default name supplied to the user will only
// be the file name without the path.
stnFile.SetSz(ofn.lpstrFileTitle);
/* Remove the extension */
cch = stnFile.Cch();
pch = stnFile.Psz() + cch;
while (cch--)
{
pch--;
if (*pch == ChLit('.'))
{
stnFile.Delete(cch);
break;
}
}
stnFile.GetSz(ofn.lpstrFile);
// Only query if we know for sure the file's there. If
// it's not known for sure the file's there, just make the
// user pick a new name.
if (tExists == tYes)
{
AssertDo(vapp.FGetStnApp(idsReplaceFile, &stnErr), "String not present");
tRet = vapp.TModal(vapp.PcrmAll(), ktpcQueryOverwrite,
&stnErr, bkYesNo, kstidQueryOverwrite, &stnFile);
}
else
{
vapp.DisplayErrors();
tRet = tNo;
}
// Redisplay the portfolio if no overwrite.
if(tRet == tNo)
{
fRedisplayPortfolio = fTrue;
// Make sure the app window is updated, otherwise the help topic
// may still be displayed while the portfolio is redisplayed.
InvalidateRect(vwig.hwndApp, NULL, TRUE);
UpdateWindow(vwig.hwndApp);
}
}
}
else
{
// The user OKed the selection, and yet with have a zero length file name.
// Something must have gone wrong with the common dialog. Treat this as a
// cancel of the portfolio. (Remember we have not set up pfni in this case.)
Bug("Portfolio selection of a file with no name");
fOKed = fFalse;
}
}
}
while(fRedisplayPortfolio);
// If the user selected a file, build up the associated fni.
if(!fOKed)
{
pfni->SetNil();
}
// Update the app window to make sure no parts of the portfolio
// window are left on the screen while the file is being saved.
// Calling UpdateMarked() does not have the desired effect here.
UpdateWindow(vwig.hwndApp);
// Report error to user if never displayed the portfolio.
if(CommDlgExtendedError() != NOERROR)
{
PushErc(ercSocPortfolioFailed);
}
// Only return fTrue if the user selected a file.
return(fOKed);
}
/***************************************************************************
OpenHookProc: Hook proc for get open/save common dlg.
Arguments: standard dialog proc args.
Returns: TRUE - Common dlg will ignore message
FALSE - Common dlg will process this message after custom dlg.
Note - on win95, hwndCustom is the handle to the custom dlg created as a
child of the common dlg.
***************************************************************************/
UINT CALLBACK OpenHookProc(HWND hwndCustom, UINT msg, UINT wParam, LONG lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
PDLGINFO pdiPortfolio;
LONG lwStyle, lwExstyle;
OPENFILENAME *lpOfn;
HWND hwndDlg;
RC rc;
WNDPROC lpOtherBtnProc;
lpOfn = (OPENFILENAME *)lParam;
pdiPortfolio = (PDLGINFO)(lpOfn->lCustData);
SetWindowLong(hwndCustom, GWL_USERDATA, (LONG)pdiPortfolio);
hwndDlg = GetParent(hwndCustom);
// Give ourselves a way to access the custom dlg hwnd
// from the common dlg subclass wndproc.
SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)hwndCustom);
// Hide common dlg controls that we're not interested in here. Use the Common Dialog
// Message for hiding the control. The documentation on CDM_HIDECONTROL doesn't really
// describe what the command actually does, so explictly disable the OK/Cancel btns here.
SendMessage(hwndDlg, CDM_HIDECONTROL, stc2, 0L); // File type label
EnableWindow(GetDlgItem(hwndDlg, stc2), FALSE);
SendMessage(hwndDlg, CDM_HIDECONTROL, cmb1, 0L); // File type combo box
EnableWindow(GetDlgItem(hwndDlg, cmb1), FALSE);
SendMessage(hwndDlg, CDM_HIDECONTROL, chx1, 0L); // Open as Read-only check box
EnableWindow(GetDlgItem(hwndDlg, chx1), FALSE);
// Even though we are hiding the OK/Cancel buttons, do not disable them.
// By doing this, we retain some default common dialog behavior. When the
// user hits the Enter key the highlighted file will be selected, and when
// the user hits the Escape key the portfolio is dismissed.
SendMessage(hwndDlg, CDM_HIDECONTROL, IDOK, 0L); // OK btn.
SendMessage(hwndDlg, CDM_HIDECONTROL, IDCANCEL, 0L); // Cancel btn.
if(pdiPortfolio->fIsOpen)
{
SendMessage(hwndDlg, CDM_HIDECONTROL, stc3, 0L); // 'File Name'
EnableWindow(GetDlgItem(hwndDlg, stc3), FALSE);
SendMessage(hwndDlg, CDM_HIDECONTROL, edt1, 0L); // File name edit ctrl
EnableWindow(GetDlgItem(hwndDlg, edt1), FALSE);
}
// If no preview required then hide the preview window.
if(pdiPortfolio->grfPrevType == 0)
{
SendMessage(hwndCustom, CDM_HIDECONTROL, IDC_PREVIEW, 0L);
EnableWindow(GetDlgItem(hwndCustom, IDC_PREVIEW), FALSE);
}
// Give the main common dlg the required style for custom display.
// This means remove the caption bar, the system menu and the thick border.
// Note, We do not need a frame round the window, as we customize its
// background entirely. Therefore we should remove WS_CAPTION, (which is
// WS_BORDER | WS_DLGFRAME), and WS_EX_DLGMODALFRAME. However, if we do
// this, then when the user navigates around the list box in the dialog,
// the app window gets repainted. Presumably this is due to win95
// invalidating an area slightly larger than the dlg without any border.
// Therefore maintain the thin border.
lwStyle = GetWindowLong( hwndDlg, GWL_STYLE);
lwStyle &= ~(WS_DLGFRAME | WS_SYSMENU);
SetWindowLong( hwndDlg, GWL_STYLE, lwStyle);
lwExstyle = GetWindowLong( hwndDlg, GWL_EXSTYLE);
lwExstyle &= ~WS_EX_DLGMODALFRAME;
SetWindowLong( hwndDlg, GWL_EXSTYLE, lwExstyle);
// IMPORTANT NOTE. Cannot move or size the portfolio here. Otherwise this
// confuses win95 when it calculates whether all the controls fit in the
// common dlg or not. Instead we must wait for the INITDONE notification.
// Note, since the portfolio is full screen now, we don't need to move
// the window anyway..
// Subclass the push btns to prevent the background flashing in the default color.
lpBtnProc = (WNDPROC)SetWindowLong( GetDlgItem(hwndCustom, IDC_BUTTON1), GWL_WNDPROC, (LONG)SubClassBtnProc);
lpOtherBtnProc = (WNDPROC)SetWindowLong( GetDlgItem(hwndCustom, IDC_BUTTON2), GWL_WNDPROC, (LONG)SubClassBtnProc);
Assert(lpBtnProc == lpOtherBtnProc, "Custom portfolio buttons (ok/cancel) have different window procs");
lpOtherBtnProc = (WNDPROC)SetWindowLong( GetDlgItem(hwndCustom, IDC_BUTTON3), GWL_WNDPROC, (LONG)SubClassBtnProc);
Assert(lpBtnProc == lpOtherBtnProc, "Custom portfolio buttons (ok/home) have different window procs");
// Subclass the preview window to allow custom draw.
lpPreviewProc = (WNDPROC)SetWindowLong( GetDlgItem(hwndCustom, IDC_PREVIEW), GWL_WNDPROC, (LONG)SubClassPreviewProc);
// Subclass the main common dlg window to stop static control backgrounds being
// fill with the current system color. Instead use a color that matches our
// custom background bitmap.
lpDlgProc = (WNDPROC)SetWindowLong( hwndDlg, GWL_WNDPROC, (LONG)SubClassDlgProc);
// For the save portfolio we want the file name control to have focus when displayed.
if(!pdiPortfolio->fIsOpen)
{
SetFocus(GetDlgItem(hwndDlg, edt1));
// Select all the text in the file name edit control.
SendMessage(GetDlgItem(hwndDlg, edt1), EM_SETSEL, 0, -1);
return(1);
}
// Allow Windows to set the focus wherever it wants to.
return(0);
}
case WM_COMMAND:
{
// If the user has clicked on one of our custom buttons, then
// simulate a click on one of the hidden common dlg buttons.
if (HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case IDC_BUTTON1:
PostMessage(GetParent(hwndCustom), WM_COMMAND, IDOK, 0);
return(1);
case IDC_BUTTON2:
PostMessage(GetParent(hwndCustom), WM_COMMAND, IDCANCEL, 0);
return(1);
case IDC_BUTTON3:
{
FNI fniUserDir;
STN stnUserDir;
SZ szUserDir;
SZ szCurFile;
HWND hwndDlg = GetParent(hwndCustom);
// The user has pressed the Go To User's Home Folder btn. So get a SZ
// for the user's home folder.
vapp.GetFniUser(&fniUserDir);
fniUserDir.GetStnPath(&stnUserDir);
stnUserDir.GetSz(szUserDir);
// Ideally there would be some CDM_ message here to tell the common dialog
// that the current folder is to be changed. Unfortunately there is no such
// message. There is also no recommended way of doing this. Note that if we
// call SetCurrentDirectory here, then the common dialog is oblivious of the
// folder change.
// SO, we shall simulate a folder change by the user. Do this by filling
// the file name edit control with the target folder, and then sending an
// OK message to the common dlg.
// This would be enough to change the folder, but we would lose the current
// contents of the file name control. Therefore store the control contents
// before we overwrite it, and reset it afterwards. Ideally there would be
// some message to retrieve the contents of a control, (eg CDM_GETCONTROLTEXT),
// but there isn't, so use a regular Windows call for this.
// Get the current text for the control.
GetDlgItemText(hwndDlg, edt1, szCurFile, sizeof(szCurFile));
// Now change folder!
SendMessage(hwndDlg, CDM_SETCONTROLTEXT, edt1, (LPARAM)szUserDir);
SendMessage(hwndDlg, WM_COMMAND, IDOK, 0);
// Restore the edit control text.
SendMessage(hwndDlg, CDM_SETCONTROLTEXT, edt1, (LPARAM)szCurFile);
return(1);
}
default:
break;
}
}
break;
}
case WM_DRAWITEM:
{
int iDlgId = (int)wParam;
DRAWITEMSTRUCT *pDrawItem = (DRAWITEMSTRUCT*)lParam;
CNO cnoDisplay = cnoNil;
PMBMP pmbmp;
// Custom draw the our push btns here.
switch (iDlgId)
{
case IDC_BUTTON1:
if(pDrawItem->itemState & ODS_SELECTED)
{
cnoDisplay = kcnoMbmpPortBtnOkSel;
}
else
{
cnoDisplay = kcnoMbmpPortBtnOk;
}
break;
case IDC_BUTTON2:
if(pDrawItem->itemState & ODS_SELECTED)
{
cnoDisplay = kcnoMbmpPortBtnCancelSel;
}
else
{
cnoDisplay = kcnoMbmpPortBtnCancel;
}
break;
case IDC_BUTTON3:
if(pDrawItem->itemState & ODS_SELECTED)
{
cnoDisplay = kcnoMbmpPortBtnHomeSel;
}
else
{
cnoDisplay = kcnoMbmpPortBtnHome;
}
break;
default:
break;
}
if(cnoDisplay != cnoNil)
{
// Select the appropriate bitmap to display.
if((pmbmp = (PMBMP)vpapp->PcrmAll()->PbacoFetch(kctgMbmp, cnoDisplay, MBMP::FReadMbmp)))
{
PGPT pgpt;
HPEN hpen, hpenold;
HBRUSH hbr, hbrold;
HFONT hfnt, hfntold;
// To ensure that we don't return from here with different objects
// selected in the supplied hdc, save them here and restore later.
// (Note that Kauai will attempt to delete things it finds selected
// in the hdc passed to PgptNew).
hpen = (HPEN)GetStockObject(NULL_PEN);
Assert(hpen != hNil, "Portfolio - draw items GetStockObject(NULL_PEN) failed");
hpenold = (HPEN)SelectObject(pDrawItem->hDC, hpen);
hbr = (HBRUSH)GetStockObject(WHITE_BRUSH);
Assert(hbr != hNil, "Portfolio - draw items GetStockObject(WHITE_BRUSH) failed");
hbrold = (HBRUSH)SelectObject(pDrawItem->hDC, hbr);
hfnt = (HFONT)GetStockObject(SYSTEM_FONT);
Assert(hfnt != hNil, "Portfolio - draw items GetStockObject(SYSTEM_FONT) failed");
hfntold = (HFONT)SelectObject(pDrawItem->hDC, hfnt);
if ((pgpt = GPT::PgptNew(pDrawItem->hDC)) != pvNil)
{
GNV gnv(pgpt);
PGNV pgnvOff;
PGPT pgptOff;
RC rcItem(pDrawItem->rcItem);
// Must create offscreen dc and blit into that. Then blit that
// to dlg on screen. If we blit straight from mbmp to screen,
// then screen flashes. (Due to white fillrect).
if((pgptOff = GPT::PgptNewOffscreen(&rcItem, 8)) != pvNil)
{
if((pgnvOff = NewObj GNV(pgptOff)) != pvNil)
{
pgnvOff->DrawMbmp(pmbmp, rcItem.xpLeft, rcItem.ypTop);
gnv.CopyPixels(pgnvOff, &rcItem, &rcItem);
GPT::Flush();
ReleasePpo(&pgnvOff);
}
ReleasePpo(&pgptOff);
}
ReleasePpo(&pgpt);
}
// Restore the currently secleted objects back into he supplied hdc.
SelectObject(pDrawItem->hDC, hpenold);
SelectObject(pDrawItem->hDC, hbrold);
SelectObject(pDrawItem->hDC, hfntold);
ReleasePpo(&pmbmp);
}
return(1);
}
break;
}
case WM_NOTIFY:
{
LPOFNOTIFY lpofNotify = (LPOFNOTIFY)lParam;
switch (lpofNotify->hdr.code)
{
case CDN_INITDONE:
{
// Win95 has finished doing any resizing of the custom dlg and the controls.
// So take any special action now to ensure the portfolio still looks good.
PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA);
RCS rcsApp;
POINT ptBtn;
int ypBtn;
PMBMP pmbmpBtn;
RC rcBmp;
RCS rcsAppScreen, rcsPreview;
int xOff = 0;
int yOff = 0;
LONG lStyle;
PCRF pcrf;
HWND hwndDlg = GetParent(hwndCustom);
HWND hwndApp = GetParent(hwndDlg);
HWND hwndPreview = GetDlgItem(hwndCustom, IDC_PREVIEW);
// Store the current size of the portfolio. We need this later when we stretch
// the background bitmap to match how win95 may have stretched the dlg controls.
GetClientRect(hwndDlg, &(pdiPortfolio->rcsDlg));
// Get the client area size of the app window.
GetClientRect(hwndApp, &rcsApp);
// Now move the custom buttons to always be to the right of the preview window.
// Make sure we keep the buttons above the bottom of the screen.
GetClientRect(hwndPreview, &rcsPreview);
ptBtn.x = rcsPreview.right;
ptBtn.y = (rcsPreview.top + rcsPreview.bottom) / 2;
MapWindowPoints(hwndPreview, hwndCustom, (POINT*)&ptBtn, 1);
// First the home button.
if((pmbmpBtn = (PMBMP)vpapp->PcrmAll()->PbacoFetch(kctgMbmp, kcnoMbmpPortBtnHome, MBMP::FReadMbmp)))
{
pmbmpBtn->GetRc(&rcBmp);
ptBtn.x += (3 * rcBmp.Dxp()) / 4;
ypBtn = min(ptBtn.y - (rcBmp.Dyp() / 2), rcsApp.bottom - (2 * rcBmp.Dyp()));
SetWindowPos(GetDlgItem(hwndCustom, IDC_BUTTON3), 0, ptBtn.x, ypBtn, rcBmp.Dxp(), rcBmp.Dyp(), SWP_NOZORDER);
ReleasePpo(&pmbmpBtn);
}
// Now the cancel button.
if((pmbmpBtn = (PMBMP)vpapp->PcrmAll()->PbacoFetch(kctgMbmp, kcnoMbmpPortBtnCancel, MBMP::FReadMbmp)))
{
pmbmpBtn->GetRc(&rcBmp);
ptBtn.x += (5 * rcBmp.Dxp()) / 4;
ypBtn = min(ptBtn.y - (rcBmp.Dyp() / 2), rcsApp.bottom - (2 * rcBmp.Dyp()));
SetWindowPos(GetDlgItem(hwndCustom, IDC_BUTTON2), 0, ptBtn.x, ypBtn, rcBmp.Dxp(), rcBmp.Dyp(), SWP_NOZORDER);
ReleasePpo(&pmbmpBtn);
}
// Now the ok button.
if((pmbmpBtn = (PMBMP)vpapp->PcrmAll()->PbacoFetch(kctgMbmp, kcnoMbmpPortBtnOk, MBMP::FReadMbmp)))
{
pmbmpBtn->GetRc(&rcBmp);
ptBtn.x += (5 * rcBmp.Dxp()) / 4;
ypBtn = min(ptBtn.y - (rcBmp.Dyp() / 2), rcsApp.bottom - (2 * rcBmp.Dyp()));
SetWindowPos(GetDlgItem(hwndCustom, IDC_BUTTON1), 0, ptBtn.x, ypBtn, rcBmp.Dxp(), rcBmp.Dyp(), SWP_NOZORDER);
ReleasePpo(&pmbmpBtn);
}
// Note, win95 may have pushed the portfolio around depending on where the task bar is.
// Ensure that the top left corner of the portfolio is in the top left of the client
// area of the app window. Note that the common dlg is owned by the app window, but
// it is not a child window itself.
// Note, if we MapWindowPoints on (0,0) here, then the returned coords are shifted by
// the task bar which is just what we don't want. So GetWindowRect instead.
GetWindowRect(hwndApp, &rcsAppScreen);
// If running in a window, then we must find the offset from the top left of the app
// window's corner to its client area.
lStyle = GetWindowLong(hwndApp, GWL_STYLE);
if(lStyle & WS_CAPTION)
{
xOff = GetSystemMetrics(SM_CXDLGFRAME);
yOff = GetSystemMetrics(SM_CYDLGFRAME);
yOff += GetSystemMetrics(SM_CYCAPTION);
}
// Now move the common dialog itself. Resize the dialog too, to be the same size
// as the app window.
SetWindowPos(hwndDlg, 0, rcsAppScreen.left + xOff, rcsAppScreen.top + yOff, rcsApp.right, rcsApp.bottom, SWP_NOZORDER);
// Custom dialog is a child of the common dlg, so (0, 0) wil position it it the common
// dialog's client area.
SetWindowPos(hwndCustom, 0, 0, 0, rcsApp.right, rcsApp.bottom, SWP_NOZORDER);
// Now play the sound associated with this portfolio is there is one.
// Note that we are not currently queueing this sound or terminating
// any currently playing sound.
if(pdiPortfolio->cnoWave != cnoNil)
{
// There is a sound for the portfolio, so find it.
if((pcrf = ((APP *)vpappb)->PcrmAll()->PcrfFindChunk(kctgWave, pdiPortfolio->cnoWave)) != pvNil)
{
vpsndm->SiiPlay(pcrf, kctgWave, pdiPortfolio->cnoWave);
}
}
break;
}
case CDN_SELCHANGE:
{
HWND hwndPreview = GetDlgItem(hwndCustom, IDC_PREVIEW);
// User has changed the file selected, so update the preview window.
InvalidateRect(hwndPreview, NULL, FALSE);
UpdateWindow(hwndPreview);
break;
}
#ifdef QUERYINPORTFOLIO
// Do this if we ever have a way of querying the user with a help topic
// from inside the portfolio.
case CDN_FILEOK:
{
PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA);
// User has hit OK or Save. Is the user trying to save over an existing file?
if(pdiPortfolio->fIsOpen != fTrue)
{
// Neither CommDlg_OpenSave_GetFilePath nor CommDlg_OpenSave_GetSpec
// always return the string with the default extension already added
// if applicable. Therefore get the file name from the returned OFN
// structure, as this stores the complete file name.
if(CchSz(lpofNotify->lpOFN->lpstrFile) != 0)
{
FNI fni;
STN stnFile, stnErr;
bool fHelp, tRet;
long lSelect;
// Now does the specified file already exist?
stnFile.SetSz(lpofNotify->lpOFN->lpstrFile);
fni.FBuildFromPath(&stnFile, 0);
if(fni.TExists() != tNo)
{
if(vpappb->TGiveAlertSz(
"The selected file already exists.\n\nDo you want to overwrite it?",
bkYesNo, cokQuestion) != tYes)
{
// Move the focus back to the file name edit ctrl.
SetFocus(GetDlgItem(GetParent(hwndCustom), edt1));
// Let win95 know that the portfolio is to stay up.
SetWindowLong(hwndCustom, DWL_MSGRESULT, 1);
return(1);
}
}
}
}
break;
}
#endif //QUERYINPORTFOLIO
default:
{
break;
}
}
break;
}
case WM_ERASEBKGND:
// We never want the background painted in the system colors.
return(1);
case WM_PAINT:
{
PDLGINFO pdiPortfolio;
pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA);
// Repaint the entire portfolio.
RepaintPortfolio(hwndCustom);
// Now the background is drawn, disallow erasing of the background in the
// system color before each future repaint.
pdiPortfolio->fDrawnBkgnd = fTrue;
return(1);
}
default:
break;
}
return(0);
}
/***************************************************************************
RepaintPortfolio: Repaint the entire portfolio.
Arguments: hwndCustom - Handle to our custom dialog, ie child of the main common dlg.
Returns: nothing
***************************************************************************/
void RepaintPortfolio(HWND hwndCustom)
{
PAINTSTRUCT ps;
TEXTMETRIC tmCaption;
SZ szCaption;
PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA);
PMBMP pmbmp, pmbmpBtn;
int iBtn;
CNO cnoBack;
// Draw the custom background for the common dlg.
BeginPaint(hwndCustom, &ps);
// Display the open or save portfolio background bitmap as appropriate.
if(pdiPortfolio->fIsOpen)
{
cnoBack = kcnoMbmpPortBackOpen;
}
else
{
cnoBack = kcnoMbmpPortBackSave;
}
// Get the background bitmap first.
if((pmbmp = (PMBMP)vpapp->PcrmAll()->PbacoFetch(kctgMbmp, cnoBack, MBMP::FReadMbmp)))
{
PGPT pgpt;
HPEN hpen, hpenold;
HBRUSH hbr, hbrold;
HFONT hfnt, hfntold;
// To ensure that we don't return from here with different objects
// selected in the supplied hdc, save them here and restore later.
// (Note that Kauai will attempt to delete things it finds selected
// in the hdc passed to PgptNew).
hpen = (HPEN)GetStockObject(NULL_PEN);
Assert(hpen != hNil, "Portfolio - draw background GetStockObject(NULL_PEN) failed");
hpenold = (HPEN)SelectObject(ps.hdc, hpen);
hbr = (HBRUSH)GetStockObject(WHITE_BRUSH);
Assert(hbr != hNil, "Portfolio - draw background GetStockObject(WHITE_BRUSH) failed");
hbrold = (HBRUSH)SelectObject(ps.hdc, hbr);
hfnt = (HFONT)GetStockObject(SYSTEM_FONT);
Assert(hfnt != hNil, "Portfolio - draw background GetStockObject(SYSTEM_FONT) failed");
hfntold = (HFONT)SelectObject(ps.hdc, hfnt);
if ((pgpt = GPT::PgptNew(ps.hdc)) != pvNil)
{
RC rcDisplay;
RCS rcsPort, rcsPreview;
GNV gnv(pgpt);
PGNV pgnvOff;
PGPT pgptOff;
HWND hwndPreview;
CNO cnoBtn;
int iBtnId;
// Get the current size of the Portfolio window.
GetClientRect(hwndCustom, &rcsPort);
rcDisplay = rcsPort;
// Must create offscreen dc and blit into that. Then blit that to dlg on screen.
// If we blit straight from mbmp to screen, then screen flashes. (Due to white FILLRECT).
if((pgptOff = GPT::PgptNewOffscreen(&rcDisplay, 8)) != pvNil)
{
if((pgnvOff = NewObj GNV(pgptOff)) != pvNil)
{
RC rcOrgPort(pdiPortfolio->rcsDlg);
RC rcClip(ps.rcPaint);
// Win95 may initially have streched the portfolio due to font sizing.
// All the portfolio controls will also have been stretched. So we must
// now stretch the portfolio background bitmap into the size win95
// originally made it, to make the background fit the current size
// of the controls.
// Note, if the user has scaled down the font then the portfolio bitmap
// will not fill the entire portfolio area now. The area outside the portfolio
// will be black. While this is not ideal, it will be rare and everything will
// still work.
pgnvOff->DrawMbmp(pmbmp, &rcOrgPort);
// While we have this offscreen dc, paint all our custom display into it now.
// First the caption text. Position the text using its size.
GetWindowText(GetParent(hwndCustom), szCaption, sizeof(szCaption));
GetTextMetrics(ps.hdc, &tmCaption);
pgnvOff->DrawRgch(szCaption, CchSz(szCaption), (tmCaption.tmAveCharWidth * 2), tmCaption.tmHeight / 4, kacrBlack, kacrClear);
// If we were to blit the current offscreen dc to the screen, then the
// display of the preview window and custom buttons will be overwritten.
// Those windows would immediately be repainted to make the portfolio
// whole again. However, the windows would flash between blitting the
// background bitmap and repainting them. Therefore add the preview
// and custom buttons to the offscreen dc now, so that when the dc
// is blitted to the screen, these controls are good.
// Note, that the preview window alone is repainted when the user selection
// changes. Also the custom buttons are redrawn when we get the notification
// to redraw them in the dlg hook proc.
// Update the preview window now.
hwndPreview = GetDlgItem(hwndCustom, IDC_PREVIEW);
GetClientRect(hwndPreview, &rcsPreview);
MapWindowPoints(hwndPreview, hwndCustom, (POINT*)&rcsPreview, 2);
OpenPreview(hwndCustom, pgnvOff, &rcsPreview);
// Now the custom buttons.
for(iBtn = 0; iBtn < 3; ++iBtn)
{
switch (iBtn)
{
case 0:
cnoBtn = kcnoMbmpPortBtnOk;
iBtnId = IDC_BUTTON1;
break;
case 1:
cnoBtn = kcnoMbmpPortBtnCancel;
iBtnId = IDC_BUTTON2;
break;
case 2:
cnoBtn = kcnoMbmpPortBtnHome;
iBtnId = IDC_BUTTON3;
break;
default:
continue;
}
if((pmbmpBtn = (PMBMP)vpapp->PcrmAll()->PbacoFetch(kctgMbmp, cnoBtn, MBMP::FReadMbmp)))
{
HWND hwndBtn = GetDlgItem(hwndCustom, iBtnId);
RCS rcsBtn;
RC rcItem;
GetClientRect(hwndBtn, &rcsBtn);
MapWindowPoints(hwndBtn, hwndCustom, (POINT*)&rcsBtn, 2);
rcItem = rcsBtn;
pgnvOff->DrawMbmp(pmbmpBtn, rcItem.xpLeft, rcItem.ypTop);
ReleasePpo(&pmbmpBtn);
}
}
// Clip the final blit, to the area which actually needs repainting.
gnv.ClipRc(&rcClip);
// Now finally blit our portfolio image to the screen.
gnv.CopyPixels(pgnvOff, &rcDisplay, &rcDisplay);
GPT::Flush();
ReleasePpo(&pgnvOff);
}
ReleasePpo(&pgptOff);
}
ReleasePpo(&pgpt);
}
// Restore the currently secleted objects back into he supplied hdc.
SelectObject(ps.hdc, hpenold);
SelectObject(ps.hdc, hbrold);
SelectObject(ps.hdc, hfntold);
ReleasePpo(&pmbmp);
}
EndPaint(hwndCustom, &ps);
return;
}
/***************************************************************************
OpenPreview: Generate display for the preview of a movie.
Arguments: hwndCustom - Handle to custom dlg window
pgnvOff - Offscreen dc for displaying preview in.
prcsPreview - RCS for displaying preview.
Returns: nothing.
***************************************************************************/
void OpenPreview(HWND hwndCustom, PGNV pgnvOff, RCS *prcsPreview)
{
STN stn;
PCFL pcfl;
PMBMP pmbmp;
FNI fni;
SZ szFile;
ERS ersT;
ERS *pers;
PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA);
bool fPreviewed = fFalse;
RC rcPreview(*prcsPreview);
// If no preview is required, then do nothing here.
if(pdiPortfolio->grfPrevType == 0)
return;
// Do not allow default error reporting to take place. This is due
// to the fact that currently any queued errors do not appear
// until the portfolio has been dismissed.
pers = vpers;
vpers = &ersT;
// Clear the current contents of the preview window.
pgnvOff->FillRc(&rcPreview, kacrBlack);
// Get the currently selected file name.
CommDlg_OpenSave_GetSpec( GetParent(hwndCustom), szFile, sizeof(szFile));
// Note the above call returns the name of the last selected file, even if the
// user has since selected a folder! If the user hits the OK btn in this case,
// win95 opens the last selected file anyway, so we are consistent here.
if(CchSz(szFile) != 0)
{
// Get an fni for the selected file.
stn.SetSz(szFile);
fni.FBuildFromPath(&stn, 0);
// If the user specified a directory, then don't preview it.
if(!fni.FDir())
{
// The name specifies a file. How should we preview it?
if(pdiPortfolio->grfPrevType & fpfPortPrevMovie)
{
// Preview it as a movie if we can.
if ((pcfl = CFL::PcflOpen(&fni, fcflNil)) != pvNil)
{
CKI ckiMovie;
KID kidScene, kidThumb;
BLCK blck;
// Get the movie chunk from the open file.
if (pcfl->FGetCkiCtg(kctgMvie, 0, &ckiMovie))
{
// Now get the scene chunk and details.
if (pcfl->FGetKidChidCtg(kctgMvie, ckiMovie.cno, 0, kctgScen, &kidScene))
{
// Get the mbmp for the movie thumbnail.
if (pcfl->FGetKidChidCtg(kctgScen, kidScene.cki.cno, 0, kctgThumbMbmp, &kidThumb) &&
pcfl->FFind(kidThumb.cki.ctg, kidThumb.cki.cno, &blck))
{
if ((pmbmp = MBMP::PmbmpRead(&blck)) != pvNil)
{
// Stretch the preview into the preview window.
pgnvOff->DrawMbmp(pmbmp, &rcPreview);
ReleasePpo(&pmbmp);
fPreviewed = fTrue;
}
}
}
}
ReleasePpo(&pcfl);
}
}
if(!fPreviewed &&
(pdiPortfolio->grfPrevType & fpfPortPrevTexture))
{
// Preview the file as a .bmp file if we can.
if ((pmbmp = MBMP::PmbmpReadNative(&fni, 0, 0, 0, fmbmpNil)) != pvNil)
{
// Stretch the bitmap in the preview window.
pgnvOff->DrawMbmp(pmbmp, &rcPreview);
ReleasePpo(&pmbmp);
fPreviewed = fTrue;
}
}
// Currently portfolio is not required to preview sound files.
}
}
// Restore the default error reporting.
vpers = pers;
return;
}
/***************************************************************************
SubClassBtnProc: Subclass proc for custom btn ctrls..
Arguments: standard dialog proc args.
Returns: TRUE/FALSE
***************************************************************************/
LRESULT CALLBACK SubClassBtnProc(HWND hwndBtn, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_ERASEBKGND:
// We draw the button entirely later, so don't change the screen
// at all here, This prevents any flashing while dlg repainted.
return(1);
default:
break;
}
return(CallWindowProc (lpBtnProc, hwndBtn, msg, wParam, lParam));
}
/***************************************************************************
SubClassPreviewProc: Subclass proc for preview window.
Arguments: standard dialog proc args.
Returns: TRUE/FALSE
***************************************************************************/
LRESULT CALLBACK SubClassPreviewProc(HWND hwndPreview, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
RCS rcsPreview;
RC rcPreview;
PGNV pgnvOff;
PGPT pgpt, pgptOff;
HPEN hpen, hpenold;
HBRUSH hbr, hbrold;
HFONT hfnt, hfntold;
// Subclass this window so that when the user selects a file, we can only
// invalidate and repaint this window, rather than repainting the entire dlg.
BeginPaint(hwndPreview, &ps);
// To ensure that we don't return from here with different objects
// selected in the supplied hdc, save them here and restore later.
// (Note that Kauai will attempt to delete things it finds selected
// in the hdc passed to PgptNew).
hpen = (HPEN)GetStockObject(NULL_PEN);
Assert(hpen != hNil, "Portfolio - draw Preview GetStockObject(NULL_PEN) failed");
hpenold = (HPEN)SelectObject(ps.hdc, hpen);
hbr = (HBRUSH)GetStockObject(WHITE_BRUSH);
Assert(hbr != hNil, "Portfolio - draw Preview GetStockObject(WHITE_BRUSH) failed");
hbrold = (HBRUSH)SelectObject(ps.hdc, hbr);
hfnt = (HFONT)GetStockObject(SYSTEM_FONT);
Assert(hfnt != hNil, "Portfolio - draw Preview GetStockObject(SYSTEM_FONT) failed");
hfntold = (HFONT)SelectObject(ps.hdc, hfnt);
if ((pgpt = GPT::PgptNew(ps.hdc)) != pvNil)
{
GNV gnv(pgpt);
GetClientRect(hwndPreview, &rcsPreview);
rcPreview = rcsPreview;
if((pgptOff = GPT::PgptNewOffscreen(&rcPreview, 8)) != pvNil)
{
if((pgnvOff = NewObj GNV(pgptOff)) != pvNil)
{
// Get the preview image into our offscreen dc.
OpenPreview(GetParent(hwndPreview), pgnvOff, &rcsPreview);
// Now update the screen.
gnv.CopyPixels(pgnvOff, &rcPreview, &rcPreview);
GPT::Flush();
ReleasePpo(&pgnvOff);
}
ReleasePpo(&pgptOff);
}
ReleasePpo(&pgpt);
}
// Restore the currently secleted objects back into he supplied hdc.
SelectObject(ps.hdc, hpenold);
SelectObject(ps.hdc, hbrold);
SelectObject(ps.hdc, hfntold);
EndPaint(hwndPreview, &ps);
return(0);
}
default:
break;
}
return(CallWindowProc (lpPreviewProc, hwndPreview, msg, wParam, lParam));
}
/***************************************************************************
SubClassDlgProc: Subclass proc for common dlg window..
Arguments: standard dialog proc args.
Returns: TRUE/FALSE
***************************************************************************/
LRESULT CALLBACK SubClassDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_HELP:
{
// Do not invoke any help while the portfolio is displayed.
return TRUE;
}
case WM_CTLCOLORSTATIC:
{
HDC hdc = (HDC)wParam;
// Process this to ensure the common dlg static controls look as good
// as possible on our custom portfolio background. We could explictly
// do this only for the two static ctrl currently used,
// (ie stc3 = File Name, stc4 = Look In), but by taking this general
// approach, if any new static ctrls are added in future versions of
// win95, they will also look ok. (Except for the fact they won't be
// known to the current custom portfolio background). This assumes
// that we never want any common dlg static controls to be drawn using
// the default system colors, but that's ok due the extent of our
// portfolio customization.
// Do not overwrite the background when writing the static control text.
SetBkMode(hdc, TRANSPARENT);
// Note, on win95 that static text always appears black, regardless of
// the current system color settings. However, rather than relying on
// this always being true, set the text color explicitly here.
SetTextColor(hdc, RGB(0, 0, 0));
// Draw the control background in the light gray that matched the custom
// background bitmap. Otherwise the background is drawn in the current
// system color, which may not match the background at all.
return((LONG)GetStockObject(LTGRAY_BRUSH));
}
case WM_SYSCOMMAND:
{
// Is a screen saver trying to start?
if (wParam == SC_SCREENSAVE)
{
// Disable the screen saver if we don't allow them to run.
if (!vpapp->FAllowScreenSaver())
return fTrue;
}
break;
}
case WM_ERASEBKGND:
{
// Since the user never sees the common dialog background, ensure that
// it can never be erased in the system color. Force a repaint of the
// custom dlg now, to prevent the common dlg controls appearing before
// the portfolio background. Note that GetDlgItem(hwndDlg, <custom dlg id>)
// returns zero here, as the Menu part of the custom dlg is zero.
HWND hwndCustom = (HWND)GetWindowLong(hwndDlg, GWL_USERDATA);
if(hwndCustom != 0)
UpdateWindow(hwndCustom);
return(1);
}
default:
break;
}
return(CallWindowProc (lpDlgProc, hwndDlg, msg, wParam, lParam));
}