ppgpict.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFXCTL_PAGE_SEG
  12. #pragma code_seg(AFXCTL_PAGE_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CPicturePropPage implementation
  21. BEGIN_MESSAGE_MAP(CPicturePropPage, CStockPropPage)
  22. //{{AFX_MSG_MAP(CPicturePropPage)
  23. ON_CBN_SELCHANGE(AFX_IDC_PROPNAME, OnSelchangePictProp)
  24. ON_WM_PAINT()
  25. ON_BN_CLICKED(AFX_IDC_BROWSE, OnBrowse)
  26. ON_BN_CLICKED(AFX_IDC_CLEAR, OnClear)
  27. //}}AFX_MSG_MAP
  28. END_MESSAGE_MAP()
  29. CPicturePropPage::CPicturePropPage() :
  30. CStockPropPage(IDD, AFX_IDS_PICTURE_PPG_CAPTION),
  31. m_pPictDisp(NULL)
  32. {
  33. //{{AFX_DATA_INIT(CPicturePropPage)
  34. // NOTE: the ClassWizard will add member initialization here
  35. //}}AFX_DATA_INIT
  36. }
  37. CPicturePropPage::~CPicturePropPage()
  38. {
  39. // Release picture, if any
  40. if (m_pPictDisp != NULL)
  41. {
  42. m_pPictDisp->Release();
  43. m_pPictDisp = NULL;
  44. }
  45. }
  46. BOOL CPicturePropPage::OnInitDialog()
  47. {
  48. m_pPictDisp = NULL;
  49. SetModifiedFlag(FALSE);
  50. CStockPropPage::OnInitDialog();
  51. OnObjectsChanged();
  52. IgnoreApply(AFX_IDC_BROWSE);
  53. IgnoreApply(AFX_IDC_PROPNAME);
  54. OnSelchangePictProp();
  55. return TRUE;
  56. }
  57. void CPicturePropPage::DoDataExchange(CDataExchange* pDX)
  58. {
  59. //{{AFX_DATA_MAP(CPicturePropPage)
  60. DDX_Control(pDX, AFX_IDC_PROPNAME, m_PropName);
  61. DDX_Control(pDX, AFX_IDC_PICTURE, m_Static);
  62. //}}AFX_DATA_MAP
  63. if (pDX->m_bSaveAndValidate)
  64. {
  65. if (IsModified())
  66. if (!SetPictureProp(pDX, m_pPictDisp, m_strPropName))
  67. GetPictureProp(pDX, &m_pPictDisp, m_strPropName);
  68. }
  69. else
  70. {
  71. GetPictureProp(pDX, &m_pPictDisp, m_strPropName);
  72. SetModifiedFlag(FALSE);
  73. }
  74. }
  75. BOOL CPicturePropPage::SetPictureProp(CDataExchange*, LPPICTUREDISP pPictDisp, LPCTSTR pszPropName)
  76. {
  77. USES_CONVERSION;
  78. COleDispatchDriver PropDispDriver;
  79. // Set the properties for all the objects
  80. ULONG nObjects;
  81. LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
  82. BOOL bSuccess = TRUE;
  83. for (ULONG i = 0; bSuccess && (i < nObjects); i++)
  84. {
  85. DISPID dwDispID;
  86. // Get the Dispatch ID for the property and if successful set the value
  87. LPCOLESTR lpOleStr = T2COLE(pszPropName);
  88. if (SUCCEEDED(ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr,
  89. 1, m_lcid, &dwDispID)))
  90. {
  91. // Set property
  92. PropDispDriver.AttachDispatch(ppDisp[i], FALSE);
  93. TRY
  94. {
  95. PropDispDriver.SetProperty(dwDispID, VT_DISPATCH, pPictDisp);
  96. }
  97. CATCH(COleDispatchException, e)
  98. {
  99. // Display message box for dispatch exceptions.
  100. e->ReportError(MB_ICONEXCLAMATION | MB_OK);
  101. DELETE_EXCEPTION(e);
  102. bSuccess = FALSE;
  103. }
  104. AND_CATCH_ALL(e)
  105. {
  106. // Ignore other exceptions.
  107. DELETE_EXCEPTION(e);
  108. }
  109. END_CATCH_ALL
  110. PropDispDriver.DetachDispatch();
  111. }
  112. }
  113. return bSuccess;
  114. }
  115. BOOL CPicturePropPage::GetPictureProp(CDataExchange*, LPPICTUREDISP* ppPictDisp, LPCTSTR pszPropName)
  116. {
  117. USES_CONVERSION;
  118. // Release previous picture, if any.
  119. if (*ppPictDisp != NULL)
  120. {
  121. (*ppPictDisp)->Release();
  122. *ppPictDisp = NULL;
  123. }
  124. COleDispatchDriver PropDispDriver;
  125. ULONG nObjects;
  126. LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
  127. for (ULONG i = 0; i < nObjects; i++)
  128. {
  129. DISPID dwDispID;
  130. // Get the Dispatch ID for the property and if successful get the value
  131. LPCOLESTR lpOleStr = T2COLE(pszPropName);
  132. if (SUCCEEDED(ppDisp[i]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr,
  133. 1, m_lcid, &dwDispID)))
  134. {
  135. // Get property
  136. LPPICTUREDISP pPictDisp = NULL;
  137. PropDispDriver.AttachDispatch(ppDisp[i], FALSE);
  138. TRY
  139. PropDispDriver.GetProperty(dwDispID, VT_DISPATCH, &pPictDisp);
  140. END_TRY
  141. PropDispDriver.DetachDispatch();
  142. // If more than one object, all pictures must be the same.
  143. if ((i != 0) && (pPictDisp != *ppPictDisp))
  144. {
  145. if (*ppPictDisp != NULL)
  146. (*ppPictDisp)->Release();
  147. *ppPictDisp = NULL;
  148. }
  149. else
  150. {
  151. *ppPictDisp = pPictDisp;
  152. }
  153. // Don't keep multiple references to the picture.
  154. if ((i != 0) && (pPictDisp != NULL))
  155. pPictDisp->Release();
  156. }
  157. }
  158. InvalidateRect(NULL);
  159. return TRUE;
  160. }
  161. /////////////////////////////////////////////////////////////////////////////
  162. // CPicturePropPage message handlers
  163. void CPicturePropPage::OnPaint()
  164. {
  165. CPaintDC dc(this); // device context for painting
  166. // Determine rectangle for drawing picture
  167. CRect rc;
  168. m_Static.GetWindowRect(&rc);
  169. rc.InflateRect(-::GetSystemMetrics(SM_CXBORDER) * 2,
  170. -::GetSystemMetrics(SM_CYBORDER) * 2);
  171. ScreenToClient(&rc);
  172. LPPICTURE pPict = NULL;
  173. if ((m_pPictDisp != NULL) &&
  174. SUCCEEDED(m_pPictDisp->QueryInterface(IID_IPicture, (LPVOID*)&pPict)))
  175. {
  176. ASSERT(pPict != NULL);
  177. // Draw it
  178. OLE_XSIZE_HIMETRIC hmWidth;
  179. OLE_YSIZE_HIMETRIC hmHeight;
  180. pPict->get_Width(&hmWidth);
  181. pPict->get_Height(&hmHeight);
  182. int cxRect = rc.Width();
  183. int cyRect = rc.Height();
  184. if ((hmWidth != 0) && (hmHeight != 0) && (cxRect != 0) && (cyRect != 0))
  185. {
  186. // Adjust aspect ratio of rectangle to match picture.
  187. int nPictureRatio = hmWidth * 1000 / hmHeight;
  188. int nRectRatio = cxRect * 1000 / cyRect;
  189. if (nPictureRatio > nRectRatio)
  190. {
  191. int dy = (cyRect - (cxRect * 1000 / nPictureRatio) + 1) / 2;
  192. rc.InflateRect(0, -dy);
  193. }
  194. else
  195. {
  196. int dx = (cxRect - (cyRect * nPictureRatio / 1000) + 1) / 2;
  197. rc.InflateRect(-dx, 0);
  198. }
  199. }
  200. pPict->Render(dc.m_hDC, rc.left, rc.top, rc.Width(), rc.Height(),
  201. 0, hmHeight-1, hmWidth, -hmHeight, &rc);
  202. pPict->Release();
  203. }
  204. }
  205. HRESULT _AfxCreateStreamOnFile(LPCTSTR pszPath, LPSTREAM* ppstm,
  206. LONG* plSize)
  207. {
  208. ASSERT(pszPath != NULL);
  209. ASSERT(ppstm != NULL);
  210. *ppstm = NULL;
  211. if (plSize != NULL)
  212. *plSize = 0;
  213. CFileStatus fstatus;
  214. CFile file;
  215. HRESULT hr = E_FAIL;
  216. LONG cb;
  217. if (file.Open(pszPath, CFile::modeRead) &&
  218. file.GetStatus(pszPath, fstatus) &&
  219. ((cb = fstatus.m_size) != -1))
  220. {
  221. HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
  222. LPVOID pvData = NULL;
  223. if (hGlobal != NULL)
  224. {
  225. if ((pvData = GlobalLock(hGlobal)) != NULL)
  226. {
  227. BOOL bRead = (file.ReadHuge(pvData, cb) == (ULONG)cb);
  228. GlobalUnlock(hGlobal);
  229. if (bRead &&
  230. SUCCEEDED(hr = CreateStreamOnHGlobal(hGlobal, TRUE, ppstm)))
  231. {
  232. ASSERT(*ppstm != NULL);
  233. if (plSize != NULL)
  234. *plSize = fstatus.m_size;
  235. hr = S_OK;
  236. }
  237. }
  238. if (FAILED(hr))
  239. GlobalFree(hGlobal);
  240. }
  241. else
  242. {
  243. hr = E_OUTOFMEMORY;
  244. }
  245. }
  246. else
  247. {
  248. hr = E_ACCESSDENIED;
  249. }
  250. return hr;
  251. }
  252. void CPicturePropPage::OnBrowse()
  253. {
  254. CString strFilter;
  255. strFilter.LoadString(AFX_IDS_PICTUREFILTER);
  256. CString strTitle;
  257. strTitle.LoadString(AFX_IDS_PICTUREBROWSETITLE);
  258. CFileDialog fdlg(TRUE, NULL, NULL,
  259. OFN_FILEMUSTEXIST |
  260. OFN_HIDEREADONLY |
  261. OFN_PATHMUSTEXIST,
  262. strFilter);
  263. fdlg.m_ofn.lpstrTitle = strTitle;
  264. int nResult = fdlg.DoModal();
  265. SetFocus();
  266. if (nResult != IDOK)
  267. return;
  268. CString strPath = fdlg.GetPathName();
  269. LPSTREAM pstm = NULL;
  270. LONG lSize;
  271. HRESULT hr;
  272. if (FAILED(hr = _AfxCreateStreamOnFile(strPath, &pstm, &lSize)))
  273. {
  274. UINT idsText;
  275. CString strText;
  276. CString strCaption;
  277. switch (GetScode(hr))
  278. {
  279. case E_OUTOFMEMORY:
  280. idsText = AFX_IDP_PICTURETOOLARGE;
  281. break;
  282. case E_ACCESSDENIED:
  283. idsText = AFX_IDP_PICTURECANTOPEN;
  284. break;
  285. default:
  286. idsText = AFX_IDP_PICTUREREADFAILED;
  287. break;
  288. }
  289. AfxFormatString1(strText, idsText, strPath);
  290. strCaption.LoadString(AFX_IDS_PICTURE_PPG_CAPTION);
  291. MessageBox(strText, strCaption, MB_OK | MB_ICONEXCLAMATION);
  292. SetFocus();
  293. return;
  294. }
  295. ASSERT(pstm != NULL);
  296. LPPICTURE pPict;
  297. if (SUCCEEDED(::OleLoadPicture(pstm, lSize, FALSE, IID_IPicture, (LPVOID *)&pPict)))
  298. {
  299. ChangePicture(pPict);
  300. }
  301. else
  302. {
  303. CString strText;
  304. CString strCaption;
  305. AfxFormatString1(strText, AFX_IDP_PICTURECANTLOAD, strPath);
  306. strCaption.LoadString(AFX_IDS_PICTURE_PPG_CAPTION);
  307. MessageBox(strText, strCaption, MB_OK | MB_ICONEXCLAMATION);
  308. SetFocus();
  309. }
  310. pstm->Release();
  311. }
  312. AFX_STATIC_DATA PICTDESC _afxPictDescEmpty = { sizeof(PICTDESC), PICTYPE_NONE, };
  313. void CPicturePropPage::OnClear()
  314. {
  315. LPPICTURE pPict;
  316. if (SUCCEEDED(::OleCreatePictureIndirect(&_afxPictDescEmpty, IID_IPicture, TRUE,
  317. (LPVOID *)&pPict)))
  318. {
  319. ChangePicture(pPict);
  320. }
  321. else
  322. {
  323. ASSERT(FALSE); // This should never happen!
  324. }
  325. }
  326. void CPicturePropPage::ChangePicture(LPPICTURE pPict)
  327. {
  328. ASSERT(pPict != NULL);
  329. LPPICTUREDISP pPictDisp = NULL;
  330. if (SUCCEEDED(pPict->QueryInterface(IID_IPictureDisp,
  331. (LPVOID*)&pPictDisp)))
  332. {
  333. ASSERT(pPictDisp != NULL);
  334. if (m_pPictDisp != NULL)
  335. m_pPictDisp->Release();
  336. m_pPictDisp = pPictDisp;
  337. SetModifiedFlag();
  338. LPPROPERTYPAGESITE pPageSite = GetPageSite();
  339. if (pPageSite != NULL)
  340. pPageSite->OnStatusChange(
  341. PROPPAGESTATUS_VALIDATE | PROPPAGESTATUS_DIRTY);
  342. InvalidateRect(NULL);
  343. }
  344. pPict->Release();
  345. }
  346. void CPicturePropPage::OnSelchangePictProp()
  347. {
  348. OnSelchangePropname(m_PropName);
  349. // disable Browse button if no property selected
  350. CComboBox* pPropName = (CComboBox*)GetDlgItem(AFX_IDC_PROPNAME);
  351. CWnd* pBrowse = GetDlgItem(AFX_IDC_BROWSE);
  352. pBrowse->EnableWindow(pPropName->GetCurSel() != CB_ERR);
  353. // redraw bitmap for new picture property
  354. CRect rect;
  355. m_Static.GetWindowRect(rect);
  356. rect.InflateRect(-::GetSystemMetrics(SM_CXBORDER),
  357. -::GetSystemMetrics(SM_CYBORDER));
  358. ScreenToClient(rect);
  359. InvalidateRect(rect);
  360. }
  361. BOOL CPicturePropPage::OnEditProperty(DISPID dispid)
  362. {
  363. return CStockPropPage::OnEditProperty(dispid, m_PropName);
  364. }
  365. void CPicturePropPage::OnObjectsChanged()
  366. {
  367. ULONG nObjects;
  368. if (GetObjectArray(&nObjects) != NULL && m_hWnd != NULL)
  369. FillPropnameList(IID_IPictureDisp, 1, m_PropName);
  370. if (m_hWnd != NULL)
  371. OnSelchangePictProp();
  372. }
  373. /////////////////////////////////////////////////////////////////////////////
  374. // Class factory for Picture property page
  375. #ifdef _AFXDLL
  376. #ifdef AFXCTL_FACT_SEG
  377. #pragma code_seg(AFXCTL_FACT_SEG)
  378. #endif
  379. IMPLEMENT_OLECREATE_EX(CPicturePropPage, "OCxx.CPicturePropPage",
  380. 0x0be35202,0x8f91,0x11ce,0x9d,0xe3,0x00,0xaa,0x00,0x4b,0xb8,0x51)
  381. BOOL CPicturePropPage::CPicturePropPageFactory::UpdateRegistry(BOOL bRegister)
  382. {
  383. if (bRegister)
  384. return AfxOleRegisterPropertyPageClass(AfxGetInstanceHandle(),
  385. m_clsid, AFX_IDS_PICTURE_PPG);
  386. else
  387. return AfxOleUnregisterClass(m_clsid, NULL);
  388. }
  389. #endif //_AFXDLL
  390. /////////////////////////////////////////////////////////////////////////////
  391. // Force any extra compiler-generated code into AFX_INIT_SEG
  392. #ifdef AFX_INIT_SEG
  393. #pragma code_seg(AFX_INIT_SEG)
  394. #endif
  395. IMPLEMENT_DYNCREATE(CPicturePropPage, CStockPropPage)