soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SAxContainer.h
Go to the documentation of this file.
1/**
2 * @file SAxContainer.h
3 * @brief Header file for ActiveX container implementation.
4 *
5 * This file contains the definitions for the ActiveX container classes
6 * used to host and manage ActiveX controls within the SOUI framework.
7 */
8#ifndef ATLACTIVEXCONTAINER_HPP
9#define ATLACTIVEXCONTAINER_HPP
10
11 #include "SAxUtil.h"
12 #include <atl.mini/SComCli.h>
13 #include <MsHtmHst.h>
14
15 SNSBEGIN
16
17 /**
18 * @struct IAxHostDelegate
19 * @brief Delegate interface for ActiveX host operations.
20 *
21 * This interface defines methods that the ActiveX host must implement
22 * to provide necessary functionality for the ActiveX control.
23 */
25 {
26 /**
27 * @brief Get the window handle of the ActiveX host.
28 * @return Window handle of the ActiveX host.
29 */
30 virtual HWND GetAxHostWindow() const = 0;
31
32 /**
33 * @brief Notify the host that the ActiveX control is being activated.
34 * @param pCtrl Pointer to the ActiveX control.
35 */
36 virtual void OnAxActivate(IUnknown* pCtrl) = 0;
37
38 /**
39 * @brief Notify the host that the ActiveX control needs to be invalidated.
40 * @param pRect Rectangle to be invalidated.
41 * @param bErase Boolean indicating if the background should be erased.
42 */
43 virtual void OnAxInvalidate(LPCRECT pRect, BOOL bErase) = 0;
44
45 /**
46 * @brief Notify the host to set or release the mouse capture.
47 * @param fCapture Boolean indicating if the capture should be set.
48 */
49 virtual void OnAxSetCapture(BOOL fCapture) = 0;
50
51 /**
52 * @brief Get a device context for the ActiveX control.
53 * @param pRect Rectangle for which the DC is needed.
54 * @param grfFlags Flags specifying the type of DC.
55 * @param phDC Pointer to receive the device context.
56 * @return HRESULT indicating success or failure.
57 */
58 virtual HRESULT OnAxGetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC) = 0;
59
60 /**
61 * @brief Release a previously obtained device context.
62 * @param hdc Device context to be released.
63 * @return HRESULT indicating success or failure.
64 */
65 virtual HRESULT OnAxReleaseDC(HDC hdc) = 0;
66 };
67
68 /**
69 * @class ActiveXSite
70 * @brief Template class for managing an ActiveX control site.
71 *
72 * This class implements the necessary interfaces to host and manage an ActiveX
73 * control within a container. It handles the lifecycle of the control and
74 * provides the required interface implementations.
75 *
76 * @tparam T The derived class that will use this template.
77 */
78 template<class T>
79 class ActiveXSite : public IOleClientSite,
80 public IOleControlSite,
81 public IOleInPlaceSiteWindowless,
82 public IAdviseSink
83 {
84 friend T;
85
86 public:
87 /**
88 * @brief Constructor for ActiveXSite.
89 */
91 : m_pAxHostDelegate(NULL)
92 , m_bVisible(true)
93 , m_bInplaceActive(false)
94 , m_dwMiscStatus(0)
95 , m_dwOleObjSink(0)
96 , m_dwViewObjectType(0)
97 , m_grfFlags(0)
98 , m_bCaptured(FALSE)
99 , m_bFocused(FALSE)
100 {
101 memset(&m_rcPos, 0, sizeof(m_rcPos));
102 }
103
104 /**
105 * @brief Destructor for ActiveXSite.
106 */
107 virtual ~ActiveXSite()
108 {
109 Clear();
110 }
111
112 /**
113 * @brief Set the delegate for ActiveX host operations.
114 * @param pAxHost Pointer to the delegate.
115 */
117 {
118 m_pAxHostDelegate = pAxHost;
119 }
120
121 /**
122 * @brief Set the external UI handler for the ActiveX control.
123 * @param pUiHandler Pointer to the UI handler.
124 */
125 void SetExternalUIHandler(IDocHostUIHandler* pUiHandler)
126 {
127 m_spDocHostUIHandler = pUiHandler;
128 }
129
130 /**
131 * @brief Get the ActiveX control.
132 * @return Pointer to the ActiveX control.
133 */
135 {
136 return m_spControl;
137 }
138
139 /**
140 * @brief Initialize the ActiveX control.
141 * @param pControl Pointer to the ActiveX control.
142 */
143 void Init(IUnknown* pControl)
144 {
145 m_spControl = pControl;
146 m_spOleObject = pControl;
147 m_spInPlaceObject = pControl;
148 }
149
150 /**
151 * @brief Clear the ActiveX control and release resources.
152 */
153 void Clear()
154 {
155 if (m_spControl != NULL)
156 {
157 if (m_spViewObject != NULL)
158 {
159 m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL);
160 m_spViewObject.Release();
161 }
162 m_spOleObjectWindowless.Release();
163 if (m_spInPlaceObject != NULL)
164 {
165 if (m_bInplaceActive)
166 {
167 m_spInPlaceObject->InPlaceDeactivate();
168 m_bInplaceActive = false;
169 }
170 m_spInPlaceObject.Release();
171 }
172 if (m_spOleObject != NULL)
173 {
174 m_spOleObject->Unadvise(m_dwOleObjSink);
175 m_spOleObject->SetClientSite(NULL);
176 m_spOleObject->Close(OLECLOSE_NOSAVE);
177 m_spOleObject.Release();
178 }
179 m_spControl = NULL;
180 }
181 }
182
183 /**
184 * @brief Initialize the ActiveX control from a stream.
185 * @param pStream Pointer to the stream containing the control data.
186 * @return HRESULT indicating success or failure.
187 */
188 HRESULT InitControl(IStream* pStream = NULL)
189 {
190 if (m_spControl == 0) return E_NOINTERFACE;
191 HRESULT hr = E_POINTER;
192 SComQIPtr<IPersistStreamInit> spPSI(m_spControl);
193 if (spPSI != NULL)
194 {
195 if (pStream != NULL)
196 hr = spPSI->Load(pStream);
197 else
198 hr = spPSI->InitNew();
199 }
200 else if (pStream)
201 {
202 SComQIPtr<IPersistStream> spPS(m_spOleObject);
203 if (spPS)
204 hr = spPS->Load(pStream);
205 }
206 return hr;
207 }
208
209 /**
210 * @brief Activate the ActiveX control.
211 * @param pStream Pointer to the stream containing the control data.
212 * @return HRESULT indicating success or failure.
213 */
214 HRESULT ActivateAx(IStream* pStream = NULL)
215 {
216 if (m_spOleObject == 0) return E_UNEXPECTED;
217 HRESULT hr;
218
219 // this must be set even before calling IPersistStreamInit::InitNew
220 hr = m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);
221 if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) {
222 hr = m_spOleObject->SetClientSite(static_cast<IOleClientSite*>(this));
223 if (FAILED(hr)) return hr;
224 }
225
226 hr = InitControl(pStream);
227 if (FAILED(hr))
228 {
229 if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
230 m_spOleObject->SetClientSite(NULL);
231 return hr;
232 }
233
234 if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) {
235 hr = m_spOleObject->SetClientSite(static_cast<IOleClientSite*>(this));
236 if (FAILED(hr)) return hr;
237 }
238
239 hr = DoInplaceActivate();
240 return hr;
241 }
242
243 /**
244 * @brief Check if a point is within the ActiveX control.
245 * @param pt Point to check.
246 * @return Boolean indicating if the point is within the control.
247 */
248 bool HitTest(const POINT& pt) const
249 {
250 if (m_spViewObject != NULL && m_dwViewObjectType == 7) {
251 DWORD dwHitResult = HITRESULT_OUTSIDE;
252 m_spViewObject->QueryHitPoint(DVASPECT_CONTENT, &m_rcPos, pt, 0, &dwHitResult);
253 return (dwHitResult == HITRESULT_HIT);
254 }
255 // else
256 return (::PtInRect(&m_rcPos, pt) != FALSE);
257 }
258
259 /**
260 * @brief Check if the control intersects with a clipping region.
261 * @param rcClip Clipping region to check.
262 * @return Boolean indicating if the control intersects with the region.
263 */
264 bool InsideClippingRegion(const RECT& rcClip) const
265 {
266 // true when top/let or bottom/right corners intersect into client area
267 const POINT* pts = (const POINT*)(&m_rcPos);
268 const POINT* ptc = (const POINT*)(&rcClip);
269 return (::PtInRect(&rcClip, pts[0]) || ::PtInRect(&rcClip, pts[1]) ||
270 ::PtInRect(&m_rcPos, ptc[0]) || ::PtInRect(&m_rcPos, ptc[1]));
271 }
272
273 /**
274 * @brief Perform a verb on the ActiveX control.
275 * @param verb Verb to perform.
276 * @return HRESULT indicating success or failure.
277 */
278 HRESULT DoVerb(long verb)
279 {
280 HRESULT hr = E_FAIL;
281 if ((m_dwMiscStatus & (OLEMISC_INVISIBLEATRUNTIME | OLEMISC_NOUIACTIVATE)) != 0)
282 {
283 hr = S_FALSE;
284 }
285 else if (m_spOleObject != NULL)
286 {
287 hr = m_spOleObject->DoVerb(verb, NULL, static_cast<IOleClientSite*>(this), 0, m_pAxHostDelegate->GetAxHostWindow(), &m_rcPos);
288 if (verb == OLEIVERB_INPLACEACTIVATE && SUCCEEDED(hr))
289 {
290 m_bInplaceActive = true;
291 }
292 else {
293 hr = E_UNEXPECTED;
294 }
295 }
296 return hr;
297 }
298
299 /**
300 * @brief Draw the ActiveX control.
301 * @param hDC Device context to draw on.
302 * @param lpClipRect Clipping rectangle.
303 * @return LRESULT indicating success or failure.
304 */
305 LRESULT Draw(HDC hDC, LPCRECT lpClipRect)
306 {
307 LRESULT lResult = S_FALSE;
308 if (lpClipRect && !InsideClippingRegion(*lpClipRect)) {
309 return lResult;
310 }
311 if (m_bVisible && m_spViewObject != NULL) {
312 RECTL rcPos = { m_rcPos.left,m_rcPos.top,m_rcPos.right,m_rcPos.bottom };
313 lResult = m_spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hDC,
314 &rcPos, NULL, NULL, 0);
315 }
316 return lResult;
317 }
318
319 /**
320 * @brief Fire an ambient property change notification.
321 * @param dispChanged DISPID of the changed property.
322 * @return HRESULT indicating success or failure.
323 */
324 HRESULT FireAmbientPropertyChange(DISPID dispChanged)
325 {
326 HRESULT hr = S_OK;
327 SComQIPtr<IOleControl, &__uuidof(IOleControl)> spOleControl(m_spControl);
328 if (spOleControl != NULL)
329 hr = spOleControl->OnAmbientPropertyChange(dispChanged);
330 return hr;
331 }
332
333 /**
334 * @brief Handle a window message for the ActiveX control.
335 * @param uMsg Message identifier.
336 * @param wParam WPARAM for the message.
337 * @param lParam LPARAM for the message.
338 * @return LRESULT indicating success or failure.
339 */
340 LRESULT OnWindowMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
341 {
342 LRESULT lResult = 0;
343 if (m_bInplaceActive && m_spOleObjectWindowless != NULL)
344 {
345 m_spOleObjectWindowless->OnWindowMessage(uMsg, wParam, lParam, &lResult);
346 }
347 return lResult;
348 }
349
350 /**
351 * @brief Query for an interface.
352 * @param iid IID of the interface to query.
353 * @param object Pointer to receive the interface.
354 * @return HRESULT indicating success or failure.
355 */
356 STDMETHOD(QueryInterface2)(REFIID iid, void** object)
357 {
358 HRESULT hr = S_OK;
359 *object = NULL;
360 if (iid == IID_IOleClientSite) {
361 *object = static_cast<IOleClientSite*>(this);
362 }
363 else if (iid == IID_IOleControlSite) {
364 *object = static_cast<IOleControlSite*>(this);
365 }
366 else if (iid == IID_IOleInPlaceSite) {
367 *object = static_cast<IOleInPlaceSite*>(this);
368 }
369 else if (iid == IID_IOleInPlaceSiteEx) {
370 *object = static_cast<IOleInPlaceSiteEx*>(this);
371 }
372 else if (iid == IID_IOleInPlaceSiteWindowless) {
373 *object = static_cast<IOleInPlaceSiteWindowless*>(this);
374 }
375 else if (iid == IID_IAdviseSink) {
376 *object = static_cast<IAdviseSink*>(this);
377 }
378 else if (iid == IID_IDocHostUIHandler && m_spDocHostUIHandler) {
379 *object = m_spDocHostUIHandler;
380 }
381 else {
382 hr = E_NOINTERFACE;
383 }
384 return hr;
385 }
386
387 /**
388 * @brief Save the object.
389 * @return HRESULT indicating success or failure.
390 */
391 STDMETHOD(SaveObject)(void)
392 {
393 ATLTRACENOTIMPL(_T("ActiveXSite::SaveObject\n"));
394 }
395
396 /**
397 * @brief Get the moniker for the object.
398 * @param dwAssign Assignment type.
399 * @param dwWhichMoniker Type of moniker.
400 * @param ppmk Pointer to receive the moniker.
401 * @return HRESULT indicating success or failure.
402 */
403 STDMETHOD(GetMoniker)(DWORD /*dwAssign*/, DWORD dwWhichMoniker, IMoniker** ppmk)
404 {
405 return E_NOTIMPL;
406 }
407
408 /**
409 * @brief Get the container for the object.
410 * @param ppContainer Pointer to receive the container.
411 * @return HRESULT indicating success or failure.
412 */
413 STDMETHOD(GetContainer)(IOleContainer** ppContainer)
414 {
415 HRESULT hr = E_POINTER;
416 if (ppContainer != NULL) {
417 hr = static_cast<T*>(this)->QueryInterface(__uuidof(IOleContainer), reinterpret_cast<void**>(ppContainer));
418 }
419 return hr;
420 }
421
422 /**
423 * @brief Show the object.
424 * @return HRESULT indicating success or failure.
425 */
426 STDMETHOD(ShowObject)(void)
427 {
428 HWND hWnd = m_pAxHostDelegate->GetAxHostWindow();
429 HRESULT hr = E_FAIL;
430 if (::IsWindow(hWnd) && ::IsRectEmpty(&m_rcPos) == FALSE)
431 {
432 m_bVisible = true;
433 if (m_bInplaceActive)
434 {
435 m_pAxHostDelegate->OnAxInvalidate(&m_rcPos, TRUE);
436 hr = S_OK;
437 }
438 }
439 return hr;
440 }
441
442 /**
443 * @brief Notify the container of a show window event.
444 * @param fShow Boolean indicating if the window is being shown.
445 * @return HRESULT indicating success or failure.
446 */
447 STDMETHOD(OnShowWindow)(BOOL fShow)
448 {
449 m_bVisible = (fShow != FALSE);
450 return S_OK;
451 }
452
453 /**
454 * @brief Request a new object layout.
455 * @return HRESULT indicating success or failure.
456 */
457 STDMETHOD(RequestNewObjectLayout)(void)
458 {
459 ATLTRACENOTIMPL(_T("ActiveXSite::RequestNewObjectLayout\n"));
460 }
461
462 /**
463 * @brief Notify the control that its info has changed.
464 * @return HRESULT indicating success or failure.
465 */
466 STDMETHOD(OnControlInfoChanged)(void)
467 {
468 return S_OK;
469 }
470
471 /**
472 * @brief Lock the control in place active state.
473 * @param fLock Boolean indicating if the lock should be set.
474 * @return HRESULT indicating success or failure.
475 */
476 STDMETHOD(LockInPlaceActive)(BOOL /*fLock*/)
477 {
478 ATLTRACENOTIMPL(_T("ActiveXSite::LockInPlaceActive\n"));
479 }
480
481 /**
482 * @brief Get the extended control.
483 * @param ppDisp Pointer to receive the extended control.
484 * @return HRESULT indicating success or failure.
485 */
486 STDMETHOD(GetExtendedControl)(IDispatch**)
487 {
488 ATLTRACENOTIMPL(_T("ActiveXSite::GetExtendedControl\n"));
489 }
490
491 /**
492 * @brief Transform coordinates between container and control.
493 * @param pPtlHimetric Source coordinates in HIMETRIC.
494 * @param pPtfContainer Destination coordinates in container.
495 * @param dwFlags Flags specifying the transformation.
496 * @return HRESULT indicating success or failure.
497 */
498 STDMETHOD(TransformCoords)(POINTL* /*pPtlHimetric*/, POINTF* /*pPtfContainer*/, DWORD /*dwFlags*/)
499 {
500 ATLTRACENOTIMPL(_T("ActiveXSite::TransformCoords\n"));
501 }
502
503 /**
504 * @brief Translate an accelerator key.
505 * @param pMsg Message structure.
506 * @param grfModifiers Modifiers for the key.
507 * @return HRESULT indicating success or failure.
508 */
509 STDMETHOD(TranslateAccelerator)(MSG* /*pMsg*/, DWORD /*grfModifiers*/)
510 {
511 ATLTRACENOTIMPL(_T("ActiveXSite::TranslateAccelerator\n"));
512 }
513
514 /**
515 * @brief Notify the control of focus change.
516 * @param fGotFocus Boolean indicating if the control got focus.
517 * @return HRESULT indicating success or failure.
518 */
519 STDMETHOD(OnFocus)(BOOL fGotFocus)
520 {
521 // ignore this, controls should use SetFocus(flag) instead
522 return S_OK;
523 }
524
525 /**
526 * @brief Show the property frame for the control.
527 * @return HRESULT indicating success or failure.
528 */
529 STDMETHOD(ShowPropertyFrame)(void)
530 {
531 ATLTRACENOTIMPL(_T("ActiveXSite::ShowPropertyFrame\n"));
532 }
533 /**
534 * @brief Check if the control supports windowless activation.
535 * @return S_OK if windowless activation is supported, otherwise an error code.
536 */
537 STDMETHOD(CanWindowlessActivate)(void)
538 {
539 // support Windowless activation
540 return S_OK;
541 }
542
543 /**
544 * @brief Check if the control currently has the mouse capture.
545 * @return S_OK if the control has the capture, S_FALSE otherwise.
546 */
547 STDMETHOD(GetCapture)(void)
548 {
549 HRESULT hr = m_bCaptured ? S_OK : S_FALSE;
550 return hr;
551 }
552
553 /**
554 * @brief Set or release the mouse capture for the control.
555 * @param fCapture Boolean indicating if the capture should be set.
556 * @return S_OK if the operation is successful.
557 */
558 STDMETHOD(SetCapture)(BOOL fCapture)
559 {
560 if (fCapture != m_bCaptured)
561 {
562 m_bCaptured = fCapture;
563 m_pAxHostDelegate->OnAxSetCapture(fCapture);
564 }
565 return S_OK;
566 }
567
568 /**
569 * @brief Check if the control currently has focus.
570 * @return S_OK if the control has focus, S_FALSE otherwise.
571 */
572 STDMETHOD(GetFocus)(void)
573 {
574 return m_bFocused ? S_OK : S_FALSE;
575 }
576
577 /**
578 * @brief Set or release focus for the control.
579 * @param fFocus Boolean indicating if the focus should be set.
580 * @return S_OK if the operation is successful.
581 */
582 STDMETHOD(SetFocus)(BOOL fFocus)
583 {
584 if (m_bFocused != fFocus)
585 {
586 m_bFocused = fFocus;
587 InvalidateRect(NULL, true);
588 }
589
590 return S_OK;
591 }
592
593 /**
594 * @brief Get a device context for the control.
595 * @param pRect Rectangle for which the DC is needed.
596 * @param grfFlags Flags specifying the type of DC.
597 * @param phDC Pointer to receive the device context.
598 * @return HRESULT indicating success or failure.
599 */
600 STDMETHOD(GetDC)(LPCRECT pRect, DWORD grfFlags, HDC* phDC)
601 {
602 return m_pAxHostDelegate->OnAxGetDC(pRect, grfFlags, phDC);
603 }
604
605 /**
606 * @brief Release a previously obtained device context.
607 * @param hDC Device context to be released.
608 * @return HRESULT indicating success or failure.
609 */
610 STDMETHOD(ReleaseDC)(HDC hDC)
611 {
612 return m_pAxHostDelegate->OnAxReleaseDC(hDC);
613 }
614
615 /**
616 * @brief Invalidate a rectangle of the control.
617 * @param pRect Rectangle to be invalidated.
618 * @param fErase Boolean indicating if the background should be erased.
619 * @return S_OK if the operation is successful.
620 */
621 STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase)
622 {
623 // Blindly honor the specified region
624 // well behaving control should pass a valid intersect rect or NULL
625 if (pRect == NULL) pRect = &m_rcPos;
626 m_pAxHostDelegate->OnAxInvalidate(pRect, fErase);
627 return S_OK;
628 }
629
630 /**
631 * @brief Invalidate a region of the control.
632 * @param hRGN Region to be invalidated.
633 * @param fErase Boolean indicating if the background should be erased.
634 * @return S_OK if the operation is successful.
635 */
636 STDMETHOD(InvalidateRgn)(HRGN /*hRGN*/, BOOL fErase)
637 {
638 return InvalidateRect(NULL, fErase);
639 }
640
641 /**
642 * @brief Scroll a rectangle of the control.
643 * @param dx Horizontal scroll amount.
644 * @param dy Vertical scroll amount.
645 * @param pRectScroll Rectangle to be scrolled.
646 * @param pRectClip Clipping rectangle.
647 * @return HRESULT indicating success or failure.
648 */
649 STDMETHOD(ScrollRect)(INT /*dx*/, INT /*dy*/, LPCRECT /*pRectScroll*/, LPCRECT /*pRectClip*/)
650 {
651 ATLTRACENOTIMPL(_T("ActiveXSite::ScrollRect\n"));
652 }
653
654 /**
655 * @brief Adjust a rectangle for the control.
656 * @param prc Rectangle to be adjusted.
657 * @return HRESULT indicating success or failure.
658 */
659 STDMETHOD(AdjustRect)(LPRECT /*prc*/)
660 {
661 ATLTRACENOTIMPL(_T("ActiveXSite::AdjustRect\n"));
662 }
663
664 /**
665 * @brief Handle a default window message for the control.
666 * @param msg Message identifier.
667 * @param wParam WPARAM for the message.
668 * @param lParam LPARAM for the message.
669 * @param plResult Pointer to receive the result of the message processing.
670 * @return S_OK if the message is processed successfully.
671 */
672 STDMETHOD(OnDefWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
673 {
674 *plResult = DefWindowProc(m_pAxHostDelegate->GetAxHostWindow(), msg, wParam, lParam);
675 return S_OK;
676 }
677
678 // IOleInPlaceSiteEx
679 /**
680 * @brief Activate the control in-place with extended options.
681 * @param pfNoRedraw Pointer to a boolean indicating if redrawing should be suppressed.
682 * @param dwFlags Flags specifying activation options.
683 * @return S_OK if the control is activated successfully, otherwise an error code.
684 */
685 STDMETHOD(OnInPlaceActivateEx)(BOOL* pfNoRedraw, DWORD dwFlags)
686 {
687 HRESULT hr = S_FALSE;
688 OleLockRunning(m_spOleObject, TRUE, FALSE);
689 if (pfNoRedraw) {
690 *pfNoRedraw = FALSE;
691 }
692
693 if ((dwFlags & ACTIVATE_WINDOWLESS) != 0) {
694 m_spOleObjectWindowless = m_spControl;
695
696 if (m_spOleObjectWindowless != NULL) {
697 m_bInplaceActive = true;
698 hr = S_OK;
699 }
700 }
701 else {
702 // object is not windowless, ensure we won't dispatch message to this control
703 m_bInplaceActive = false;
704 }
705 return hr;
706 }
707
708 /**
709 * @brief Deactivate the control in-place with extended options.
710 * @param fNoRedraw Boolean indicating if redrawing should be suppressed.
711 * @return S_OK if the control is deactivated successfully.
712 */
713 STDMETHOD(OnInPlaceDeactivateEx)(BOOL /*fNoRedraw*/)
714 {
715 m_bInplaceActive = false;
716 return S_OK;
717 }
718
719 /**
720 * @brief Request UI activation for the control.
721 * @return S_OK if the request is successful.
722 */
723 STDMETHOD(RequestUIActivate)(void)
724 {
725 return S_OK;
726 }
727
728 // IOleInPlaceSite
729 /**
730 * @brief Check if the control can be activated in-place.
731 * @return S_OK if in-place activation is possible, otherwise an error code.
732 */
733 STDMETHOD(CanInPlaceActivate)(void)
734 {
735 return S_OK;
736 }
737
738 /**
739 * @brief Activate the control in-place.
740 * @return S_OK if the control is activated successfully, otherwise an error code.
741 */
742 STDMETHOD(OnInPlaceActivate)(void)
743 {
744 return S_OK;
745 }
746
747 /**
748 * @brief Activate the control's user interface.
749 * @return S_OK if the UI is activated successfully, otherwise an error code.
750 */
751 STDMETHOD(OnUIActivate)(void)
752 {
753 return S_OK;
754 }
755
756 /**
757 * @brief Get the window context for the control.
758 * @param ppFrame Pointer to receive the in-place frame.
759 * @param ppDoc Pointer to receive the in-place document.
760 * @param lprcPosRect Pointer to receive the position rectangle.
761 * @param lprcClipRect Pointer to receive the clipping rectangle.
762 * @param lpFrameInfo Pointer to receive the frame information.
763 * @return S_OK if the window context is retrieved successfully.
764 */
765 STDMETHOD(GetWindowContext)(IOleInPlaceFrame** ppFrame,
766 IOleInPlaceUIWindow** ppDoc,
767 LPRECT lprcPosRect,
768 LPRECT lprcClipRect,
769 LPOLEINPLACEFRAMEINFO lpFrameInfo)
770 {
771 if (ppFrame) {
772 *ppFrame = NULL;
773 }
774 if (ppDoc) {
775 *ppDoc = NULL;
776 }
777 if (lprcPosRect) {
778 memcpy(lprcPosRect, &m_rcPos, sizeof(m_rcPos));
779 }
780 if (lprcClipRect) {
781 memcpy(lprcClipRect, &m_rcPos, sizeof(m_rcPos));
782 }
783 if (lpFrameInfo) {
784 lpFrameInfo->fMDIApp = FALSE;
785 lpFrameInfo->hwndFrame = m_pAxHostDelegate->GetAxHostWindow();
786 lpFrameInfo->haccel = NULL;
787 lpFrameInfo->cAccelEntries = 0;
788 }
789 return S_OK;
790 }
791
792 /**
793 * @brief Scroll the control.
794 * @param scrollExtant Size of the scroll.
795 * @return HRESULT indicating success or failure.
796 */
797 STDMETHOD(Scroll)(SIZE /*scrollExtant*/)
798 {
799 ATLTRACENOTIMPL(_T("ActiveXSite::Scroll\n"));
800 }
801
802 /**
803 * @brief Deactivate the control's user interface.
804 * @param fUndoable Boolean indicating if the deactivation can be undone.
805 * @return S_OK if the UI is deactivated successfully.
806 */
807 STDMETHOD(OnUIDeactivate)(BOOL /*fUndoable*/)
808 {
809 return S_OK;
810 }
811
812 /**
813 * @brief Deactivate the control in-place.
814 * @return S_OK if the control is deactivated successfully.
815 */
816 STDMETHOD(OnInPlaceDeactivate)(void)
817 {
818 return OnInPlaceDeactivateEx(TRUE);
819 }
820
821 /**
822 * @brief Discard the undo state of the control.
823 * @return HRESULT indicating success or failure.
824 */
825 STDMETHOD(DiscardUndoState)(void)
826 {
827 ATLTRACENOTIMPL(_T("ActiveXSite::DiscardUndoState"));
828 }
829
830 /**
831 * @brief Deactivate and undo the control.
832 * @return HRESULT indicating success or failure.
833 */
834 STDMETHOD(DeactivateAndUndo)(void)
835 {
836 ATLTRACENOTIMPL(_T("ActiveXSite::DeactivateAndUndo"));
837 }
838
839 /**
840 * @brief Handle a change in the position rectangle of the control.
841 * @param lprcPosRect New position rectangle.
842 * @return S_OK if the position rectangle is updated successfully.
843 */
844 STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect)
845 {
846 HRESULT hr = E_UNEXPECTED;
847 hr = S_OK;
848 if (lprcPosRect && memcmp(&m_rcPos, lprcPosRect, sizeof(m_rcPos)) != 0)
849 {
850 if (m_spInPlaceObject)
851 {
852 memcpy(&m_rcPos, lprcPosRect, sizeof(m_rcPos));
853 hr = m_spInPlaceObject->SetObjectRects(&m_rcPos, &m_rcPos);
854 }
855 if (SUCCEEDED(hr))
856 {
857 hr = SetExtent(m_rcPos.right - m_rcPos.left, m_rcPos.bottom - m_rcPos.top);
858 }
859 }
860 return hr;
861 }
862
863 // IOleWindow
864 /**
865 * @brief Get the window handle for the control.
866 * @param phwnd Pointer to receive the window handle.
867 * @return S_OK if the window handle is retrieved successfully.
868 */
869 STDMETHOD(GetWindow)(HWND* phwnd)
870 {
871 *phwnd = m_pAxHostDelegate->GetAxHostWindow();
872 return S_OK;
873 }
874
875 /**
876 * @brief Handle context-sensitive help for the control.
877 * @param fEnterMode Boolean indicating if help should be entered.
878 * @return HRESULT indicating success or failure.
879 */
880 STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/)
881 {
882 ATLTRACENOTIMPL(_T("ActiveXSite::ContextSensitiveHelp\n"));
883 }
884
885 // IAdviseSink
886 /**
887 * @brief Handle a change in data.
888 * @param pFormatetc Format of the data.
889 * @param pStgmed Storage medium containing the data.
890 */
891 STDMETHOD_(void, OnDataChange)(FORMATETC* /*pFormatetc*/, STGMEDIUM* /*pStgmed*/)
892 {
893 }
894
895 /**
896 * @brief Handle a change in view.
897 * @param dwAspect Aspect of the view.
898 * @param lindex Index of the view.
899 */
900 STDMETHOD_(void, OnViewChange)(DWORD /*dwAspect*/, LONG /*lindex*/)
901 {
902 }
903
904 /**
905 * @brief Handle a rename of the object.
906 * @param pmk Moniker of the object.
907 */
908 STDMETHOD_(void, OnRename)(IMoniker* /*pmk*/)
909 {
910 }
911
912 /**
913 * @brief Handle a save operation.
914 */
915 STDMETHOD_(void, OnSave)(void)
916 {
917 }
918
919 /**
920 * @brief Handle a close operation.
921 */
922 STDMETHOD_(void, OnClose)(void)
923 {
924 }
925
926 protected:
927 /**
928 * @brief Set the extent (size) of the control.
929 * @param width Width of the control in pixels.
930 * @param height Height of the control in pixels.
931 * @return HRESULT indicating success or failure.
932 */
933 HRESULT SetExtent(int width, int height)
934 {
935 HRESULT hr = E_UNEXPECTED;
936 if (m_spOleObject != NULL)
937 {
938 SIZEL pxsize = { width, height };
939 SIZEL hmsize = { 0 };
940 SPixelToHiMetric(&pxsize, &hmsize);
941 hr = m_spOleObject->SetExtent(DVASPECT_CONTENT, &hmsize);
942 hr = m_spOleObject->GetExtent(DVASPECT_CONTENT, &hmsize);
943 SHiMetricToPixel(&hmsize, &pxsize);
944 m_rcPos.right = m_rcPos.left + pxsize.cx;
945 m_rcPos.bottom = m_rcPos.top + pxsize.cy;
946 }
947 return hr;
948 }
949
950 /**
951 * @brief Perform in-place activation of the control.
952 * @return HRESULT indicating success or failure.
953 */
955 {
956 HRESULT hr;
957 m_pAxHostDelegate->OnAxActivate(m_spControl);
958 m_dwViewObjectType = 0;
959 hr = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), reinterpret_cast<void**>(&m_spViewObject));
960 if (FAILED(hr))
961 {
962 hr = m_spOleObject->QueryInterface(__uuidof(IViewObject2), reinterpret_cast<void**>(&m_spViewObject));
963 if (SUCCEEDED(hr))
964 m_dwViewObjectType = 3;
965 }
966 else {
967 m_dwViewObjectType = 7;
968 }
969
970 if (FAILED(hr))
971 {
972 hr = m_spOleObject->QueryInterface(__uuidof(IViewObject), reinterpret_cast<void**>(&m_spViewObject));
973 if (SUCCEEDED(hr))
974 m_dwViewObjectType = 1;
975 }
976 SComQIPtr<IAdviseSink> advise_sink(m_spControl);
977 m_spOleObject->Advise(advise_sink, &m_dwOleObjSink);
978 if (m_spViewObject)
979 hr = m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, advise_sink);
980 m_spOleObject->SetHostNames(OLESTR("SOUIAXWIN"), NULL);
981
982 // Do Inplace activate if possible
983 hr = DoVerb(OLEIVERB_INPLACEACTIVATE);
984 return hr;
985 }
986
987 private:
988 bool m_bVisible; /**< Flag indicating if the control is visible. */
989 bool m_bInplaceActive; /**< Flag indicating if the control is in-place active. */
990 BOOL m_bFocused; /**< Flag indicating if the control is focused. */
991 BOOL m_bCaptured; /**< Flag indicating if the control has captured the mouse. */
992 DWORD m_dwMiscStatus; /**< Miscellaneous status flags. */
993 DWORD m_dwViewObjectType; /**< Type of view object. */
994 DWORD m_dwOleObjSink; /**< Sink cookie for OLE object advise. */
995 DWORD m_grfFlags; /**< Flags for various purposes. */
996
997 RECT m_rcPos; /**< Rectangle position of the control. */
998 SComPtr<IUnknown> m_spControl; /**< Smart pointer to the control object. */
999 SComPtr<IViewObjectEx> m_spViewObject; /**< Smart pointer to the view object. */
1000 SComQIPtr<IOleObject> m_spOleObject; /**< Smart pointer to the OLE object. */
1001 SComQIPtr<IOleInPlaceObject> m_spInPlaceObject; /**< Smart pointer to the in-place object. */
1002 SComQIPtr<IOleInPlaceObjectWindowless> m_spOleObjectWindowless; /**< Smart pointer to the windowless in-place object. */
1003 SComPtr<IDocHostUIHandler> m_spDocHostUIHandler; /**< Smart pointer to the document host UI handler. */
1004 IAxHostDelegate* m_pAxHostDelegate; /**< Pointer to the host delegate. */
1005 };
1006
1007 /**
1008 * @brief Implementation of an ActiveX container.
1009 *
1010 * This class implements the necessary interfaces to host ActiveX controls,
1011 * including IOleContainer, IBindHost, IServiceProvider, and ActiveXSite.
1012 */
1013 class SAxContainer : public IOleContainer,
1014 public IBindHost,
1015 public IServiceProvider,
1016 public MinimumIDispatchImpl,
1017 public ActiveXSite<SAxContainer>
1018 {
1019 public:
1020 /**
1021 * @brief Constructor for SAxContainer.
1022 */
1024
1025 /**
1026 * @brief Destructor for SAxContainer.
1027 */
1028 virtual ~SAxContainer();
1029
1030 /**
1031 * @brief Create an ActiveX control.
1032 * @param guid CLSID of the control to create.
1033 * @param dwClsCtx Context in which the control is to be run.
1034 * @return TRUE if successful, FALSE otherwise.
1035 */
1036 BOOL CreateControl(REFGUID guid, DWORD dwClsCtx = CLSCTX_INPROC_SERVER);
1037
1038 ///////////////////////////////////////////////////////////////////////////
1039 // IOleContainer
1040
1041 /**
1042 * @brief Enumerate objects in the container.
1043 * @param grfFlags Flags indicating what objects to enumerate.
1044 * @param ppenum Pointer to the IEnumUnknown interface pointer.
1045 * @return HRESULT indicating success or failure.
1046 */
1047 STDMETHOD(EnumObjects)(DWORD /*grfFlags*/, IEnumUnknown** /*ppenum*/)
1048 {
1049 ATLTRACENOTIMPL(_T("ActiveXContainerImpl::EnumObjects\n"));
1050 }
1051
1052 /**
1053 * @brief Lock or unlock the container.
1054 * @param fLock TRUE to lock the container, FALSE to unlock.
1055 * @return HRESULT indicating success or failure.
1056 */
1057 STDMETHOD(LockContainer)(BOOL /*fLock*/)
1058 {
1059 ATLTRACENOTIMPL(_T("ActiveXContainerImpl::LockContainer\n"));
1060 }
1061
1062 // IOleContainer::IParseDisplayName
1063
1064 /**
1065 * @brief Parse a display name into a moniker.
1066 * @param pbc Bind context.
1067 * @param pszDisplayName Display name to parse.
1068 * @param pchEaten Number of characters parsed.
1069 * @param ppmkOut Pointer to the IMoniker interface pointer.
1070 * @return HRESULT indicating success or failure.
1071 */
1072 STDMETHOD(ParseDisplayName)(IBindCtx* /*pbc*/, LPOLESTR /*pszDisplayName*/,
1073 ULONG* /*pchEaten*/, IMoniker** /*ppmkOut*/)
1074 {
1075 ATLTRACENOTIMPL(_T("ActiveXContainerImpl::ParseDisplayName\n"));
1076 }
1077
1078 ///////////////////////////////////////////////////////////////////////////
1079 // IBindHost
1080
1081 /**
1082 * @brief Create a moniker from a display name.
1083 * @param szName Display name.
1084 * @param pBC Bind context.
1085 * @param ppmk Pointer to the IMoniker interface pointer.
1086 * @param dwReserved Reserved.
1087 * @return HRESULT indicating success or failure.
1088 */
1089 STDMETHOD(CreateMoniker)(LPOLESTR szName, IBindCtx* pBC,
1090 IMoniker** ppmk, DWORD dwReserved);
1091
1092 /**
1093 * @brief Bind a moniker to a storage object.
1094 * @param pMk Moniker.
1095 * @param pBC Bind context.
1096 * @param pBSC Bind status callback.
1097 * @param riid Interface identifier.
1098 * @param ppvObj Pointer to the interface pointer.
1099 * @return HRESULT indicating success or failure.
1100 */
1101 STDMETHOD(MonikerBindToStorage)(IMoniker* pMk, IBindCtx* pBC,
1102 IBindStatusCallback* pBSC, REFIID riid, void** ppvObj);
1103
1104 /**
1105 * @brief Bind a moniker to an object.
1106 * @param pMk Moniker.
1107 * @param pBC Bind context.
1108 * @param pBSC Bind status callback.
1109 * @param riid Interface identifier.
1110 * @param ppvObj Pointer to the interface pointer.
1111 * @return HRESULT indicating success or failure.
1112 */
1113 STDMETHOD(MonikerBindToObject)(IMoniker* pMk, IBindCtx* pBC,
1114 IBindStatusCallback* pBSC, REFIID riid, void** ppvObj);
1115
1116 ///////////////////////////////////////////////////////////////////////////
1117 // IServiceProvider
1118
1119 /**
1120 * @brief Query for a service.
1121 * @param guidService Service identifier.
1122 * @param riid Interface identifier.
1123 * @param ppvObject Pointer to the interface pointer.
1124 * @return HRESULT indicating success or failure.
1125 */
1126 STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppvObject);
1127
1128 /**
1129 * @brief Query for an interface.
1130 * @param iid Interface identifier.
1131 * @param object Pointer to the interface pointer.
1132 * @return HRESULT indicating success or failure.
1133 */
1134 STDMETHOD(QueryInterface)(REFIID iid, void** object);
1135
1136 /**
1137 * @brief Increment the reference count.
1138 * @return New reference count.
1139 */
1140 STDMETHOD_(ULONG, AddRef)();
1141
1142 /**
1143 * @brief Decrement the reference count.
1144 * @return New reference count.
1145 */
1146 STDMETHOD_(ULONG, Release)();
1147
1148 private:
1149 LONG m_lRefCnt; /**< Reference count for COM object management. */
1150 };
1151
1152
1153
1154 SNSEND
1155
1156 #endif //ATLACTIVEXCONTAINER_HPP
STDMETHOD ReleaseDC(HDC hDC)
Release a previously obtained device context.
STDMETHOD ScrollRect(INT, INT, LPCRECT, LPCRECT)
Scroll a rectangle of the control.
STDMETHOD InvalidateRect(LPCRECT pRect, BOOL fErase)
Invalidate a rectangle of the control.
HRESULT ActivateAx(IStream *pStream=NULL)
Activate the ActiveX control.
LRESULT OnWindowMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
Handle a window message for the ActiveX control.
STDMETHOD InvalidateRgn(HRGN, BOOL fErase)
Invalidate a region of the control.
void SetAxHost(IAxHostDelegate *pAxHost)
Set the delegate for ActiveX host operations.
STDMETHOD CanWindowlessActivate(void)
Check if the control supports windowless activation.
STDMETHOD ShowPropertyFrame(void)
Show the property frame for the control.
STDMETHOD ShowObject(void)
Show the object.
STDMETHOD OnInPlaceDeactivateEx(BOOL)
Deactivate the control in-place with extended options.
void OnViewChange(DWORD, LONG)
Handle a change in view.
STDMETHOD LockInPlaceActive(BOOL)
Lock the control in place active state.
STDMETHOD OnFocus(BOOL fGotFocus)
Notify the control of focus change.
STDMETHOD RequestNewObjectLayout(void)
Request a new object layout.
void OnSave(void)
Handle a save operation.
STDMETHOD Scroll(SIZE)
Scroll the control.
void OnDataChange(FORMATETC *, STGMEDIUM *)
Handle a change in data.
void OnClose(void)
Handle a close operation.
STDMETHOD GetCapture(void)
Check if the control currently has the mouse capture.
STDMETHOD OnShowWindow(BOOL fShow)
Notify the container of a show window event.
HRESULT FireAmbientPropertyChange(DISPID dispChanged)
Fire an ambient property change notification.
STDMETHOD CanInPlaceActivate(void)
Check if the control can be activated in-place.
STDMETHOD AdjustRect(LPRECT)
Adjust a rectangle for the control.
STDMETHOD OnPosRectChange(LPCRECT lprcPosRect)
Handle a change in the position rectangle of the control.
STDMETHOD OnControlInfoChanged(void)
Notify the control that its info has changed.
STDMETHOD OnInPlaceActivate(void)
Activate the control in-place.
void Init(IUnknown *pControl)
Initialize the ActiveX control.
STDMETHOD GetDC(LPCRECT pRect, DWORD grfFlags, HDC *phDC)
Get a device context for the control.
void SetExternalUIHandler(IDocHostUIHandler *pUiHandler)
Set the external UI handler for the ActiveX control.
STDMETHOD SetFocus(BOOL fFocus)
Set or release focus for the control.
STDMETHOD RequestUIActivate(void)
Request UI activation for the control.
STDMETHOD GetContainer(IOleContainer **ppContainer)
Get the container for the object.
void Clear()
Clear the ActiveX control and release resources.
STDMETHOD OnInPlaceDeactivate(void)
Deactivate the control in-place.
STDMETHOD DeactivateAndUndo(void)
Deactivate and undo the control.
STDMETHOD OnUIActivate(void)
Activate the control's user interface.
HRESULT DoInplaceActivate()
Perform in-place activation of the control.
bool HitTest(const POINT &pt) const
Check if a point is within the ActiveX control.
STDMETHOD ContextSensitiveHelp(BOOL)
Handle context-sensitive help for the control.
HRESULT SetExtent(int width, int height)
Set the extent (size) of the control.
virtual ~ActiveXSite()
Destructor for ActiveXSite.
STDMETHOD DiscardUndoState(void)
Discard the undo state of the control.
STDMETHOD GetMoniker(DWORD, DWORD dwWhichMoniker, IMoniker **ppmk)
Get the moniker for the object.
STDMETHOD GetExtendedControl(IDispatch **)
Get the extended control.
ActiveXSite()
Constructor for ActiveXSite.
HRESULT DoVerb(long verb)
Perform a verb on the ActiveX control.
STDMETHOD OnInPlaceActivateEx(BOOL *pfNoRedraw, DWORD dwFlags)
Activate the control in-place with extended options.
STDMETHOD QueryInterface2(REFIID iid, void **object)
Query for an interface.
STDMETHOD TranslateAccelerator(MSG *, DWORD)
Translate an accelerator key.
STDMETHOD GetFocus(void)
Check if the control currently has focus.
STDMETHOD OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
Handle a default window message for the control.
bool InsideClippingRegion(const RECT &rcClip) const
Check if the control intersects with a clipping region.
STDMETHOD SetCapture(BOOL fCapture)
Set or release the mouse capture for the control.
LRESULT Draw(HDC hDC, LPCRECT lpClipRect)
Draw the ActiveX control.
HRESULT InitControl(IStream *pStream=NULL)
Initialize the ActiveX control from a stream.
STDMETHOD TransformCoords(POINTL *, POINTF *, DWORD)
Transform coordinates between container and control.
IUnknown * GetActiveXControl()
Get the ActiveX control.
STDMETHOD GetWindow(HWND *phwnd)
Get the window handle for the control.
STDMETHOD SaveObject(void)
Save the object.
STDMETHOD OnUIDeactivate(BOOL)
Deactivate the control's user interface.
void OnRename(IMoniker *)
Handle a rename of the object.
STDMETHOD GetWindowContext(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
Get the window context for the control.
ULONG AddRef()
Increment the reference count.
ULONG Release()
Decrement the reference count.
BOOL CreateControl(REFGUID guid, DWORD dwClsCtx=CLSCTX_INPROC_SERVER)
Create an ActiveX control.
STDMETHOD LockContainer(BOOL)
Lock or unlock the container.
SAxContainer()
Constructor for SAxContainer.
STDMETHOD ParseDisplayName(IBindCtx *, LPOLESTR, ULONG *, IMoniker **)
Parse a display name into a moniker.
STDMETHOD MonikerBindToObject(IMoniker *pMk, IBindCtx *pBC, IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
Bind a moniker to an object.
STDMETHOD CreateMoniker(LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
Create a moniker from a display name.
STDMETHOD EnumObjects(DWORD, IEnumUnknown **)
Enumerate objects in the container.
STDMETHOD QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
Query for a service.
STDMETHOD MonikerBindToStorage(IMoniker *pMk, IBindCtx *pBC, IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
Bind a moniker to a storage object.
virtual ~SAxContainer()
Destructor for SAxContainer.
STDMETHOD QueryInterface(REFIID iid, void **object)
Query for an interface.
Delegate interface for ActiveX host operations.
virtual void OnAxInvalidate(LPCRECT pRect, BOOL bErase)=0
Notify the host that the ActiveX control needs to be invalidated.
virtual void OnAxSetCapture(BOOL fCapture)=0
Notify the host to set or release the mouse capture.
virtual void OnAxActivate(IUnknown *pCtrl)=0
Notify the host that the ActiveX control is being activated.
virtual HRESULT OnAxGetDC(LPCRECT pRect, DWORD grfFlags, HDC *phDC)=0
Get a device context for the ActiveX control.
virtual HWND GetAxHostWindow() const =0
Get the window handle of the ActiveX host.
virtual HRESULT OnAxReleaseDC(HDC hdc)=0
Release a previously obtained device context.