mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
492 lines
11 KiB
492 lines
11 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef AFXCTL_PAGE_SEG
|
|
#pragma code_seg(AFXCTL_PAGE_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPicturePropPage implementation
|
|
|
|
BEGIN_MESSAGE_MAP(CPicturePropPage, CStockPropPage)
|
|
//{{AFX_MSG_MAP(CPicturePropPage)
|
|
ON_CBN_SELCHANGE(AFX_IDC_PROPNAME, OnSelchangePictProp)
|
|
ON_WM_PAINT()
|
|
ON_BN_CLICKED(AFX_IDC_BROWSE, OnBrowse)
|
|
ON_BN_CLICKED(AFX_IDC_CLEAR, OnClear)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
CPicturePropPage::CPicturePropPage() :
|
|
CStockPropPage(IDD, AFX_IDS_PICTURE_PPG_CAPTION),
|
|
m_pPictDisp(NULL)
|
|
{
|
|
//{{AFX_DATA_INIT(CPicturePropPage)
|
|
// NOTE: the ClassWizard will add member initialization here
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
CPicturePropPage::~CPicturePropPage()
|
|
{
|
|
// Release picture, if any
|
|
|
|
if (m_pPictDisp != NULL)
|
|
{
|
|
m_pPictDisp->Release();
|
|
m_pPictDisp = NULL;
|
|
}
|
|
}
|
|
|
|
BOOL CPicturePropPage::OnInitDialog()
|
|
{
|
|
m_pPictDisp = NULL;
|
|
SetModifiedFlag(FALSE);
|
|
CStockPropPage::OnInitDialog();
|
|
OnObjectsChanged();
|
|
IgnoreApply(AFX_IDC_BROWSE);
|
|
IgnoreApply(AFX_IDC_PROPNAME);
|
|
OnSelchangePictProp();
|
|
return TRUE;
|
|
}
|
|
|
|
void CPicturePropPage::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
//{{AFX_DATA_MAP(CPicturePropPage)
|
|
DDX_Control(pDX, AFX_IDC_PROPNAME, m_PropName);
|
|
DDX_Control(pDX, AFX_IDC_PICTURE, m_Static);
|
|
//}}AFX_DATA_MAP
|
|
|
|
if (pDX->m_bSaveAndValidate)
|
|
{
|
|
if (IsModified())
|
|
if (!SetPictureProp(pDX, m_pPictDisp, m_strPropName))
|
|
GetPictureProp(pDX, &m_pPictDisp, m_strPropName);
|
|
}
|
|
else
|
|
{
|
|
GetPictureProp(pDX, &m_pPictDisp, m_strPropName);
|
|
SetModifiedFlag(FALSE);
|
|
}
|
|
}
|
|
|
|
BOOL CPicturePropPage::SetPictureProp(CDataExchange*, LPPICTUREDISP pPictDisp, LPCTSTR pszPropName)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
COleDispatchDriver PropDispDriver;
|
|
|
|
// Set the properties for all the objects
|
|
|
|
ULONG nObjects;
|
|
LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
|
|
BOOL bSuccess = TRUE;
|
|
|
|
for (ULONG i = 0; bSuccess && (i < nObjects); i++)
|
|
{
|
|
DISPID dwDispID;
|
|
|
|
// Get the Dispatch ID for the property and if successful set the value
|
|
LPCOLESTR lpOleStr = T2COLE(pszPropName);
|
|
if (SUCCEEDED(ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr,
|
|
1, m_lcid, &dwDispID)))
|
|
{
|
|
// Set property
|
|
PropDispDriver.AttachDispatch(ppDisp[i], FALSE);
|
|
TRY
|
|
{
|
|
PropDispDriver.SetProperty(dwDispID, VT_DISPATCH, pPictDisp);
|
|
}
|
|
CATCH(COleDispatchException, e)
|
|
{
|
|
// Display message box for dispatch exceptions.
|
|
e->ReportError(MB_ICONEXCLAMATION | MB_OK);
|
|
DELETE_EXCEPTION(e);
|
|
|
|
bSuccess = FALSE;
|
|
}
|
|
AND_CATCH_ALL(e)
|
|
{
|
|
// Ignore other exceptions.
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
PropDispDriver.DetachDispatch();
|
|
}
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL CPicturePropPage::GetPictureProp(CDataExchange*, LPPICTUREDISP* ppPictDisp, LPCTSTR pszPropName)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
// Release previous picture, if any.
|
|
if (*ppPictDisp != NULL)
|
|
{
|
|
(*ppPictDisp)->Release();
|
|
*ppPictDisp = NULL;
|
|
}
|
|
|
|
COleDispatchDriver PropDispDriver;
|
|
|
|
ULONG nObjects;
|
|
LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
|
|
|
|
for (ULONG i = 0; i < nObjects; i++)
|
|
{
|
|
DISPID dwDispID;
|
|
|
|
// Get the Dispatch ID for the property and if successful get the value
|
|
LPCOLESTR lpOleStr = T2COLE(pszPropName);
|
|
if (SUCCEEDED(ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr,
|
|
1, m_lcid, &dwDispID)))
|
|
{
|
|
// Get property
|
|
LPPICTUREDISP pPictDisp = NULL;
|
|
|
|
PropDispDriver.AttachDispatch(ppDisp[i], FALSE);
|
|
TRY
|
|
PropDispDriver.GetProperty(dwDispID, VT_DISPATCH, &pPictDisp);
|
|
END_TRY
|
|
PropDispDriver.DetachDispatch();
|
|
|
|
// If more than one object, all pictures must be the same.
|
|
|
|
if ((i != 0) && (pPictDisp != *ppPictDisp))
|
|
{
|
|
if (*ppPictDisp != NULL)
|
|
(*ppPictDisp)->Release();
|
|
|
|
*ppPictDisp = NULL;
|
|
}
|
|
else
|
|
{
|
|
*ppPictDisp = pPictDisp;
|
|
}
|
|
|
|
// Don't keep multiple references to the picture.
|
|
|
|
if ((i != 0) && (pPictDisp != NULL))
|
|
pPictDisp->Release();
|
|
}
|
|
}
|
|
|
|
InvalidateRect(NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPicturePropPage message handlers
|
|
|
|
void CPicturePropPage::OnPaint()
|
|
{
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
// Determine rectangle for drawing picture
|
|
|
|
CRect rc;
|
|
m_Static.GetWindowRect(&rc);
|
|
rc.InflateRect(-::GetSystemMetrics(SM_CXBORDER) * 2,
|
|
-::GetSystemMetrics(SM_CYBORDER) * 2);
|
|
ScreenToClient(&rc);
|
|
|
|
LPPICTURE pPict = NULL;
|
|
|
|
if ((m_pPictDisp != NULL) &&
|
|
SUCCEEDED(m_pPictDisp->QueryInterface(IID_IPicture, (LPVOID*)&pPict)))
|
|
{
|
|
ASSERT(pPict != NULL);
|
|
|
|
// Draw it
|
|
|
|
OLE_XSIZE_HIMETRIC hmWidth;
|
|
OLE_YSIZE_HIMETRIC hmHeight;
|
|
|
|
pPict->get_Width(&hmWidth);
|
|
pPict->get_Height(&hmHeight);
|
|
|
|
int cxRect = rc.Width();
|
|
int cyRect = rc.Height();
|
|
if ((hmWidth != 0) && (hmHeight != 0) && (cxRect != 0) && (cyRect != 0))
|
|
{
|
|
// Adjust aspect ratio of rectangle to match picture.
|
|
|
|
int nPictureRatio = hmWidth * 1000 / hmHeight;
|
|
int nRectRatio = cxRect * 1000 / cyRect;
|
|
|
|
if (nPictureRatio > nRectRatio)
|
|
{
|
|
int dy = (cyRect - (cxRect * 1000 / nPictureRatio) + 1) / 2;
|
|
rc.InflateRect(0, -dy);
|
|
}
|
|
else
|
|
{
|
|
int dx = (cxRect - (cyRect * nPictureRatio / 1000) + 1) / 2;
|
|
rc.InflateRect(-dx, 0);
|
|
}
|
|
}
|
|
|
|
pPict->Render(dc.m_hDC, rc.left, rc.top, rc.Width(), rc.Height(),
|
|
0, hmHeight-1, hmWidth, -hmHeight, &rc);
|
|
|
|
pPict->Release();
|
|
}
|
|
}
|
|
|
|
HRESULT _AfxCreateStreamOnFile(LPCTSTR pszPath, LPSTREAM* ppstm,
|
|
LONG* plSize)
|
|
{
|
|
ASSERT(pszPath != NULL);
|
|
ASSERT(ppstm != NULL);
|
|
|
|
*ppstm = NULL;
|
|
|
|
if (plSize != NULL)
|
|
*plSize = 0;
|
|
|
|
CFileStatus fstatus;
|
|
CFile file;
|
|
HRESULT hr = E_FAIL;
|
|
LONG cb;
|
|
|
|
if (file.Open(pszPath, CFile::modeRead) &&
|
|
file.GetStatus(pszPath, fstatus) &&
|
|
((cb = fstatus.m_size) != -1))
|
|
{
|
|
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
|
|
LPVOID pvData = NULL;
|
|
|
|
if (hGlobal != NULL)
|
|
{
|
|
if ((pvData = GlobalLock(hGlobal)) != NULL)
|
|
{
|
|
BOOL bRead = (file.ReadHuge(pvData, cb) == (ULONG)cb);
|
|
GlobalUnlock(hGlobal);
|
|
|
|
if (bRead &&
|
|
SUCCEEDED(hr = CreateStreamOnHGlobal(hGlobal, TRUE, ppstm)))
|
|
{
|
|
ASSERT(*ppstm != NULL);
|
|
if (plSize != NULL)
|
|
*plSize = fstatus.m_size;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
GlobalFree(hGlobal);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_ACCESSDENIED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CPicturePropPage::OnBrowse()
|
|
{
|
|
CString strFilter;
|
|
strFilter.LoadString(AFX_IDS_PICTUREFILTER);
|
|
|
|
CString strTitle;
|
|
strTitle.LoadString(AFX_IDS_PICTUREBROWSETITLE);
|
|
|
|
CFileDialog fdlg(TRUE, NULL, NULL,
|
|
OFN_FILEMUSTEXIST |
|
|
OFN_HIDEREADONLY |
|
|
OFN_PATHMUSTEXIST,
|
|
strFilter);
|
|
|
|
fdlg.m_ofn.lpstrTitle = strTitle;
|
|
|
|
int nResult = fdlg.DoModal();
|
|
SetFocus();
|
|
|
|
if (nResult != IDOK)
|
|
return;
|
|
|
|
CString strPath = fdlg.GetPathName();
|
|
|
|
LPSTREAM pstm = NULL;
|
|
LONG lSize;
|
|
HRESULT hr;
|
|
|
|
if (FAILED(hr = _AfxCreateStreamOnFile(strPath, &pstm, &lSize)))
|
|
{
|
|
UINT idsText;
|
|
CString strText;
|
|
CString strCaption;
|
|
|
|
switch (GetScode(hr))
|
|
{
|
|
case E_OUTOFMEMORY:
|
|
idsText = AFX_IDP_PICTURETOOLARGE;
|
|
break;
|
|
|
|
case E_ACCESSDENIED:
|
|
idsText = AFX_IDP_PICTURECANTOPEN;
|
|
break;
|
|
|
|
default:
|
|
idsText = AFX_IDP_PICTUREREADFAILED;
|
|
break;
|
|
}
|
|
|
|
AfxFormatString1(strText, idsText, strPath);
|
|
strCaption.LoadString(AFX_IDS_PICTURE_PPG_CAPTION);
|
|
MessageBox(strText, strCaption, MB_OK | MB_ICONEXCLAMATION);
|
|
SetFocus();
|
|
return;
|
|
}
|
|
|
|
ASSERT(pstm != NULL);
|
|
|
|
LPPICTURE pPict;
|
|
if (SUCCEEDED(OleLoadPicture(pstm, lSize, FALSE, IID_IPicture, (LPVOID *)&pPict)))
|
|
{
|
|
ChangePicture(pPict);
|
|
}
|
|
else
|
|
{
|
|
CString strText;
|
|
CString strCaption;
|
|
AfxFormatString1(strText, AFX_IDP_PICTURECANTLOAD, strPath);
|
|
strCaption.LoadString(AFX_IDS_PICTURE_PPG_CAPTION);
|
|
MessageBox(strText, strCaption, MB_OK | MB_ICONEXCLAMATION);
|
|
SetFocus();
|
|
}
|
|
|
|
pstm->Release();
|
|
}
|
|
|
|
static PICTDESC _pictDescEmpty =
|
|
{
|
|
sizeof(PICTDESC),
|
|
PICTYPE_NONE,
|
|
};
|
|
|
|
void CPicturePropPage::OnClear()
|
|
{
|
|
LPPICTURE pPict;
|
|
if (SUCCEEDED(OleCreatePictureIndirect(&_pictDescEmpty, IID_IPicture, TRUE,
|
|
(LPVOID *)&pPict)))
|
|
{
|
|
ChangePicture(pPict);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(FALSE); // This should never happen!
|
|
}
|
|
}
|
|
|
|
void CPicturePropPage::ChangePicture(LPPICTURE pPict)
|
|
{
|
|
ASSERT(pPict != NULL);
|
|
|
|
LPPICTUREDISP pPictDisp = NULL;
|
|
if (SUCCEEDED(pPict->QueryInterface(IID_IPictureDisp,
|
|
(LPVOID*)&pPictDisp)))
|
|
{
|
|
ASSERT(pPictDisp != NULL);
|
|
|
|
if (m_pPictDisp != NULL)
|
|
m_pPictDisp->Release();
|
|
|
|
m_pPictDisp = pPictDisp;
|
|
SetModifiedFlag();
|
|
|
|
LPPROPERTYPAGESITE pPageSite = GetPageSite();
|
|
if (pPageSite != NULL)
|
|
pPageSite->OnStatusChange(
|
|
PROPPAGESTATUS_VALIDATE | PROPPAGESTATUS_DIRTY);
|
|
|
|
InvalidateRect(NULL);
|
|
}
|
|
|
|
pPict->Release();
|
|
}
|
|
|
|
void CPicturePropPage::OnSelchangePictProp()
|
|
{
|
|
OnSelchangePropname(m_PropName);
|
|
|
|
// disable Browse button if no property selected
|
|
CComboBox* pPropName = (CComboBox*)GetDlgItem(AFX_IDC_PROPNAME);
|
|
CWnd* pBrowse = GetDlgItem(AFX_IDC_BROWSE);
|
|
pBrowse->EnableWindow(pPropName->GetCurSel() != CB_ERR);
|
|
|
|
// redraw bitmap for new picture property
|
|
CRect rect;
|
|
|
|
m_Static.GetWindowRect(rect);
|
|
rect.InflateRect(-::GetSystemMetrics(SM_CXBORDER),
|
|
-::GetSystemMetrics(SM_CYBORDER));
|
|
ScreenToClient(rect);
|
|
|
|
InvalidateRect(rect);
|
|
}
|
|
|
|
BOOL CPicturePropPage::OnEditProperty(DISPID dispid)
|
|
{
|
|
return CStockPropPage::OnEditProperty(dispid, m_PropName);
|
|
}
|
|
|
|
void CPicturePropPage::OnObjectsChanged()
|
|
{
|
|
ULONG nObjects;
|
|
if (GetObjectArray(&nObjects) != NULL && m_hWnd != NULL)
|
|
FillPropnameList(IID_IPictureDisp, 1, m_PropName);
|
|
|
|
if (m_hWnd != NULL)
|
|
OnSelchangePictProp();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Class factory for Picture property page
|
|
|
|
#ifdef AFXCTL_FACT_SEG
|
|
#pragma code_seg(AFXCTL_FACT_SEG)
|
|
#endif
|
|
|
|
IMPLEMENT_OLECREATE_EX(CPicturePropPage, "OCxx.CPicturePropPage",
|
|
0x0be35202,0x8f91,0x11ce,0x9d,0xe3,0x00,0xaa,0x00,0x4b,0xb8,0x51)
|
|
|
|
BOOL CPicturePropPage::CPicturePropPageFactory::UpdateRegistry(BOOL bRegister)
|
|
{
|
|
if (bRegister)
|
|
return AfxOleRegisterPropertyPageClass(AfxGetInstanceHandle(),
|
|
m_clsid, AFX_IDS_PICTURE_PPG);
|
|
else
|
|
return AfxOleUnregisterClass(m_clsid, NULL);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Force any extra compiler-generated code into AFX_INIT_SEG
|
|
|
|
#ifdef AFX_INIT_SEG
|
|
#pragma code_seg(AFX_INIT_SEG)
|
|
#endif
|
|
|
|
IMPLEMENT_DYNCREATE(CPicturePropPage, CStockPropPage)
|