ctlprop.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563
  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_PROP_SEG
  12. #pragma code_seg(AFXCTL_PROP_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #ifndef _DEBUG
  19. #pragma intrinsic(memset)
  20. #endif
  21. #define new DEBUG_NEW
  22. /////////////////////////////////////////////////////////////////////////////
  23. // Stock property mask
  24. #define STOCKPROP_BACKCOLOR 0x00000001
  25. #define STOCKPROP_CAPTION 0x00000002
  26. #define STOCKPROP_FONT 0x00000004
  27. #define STOCKPROP_FORECOLOR 0x00000008
  28. #define STOCKPROP_TEXT 0x00000010
  29. #define STOCKPROP_BORDERSTYLE 0x00000020
  30. #define STOCKPROP_ENABLED 0x00000040
  31. #define STOCKPROP_APPEARANCE 0x00000080
  32. AFX_STATIC_DATA const DWORD _afxStockProps[] =
  33. {
  34. STOCKPROP_BACKCOLOR, // -501
  35. 0, // -502
  36. 0, // -503
  37. STOCKPROP_BORDERSTYLE, // -504
  38. 0, // -505
  39. 0, // -506
  40. 0, // -507
  41. 0, // -508
  42. 0, // -509
  43. 0, // -510
  44. 0, // -511
  45. STOCKPROP_FONT, // -512
  46. STOCKPROP_FORECOLOR, // -513
  47. STOCKPROP_ENABLED, // -514
  48. 0, // -515
  49. 0, // -516
  50. STOCKPROP_TEXT, // -517
  51. STOCKPROP_CAPTION, // -518
  52. 0, // -519
  53. STOCKPROP_APPEARANCE, // -520
  54. };
  55. void COleControl::InitStockPropMask()
  56. {
  57. const AFX_DISPMAP* pDispMap = GetDispatchMap();
  58. const AFX_DISPMAP_ENTRY* pEntry;
  59. ASSERT(pDispMap != NULL);
  60. // If stock property mask is already initialized, we're outta here.
  61. if (*pDispMap->lpStockPropMask != (DWORD)-1)
  62. return;
  63. AfxLockGlobals(CRIT_STOCKMASK);
  64. if (*pDispMap->lpStockPropMask == (DWORD)-1)
  65. {
  66. const AFX_DISPMAP* pDispMapTop = pDispMap;
  67. DWORD dwStockPropMask = 0;
  68. while (pDispMap != NULL)
  69. {
  70. pEntry = pDispMap->lpEntries;
  71. while (pEntry->nPropOffset != -1)
  72. {
  73. int nIndex = DISPID_BACKCOLOR - pEntry->lDispID;
  74. DWORD dwFlag;
  75. if (nIndex >= 0 && nIndex < _countof(_afxStockProps) &&
  76. (dwFlag = _afxStockProps[nIndex]) != 0)
  77. {
  78. dwStockPropMask |= dwFlag;
  79. }
  80. ++pEntry;
  81. }
  82. // check base class
  83. #ifdef _AFXDLL
  84. pDispMap = (*pDispMap->pfnGetBaseMap)();
  85. #else
  86. pDispMap = pDispMap->pBaseMap;
  87. #endif
  88. }
  89. *pDispMapTop->lpStockPropMask = dwStockPropMask;
  90. }
  91. AfxUnlockGlobals(CRIT_STOCKMASK);
  92. }
  93. AFX_STATIC void AFXAPI _AfxToggleBorderStyle(CWnd* pWnd)
  94. {
  95. if (pWnd->m_hWnd != NULL)
  96. {
  97. // toggle border style and force redraw of border
  98. ::SetWindowLong(pWnd->m_hWnd, GWL_STYLE, pWnd->GetStyle() ^ WS_BORDER);
  99. ::SetWindowPos(pWnd->m_hWnd, NULL, 0, 0, 0, 0,
  100. SWP_DRAWFRAME | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  101. }
  102. }
  103. AFX_STATIC void AFXAPI _AfxToggleAppearance(CWnd* pWnd)
  104. {
  105. if (pWnd->m_hWnd != NULL)
  106. {
  107. // toggle border style and force redraw of border
  108. ::SetWindowLong(pWnd->m_hWnd, GWL_EXSTYLE, pWnd->GetExStyle() ^
  109. WS_EX_CLIENTEDGE);
  110. ::SetWindowPos(pWnd->m_hWnd, NULL, 0, 0, 0, 0,
  111. SWP_DRAWFRAME | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  112. }
  113. }
  114. /////////////////////////////////////////////////////////////////////////////
  115. // Property exchange for stock properties
  116. void COleControl::ExchangeStockProps(CPropExchange* pPX)
  117. {
  118. BOOL bLoading = pPX->IsLoading();
  119. DWORD dwStockPropMask = GetStockPropMask();
  120. DWORD dwPersistMask = dwStockPropMask;
  121. PX_ULong(pPX, _T("_StockProps"), dwPersistMask);
  122. if (dwStockPropMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  123. {
  124. CString strText;
  125. if (dwPersistMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  126. {
  127. if (!bLoading)
  128. strText = InternalGetText();
  129. if (dwStockPropMask & STOCKPROP_CAPTION)
  130. PX_String(pPX, _T("Caption"), strText, _T(""));
  131. if (dwStockPropMask & STOCKPROP_TEXT)
  132. PX_String(pPX, _T("Text"), strText, _T(""));
  133. }
  134. if (bLoading)
  135. {
  136. TRY
  137. SetText(strText);
  138. END_TRY
  139. }
  140. }
  141. if (dwStockPropMask & STOCKPROP_FORECOLOR)
  142. {
  143. if (dwPersistMask & STOCKPROP_FORECOLOR)
  144. PX_Color(pPX, _T("ForeColor"), m_clrForeColor, AmbientForeColor());
  145. else if (bLoading)
  146. m_clrForeColor = AmbientForeColor();
  147. }
  148. if (dwStockPropMask & STOCKPROP_BACKCOLOR)
  149. {
  150. if (dwPersistMask & STOCKPROP_BACKCOLOR)
  151. PX_Color(pPX, _T("BackColor"), m_clrBackColor, AmbientBackColor());
  152. else if (bLoading)
  153. m_clrBackColor = AmbientBackColor();
  154. }
  155. if (dwStockPropMask & STOCKPROP_FONT)
  156. {
  157. LPFONTDISP pFontDispAmbient = AmbientFont();
  158. BOOL bChanged = TRUE;
  159. if (dwPersistMask & STOCKPROP_FONT)
  160. bChanged = PX_Font(pPX, _T("Font"), m_font, NULL, pFontDispAmbient);
  161. else if (bLoading)
  162. m_font.InitializeFont(NULL, pFontDispAmbient);
  163. if (bLoading && bChanged)
  164. OnFontChanged();
  165. RELEASE(pFontDispAmbient);
  166. }
  167. if (dwStockPropMask & STOCKPROP_BORDERSTYLE)
  168. {
  169. short sBorderStyle = m_sBorderStyle;
  170. if (dwPersistMask & STOCKPROP_BORDERSTYLE)
  171. PX_Short(pPX, _T("BorderStyle"), m_sBorderStyle, 0);
  172. else if (bLoading)
  173. m_sBorderStyle = 0;
  174. if (sBorderStyle != m_sBorderStyle)
  175. _AfxToggleBorderStyle(this);
  176. }
  177. if (dwStockPropMask & STOCKPROP_ENABLED)
  178. {
  179. BOOL bEnabled = m_bEnabled;
  180. if (dwPersistMask & STOCKPROP_ENABLED)
  181. PX_Bool(pPX, _T("Enabled"), m_bEnabled, TRUE);
  182. else if (bLoading)
  183. m_bEnabled = TRUE;
  184. if ((bEnabled != m_bEnabled) && (m_hWnd != NULL))
  185. ::EnableWindow(m_hWnd, m_bEnabled);
  186. }
  187. if (dwStockPropMask & STOCKPROP_APPEARANCE)
  188. {
  189. short sAppearance = m_sAppearance;
  190. if (dwPersistMask & STOCKPROP_APPEARANCE)
  191. PX_Short(pPX, _T("Appearance"), m_sAppearance, 0);
  192. else if (bLoading)
  193. m_sAppearance = AmbientAppearance();
  194. if (sAppearance != m_sAppearance)
  195. _AfxToggleAppearance(this);
  196. }
  197. }
  198. /////////////////////////////////////////////////////////////////////////////
  199. // Serialization for stock properties
  200. void COleControl::SerializeStockProps(CArchive& ar)
  201. {
  202. BOOL bLoading = ar.IsLoading();
  203. DWORD dwStockPropMask = GetStockPropMask();
  204. DWORD dwPersistMask = dwStockPropMask;
  205. if (bLoading)
  206. {
  207. ar >> dwPersistMask;
  208. if (dwStockPropMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  209. {
  210. if (dwPersistMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  211. {
  212. CString strText;
  213. ar >> strText;
  214. TRY
  215. SetText(strText);
  216. END_TRY
  217. }
  218. else
  219. {
  220. TRY
  221. SetText(_T(""));
  222. END_TRY
  223. }
  224. }
  225. if (dwStockPropMask & STOCKPROP_FORECOLOR)
  226. {
  227. if (dwPersistMask & STOCKPROP_FORECOLOR)
  228. ar >> m_clrForeColor;
  229. else
  230. m_clrForeColor = AmbientForeColor();
  231. }
  232. if (dwStockPropMask & STOCKPROP_BACKCOLOR)
  233. {
  234. if (dwPersistMask & STOCKPROP_BACKCOLOR)
  235. ar >> m_clrBackColor;
  236. else
  237. m_clrBackColor = AmbientBackColor();
  238. }
  239. if (dwStockPropMask & STOCKPROP_FONT)
  240. {
  241. BOOL bRead = FALSE;
  242. if (dwPersistMask & STOCKPROP_FONT)
  243. {
  244. BYTE bFlag;
  245. ar >> bFlag;
  246. if (bFlag != 0xFF)
  247. {
  248. CArchiveStream stm(&ar);
  249. LPSTREAM pstm = _AfxGetArchiveStream(ar, stm);
  250. LPFONT pFont = _AfxCreateFontFromStream(pstm);
  251. if (pFont != NULL)
  252. {
  253. m_font.SetFont(pFont);
  254. bRead = TRUE;
  255. }
  256. }
  257. }
  258. if (! bRead)
  259. {
  260. LPFONTDISP pFontDispAmbient = AmbientFont();
  261. m_font.InitializeFont(NULL, pFontDispAmbient);
  262. RELEASE(pFontDispAmbient);
  263. }
  264. OnFontChanged();
  265. }
  266. if (dwStockPropMask & STOCKPROP_BORDERSTYLE)
  267. {
  268. if (dwPersistMask & STOCKPROP_BORDERSTYLE)
  269. {
  270. short sBorderStyle = m_sBorderStyle;
  271. ar >> m_sBorderStyle;
  272. if (sBorderStyle != m_sBorderStyle)
  273. _AfxToggleBorderStyle(this);
  274. }
  275. else
  276. {
  277. m_sBorderStyle = 0;
  278. }
  279. }
  280. if (dwStockPropMask & STOCKPROP_ENABLED)
  281. {
  282. if (dwPersistMask & STOCKPROP_ENABLED)
  283. {
  284. BOOL bEnabled = m_bEnabled;
  285. ar >> m_bEnabled;
  286. if ((bEnabled != m_bEnabled) && (m_hWnd != NULL))
  287. ::EnableWindow(m_hWnd, m_bEnabled);
  288. }
  289. else
  290. {
  291. m_bEnabled = TRUE;
  292. }
  293. }
  294. if (dwStockPropMask & STOCKPROP_APPEARANCE)
  295. {
  296. if (dwPersistMask & STOCKPROP_APPEARANCE)
  297. {
  298. short sAppearance = m_sAppearance;
  299. ar >> m_sAppearance;
  300. if (sAppearance != m_sAppearance)
  301. _AfxToggleAppearance(this);
  302. }
  303. else
  304. {
  305. m_sAppearance = AmbientAppearance();
  306. }
  307. }
  308. }
  309. else
  310. {
  311. ar << dwPersistMask;
  312. if (dwStockPropMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  313. ar << m_strText;
  314. if (dwStockPropMask & STOCKPROP_FORECOLOR)
  315. ar << m_clrForeColor;
  316. if (dwStockPropMask & STOCKPROP_BACKCOLOR)
  317. ar << m_clrBackColor;
  318. if (dwStockPropMask & STOCKPROP_FONT)
  319. {
  320. BOOL bWrite = FALSE;
  321. LPFONT pFont = m_font.m_pFont;
  322. if (pFont != NULL)
  323. {
  324. // If same as ambient font (or error), write 0xFF for the flag
  325. LPFONTDISP pFontDispAmbient = AmbientFont();
  326. if (!_AfxIsSameFont(m_font, NULL, pFontDispAmbient))
  327. {
  328. LPPERSISTSTREAM pps = NULL;
  329. if (SUCCEEDED(pFont->QueryInterface(IID_IPersistStream,
  330. (LPVOID*)&pps)))
  331. {
  332. ASSERT_POINTER(pps, IPersistStream);
  333. ar << (BYTE)0x00;
  334. CArchiveStream stm(&ar);
  335. LPSTREAM pstm = _AfxGetArchiveStream(ar, stm);
  336. bWrite = SUCCEEDED(::OleSaveToStream(pps, pstm));
  337. pps->Release();
  338. if (!bWrite)
  339. AfxThrowArchiveException(CArchiveException::generic);
  340. }
  341. }
  342. RELEASE(pFontDispAmbient);
  343. }
  344. if (! bWrite)
  345. {
  346. ar << (BYTE)0xFF;
  347. }
  348. }
  349. if (dwStockPropMask & STOCKPROP_BORDERSTYLE)
  350. ar << m_sBorderStyle;
  351. if (dwStockPropMask & STOCKPROP_ENABLED)
  352. ar << m_bEnabled;
  353. if (dwStockPropMask & STOCKPROP_APPEARANCE)
  354. ar << m_sAppearance;
  355. }
  356. }
  357. /////////////////////////////////////////////////////////////////////////////
  358. // Initialization for stock properties
  359. void COleControl::ResetStockProps()
  360. {
  361. DWORD dwStockPropMask = GetStockPropMask();
  362. if (dwStockPropMask & (STOCKPROP_CAPTION | STOCKPROP_TEXT))
  363. {
  364. TRY
  365. SetText(_T(""));
  366. END_TRY
  367. }
  368. if (dwStockPropMask & STOCKPROP_FORECOLOR)
  369. m_clrForeColor = AmbientForeColor();
  370. if (dwStockPropMask & STOCKPROP_BACKCOLOR)
  371. m_clrBackColor = AmbientBackColor();
  372. if (dwStockPropMask & STOCKPROP_FONT)
  373. {
  374. LPFONTDISP pFontDispAmbient = AmbientFont();
  375. m_font.InitializeFont(NULL, pFontDispAmbient);
  376. RELEASE(pFontDispAmbient);
  377. OnFontChanged();
  378. }
  379. if (dwStockPropMask & STOCKPROP_BORDERSTYLE)
  380. m_sBorderStyle = 0;
  381. if (dwStockPropMask & STOCKPROP_ENABLED)
  382. m_bEnabled = TRUE;
  383. if (dwStockPropMask & STOCKPROP_APPEARANCE)
  384. m_sAppearance = AmbientAppearance();
  385. }
  386. /////////////////////////////////////////////////////////////////////////////
  387. // Appearance property
  388. short COleControl::GetAppearance()
  389. {
  390. return m_sAppearance;
  391. }
  392. void COleControl::SetAppearance(short sAppearance)
  393. {
  394. if (sAppearance != 0 && sAppearance != 1)
  395. ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
  396. // Is the property changing?
  397. if (m_sAppearance == sAppearance)
  398. return;
  399. if (!BoundPropertyRequestEdit(DISPID_APPEARANCE))
  400. SetNotPermitted();
  401. ASSERT((m_hWnd == NULL) ||
  402. ((GetExStyle() & WS_EX_CLIENTEDGE) == (DWORD)(m_sAppearance ?
  403. WS_EX_CLIENTEDGE : 0)));
  404. m_sAppearance = sAppearance;
  405. m_bModified = TRUE;
  406. _AfxToggleAppearance(this);
  407. OnAppearanceChanged();
  408. BoundPropertyChanged(DISPID_APPEARANCE);
  409. }
  410. void COleControl::OnAppearanceChanged()
  411. {
  412. // Can be overridden by subclass
  413. InvalidateControl();
  414. }
  415. /////////////////////////////////////////////////////////////////////////////
  416. // BackColor property
  417. OLE_COLOR COleControl::GetBackColor()
  418. {
  419. return m_clrBackColor;
  420. }
  421. void COleControl::SetBackColor(OLE_COLOR clrBackColor)
  422. {
  423. // Is the property changing?
  424. if (m_clrBackColor == clrBackColor)
  425. return;
  426. if (FAILED(::OleTranslateColor(clrBackColor, NULL, NULL)))
  427. ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
  428. if (!BoundPropertyRequestEdit(DISPID_BACKCOLOR))
  429. SetNotPermitted();
  430. m_clrBackColor = clrBackColor;
  431. m_bModified = TRUE;
  432. OnBackColorChanged();
  433. BoundPropertyChanged(DISPID_BACKCOLOR);
  434. }
  435. void COleControl::OnBackColorChanged()
  436. {
  437. // Can be overridden by subclass
  438. InvalidateControl();
  439. }
  440. /////////////////////////////////////////////////////////////////////////////
  441. // BorderStyle property
  442. short COleControl::GetBorderStyle()
  443. {
  444. return m_sBorderStyle;
  445. }
  446. void COleControl::SetBorderStyle(short sBorderStyle)
  447. {
  448. if (sBorderStyle != 0 && sBorderStyle != 1)
  449. ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
  450. // Is the property changing?
  451. if (m_sBorderStyle == sBorderStyle)
  452. return;
  453. if (!BoundPropertyRequestEdit(DISPID_BORDERSTYLE))
  454. SetNotPermitted();
  455. ASSERT((m_hWnd == NULL) ||
  456. ((GetStyle() & WS_BORDER) == (DWORD)(m_sBorderStyle ? WS_BORDER : 0)));
  457. m_sBorderStyle = sBorderStyle;
  458. m_bModified = TRUE;
  459. _AfxToggleBorderStyle(this);
  460. OnBorderStyleChanged();
  461. BoundPropertyChanged(DISPID_BORDERSTYLE);
  462. }
  463. void COleControl::OnBorderStyleChanged()
  464. {
  465. // Can be overridden by subclass
  466. InvalidateControl();
  467. }
  468. /////////////////////////////////////////////////////////////////////////////
  469. // Text and Caption properties
  470. const CString& COleControl::InternalGetText()
  471. {
  472. // Some subclassed controls (such as edit controls and comboboxes) change
  473. // the window text without sending WM_SETTEXT. Therefore, we need to
  474. // ensure that m_strText is up-to-date.
  475. if (m_hWnd != NULL && IsSubclassedControl())
  476. {
  477. // Usually, the window text will be shorter than 32 characters.
  478. // When it is, we can be more efficient.
  479. const int _cchUsual = 32;
  480. if (DefWindowProc(WM_GETTEXT, (WPARAM)_cchUsual,
  481. (LPARAM)m_strText.GetBufferSetLength(_cchUsual)) >= _cchUsual - 1)
  482. {
  483. // Text was too long: allocate a bigger buffer.
  484. int nLen = DefWindowProc(WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) + 1;
  485. DefWindowProc(WM_GETTEXT, (WPARAM)nLen,
  486. (LPARAM)m_strText.GetBufferSetLength(nLen));
  487. }
  488. m_strText.ReleaseBuffer();
  489. }
  490. return m_strText;
  491. }
  492. BSTR COleControl::GetText()
  493. {
  494. return ((CString&)InternalGetText()).AllocSysString();
  495. }
  496. void COleControl::SetText(LPCTSTR pszText)
  497. {
  498. LRESULT lResult;
  499. if (m_hWnd != NULL)
  500. lResult = SendMessage(WM_SETTEXT, 0, (LPARAM)pszText);
  501. else
  502. lResult = OnSetText(0, (LPARAM)pszText);
  503. if (lResult == -1)
  504. SetNotPermitted();
  505. }
  506. LRESULT COleControl::OnSetText(WPARAM wParam, LPARAM lParam)
  507. {
  508. ASSERT(lParam == 0 || AfxIsValidString((LPCTSTR)lParam));
  509. CString str = InternalGetText();
  510. // Is the property changing?
  511. if ((lParam == 0 && str.IsEmpty()) ||
  512. (lParam != 0 && str == (LPCTSTR)lParam))
  513. return 0;
  514. DWORD dwStockPropMask = GetStockPropMask();
  515. if (dwStockPropMask & STOCKPROP_CAPTION)
  516. if (!BoundPropertyRequestEdit(DISPID_CAPTION))
  517. return -1;
  518. if (dwStockPropMask & STOCKPROP_TEXT)
  519. if (!BoundPropertyRequestEdit(DISPID_TEXT))
  520. return -1;
  521. LRESULT lResult = 0;
  522. m_strText = (LPCTSTR)lParam;
  523. m_bModified = TRUE;
  524. if (m_hWnd != NULL)
  525. lResult = DefWindowProc(WM_SETTEXT, wParam, lParam);
  526. OnTextChanged();
  527. if (dwStockPropMask & STOCKPROP_CAPTION)
  528. BoundPropertyChanged(DISPID_CAPTION);
  529. if (dwStockPropMask & STOCKPROP_TEXT)
  530. BoundPropertyChanged(DISPID_TEXT);
  531. return lResult;
  532. }
  533. void COleControl::OnTextChanged()
  534. {
  535. // Can be overridden by subclass
  536. InvalidateControl();
  537. }
  538. /////////////////////////////////////////////////////////////////////////////
  539. // Enabled property
  540. BOOL COleControl::GetEnabled()
  541. {
  542. return m_bEnabled;
  543. }
  544. void COleControl::SetEnabled(BOOL bEnabled)
  545. {
  546. // Is the property changing?
  547. if (m_bEnabled == bEnabled)
  548. return;
  549. if (!BoundPropertyRequestEdit(DISPID_ENABLED))
  550. SetNotPermitted();
  551. m_bEnabled = bEnabled;
  552. m_bModified = TRUE;
  553. if (m_hWnd != NULL)
  554. ::EnableWindow(m_hWnd, m_bEnabled);
  555. // If the control is UI Active and the Enabled property changed to FALSE,
  556. // then UI Deactivate the control.
  557. if (m_bUIActive && !bEnabled)
  558. m_xOleInPlaceObject.UIDeactivate();
  559. OnEnabledChanged();
  560. BoundPropertyChanged(DISPID_ENABLED);
  561. }
  562. void COleControl::OnEnabledChanged()
  563. {
  564. // Can be overridden by subclass
  565. InvalidateControl();
  566. }
  567. /////////////////////////////////////////////////////////////////////////////
  568. // Font property
  569. CFontHolder& COleControl::InternalGetFont()
  570. {
  571. return m_font;
  572. }
  573. LPFONTDISP COleControl::GetFont()
  574. {
  575. return m_font.GetFontDispatch();
  576. }
  577. void COleControl::SetFont(LPFONTDISP pFontDisp)
  578. {
  579. ASSERT((pFontDisp == NULL) ||
  580. AfxIsValidAddress(pFontDisp, sizeof(IDispatch), FALSE));
  581. m_font.InitializeFont(NULL, pFontDisp);
  582. m_bModified = TRUE;
  583. OnFontChanged();
  584. BoundPropertyChanged(DISPID_FONT);
  585. }
  586. void COleControl::OnFontChanged()
  587. {
  588. // Can be overridden by subclass
  589. // Send WM_SETFONT to control's window
  590. if ((m_hWnd != NULL) &&
  591. (GetStockPropMask() & STOCKPROP_FONT) &&
  592. IsSubclassedControl())
  593. {
  594. HFONT hFontPrev = (HFONT)SendMessage(WM_GETFONT, 0, 0);
  595. CFontHolder& font = InternalGetFont();
  596. if (font.m_pFont != NULL)
  597. {
  598. HFONT hFont = font.GetFontHandle();
  599. font.m_pFont->AddRefHfont(hFont);
  600. SendMessage(WM_SETFONT, (WPARAM)hFont, 0);
  601. if (m_hFontPrev != NULL)
  602. {
  603. ASSERT(hFontPrev == m_hFontPrev);
  604. font.m_pFont->ReleaseHfont(hFontPrev);
  605. }
  606. m_hFontPrev = hFont;
  607. }
  608. else
  609. {
  610. SendMessage(WM_SETFONT, NULL, 0);
  611. m_hFontPrev = NULL;
  612. }
  613. }
  614. // Invalidate the control
  615. InvalidateControl();
  616. }
  617. /////////////////////////////////////////////////////////////////////////////
  618. // ForeColor property
  619. OLE_COLOR COleControl::GetForeColor()
  620. {
  621. return m_clrForeColor;
  622. }
  623. void COleControl::SetForeColor(OLE_COLOR clrForeColor)
  624. {
  625. // Is the property changing?
  626. if (m_clrForeColor == clrForeColor)
  627. return;
  628. if (FAILED(::OleTranslateColor(clrForeColor, NULL, NULL)))
  629. ThrowError(CTL_E_INVALIDPROPERTYVALUE, AFX_IDP_E_INVALIDPROPERTYVALUE);
  630. if (!BoundPropertyRequestEdit(DISPID_FORECOLOR))
  631. SetNotPermitted();
  632. m_clrForeColor = clrForeColor;
  633. m_bModified = TRUE;
  634. OnForeColorChanged();
  635. BoundPropertyChanged(DISPID_FORECOLOR);
  636. }
  637. void COleControl::OnForeColorChanged()
  638. {
  639. // Can be overridden by subclass
  640. InvalidateControl();
  641. }
  642. /////////////////////////////////////////////////////////////////////////////
  643. // hWnd property
  644. OLE_HANDLE COleControl::GetHwnd()
  645. {
  646. #ifdef _AFXDLL
  647. return (OLE_HANDLE)((m_bInPlaceActive || m_bOpen) ? m_hWnd : NULL);
  648. #else
  649. return (OLE_HANDLE)(m_bInPlaceActive ? m_hWnd : NULL);
  650. #endif
  651. }
  652. /////////////////////////////////////////////////////////////////////////////
  653. // ReadyState property
  654. long COleControl::GetReadyState()
  655. {
  656. return m_lReadyState;
  657. }
  658. ////////////////////////////////////////////////////////////////////////////
  659. // COleControl::XFontNotification
  660. STDMETHODIMP_(ULONG) COleControl::XFontNotification::AddRef()
  661. {
  662. return 1;
  663. }
  664. STDMETHODIMP_(ULONG) COleControl::XFontNotification::Release()
  665. {
  666. return 0;
  667. }
  668. STDMETHODIMP COleControl::XFontNotification::QueryInterface(
  669. REFIID iid, LPVOID* ppvObj)
  670. {
  671. ASSERT(ppvObj != NULL);
  672. if (IsEqualIID(iid, IID_IUnknown) ||
  673. IsEqualIID(iid, IID_IPropertyNotifySink))
  674. {
  675. *ppvObj = this;
  676. return S_OK;
  677. }
  678. return E_NOINTERFACE;
  679. }
  680. STDMETHODIMP COleControl::XFontNotification::OnChanged(DISPID)
  681. {
  682. METHOD_PROLOGUE_EX(COleControl, FontNotification)
  683. pThis->OnFontChanged();
  684. pThis->m_bModified = TRUE;
  685. pThis->BoundPropertyChanged(DISPID_FONT);
  686. return S_OK;
  687. }
  688. STDMETHODIMP COleControl::XFontNotification::OnRequestEdit(DISPID)
  689. {
  690. return S_OK;
  691. }
  692. CFont* COleControl::SelectStockFont(CDC* pDC)
  693. {
  694. return SelectFontObject(pDC, m_font);
  695. }
  696. CFont* COleControl::SelectFontObject(CDC* pDC, CFontHolder& fontHolder)
  697. {
  698. return fontHolder.Select(pDC, m_rcBounds.Height(), m_cyExtent);
  699. }
  700. void COleControl::GetStockTextMetrics(LPTEXTMETRIC lptm)
  701. {
  702. m_font.QueryTextMetrics(lptm);
  703. }
  704. void COleControl::GetFontTextMetrics(LPTEXTMETRIC lptm, CFontHolder& fontHolder)
  705. {
  706. fontHolder.QueryTextMetrics(lptm);
  707. }
  708. /////////////////////////////////////////////////////////////////////////////
  709. // Ambient property access
  710. BOOL AFXAPI _GetI4Property(LPDISPATCH pDispatch, DISPID dwDispID, DWORD* pdwResult)
  711. {
  712. if (pDispatch == NULL)
  713. return FALSE;
  714. DISPPARAMS dispparams;
  715. memset(&dispparams, 0, sizeof dispparams);
  716. VARIANT vaResult;
  717. AfxVariantInit(&vaResult);
  718. EXCEPINFO excepInfo;
  719. memset(&excepInfo, 0, sizeof excepInfo);
  720. UINT nArgErr = (UINT)-1; // initialize to invalid arg
  721. HRESULT hr = pDispatch->Invoke(dwDispID, IID_NULL, 0, DISPATCH_PROPERTYGET,
  722. &dispparams, &vaResult, &excepInfo, &nArgErr);
  723. if (SUCCEEDED(hr))
  724. {
  725. if ((V_VT(&vaResult) == VT_I4) ||
  726. SUCCEEDED(VariantChangeType(&vaResult, &vaResult, 0, VT_I4)))
  727. {
  728. *pdwResult = V_I4(&vaResult);
  729. return TRUE;
  730. }
  731. }
  732. VariantClear(&vaResult);
  733. if (excepInfo.bstrSource != NULL)
  734. SysFreeString(excepInfo.bstrSource);
  735. if (excepInfo.bstrDescription != NULL)
  736. SysFreeString(excepInfo.bstrDescription);
  737. if (excepInfo.bstrHelpFile != NULL)
  738. SysFreeString(excepInfo.bstrHelpFile);
  739. return FALSE;
  740. }
  741. COleDispatchDriver* COleControl::GetAmbientDispatchDriver()
  742. {
  743. if (m_ambientDispDriver.m_lpDispatch == NULL)
  744. {
  745. // Initialize pointer to ambient property dispinterface.
  746. IDispatch* pDispatch = NULL;
  747. if (m_pClientSite != NULL &&
  748. SUCCEEDED(m_pClientSite->QueryInterface(IID_IDispatch,
  749. reinterpret_cast<void**>(&pDispatch))))
  750. {
  751. ASSERT(pDispatch != NULL);
  752. m_ambientDispDriver.AttachDispatch(pDispatch);
  753. }
  754. }
  755. return &m_ambientDispDriver;
  756. }
  757. AFX_STATIC_DATA const DWORD _afxAmbientFlags[] =
  758. {
  759. QACONTAINER_MESSAGEREFLECT, // -706
  760. 0, // -707
  761. 0, // -708
  762. QACONTAINER_USERMODE, // -709
  763. QACONTAINER_UIDEAD, // -710
  764. QACONTAINER_SHOWGRABHANDLES, // -711
  765. QACONTAINER_SHOWHATCHING, // -712
  766. QACONTAINER_DISPLAYASDEFAULT, // -713
  767. QACONTAINER_SUPPORTSMNEMONICS, // -714
  768. QACONTAINER_AUTOCLIP, // -715
  769. };
  770. BOOL COleControl::GetAmbientProperty(DISPID dwDispID, VARTYPE vtProp, void* pvProp)
  771. {
  772. // First, check whether ambient property can be obtained from cache.
  773. _AFXCTL_AMBIENT_CACHE* pAmbientCache = _afxAmbientCache;
  774. if (pAmbientCache->m_bValid)
  775. {
  776. switch (vtProp)
  777. {
  778. // Fetch boolean by selecting appropriate flag in cache.
  779. case VT_BOOL:
  780. {
  781. int nIndex = DISPID_AMBIENT_MESSAGEREFLECT - dwDispID;
  782. DWORD dwFlag;
  783. if (nIndex >= 0 && nIndex < _countof(_afxAmbientFlags) &&
  784. (dwFlag = _afxAmbientFlags[nIndex]) != 0)
  785. {
  786. *(BOOL*)pvProp =
  787. ((pAmbientCache->m_dwAmbientFlags & dwFlag) != 0);
  788. return TRUE;
  789. }
  790. }
  791. break;
  792. // Fetch color, appearance, or font from corresponding cache entry.
  793. case VT_I4:
  794. switch (dwDispID)
  795. {
  796. case DISPID_AMBIENT_FORECOLOR:
  797. *(DWORD*)pvProp = pAmbientCache->m_colorFore;
  798. return TRUE;
  799. case DISPID_AMBIENT_BACKCOLOR:
  800. *(DWORD*)pvProp = pAmbientCache->m_colorBack;
  801. return TRUE;
  802. case DISPID_AMBIENT_APPEARANCE:
  803. *(DWORD*)pvProp = pAmbientCache->m_dwAppearance;
  804. return TRUE;
  805. }
  806. break;
  807. case VT_I2:
  808. if (dwDispID == DISPID_AMBIENT_APPEARANCE)
  809. {
  810. *(short*)pvProp = (short)pAmbientCache->m_dwAppearance;
  811. return TRUE;
  812. }
  813. break;
  814. case VT_DISPATCH:
  815. if ((dwDispID == DISPID_AMBIENT_FONT) &&
  816. (pAmbientCache->m_pFont != NULL) &&
  817. SUCCEEDED(pAmbientCache->m_pFont->QueryInterface(IID_IFontDisp,
  818. reinterpret_cast<void**>(pvProp))))
  819. {
  820. return TRUE;
  821. }
  822. break;
  823. }
  824. }
  825. // If there's no ambient dispatch interface available, then fail.
  826. COleDispatchDriver* pDispDriver = GetAmbientDispatchDriver();
  827. if (pDispDriver->m_lpDispatch == NULL)
  828. return FALSE;
  829. // If requested property is of type VT_I4, use optimized function.
  830. if (vtProp == VT_I4)
  831. return _GetI4Property(pDispDriver->m_lpDispatch, dwDispID,
  832. (DWORD*)pvProp);
  833. // If none of the above apply, just use the dispatch driver.
  834. BOOL bSuccess = FALSE;
  835. TRY
  836. {
  837. pDispDriver->GetProperty(dwDispID, vtProp, pvProp);
  838. bSuccess = TRUE;
  839. }
  840. END_TRY
  841. return bSuccess;
  842. }
  843. short COleControl::AmbientAppearance()
  844. {
  845. DWORD dwAppearance;
  846. if (!GetAmbientProperty(DISPID_AMBIENT_APPEARANCE, VT_I4, &dwAppearance))
  847. dwAppearance = 0;
  848. return (short)dwAppearance;
  849. }
  850. OLE_COLOR COleControl::AmbientBackColor()
  851. {
  852. OLE_COLOR clrBackColor;
  853. if (!GetAmbientProperty(DISPID_AMBIENT_BACKCOLOR, VT_I4, &clrBackColor))
  854. clrBackColor = GetSysColor(COLOR_WINDOW);
  855. return clrBackColor;
  856. }
  857. CString COleControl::AmbientDisplayName()
  858. {
  859. CString strDisplayName;
  860. GetAmbientProperty(DISPID_AMBIENT_DISPLAYNAME, VT_BSTR, &strDisplayName);
  861. return strDisplayName;
  862. }
  863. LPFONTDISP COleControl::AmbientFont()
  864. {
  865. // Note: Caller MUST Release the font!
  866. LPFONTDISP pDisp;
  867. if (!GetAmbientProperty(DISPID_AMBIENT_FONT, VT_DISPATCH, &pDisp))
  868. pDisp = NULL;
  869. return pDisp;
  870. }
  871. OLE_COLOR COleControl::AmbientForeColor()
  872. {
  873. OLE_COLOR clrForeColor;
  874. if (!GetAmbientProperty(DISPID_AMBIENT_FORECOLOR, VT_I4, &clrForeColor))
  875. clrForeColor = GetSysColor(COLOR_WINDOWTEXT);
  876. return clrForeColor;
  877. }
  878. LCID COleControl::AmbientLocaleID()
  879. {
  880. LCID lcid;
  881. if (!GetAmbientProperty(DISPID_AMBIENT_LOCALEID, VT_I4, &lcid))
  882. lcid = 0;
  883. return lcid;
  884. }
  885. CString COleControl::AmbientScaleUnits()
  886. {
  887. CString strScaleUnits;
  888. GetAmbientProperty(DISPID_AMBIENT_SCALEUNITS, VT_BSTR, &strScaleUnits);
  889. return strScaleUnits;
  890. }
  891. short COleControl::AmbientTextAlign()
  892. {
  893. short iTextAlign;
  894. if (!GetAmbientProperty(DISPID_AMBIENT_TEXTALIGN, VT_I2, &iTextAlign))
  895. iTextAlign = 0;
  896. return iTextAlign;
  897. }
  898. BOOL COleControl::AmbientUserMode()
  899. {
  900. BOOL bUserMode;
  901. if (!GetAmbientProperty(DISPID_AMBIENT_USERMODE, VT_BOOL, &bUserMode))
  902. bUserMode = TRUE;
  903. return bUserMode;
  904. }
  905. BOOL COleControl::AmbientUIDead()
  906. {
  907. BOOL bUIDead;
  908. if (!GetAmbientProperty(DISPID_AMBIENT_UIDEAD, VT_BOOL, &bUIDead))
  909. bUIDead = FALSE;
  910. return bUIDead;
  911. }
  912. BOOL COleControl::AmbientShowGrabHandles()
  913. {
  914. BOOL bShowGrab;
  915. if (!GetAmbientProperty(DISPID_AMBIENT_SHOWGRABHANDLES, VT_BOOL, &bShowGrab))
  916. bShowGrab = TRUE;
  917. return bShowGrab;
  918. }
  919. BOOL COleControl::AmbientShowHatching()
  920. {
  921. BOOL bShowHatch;
  922. if (!GetAmbientProperty(DISPID_AMBIENT_SHOWHATCHING, VT_BOOL, &bShowHatch))
  923. bShowHatch = TRUE;
  924. return bShowHatch;
  925. }
  926. /////////////////////////////////////////////////////////////////////////////
  927. // Calls to IPropertyNotifySink
  928. void COleControl::BoundPropertyChanged(DISPID dispid)
  929. {
  930. POSITION pos = m_xPropConnPt.GetStartPosition();
  931. LPPROPERTYNOTIFYSINK pPropNotifySink;
  932. while (pos != NULL)
  933. {
  934. pPropNotifySink =
  935. (LPPROPERTYNOTIFYSINK)m_xPropConnPt.GetNextConnection(pos);
  936. ASSERT(pPropNotifySink != NULL);
  937. pPropNotifySink->OnChanged(dispid);
  938. }
  939. }
  940. BOOL COleControl::BoundPropertyRequestEdit(DISPID dispid)
  941. {
  942. POSITION pos = m_xPropConnPt.GetStartPosition();
  943. LPPROPERTYNOTIFYSINK pPropNotifySink;
  944. while (pos != NULL)
  945. {
  946. pPropNotifySink =
  947. (LPPROPERTYNOTIFYSINK)m_xPropConnPt.GetNextConnection(pos);
  948. ASSERT(pPropNotifySink != NULL);
  949. if (pPropNotifySink->OnRequestEdit(dispid) != S_OK)
  950. return FALSE;
  951. }
  952. // All of the sinks said yes, so it's ok.
  953. return TRUE;
  954. }
  955. /////////////////////////////////////////////////////////////////////////////
  956. // Function to call when BoundPropertyRequestEdit fails
  957. void COleControl::SetNotPermitted()
  958. {
  959. ThrowError(CTL_E_SETNOTPERMITTED, AFX_IDP_E_SETNOTPERMITTED);
  960. }
  961. /////////////////////////////////////////////////////////////////////////////
  962. // Placeholder functions for read-only or write-only properties
  963. void COleControl::SetNotSupported()
  964. {
  965. ThrowError(CTL_E_SETNOTSUPPORTED, AFX_IDP_E_SETNOTSUPPORTED);
  966. }
  967. void COleControl::GetNotSupported()
  968. {
  969. ThrowError(CTL_E_GETNOTSUPPORTED, AFX_IDP_E_GETNOTSUPPORTED);
  970. }
  971. /////////////////////////////////////////////////////////////////////////////
  972. // COleControl::XPerPropertyBrowsing
  973. STDMETHODIMP_(ULONG) COleControl::XPerPropertyBrowsing::AddRef()
  974. {
  975. METHOD_PROLOGUE_EX_(COleControl, PerPropertyBrowsing)
  976. return (ULONG)pThis->ExternalAddRef();
  977. }
  978. STDMETHODIMP_(ULONG) COleControl::XPerPropertyBrowsing::Release()
  979. {
  980. METHOD_PROLOGUE_EX_(COleControl, PerPropertyBrowsing)
  981. return (ULONG)pThis->ExternalRelease();
  982. }
  983. STDMETHODIMP COleControl::XPerPropertyBrowsing::QueryInterface(
  984. REFIID iid, LPVOID* ppvObj)
  985. {
  986. METHOD_PROLOGUE_EX_(COleControl, PerPropertyBrowsing)
  987. return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  988. }
  989. STDMETHODIMP COleControl::XPerPropertyBrowsing::GetDisplayString(
  990. DISPID dispid, BSTR* lpbstr)
  991. {
  992. METHOD_PROLOGUE_EX(COleControl, PerPropertyBrowsing)
  993. ASSERT_NULL_OR_POINTER(lpbstr, BSTR);
  994. CString strValue;
  995. BOOL bSuccess = pThis->OnGetDisplayString(dispid, strValue);
  996. if (lpbstr != NULL)
  997. *lpbstr = (bSuccess ? strValue.AllocSysString() : NULL);
  998. return bSuccess ? S_OK : S_FALSE;
  999. }
  1000. BOOL COleControl::OnGetDisplayString(DISPID dispid, CString& strValue)
  1001. {
  1002. TRY
  1003. {
  1004. switch (dispid)
  1005. {
  1006. case DISPID_FONT:
  1007. return m_font.GetDisplayString(strValue);
  1008. case DISPID_BORDERSTYLE:
  1009. return strValue.LoadString(m_sBorderStyle == 0 ?
  1010. AFX_IDS_BORDERSTYLE_0 : AFX_IDS_BORDERSTYLE_1);
  1011. }
  1012. }
  1013. END_TRY
  1014. return FALSE;
  1015. }
  1016. STDMETHODIMP COleControl::XPerPropertyBrowsing::MapPropertyToPage(
  1017. DISPID dispid, LPCLSID lpclsid)
  1018. {
  1019. METHOD_PROLOGUE_EX(COleControl, PerPropertyBrowsing)
  1020. ASSERT_NULL_OR_POINTER(lpclsid, CLSID);
  1021. CLSID clsid = GUID_NULL;
  1022. BOOL bPageOptional = FALSE;
  1023. BOOL bSuccess = pThis->OnMapPropertyToPage(dispid, &clsid, &bPageOptional);
  1024. if (lpclsid != NULL)
  1025. *lpclsid = (bSuccess ? clsid : GUID_NULL);
  1026. return bSuccess ? (bPageOptional ? S_OK : S_FALSE) :
  1027. PERPROP_E_NOPAGEAVAILABLE;
  1028. }
  1029. BOOL COleControl::OnMapPropertyToPage(DISPID dispid, LPCLSID lpclsid,
  1030. BOOL* pbPageOptional)
  1031. {
  1032. switch (dispid)
  1033. {
  1034. case DISPID_FONT:
  1035. *lpclsid = CLSID_CFontPropPage;
  1036. *pbPageOptional = TRUE;
  1037. return TRUE;
  1038. case DISPID_BACKCOLOR:
  1039. case DISPID_FORECOLOR:
  1040. *lpclsid = CLSID_CColorPropPage;
  1041. *pbPageOptional = TRUE;
  1042. return TRUE;
  1043. }
  1044. return FALSE;
  1045. }
  1046. inline LPOLESTR AFXAPI _AfxCopyString(LPCTSTR psz)
  1047. {
  1048. if (psz == NULL)
  1049. return NULL;
  1050. int cch = lstrlen(psz) + 1;
  1051. LPOLESTR pszCopy = NULL;
  1052. if ((pszCopy = (LPOLESTR)CoTaskMemAlloc(cch * sizeof(OLECHAR))) != NULL)
  1053. {
  1054. #ifdef _UNICODE
  1055. wcscpy(pszCopy, psz);
  1056. #elif !defined(OLE2ANSI)
  1057. MultiByteToWideChar(CP_ACP, 0, psz, -1, pszCopy, cch);
  1058. #else
  1059. lstrcpy(pszCopy, psz);
  1060. #endif
  1061. }
  1062. return pszCopy;
  1063. }
  1064. STDMETHODIMP COleControl::XPerPropertyBrowsing::GetPredefinedStrings(
  1065. DISPID dispid, CALPOLESTR* lpcaStringsOut, CADWORD* lpcaCookiesOut)
  1066. {
  1067. METHOD_PROLOGUE_EX(COleControl, PerPropertyBrowsing)
  1068. if ((lpcaStringsOut == NULL) || (lpcaCookiesOut == NULL))
  1069. return E_POINTER;
  1070. ASSERT_POINTER(lpcaStringsOut, CALPOLESTR);
  1071. ASSERT_POINTER(lpcaCookiesOut, CADWORD);
  1072. CStringArray stringArray;
  1073. CDWordArray cookieArray;
  1074. BOOL bSuccess = pThis->OnGetPredefinedStrings(dispid, &stringArray,
  1075. &cookieArray);
  1076. if (bSuccess)
  1077. {
  1078. // Allocate and fill arrays to return.
  1079. ASSERT(stringArray.GetSize() == cookieArray.GetSize());
  1080. int iElem = 0;
  1081. LPOLESTR lpszCopy;
  1082. ULONG cElems = stringArray.GetSize();
  1083. lpcaStringsOut->pElems = (LPOLESTR*)CoTaskMemAlloc(
  1084. sizeof(LPOLESTR) * cElems);
  1085. if (lpcaStringsOut->pElems == NULL)
  1086. return E_OUTOFMEMORY;
  1087. lpcaCookiesOut->pElems = (DWORD*)CoTaskMemAlloc(
  1088. sizeof(DWORD*) * cElems);
  1089. if (lpcaCookiesOut->pElems == NULL)
  1090. {
  1091. CoTaskMemFree(lpcaStringsOut->pElems);
  1092. return E_OUTOFMEMORY;
  1093. }
  1094. lpcaStringsOut->cElems = cElems;
  1095. lpcaCookiesOut->cElems = cElems;
  1096. for (iElem = 0; iElem < (int)cElems; iElem++)
  1097. {
  1098. lpszCopy = _AfxCopyString(stringArray.GetAt(iElem));
  1099. if (lpszCopy == NULL)
  1100. {
  1101. // cleanup everything allocated so far...
  1102. while (--iElem >= 0)
  1103. CoTaskMemFree(lpcaStringsOut->pElems[iElem]);
  1104. CoTaskMemFree(lpcaCookiesOut->pElems);
  1105. CoTaskMemFree(lpcaStringsOut->pElems);
  1106. return E_OUTOFMEMORY;
  1107. }
  1108. lpcaStringsOut->pElems[iElem] = lpszCopy;
  1109. lpcaCookiesOut->pElems[iElem] = cookieArray.GetAt(iElem);
  1110. }
  1111. }
  1112. return bSuccess ? S_OK : S_FALSE;
  1113. }
  1114. BOOL COleControl::OnGetPredefinedStrings(DISPID dispid,
  1115. CStringArray* pStringArray, CDWordArray* pCookieArray)
  1116. {
  1117. BOOL bResult = FALSE;
  1118. switch (dispid)
  1119. {
  1120. case DISPID_BORDERSTYLE:
  1121. TRY
  1122. {
  1123. CString str;
  1124. str.LoadString(AFX_IDS_BORDERSTYLE_0);
  1125. pStringArray->Add(str);
  1126. pCookieArray->Add(0);
  1127. str.LoadString(AFX_IDS_BORDERSTYLE_1);
  1128. pStringArray->Add(str);
  1129. pCookieArray->Add(1);
  1130. bResult = TRUE;
  1131. }
  1132. CATCH (CException, e)
  1133. {
  1134. pStringArray->RemoveAll();
  1135. pCookieArray->RemoveAll();
  1136. bResult = FALSE;
  1137. }
  1138. END_CATCH
  1139. break;
  1140. }
  1141. return bResult;
  1142. }
  1143. STDMETHODIMP COleControl::XPerPropertyBrowsing::GetPredefinedValue(
  1144. DISPID dispid, DWORD dwCookie, VARIANT* lpvarOut)
  1145. {
  1146. METHOD_PROLOGUE_EX(COleControl, PerPropertyBrowsing)
  1147. ASSERT_POINTER(lpvarOut, VARIANT);
  1148. return pThis->OnGetPredefinedValue(dispid, dwCookie, lpvarOut) ?
  1149. S_OK : E_FAIL;
  1150. }
  1151. BOOL COleControl::OnGetPredefinedValue(DISPID dispid, DWORD dwCookie,
  1152. VARIANT* lpvarOut)
  1153. {
  1154. switch (dispid)
  1155. {
  1156. case DISPID_BORDERSTYLE:
  1157. if ((dwCookie == 0) || (dwCookie == 1))
  1158. {
  1159. VariantClear(lpvarOut);
  1160. V_VT(lpvarOut) = VT_I4;
  1161. V_I4(lpvarOut) = dwCookie;
  1162. return TRUE;
  1163. }
  1164. break;
  1165. }
  1166. return FALSE;
  1167. }
  1168. void COleControl::Load(LPCTSTR strNewPath, CDataPathProperty& prop)
  1169. {
  1170. prop.SetControl(this);
  1171. prop.Open(strNewPath);
  1172. }
  1173. /////////////////////////////////////////////////////////////////////////////
  1174. // CDataPathProperty implementation
  1175. BOOL CDataPathProperty::Open(CFileException* pError)
  1176. {
  1177. return CAsyncMonikerFile::Open(m_strPath, m_pControl ? m_pControl->GetClientSite() : NULL, pError);
  1178. }
  1179. BOOL CDataPathProperty::Open(LPCTSTR lpszPath, CFileException* pError)
  1180. {
  1181. SetPath(lpszPath);
  1182. return Open(pError);
  1183. }
  1184. BOOL CDataPathProperty::Open(COleControl* pControl, CFileException* pError)
  1185. {
  1186. SetControl(pControl);
  1187. return Open(pError);
  1188. }
  1189. BOOL CDataPathProperty::Open(LPCTSTR lpszPath, COleControl* pControl, CFileException* pError)
  1190. {
  1191. SetControl(pControl);
  1192. SetPath(lpszPath);
  1193. return Open(pError);
  1194. }
  1195. void CDataPathProperty::ResetData()
  1196. {
  1197. }
  1198. #ifdef _DEBUG
  1199. void CDataPathProperty::AssertValid() const
  1200. {
  1201. CAsyncMonikerFile::AssertValid();
  1202. }
  1203. void CDataPathProperty::Dump(CDumpContext& dc) const
  1204. {
  1205. CAsyncMonikerFile::Dump(dc);
  1206. dc << "\nm_pControl = " << m_pControl;
  1207. dc << "\nm_strPath = \"" << m_strPath;
  1208. dc << "\"\n";
  1209. }
  1210. #endif //_DEBUG
  1211. /////////////////////////////////////////////////////////////////////////////
  1212. // CCachedDataPathProperty implementation
  1213. AFX_STATIC inline DWORD _AfxTransferFileContent(CFile* pFrom, CFile* pTo)
  1214. {
  1215. BYTE buff[1024];
  1216. DWORD dwRead = 0;
  1217. DWORD dwActual;
  1218. do
  1219. {
  1220. dwActual = pFrom->Read(buff, 1024);
  1221. pTo->Write(buff, dwActual);
  1222. dwRead += dwActual;
  1223. }
  1224. while (dwActual > 0);
  1225. return dwRead;
  1226. }
  1227. void CCachedDataPathProperty::OnDataAvailable(DWORD dwSize, DWORD bscfFlag)
  1228. {
  1229. UNUSED_ALWAYS(bscfFlag);
  1230. UNUSED_ALWAYS(dwSize);
  1231. DWORD dwPos = m_Cache.GetPosition();
  1232. TRY
  1233. {
  1234. // Cache the data in our mem file.
  1235. m_Cache.SeekToEnd();
  1236. _AfxTransferFileContent(this, &m_Cache);
  1237. }
  1238. CATCH_ALL(e)
  1239. {
  1240. m_Cache.Seek(dwPos, CFile::begin);
  1241. THROW_LAST();
  1242. }
  1243. END_CATCH_ALL
  1244. m_Cache.Seek(dwPos, CFile::begin);
  1245. }
  1246. void CCachedDataPathProperty::Close()
  1247. {
  1248. m_Cache.SetLength(0);
  1249. CDataPathProperty::Close();
  1250. }
  1251. void CCachedDataPathProperty::ResetData()
  1252. {
  1253. m_Cache.SetLength(0);
  1254. }
  1255. #ifdef _DEBUG
  1256. void CCachedDataPathProperty::AssertValid() const
  1257. {
  1258. CDataPathProperty::AssertValid();
  1259. m_Cache.AssertValid();
  1260. }
  1261. void CCachedDataPathProperty::Dump(CDumpContext& dc) const
  1262. {
  1263. CDataPathProperty::Dump(dc);
  1264. m_Cache.Dump(dc);
  1265. }
  1266. #endif //_DEBUG
  1267. /////////////////////////////////////////////////////////////////////////////
  1268. // Force any extra compiler-generated code into AFX_INIT_SEG
  1269. #ifdef AFX_INIT_SEG
  1270. #pragma code_seg(AFX_INIT_SEG)
  1271. #endif
  1272. IMPLEMENT_DYNAMIC(CDataPathProperty, CAsyncMonikerFile)
  1273. IMPLEMENT_DYNAMIC(CCachedDataPathProperty, CDataPathProperty)