Source code of Windows XP (NT5)
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.

1085 lines
30 KiB

  1. //=--------------------------------------------------------------------------=
  2. // ControlMisc.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // things that aren't elsewhere, such as property pages, and connection
  13. // points.
  14. //
  15. #include "pch.h"
  16. #include "CtrlObj.H"
  17. #include "CtlHelp.H"
  18. #include <stdarg.h>
  19. // for ASSERT and FAIL
  20. //
  21. SZTHISFILE
  22. // this is used in our window proc so that we can find out who was last created
  23. //
  24. static COleControl *s_pLastControlCreated;
  25. //=--------------------------------------------------------------------------=
  26. // COleControl::COleControl
  27. //=--------------------------------------------------------------------------=
  28. // constructor
  29. //
  30. // Parameters:
  31. // IUnknown * - [in] controlling Unknown
  32. // int - [in] type of primary dispatch interface OBJECT_TYPE_*
  33. // void * - [in] pointer to entire object
  34. //
  35. // Notes:
  36. //
  37. COleControl::COleControl
  38. (
  39. IUnknown *pUnkOuter,
  40. int iPrimaryDispatch,
  41. void *pMainInterface
  42. )
  43. : CAutomationObjectWEvents(pUnkOuter, iPrimaryDispatch, pMainInterface)
  44. {
  45. // initialize all our variables -- we decided against using a memory-zeroing
  46. // memory allocator, so we sort of have to do this work now ...
  47. //
  48. m_pClientSite = NULL;
  49. m_pControlSite = NULL;
  50. m_pInPlaceSite = NULL;
  51. m_pInPlaceFrame = NULL;
  52. m_pInPlaceUIWindow = NULL;
  53. m_pInPlaceSiteWndless = NULL;
  54. // certain hosts don't like 0,0 as your initial size, so we're going to set
  55. // our initial size to 100,50 [so it's at least sort of visible on the screen]
  56. //
  57. m_Size.cx = 100;
  58. m_Size.cy = 50;
  59. memset(&m_rcLocation, 0, sizeof(m_rcLocation));
  60. m_hwnd = NULL;
  61. m_hwndParent = NULL;
  62. m_hwndReflect = NULL;
  63. m_fHostReflects = TRUE;
  64. m_fCheckedReflecting = FALSE;
  65. m_pSimpleFrameSite = NULL;
  66. m_pOleAdviseHolder = NULL;
  67. m_pViewAdviseSink = NULL;
  68. m_pDispAmbient = NULL;
  69. m_fDirty = FALSE;
  70. m_fModeFlagValid = FALSE;
  71. m_fInPlaceActive = FALSE;
  72. m_fInPlaceVisible = FALSE;
  73. m_fUIActive = FALSE;
  74. m_fSaveSucceeded = FALSE;
  75. m_fViewAdvisePrimeFirst = FALSE;
  76. m_fViewAdviseOnlyOnce = FALSE;
  77. m_fRunMode = FALSE;
  78. m_fChangingExtents = FALSE;
  79. }
  80. //=--------------------------------------------------------------------------=
  81. // COleControl::~COleControl
  82. //=--------------------------------------------------------------------------=
  83. // "We are all of us resigned to death; it's life we aren't resigned to."
  84. // - Graham Greene (1904-91)
  85. //
  86. // Notes:
  87. //
  88. COleControl::~COleControl()
  89. {
  90. ASSERT(!m_hwnd, "We shouldn't have a window any more!");
  91. if (m_hwndReflect) {
  92. SetWindowLong(m_hwndReflect, GWL_USERDATA, 0);
  93. DestroyWindow(m_hwndReflect);
  94. }
  95. // clean up all the pointers we're holding around.
  96. //
  97. QUICK_RELEASE(m_pClientSite);
  98. QUICK_RELEASE(m_pControlSite);
  99. QUICK_RELEASE(m_pInPlaceSite);
  100. QUICK_RELEASE(m_pInPlaceFrame);
  101. QUICK_RELEASE(m_pInPlaceUIWindow);
  102. QUICK_RELEASE(m_pSimpleFrameSite);
  103. QUICK_RELEASE(m_pOleAdviseHolder);
  104. QUICK_RELEASE(m_pViewAdviseSink);
  105. QUICK_RELEASE(m_pDispAmbient);
  106. QUICK_RELEASE(m_pInPlaceSiteWndless);
  107. }
  108. #ifndef DEBUG
  109. #pragma optimize("t", on)
  110. #endif // DEBUG
  111. //=--------------------------------------------------------------------------=
  112. // COleControl::InternalQueryInterface
  113. //=--------------------------------------------------------------------------=
  114. // derived-controls should delegate back to this when they decide to support
  115. // additional interfaces
  116. //
  117. // Parameters:
  118. // REFIID - [in] interface they want
  119. // void ** - [out] where they want to put the resulting object ptr.
  120. //
  121. // Output:
  122. // HRESULT - S_OK, E_NOINTERFACE
  123. //
  124. // Notes:
  125. // - NOTE: this function is speed critical!!!!
  126. //
  127. HRESULT COleControl::InternalQueryInterface
  128. (
  129. REFIID riid,
  130. void **ppvObjOut
  131. )
  132. {
  133. switch (riid.Data1)
  134. {
  135. // private interface for prop page support
  136. QI_INHERITS(this, IOleControl);
  137. QI_INHERITS(this, IPointerInactive);
  138. QI_INHERITS(this, IQuickActivate);
  139. QI_INHERITS(this, IOleObject);
  140. QI_INHERITS((IPersistStorage *)this, IPersist);
  141. QI_INHERITS(this, IPersistStreamInit);
  142. QI_INHERITS(this, IOleInPlaceObject);
  143. QI_INHERITS(this, IOleInPlaceObjectWindowless);
  144. QI_INHERITS((IOleInPlaceActiveObject *)this, IOleWindow);
  145. QI_INHERITS(this, IOleInPlaceActiveObject);
  146. QI_INHERITS(this, IViewObject);
  147. QI_INHERITS(this, IViewObject2);
  148. QI_INHERITS(this, IViewObjectEx);
  149. QI_INHERITS(this, ISpecifyPropertyPages);
  150. QI_INHERITS(this, IPersistStorage);
  151. QI_INHERITS(this, IPersistPropertyBag);
  152. QI_INHERITS(this, IProvideClassInfo);
  153. QI_INHERITS(this, IControlPrv);
  154. default:
  155. goto NoInterface;
  156. }
  157. // we like the interface, so addref and return
  158. //
  159. ((IUnknown *)(*ppvObjOut))->AddRef();
  160. return S_OK;
  161. NoInterface:
  162. // delegate to super-class for automation interfaces, etc ...
  163. //
  164. return CAutomationObjectWEvents::InternalQueryInterface(riid, ppvObjOut);
  165. }
  166. #ifndef DEBUG
  167. #pragma optimize("s", on)
  168. #endif // DEBUG
  169. //=--------------------------------------------------------------------------=
  170. // COleControl::BeforeDestroyObject [overridden]
  171. //=--------------------------------------------------------------------------=
  172. // if we're in the process of shutting down and destroying ourselves, then we
  173. // need to trash our window here so we can avoid pure virtual calls from
  174. // within colecontol's destructor
  175. //
  176. // Notes:
  177. //
  178. void COleControl::BeforeDestroyObject
  179. (
  180. void
  181. )
  182. {
  183. if (m_hwnd) {
  184. DestroyWindow(m_hwnd);
  185. m_hwnd = NULL;
  186. }
  187. }
  188. //=--------------------------------------------------------------------------=
  189. // COleControl::GetPages [ISpecifyPropertyPages]
  190. //=--------------------------------------------------------------------------=
  191. // returns a counted array with the guids for our property pages.
  192. //
  193. // parameters:
  194. // CAUUID * - [out] where to put the counted array.
  195. //
  196. // Output:
  197. // HRESULT
  198. //
  199. // NOtes:
  200. //
  201. STDMETHODIMP COleControl::GetPages
  202. (
  203. CAUUID *pPages
  204. )
  205. {
  206. const GUID **pElems;
  207. void *pv;
  208. WORD x;
  209. // if there are no property pages, this is actually pretty easy.
  210. //
  211. if (!CPROPPAGESOFCONTROL(m_ObjectType)) {
  212. pPages->cElems = 0;
  213. pPages->pElems = NULL;
  214. return S_OK;
  215. }
  216. // fill out the Counted array, using IMalloc'd memory.
  217. //
  218. pPages->cElems = CPROPPAGESOFCONTROL(m_ObjectType);
  219. pv = CoTaskMemAlloc(sizeof(GUID) * (pPages->cElems));
  220. RETURN_ON_NULLALLOC(pv);
  221. pPages->pElems = (GUID *)pv;
  222. // loop through our array of pages and get 'em.
  223. //
  224. pElems = PPROPPAGESOFCONTROL(m_ObjectType);
  225. for (x = 0; x < pPages->cElems; x++)
  226. pPages->pElems[x] = *(pElems[x]);
  227. return S_OK;
  228. }
  229. //=--------------------------------------------------------------------------=
  230. // COleControl::CreateInPlaceWindow
  231. //=--------------------------------------------------------------------------=
  232. // creates the window with which we will be working.
  233. // yay.
  234. //
  235. // Parameters:
  236. // int - [in] left
  237. // int - [in] top
  238. // BOOL - [in] can we skip redrawing?
  239. //
  240. // Output:
  241. // HWND
  242. //
  243. // Notes:
  244. // - DANGER! DANGER! this function is protected so that anybody can call it
  245. // from their control. however, people should be extremely careful of when
  246. // and why they do this. preferably, this function would only need to be
  247. // called by an end-control writer in design mode to take care of some
  248. // hosting/painting issues. otherwise, the framework should be left to
  249. // call it when it wants.
  250. //
  251. HWND COleControl::CreateInPlaceWindow
  252. (
  253. int x,
  254. int y,
  255. BOOL fNoRedraw
  256. )
  257. {
  258. BOOL fVisible;
  259. DWORD dwWindowStyle, dwExWindowStyle;
  260. char szWindowTitle[128];
  261. // if we've already got a window, do nothing.
  262. //
  263. if (m_hwnd)
  264. return m_hwnd;
  265. // get the user to register the class if it's not already
  266. // been done. we have to critical section this since more than one thread
  267. // can be trying to create this control
  268. //
  269. ENTERCRITICALSECTION1(&g_CriticalSection);
  270. if (!CTLWNDCLASSREGISTERED(m_ObjectType)) {
  271. if (!RegisterClassData()) {
  272. LEAVECRITICALSECTION1(&g_CriticalSection);
  273. return NULL;
  274. } else
  275. CTLWNDCLASSREGISTERED(m_ObjectType) = TRUE;
  276. }
  277. LEAVECRITICALSECTION1(&g_CriticalSection);
  278. // let the user set up things like the window title, the
  279. // style, and anything else they feel interested in fiddling
  280. // with.
  281. //
  282. dwWindowStyle = dwExWindowStyle = 0;
  283. szWindowTitle[0] = '\0';
  284. if (!BeforeCreateWindow(&dwWindowStyle, &dwExWindowStyle, szWindowTitle))
  285. return NULL;
  286. dwWindowStyle |= (WS_CHILD | WS_CLIPSIBLINGS);
  287. // create window visible if parent hidden (common case)
  288. // otherwise, create hidden, then shown. this is a little subtle, but
  289. // it makes sense eventually.
  290. //
  291. if (!m_hwndParent)
  292. m_hwndParent = GetParkingWindow();
  293. fVisible = IsWindowVisible(m_hwndParent);
  294. // This one kinda sucks -- if a control is subclassed, and we're in
  295. // a host that doesn't support Message Reflecting, we have to create
  296. // the user window in another window which will do all the reflecting.
  297. // VERY blech. [don't however, bother in design mode]
  298. //
  299. if (SUBCLASSWNDPROCOFCONTROL(m_ObjectType) && (m_hwndParent != GetParkingWindow())) {
  300. // determine if the host supports message reflecting.
  301. //
  302. if (!m_fCheckedReflecting) {
  303. VARIANT_BOOL f;
  304. if (!GetAmbientProperty(DISPID_AMBIENT_MESSAGEREFLECT, VT_BOOL, &f) || !f)
  305. m_fHostReflects = FALSE;
  306. m_fCheckedReflecting = TRUE;
  307. }
  308. // if the host doesn't support reflecting, then we have to create
  309. // an extra window around the control window, and then parent it
  310. // off that.
  311. //
  312. if (!m_fHostReflects) {
  313. ASSERT(m_hwndReflect == NULL, "Where'd this come from?");
  314. m_hwndReflect = CreateReflectWindow(!fVisible, m_hwndParent, x, y, &m_Size);
  315. if (!m_hwndReflect)
  316. return NULL;
  317. SetWindowLong(m_hwndReflect, GWL_USERDATA, (long)this);
  318. dwWindowStyle |= WS_VISIBLE;
  319. }
  320. } else {
  321. if (!fVisible)
  322. dwWindowStyle |= WS_VISIBLE;
  323. }
  324. // we have to mutex the entire create window process since we need to use
  325. // the s_pLastControlCreated to pass in the object pointer. nothing too
  326. // serious
  327. //
  328. ENTERCRITICALSECTION2(&g_CriticalSection);
  329. s_pLastControlCreated = this;
  330. m_fCreatingWindow = TRUE;
  331. // finally, go create the window, parenting it as appropriate.
  332. //
  333. m_hwnd = CreateWindowEx(dwExWindowStyle,
  334. WNDCLASSNAMEOFCONTROL(m_ObjectType),
  335. szWindowTitle,
  336. dwWindowStyle,
  337. (m_hwndReflect) ? 0 : x,
  338. (m_hwndReflect) ? 0 : y,
  339. m_Size.cx, m_Size.cy,
  340. (m_hwndReflect) ? m_hwndReflect : m_hwndParent,
  341. NULL, g_hInstance, NULL);
  342. // clean up some variables, and leave the critical section
  343. //
  344. m_fCreatingWindow = FALSE;
  345. s_pLastControlCreated = NULL;
  346. LEAVECRITICALSECTION2(&g_CriticalSection);
  347. if (m_hwnd) {
  348. // let the derived-control do something if they so desire
  349. //
  350. if (!AfterCreateWindow()) {
  351. DestroyWindow(m_hwnd);
  352. return NULL;
  353. }
  354. // if we didn't create the window visible, show it now.
  355. //
  356. if (fVisible)
  357. SetWindowPos(m_hwnd, NULL, 0, 0, 0, 0,
  358. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | ((fNoRedraw) ? SWP_NOREDRAW : 0));
  359. }
  360. return m_hwnd;
  361. }
  362. //=--------------------------------------------------------------------------=
  363. // COleControl::SetInPlaceParent [helper]
  364. //=--------------------------------------------------------------------------=
  365. // sets up the parent window for our control.
  366. //
  367. // Parameters:
  368. // HWND - [in] new parent window
  369. //
  370. // Notes:
  371. //
  372. void COleControl::SetInPlaceParent
  373. (
  374. HWND hwndParent
  375. )
  376. {
  377. #ifdef DEBUG
  378. HWND hwndOld;
  379. DWORD dw;
  380. #endif
  381. ASSERT(!m_pInPlaceSiteWndless, "This routine should only get called for windowed OLE controls");
  382. if (m_hwndParent == hwndParent)
  383. return;
  384. m_hwndParent = hwndParent;
  385. if (m_hwnd)
  386. {
  387. #ifdef DEBUG
  388. hwndOld =
  389. #endif
  390. SetParent(GetOuterWindow(), hwndParent);
  391. #ifdef DEBUG
  392. if (hwndOld == NULL)
  393. {
  394. dw = GetLastError();
  395. ASSERT(dw == 0, "SetParent failed");
  396. }
  397. #endif
  398. }
  399. }
  400. //=--------------------------------------------------------------------------=
  401. // COleControl::ControlWindowProc
  402. //=--------------------------------------------------------------------------=
  403. // default window proc for an OLE Control. controls will have their own
  404. // window proc called from this one, after some processing is done.
  405. //
  406. // Parameters:
  407. // - see win32sdk docs.
  408. //
  409. // Notes:
  410. //
  411. LRESULT CALLBACK COleControl::ControlWindowProc
  412. (
  413. HWND hwnd,
  414. UINT msg,
  415. WPARAM wParam,
  416. LPARAM lParam
  417. )
  418. {
  419. COleControl *pCtl = ControlFromHwnd(hwnd);
  420. HRESULT hr;
  421. LRESULT lResult = 0;
  422. DWORD dwCookie;
  423. BYTE fSimpleFrame = FALSE;
  424. // if the value isn't a positive value, then it's in some special
  425. // state [creation or destruction] this is safe because under win32,
  426. // the upper 2GB of an address space aren't available.
  427. //
  428. if ((LONG)pCtl == 0) {
  429. pCtl = s_pLastControlCreated;
  430. SetWindowLong(hwnd, GWL_USERDATA, (LONG)pCtl);
  431. pCtl->m_hwnd = hwnd;
  432. } else if ((ULONG)pCtl == 0xffffffff) {
  433. return DefWindowProc(hwnd, msg, wParam, lParam);
  434. }
  435. // this is unfortunate. if the control gets destroyed while processing a
  436. // message [ie, 'End' in an event, etc ....], we need to be able to
  437. // contine through to the end of this routine, past the post-processing.
  438. // to do this, we need to force a ref count on the control to keep it
  439. // around. blech
  440. //
  441. pCtl->ExternalAddRef();
  442. // message preprocessing
  443. //
  444. if (pCtl->m_pSimpleFrameSite) {
  445. hr = pCtl->m_pSimpleFrameSite->PreMessageFilter(hwnd, msg, wParam, lParam, &lResult, &dwCookie);
  446. if (hr == S_FALSE) goto Done;
  447. }
  448. // for certain messages, do not call the user window proc. instead,
  449. // we have something else we'd like to do.
  450. //
  451. switch (msg) {
  452. case WM_PAINT:
  453. {
  454. // call the user's OnDraw routine.
  455. //
  456. PAINTSTRUCT ps;
  457. RECT rc;
  458. HDC hdc;
  459. // if we're given an HDC, then use it
  460. //
  461. if (!wParam)
  462. {
  463. hdc = BeginPaint(hwnd, &ps);
  464. }
  465. else
  466. hdc = (HDC)wParam;
  467. GetClientRect(hwnd, &rc);
  468. pCtl->OnDraw(DVASPECT_CONTENT, hdc, (RECTL *)&rc, NULL, NULL, TRUE);
  469. if (!wParam)
  470. {
  471. EndPaint(hwnd, &ps);
  472. }
  473. }
  474. break;
  475. case WM_DESTROY:
  476. pCtl->BeforeDestroyWindow();
  477. // fall through so that controls will send this to the parent window class.
  478. default:
  479. // call the derived-control's window proc
  480. //
  481. lResult = pCtl->WindowProc(msg, wParam, lParam);
  482. break;
  483. }
  484. // message postprocessing
  485. //
  486. switch (msg) {
  487. case WM_NCDESTROY:
  488. // after this point, the window doesn't exist any more
  489. //
  490. SetWindowLong(hwnd, GWL_USERDATA, 0xffffffff);
  491. // We've been destroyed so reset our parent to NULL, so that it gets regenerated when we're recreated
  492. //
  493. pCtl->m_hwndParent = NULL;
  494. pCtl->m_hwnd = NULL;
  495. break;
  496. case WM_SETFOCUS:
  497. case WM_KILLFOCUS:
  498. // give the control site focus notification
  499. //
  500. if (pCtl->m_fInPlaceActive && pCtl->m_pControlSite)
  501. pCtl->m_pControlSite->OnFocus(msg == WM_SETFOCUS);
  502. break;
  503. case WM_SIZE:
  504. // a change in size is a change in view
  505. //
  506. if (!pCtl->m_fCreatingWindow)
  507. pCtl->ViewChanged();
  508. break;
  509. }
  510. // lastly, simple frame postmessage processing
  511. //
  512. if (pCtl->m_pSimpleFrameSite)
  513. pCtl->m_pSimpleFrameSite->PostMessageFilter(hwnd, msg, wParam, lParam, &lResult, dwCookie);
  514. Done:
  515. pCtl->ExternalRelease();
  516. return lResult;
  517. }
  518. //=--------------------------------------------------------------------------=
  519. // COleControl::SetFocus
  520. //=--------------------------------------------------------------------------=
  521. // we have to override this routine to get UI Activation correct.
  522. //
  523. // Parameters:
  524. // BOOL - [in] true means take, false release
  525. //
  526. // Output:
  527. // BOOL
  528. //
  529. // Notes:
  530. // - CONSIDER: this is pretty messy, and it's still not entirely clear
  531. // what the ole control/focus story is.
  532. //
  533. BOOL COleControl::SetFocus
  534. (
  535. BOOL fGrab
  536. )
  537. {
  538. HRESULT hr;
  539. HWND hwnd;
  540. // first thing to do is check out UI Activation state, and then set
  541. // focus [either with windows api, or via the host for windowless
  542. // controls]
  543. //
  544. if (m_pInPlaceSiteWndless) {
  545. if (!m_fUIActive && fGrab)
  546. if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE))) return FALSE;
  547. hr = m_pInPlaceSiteWndless->SetFocus(fGrab);
  548. return (hr == S_OK) ? TRUE : FALSE;
  549. } else {
  550. // we've got a window.
  551. //
  552. if (m_fInPlaceActive) {
  553. hwnd = (fGrab) ? m_hwnd : m_hwndParent;
  554. if (!m_fUIActive && fGrab)
  555. return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
  556. else
  557. return (::SetFocus(hwnd) == hwnd);
  558. } else
  559. return FALSE;
  560. }
  561. // dead code
  562. }
  563. //=--------------------------------------------------------------------------=
  564. // ReflectOcmMessage
  565. //=--------------------------------------------------------------------------=
  566. // Reflects window messages on to the child window.
  567. //
  568. // Parameters and Output:
  569. // - see win32 sdk docs
  570. //
  571. // Returns: TRUE if an OCM_ message was reflect
  572. // FALSE if no OCM_ message was reflected
  573. //
  574. // The return value from SendMessage is stored is returned in pLResult
  575. //
  576. // Notes:
  577. //
  578. BOOL COleControl::ReflectOcmMessage
  579. (
  580. HWND hwnd,
  581. UINT msg,
  582. WPARAM wParam,
  583. LPARAM lParam,
  584. LRESULT *pLResult
  585. )
  586. {
  587. COleControl *pCtl;
  588. ASSERT(pLResult, "RESULT pointer is NULL");
  589. *pLResult = 0;
  590. switch(msg)
  591. {
  592. case WM_COMMAND:
  593. case WM_NOTIFY:
  594. case WM_CTLCOLORBTN:
  595. case WM_CTLCOLORDLG:
  596. case WM_CTLCOLOREDIT:
  597. case WM_CTLCOLORLISTBOX:
  598. case WM_CTLCOLORMSGBOX:
  599. case WM_CTLCOLORSCROLLBAR:
  600. case WM_CTLCOLORSTATIC:
  601. case WM_DRAWITEM:
  602. case WM_MEASUREITEM:
  603. case WM_DELETEITEM:
  604. case WM_VKEYTOITEM:
  605. case WM_CHARTOITEM:
  606. case WM_COMPAREITEM:
  607. case WM_HSCROLL:
  608. case WM_VSCROLL:
  609. case WM_PARENTNOTIFY:
  610. pCtl = (COleControl *)GetWindowLong(hwnd, GWL_USERDATA);
  611. if (pCtl)
  612. {
  613. *pLResult = SendMessage(pCtl->m_hwnd, OCM__BASE + msg, wParam, lParam);
  614. return TRUE;
  615. }
  616. break;
  617. }
  618. return FALSE;
  619. }
  620. //=--------------------------------------------------------------------------=
  621. // COleControl::ReflectWindowProc
  622. //=--------------------------------------------------------------------------=
  623. // reflects window messages on to the child window.
  624. //
  625. // Parameters and Output:
  626. // - see win32 sdk docs
  627. //
  628. // Notes:
  629. //
  630. LRESULT CALLBACK COleControl::ReflectWindowProc
  631. (
  632. HWND hwnd,
  633. UINT msg,
  634. WPARAM wParam,
  635. LPARAM lParam
  636. )
  637. {
  638. LRESULT lResult;
  639. COleControl *pCtl;
  640. switch (msg) {
  641. case WM_SETFOCUS:
  642. pCtl = (COleControl *)GetWindowLong(hwnd, GWL_USERDATA);
  643. if (pCtl)
  644. {
  645. return pCtl->SetFocus(TRUE);
  646. }
  647. break;
  648. case WM_SIZE:
  649. pCtl = (COleControl *)GetWindowLong(hwnd, GWL_USERDATA);
  650. if (pCtl != NULL)
  651. ::MoveWindow(pCtl->m_hwnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  652. // continue with default processing
  653. break;
  654. }
  655. // If the message is reflected then return the result of the OCM_ message
  656. //
  657. if (ReflectOcmMessage(hwnd, msg, wParam, lParam, &lResult))
  658. return lResult;
  659. return DefWindowProc(hwnd, msg, wParam, lParam);
  660. }
  661. //=--------------------------------------------------------------------------=
  662. // COleControl::GetAmbientProperty [callable]
  663. //=--------------------------------------------------------------------------=
  664. // returns the value of an ambient property
  665. //
  666. // Parameters:
  667. // DISPID - [in] property to get
  668. // VARTYPE - [in] type of desired data
  669. // void * - [out] where to put the data
  670. //
  671. // Output:
  672. // BOOL - FALSE means didn't work.
  673. //
  674. // Notes:
  675. //
  676. BOOL COleControl::GetAmbientProperty
  677. (
  678. DISPID dispid,
  679. VARTYPE vt,
  680. void *pData
  681. )
  682. {
  683. DISPPARAMS dispparams;
  684. VARIANT v, v2;
  685. HRESULT hr;
  686. v.vt = VT_EMPTY;
  687. v.lVal = 0;
  688. v2.vt = VT_EMPTY;
  689. v2.lVal = 0;
  690. // get a pointer to the source of ambient properties.
  691. //
  692. if (!m_pDispAmbient) {
  693. if (m_pClientSite)
  694. m_pClientSite->QueryInterface(IID_IDispatch, (void **)&m_pDispAmbient);
  695. if (!m_pDispAmbient)
  696. return FALSE;
  697. }
  698. // now go and get the property into a variant.
  699. //
  700. memset(&dispparams, 0, sizeof(DISPPARAMS));
  701. hr = m_pDispAmbient->Invoke(dispid, IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams,
  702. &v, NULL, NULL);
  703. if (FAILED(hr)) return FALSE;
  704. // we've got the variant, so now go an coerce it to the type that the user
  705. // wants. if the types are the same, then this will copy the stuff to
  706. // do appropriate ref counting ...
  707. //
  708. hr = VariantChangeType(&v2, &v, 0, vt);
  709. if (FAILED(hr)) {
  710. VariantClear(&v);
  711. return FALSE;
  712. }
  713. // copy the data to where the user wants it
  714. //
  715. CopyMemory(pData, &(v2.lVal), g_rgcbDataTypeSize[vt]);
  716. VariantClear(&v);
  717. return TRUE;
  718. }
  719. //=--------------------------------------------------------------------------=
  720. // COleControl::GetAmbientFont [callable]
  721. //=--------------------------------------------------------------------------=
  722. // gets the current font for the user.
  723. //
  724. // Parameters:
  725. // IFont ** - [out] where to put the font.
  726. //
  727. // Output:
  728. // BOOL - FALSE means couldn't get it.
  729. //
  730. // Notes:
  731. //
  732. BOOL COleControl::GetAmbientFont
  733. (
  734. IFont **ppFont
  735. )
  736. {
  737. IDispatch *pFontDisp;
  738. // we don't have to do much here except get the ambient property and QI
  739. // it for the user.
  740. //
  741. *ppFont = NULL;
  742. if (!GetAmbientProperty(DISPID_AMBIENT_FONT, VT_DISPATCH, &pFontDisp))
  743. return FALSE;
  744. pFontDisp->QueryInterface(IID_IFont, (void **)ppFont);
  745. pFontDisp->Release();
  746. return (*ppFont) ? TRUE : FALSE;
  747. }
  748. //=--------------------------------------------------------------------------=
  749. // COleControl::DesignMode
  750. //=--------------------------------------------------------------------------=
  751. // returns TRUE if we're in Design mode.
  752. //
  753. // Output:
  754. // BOOL - true is design mode, false is run mode
  755. //
  756. // Notes:
  757. //
  758. BOOL COleControl::DesignMode
  759. (
  760. void
  761. )
  762. {
  763. VARIANT_BOOL f;
  764. // if we don't already know our run mode, go and get it. we'll assume
  765. // it's true unless told otherwise
  766. //
  767. if (!m_fModeFlagValid) {
  768. f = TRUE;
  769. if (!GetAmbientProperty(DISPID_AMBIENT_USERMODE, VT_BOOL, &f))
  770. return FALSE;
  771. m_fModeFlagValid = TRUE;
  772. m_fRunMode = f;
  773. }
  774. return !m_fRunMode;
  775. }
  776. //=--------------------------------------------------------------------------=
  777. // COleControl::AfterCreateWindow [overridable]
  778. //=--------------------------------------------------------------------------=
  779. // something the user can pay attention to
  780. //
  781. // Output:
  782. // BOOL - false means fatal error, can't continue
  783. // Notes:
  784. //
  785. BOOL COleControl::AfterCreateWindow
  786. (
  787. void
  788. )
  789. {
  790. return TRUE;
  791. }
  792. //=--------------------------------------------------------------------------=
  793. // COleControl::BeforeCreateWindow [overridable]
  794. //=--------------------------------------------------------------------------=
  795. // called just before we create a window. the user should register their
  796. // window class here, and set up any other things, such as the title of
  797. // the window, and/or sytle bits, etc ...
  798. //
  799. // Parameters:
  800. // DWORD * - [out] dwWindowFlags
  801. // DWORD * - [out] dwExWindowFlags
  802. // LPSTR - [out] name of window to create
  803. //
  804. // Output:
  805. // BOOL - false means fatal error, can't continue
  806. //
  807. // Notes:
  808. //
  809. BOOL COleControl::BeforeCreateWindow
  810. (
  811. DWORD *pdwWindowStyle,
  812. DWORD *pdwExWindowStyle,
  813. LPSTR pszWindowTitle
  814. )
  815. {
  816. return TRUE;
  817. }
  818. //=--------------------------------------------------------------------------=
  819. // COleControl::InvalidateControl [callable]
  820. //=--------------------------------------------------------------------------=
  821. void COleControl::InvalidateControl
  822. (
  823. LPCRECT lpRect
  824. )
  825. {
  826. if (m_fInPlaceActive)
  827. OcxInvalidateRect(lpRect, TRUE);
  828. else
  829. ViewChanged();
  830. // CONSIDER: one might want to call pOleAdviseHolder->OnDataChanged() here
  831. // if there was support for IDataObject
  832. }
  833. //=--------------------------------------------------------------------------=
  834. // COleControl::SetControlSize [callable]
  835. //=--------------------------------------------------------------------------=
  836. // sets the control size. they'll give us the size in pixels. we've got to
  837. // convert them back to HIMETRIC before passing them on!
  838. //
  839. // Parameters:
  840. // SIZEL * - [in] new size
  841. //
  842. // Output:
  843. // BOOL
  844. //
  845. // Notes:
  846. //
  847. BOOL COleControl::SetControlSize
  848. (
  849. SIZEL *pSize
  850. )
  851. {
  852. HRESULT hr;
  853. SIZEL slHiMetric;
  854. PixelToHiMetric(pSize, &slHiMetric);
  855. hr = SetExtent(DVASPECT_CONTENT, &slHiMetric);
  856. return (FAILED(hr)) ? FALSE : TRUE;
  857. }
  858. //=--------------------------------------------------------------------------=
  859. // COleControl::RecreateControlWindow [callable]
  860. //=--------------------------------------------------------------------------=
  861. // called by a [subclassed, typically] control to recreate it's control
  862. // window.
  863. //
  864. // Parameters:
  865. // none
  866. //
  867. // Output:
  868. // HRESULT
  869. //
  870. // Notes:
  871. // - NOTE: USE ME EXTREMELY SPARINGLY! THIS IS AN EXTREMELY EXPENSIVE
  872. // OPERATION!
  873. //
  874. HRESULT COleControl::RecreateControlWindow
  875. (
  876. void
  877. )
  878. {
  879. HRESULT hr;
  880. HWND hwndPrev;
  881. BYTE fUIActive = m_fUIActive;
  882. // we need to correctly preserve the control's position within the
  883. // z-order here.
  884. //
  885. if (m_hwnd)
  886. hwndPrev = ::GetWindow(m_hwnd, GW_HWNDPREV);
  887. // if we're in place active, then we have to deactivate, and reactivate
  888. // ourselves with the new window ...
  889. //
  890. if (m_fInPlaceActive) {
  891. hr = InPlaceDeactivate();
  892. RETURN_ON_FAILURE(hr);
  893. hr = InPlaceActivate((fUIActive) ? OLEIVERB_UIACTIVATE : OLEIVERB_INPLACEACTIVATE);
  894. RETURN_ON_FAILURE(hr);
  895. } else if (m_hwnd) {
  896. DestroyWindow(m_hwnd);
  897. if (m_hwndReflect) {
  898. DestroyWindow(m_hwndReflect);
  899. m_hwndReflect = NULL;
  900. }
  901. CreateInPlaceWindow(0, 0, FALSE);
  902. }
  903. // restore z-order position
  904. //
  905. if (m_hwnd)
  906. SetWindowPos(m_hwnd, hwndPrev, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  907. return m_hwnd ? S_OK : E_FAIL;
  908. }
  909. // from Globals.C. don't need to mutex it here since we only read it.
  910. //
  911. extern HINSTANCE g_hInstResources;
  912. //=--------------------------------------------------------------------------=
  913. // COleControl::GetResourceHandle [callable]
  914. //=--------------------------------------------------------------------------=
  915. // gets the HINSTANCE of the DLL where the control should get resources
  916. // from. implemented in such a way to support satellite DLLs.
  917. //
  918. // Output:
  919. // HINSTANCE
  920. //
  921. // Notes:
  922. //
  923. HINSTANCE COleControl::GetResourceHandle
  924. (
  925. void
  926. )
  927. {
  928. if (!g_fSatelliteLocalization)
  929. return g_hInstance;
  930. // if we've already got it, then there's not all that much to do.
  931. // don't need to crit sect this one right here since even if they do fall
  932. // into the ::GetResourceHandle call, it'll properly deal with things.
  933. //
  934. if (g_hInstResources)
  935. return g_hInstResources;
  936. // we'll get the ambient localeid from the host, and pass that on to the
  937. // automation object.
  938. //
  939. // crit sect this for apartment threading support.
  940. //
  941. ENTERCRITICALSECTION1(&g_CriticalSection);
  942. if (!g_fHaveLocale)
  943. // if we can't get the ambient locale id, then we'll just continue
  944. // with the globally set up value.
  945. //
  946. if (!GetAmbientProperty(DISPID_AMBIENT_LOCALEID, VT_I4, &g_lcidLocale))
  947. goto Done;
  948. g_fHaveLocale = TRUE;
  949. Done:
  950. LEAVECRITICALSECTION1(&g_CriticalSection);
  951. return ::GetResourceHandle();
  952. }
  953. //=--------------------------------------------------------------------------=
  954. // COleControl::GetControl [IControlPrv]
  955. //=--------------------------------------------------------------------------=
  956. // Returns a pointer to the COleControl class
  957. //
  958. HRESULT COleControl::GetControl(COleControl **ppOleControl)
  959. {
  960. CHECK_POINTER(ppOleControl);
  961. *ppOleControl = this;
  962. (*ppOleControl)->AddRef();
  963. return S_OK;
  964. }