Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cOleClientSite.h
Go to the documentation of this file.
1 //
4 //
5 
6 #ifndef _INC_cOleClientSite_H
7 #define _INC_cOleClientSite_H
8 #ifndef NO_PRAGMA_ONCE
9 #pragma once
10 #endif
11 
12 #include "cOleControl.h"
13 
14 #if defined(_WIN32) && defined(_MSC_VER)
15 
16 // #undef TranslateAccelerator
17 
18 namespace GrayLib
19 {
20  class GRAYLIB_LINK cOleClientSite : public cRefBase
21  , public IOleClientSite
22  , public IOleInPlaceSite
23  , public IDocHostUIHandler
24  , public IOleInPlaceFrame
25  {
29 
30  public:
31  cOleControl* m_pOleControl; // my parent control. cOleWebBrowser
32  bool m_bShowWindow;
33  BORDERWIDTHS m_BorderWidths;
34 
35  public:
36  cOleClientSite(cOleControl* pOleControl)
37  : m_pOleControl(pOleControl)
38  , m_bShowWindow(true)
39  {
40  cMem::Zero(&m_BorderWidths, sizeof(m_BorderWidths));
41  AddRef(); // extra ref for some reason. We die on IOleObject Close(OLECLOSE_NOSAVE)->destruct if we don't have this! TODO FIXME ???
42  }
43  virtual ~cOleClientSite()
44  {
45  }
46 
47  IUNKNOWN_DISAMBIG_R(cRefBase);
48 
49  void DisposeThis()
50  {
51  // my parent went away. but i must live on because i have references.
52  m_pOleControl = nullptr;
53  }
54 
55  HRESULT OnNotImpl()
56  {
57  // This shouldn't get called in the stub version.
58 
59  // So, for these "dummy functions" that we don't expect the browser to call, we'll just stick in some
60  // assembly code that causes a debugger breakpoint and tells the browser object that we don't support
61  // the functionality. That way, if you try to do more things with the browser object, and it starts
62  // calling these "dummy functions", you'll know which ones you should add more meaningful code to.
63  ASSERT(0);
64  if (m_pOleControl == nullptr)
65  return E_NOTIMPL;
66  return m_pOleControl->ReturnError(E_NOTIMPL);
67  }
68 
69  STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) override
70  {
72  // We give the browser object a pointer to our IOleClientSite object when we call OleCreate() or DoVerb().
73 
74  // The browser object calls this when it wants a pointer to one of our
75  // IOleClientSite, IDocHostUIHandler, or IOleInPlaceSite structures.They
76  // are all accessible via the cOleClientSite struct we allocated in
77  // EmbedBrowserObject() and passed to DoVerb() and OleCreate().
78 
79  // It just so happens that the first arg passed to us is our cOleClientSite struct we allocated
80  // and passed to DoVerb() and OleCreate(). Nevermind that 'this' is declared is an IOleClientSite *.
81  // Remember that in EmbedBrowserObject(), we allocated our own cOleClientSite struct, and lied
82  // to OleCreate() and DoVerb() -- passing our cOleClientSite struct and saying it was an
83  // IOleClientSite struct. It's ok. An cOleClientSite starts with an embedded IOleClientSite, so
84  // the browser didn't mind. So that's what the browser object is passing us now. The browser doesn't
85  // know that it's really an cOleClientSite struct. But we do. So we can recast it and use it as
86  // so here.
87 
88  cOleClientSite* pThis = this;
89 
90  if (riid == __uuidof(IUnknown)
91  || riid == __uuidof(IOleClientSite))
92  {
93  *ppvObject = static_cast<IOleClientSite*>(pThis);
94  }
95 
96  else if (riid == __uuidof(IOleInPlaceSite))
97  {
98  *ppvObject = static_cast<IOleInPlaceSite*>(pThis);
99  }
100 
101  else if (riid == __uuidof(IDocHostUIHandler))
102  {
103  *ppvObject = static_cast<IDocHostUIHandler*>(pThis);
104  }
105 
106  else if (riid == __uuidof(IOleInPlaceFrame))
107  {
108  *ppvObject = static_cast<IOleInPlaceFrame*>(pThis);
109  }
110 
111  else
112  {
113  // NOT __uuidof(IServiceProvider)
114  return cRefBase::QueryInterface(riid, ppvObject);
115  }
116 
117  AddRef();
118  return S_OK;
119  }
120 
121  public:
122  STDMETHOD(SaveObject)() override
123  {
125  return OnNotImpl();
126  }
127  STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker ** ppmk) override
128  {
130  UNREFERENCED_PARAMETER(dwAssign);
131  UNREFERENCED_PARAMETER(dwWhichMoniker);
133  return E_NOTIMPL; // this is ok.
134  }
135  STDMETHOD(GetContainer)(LPOLECONTAINER FAR* ppContainer) override
136  {
139  *ppContainer = nullptr;
140  return E_NOINTERFACE;
141  }
142  STDMETHOD(ShowObject)() override
143  {
145  return S_OK;
146  }
147  STDMETHOD(OnShowWindow)(BOOL fShow) override
148  {
151  m_bShowWindow = fShow;
152  return S_OK;
153  }
154  STDMETHOD(RequestNewObjectLayout)() override
155  {
157  return OnNotImpl();
158  }
159 
160  public:
161  STDMETHOD(GetWindow)(HWND FAR* lphwnd) override
162  {
169 
170  if (m_pOleControl == nullptr)
171  *lphwnd = HANDLE_NULL;
172  else
173  *lphwnd = m_pOleControl->get_WndFrame();
174  return S_OK;
175  }
176 
177  STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) override
178  {
180  UNREFERENCED_PARAMETER(fEnterMode);
181  return OnNotImpl();
182  }
183  STDMETHOD(CanInPlaceActivate)() override
184  {
187  return S_OK;
188  }
189  STDMETHOD(OnInPlaceActivate)() override
190  {
193  return S_OK;
194  }
195  STDMETHOD(OnUIActivate)() override
196  {
198  return S_OK;
199  }
200  STDMETHOD(GetWindowContext)(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) override
201  {
204  UNREFERENCED_PARAMETER(lprcClipRect);
205  UNREFERENCED_PARAMETER(lprcPosRect);
206 
207  if (this->m_pOleControl == nullptr) // disposed.
208  return E_POINTER;
209  *lplpFrame = static_cast<IOleInPlaceFrame*>(this);
210 
211  // We have no OLEINPLACEUIWINDOW
212  *lplpDoc = nullptr;
213 
214  // Fill in some other info for the browser
215  lpFrameInfo->fMDIApp = false;
216  lpFrameInfo->hwndFrame = m_pOleControl->get_WndFrame();
217  lpFrameInfo->haccel = 0;
218  lpFrameInfo->cAccelEntries = 0;
219 
220  // Give the browser the dimensions of where it can draw. We give it our entire window to fill.
221  // We do this in COleInPlaceSite::OnPosRectChange() which is called right when a window is first
222  // created anyway, so no need to duplicate it here.
223  // GetClientRect(lpFrameInfo->hwndFrame, lprcPosRect);
224  // GetClientRect(lpFrameInfo->hwndFrame, lprcClipRect);
225 
226  return S_OK;
227  }
228 
229  STDMETHOD(Scroll)(SIZE scrollExtent) override
230  {
232  UNREFERENCED_PARAMETER(scrollExtent);
233  return OnNotImpl();
234  }
235 
236  STDMETHOD(OnUIDeactivate)(BOOL fUndoable) override
237  {
239  UNREFERENCED_PARAMETER(fUndoable);
240  return S_OK;
241  }
242  STDMETHOD(OnInPlaceDeactivate)() override
243  {
245  return S_OK;
246  }
247  STDMETHOD(DiscardUndoState)() override
248  {
250  return OnNotImpl();
251  }
252  STDMETHOD(DeactivateAndUndo)() override
253  {
255  return OnNotImpl();
256  }
257 
258  STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect) override
259  {
261  // Called when the position of the browser object is changed, such as when we call the IWebBrowser2's
262  // put_Width(), put_Height(), put_Left(), or put_Right().
263 
264  if (m_pOleControl == nullptr || lprcPosRect == nullptr)
265  {
266  return E_POINTER;
267  }
268 
269  // Don't use put_Rect() because it would feedback?
270  HRESULT hRes = m_pOleControl->SetRect(*lprcPosRect, 0);
272  return S_OK; // S_OK
273  }
274 
275  public:
276  STDMETHOD(ShowContextMenu)(DWORD dwID, POINT __RPC_FAR *ppt, IUnknown __RPC_FAR *pcmdtReserved, IDispatch __RPC_FAR *pdispReserved) override
277  {
286  //
287  // typedef struct COleDocHostUIHandler {
288  // IDocHostUIHandler ui; // The IDocHostUIHandler must be first!
289  // HWND window;
290  // } IDocHostUIHandlerEx;
291  //
292  // Of course, we'd need a unique IDocHostUIHandlerEx object for each window, so
293  // EmbedBrowserObject() would have to allocate one of those too. And that's
294  // what we'd pass to our browser object (and it would in turn pass it to us
295  // here, instead of 'This' being a IDocHostUIHandler *).
296 
297  // We will return S_OK to tell the browser not to display its default context menu,
298  // or return S_FALSE to let the browser show its default context menu. For this
299  // example, we wish to disable the browser's default context menu.
300 
301  UNREFERENCED_PARAMETER(pdispReserved);
302  UNREFERENCED_PARAMETER(pcmdtReserved);
305 
306  return S_OK;
307  }
308 
309  STDMETHOD(GetHostInfo)(DOCHOSTUIINFO __RPC_FAR *pInfo) override
310  {
313 
314  pInfo->cbSize = sizeof(DOCHOSTUIINFO);
315 
316  // Set some flags. We don't want any 3D border. You can do other things like hide
317  // the scroll bar (DOCHOSTUIFLAG_SCROLL_NO), display picture display (DOCHOSTUIFLAG_NOPICS),
318  // disable any script running when the page is loaded (DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE),
319  // open a site in a new browser window when the user clicks on some link (DOCHOSTUIFLAG_OPENNEWWIN),
320  // and lots of other things. See the MSDN docs on the DOCHOSTUIINFO struct passed to us.
321  pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER;
322 
323  // Set what happens when the user double-clicks on the object. Here we use the default.
324  pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
325 
326  return S_OK;
327  }
328 
329  STDMETHOD(ShowUI)(DWORD dwID, IOleInPlaceActiveObject __RPC_FAR *pActiveObject, IOleCommandTarget __RPC_FAR *pCommandTarget, IOleInPlaceFrame __RPC_FAR *pFrame, IOleInPlaceUIWindow __RPC_FAR *pDoc) override
330  {
336  UNREFERENCED_PARAMETER(pFrame);
337  UNREFERENCED_PARAMETER(pCommandTarget);
338  UNREFERENCED_PARAMETER(pActiveObject);
341  return S_OK;
342  }
343 
344  STDMETHOD(HideUI)() override
345  {
348  return S_OK;
349  }
350 
351  STDMETHOD(UpdateUI)() override
352  {
357  return S_OK;
358  }
359 
360  STDMETHOD(EnableModeless)(BOOL fEnable) override
361  {
365  UNREFERENCED_PARAMETER(fEnable);
366  return S_OK;
367  }
368  STDMETHOD(OnDocWindowActivate)(BOOL fActivate) override
369  {
373  UNREFERENCED_PARAMETER(fActivate);
374  return S_OK;
375  }
376 
377  STDMETHOD(OnFrameWindowActivate)(BOOL fActivate) override
378  {
381  UNREFERENCED_PARAMETER(fActivate);
382  return S_OK;
383  }
384  STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR *pUIWindow, BOOL fRameWindow) override
385  {
388  UNREFERENCED_PARAMETER(prcBorder);
389  UNREFERENCED_PARAMETER(pUIWindow);
390  UNREFERENCED_PARAMETER(fRameWindow);
391  return S_OK;
392  }
393  STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID) override
394  {
396  // Called from the browser object's TranslateAccelerator routines to translate key strokes to commands.
397  // We don't intercept any keystrokes, so we do nothing here. But for example, if we wanted to
398  // override the TAB key, perhaps do something with it ourselves, and then tell the browser
399  // not to do anything with this keystroke, we'd do:
400  //
401  // if (pMsg && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB)
402  // {
403  // // Here we do something as a result of a TAB key press.
404  //
405  // // Tell the browser not to do anything with it.
406  // return S_FALSE;
407  // }
408  //
409  // // Otherwise, let the browser do something with this message.
410  // return S_OK;
411 
412  // For our example, we want to make sure that the user can invoke some key to popup the context
413  // menu, so we'll tell it to ignore all messages.
414 
415  UNREFERENCED_PARAMETER(lpMsg);
416  UNREFERENCED_PARAMETER(pguidCmdGroup);
417  UNREFERENCED_PARAMETER(nCmdID);
418 
419  return S_FALSE;
420  }
421  STDMETHOD(GetOptionKeyPath)(LPOLESTR __RPC_FAR *pchKey, DWORD dw) override
422  {
424  // Called by the browser object to find where the host wishes the browser to get its options in the registry.
425  // We can use this to prevent the browser from using its default settings in the registry, by telling it to use
426  // some other registry key we've setup with the options we want.
427  // Let the browser use its default registry settings.
428  UNREFERENCED_PARAMETER(pchKey);
430  return S_FALSE;
431  }
432  STDMETHOD(GetDropTarget)(IDropTarget __RPC_FAR *pDropTarget, IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget) override
433  {
435  // Called by the browser object when it is used as a drop target. We can supply our own IDropTarget object,
436  // IDropTarget functions, and IDropTarget VTable if we want to determine what happens when someone drags and
437  // drops some object on our embedded browser object.
438  // Return our IDropTarget object associated with this IDocHostUIHandler object. I don't
439  // know why we don't do this via COleDocHostUIHandler::QueryInterface(), but we don't.
440 
441  // NOTE: If we want/need an IDropTarget interface, then we would have had to setup our own
442  // IDropTarget functions, IDropTarget VTable, and create an IDropTarget object. We'd want to put
443  // a pointer to the IDropTarget object in our own custom IDocHostUIHandlerEx object (like how
444  // we may add an HWND field for the use of COleDocHostUIHandler::ShowContextMenu). So when we created our
445  // IDocHostUIHandlerEx object, maybe we'd add a 'idrop' field to the end of it, and
446  // store a pointer to our IDropTarget object there. Then we could return this pointer as so:
447  //
448  // *pDropTarget = ((IDocHostUIHandlerEx FAR *)this)->idrop;
449  // return S_OK;
450 
451  // But for our purposes, we don't need an IDropTarget object, so we'll tell whomever is calling
452  // us that we don't have one.
453 
454  UNREFERENCED_PARAMETER(pDropTarget);
455  UNREFERENCED_PARAMETER(ppDropTarget);
456 
457  return S_FALSE;
458  }
459  STDMETHOD(GetExternal)(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) override
460  {
462  // Called by the browser when it wants a pointer to our IDispatch object. This object allows us to expose
463  // our own automation interface (ie, our own COM objects) to other entities that are running within the
464  // context of the browser so they can call our functions if they want. An example could be a javascript
465  // running in the URL we display could call our IDispatch functions. We'd write them so that any args passed
466  // to them would use the generic datatypes like a BSTR for utmost flexibility.
467  // Return our IDispatch object associated with this IDocHostUIHandler object. I don't
468  // know why we don't do this via COleDocHostUIHandler::QueryInterface(), but we don't.
469 
470  // NOTE: If we want/need an IDispatch interface, then we would have had to setup our own
471  // IDispatch functions, IDispatch VTable, and create an IDispatch object. We'd want to put
472  // a pointer to the IDispatch object in our custom COleDocHostUIHandler object (like how
473  // we may add an HWND field for the use of COleDocHostUIHandler::ShowContextMenu). So when we defined our
474  // COleDocHostUIHandler object, maybe we'd add a 'idispatch' field to the end of it, and
475  // store a pointer to our IDispatch object there. Then we could return this pointer as so:
476  //
477  // *ppDispatch = ((COleDocHostUIHandler FAR *)this)->idispatch;
478  // return S_OK;
479 
480  // But for our purposes, we don't need an IDispatch object, so we'll tell whomever is calling
481  // us that we don't have one. Note: We must set ppDispatch to 0 if we don't return our own
482  // IDispatch object.
483  *ppDispatch = nullptr;
484  return S_FALSE;
485  }
486  STDMETHOD(TranslateUrl)(DWORD dwTranslate, OLECHAR __RPC_FAR *pchURLIn, OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut) override
487  {
489  // Called by the browser object to give us an opportunity to modify the URL to be loaded.
490  // We don't need to modify the URL. Note: We need to set ppchURLOut to 0 if we don't
491  // return an OLECHAR (buffer) containing a modified version of pchURLIn.
492  UNREFERENCED_PARAMETER(dwTranslate);
493  UNREFERENCED_PARAMETER(pchURLIn);
494  *ppchURLOut = '\0';
495  return S_FALSE;
496  }
497  STDMETHOD(FilterDataObject)(IDataObject __RPC_FAR *pDO, IDataObject __RPC_FAR *__RPC_FAR *ppDORet) override
498  {
500  // Called by the browser when it does cut/paste to the clipboard. This allows us to block certain clipboard
501  // formats or support additional clipboard formats.
502  // Return our IDataObject object associated with this IDocHostUIHandler object. I don't
503  // know why we don't do this via COleDocHostUIHandler::QueryInterface(), but we don't.
504 
505  // NOTE: If we want/need an IDataObject interface, then we would have had to setup our own
506  // IDataObject functions, IDataObject VTable, and create an IDataObject object. We'd want to put
507  // a pointer to the IDataObject object in our custom COleDocHostUIHandler object (like how
508  // we may add an HWND field for the use of COleDocHostUIHandler::ShowContextMenu). So when we defined our
509  // COleDocHostUIHandler object, maybe we'd add a 'idata' field to the end of it, and
510  // store a pointer to our IDataObject object there. Then we could return this pointer as so:
511  //
512  // *ppDORet = ((COleDocHostUIHandler FAR *)this)->idata;
513  // return S_OK;
514 
515  // But for our purposes, we don't need an IDataObject object, so we'll tell whomever is calling
516  // us that we don't have one. Note: We must set ppDORet to 0 if we don't return our own
517  // IDataObject object.
518 
520 
521  *ppDORet = nullptr;
522  return S_FALSE;
523  }
524 
525  public:
526  STDMETHOD(GetBorder)(LPRECT lprectBorder) override
527  {
529  UNREFERENCED_PARAMETER(lprectBorder);
530  return OnNotImpl();
531  }
532  STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS pborderwidths) override
533  {
534  // override IOleInPlaceFrame
535  UNREFERENCED_PARAMETER(pborderwidths);
536  return OnNotImpl();
537  }
538  STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS pborderwidths) override
539  {
540  // override IOleInPlaceFrame
541  if (pborderwidths != nullptr)
542  {
543  ::memcpy(&m_BorderWidths, pborderwidths, sizeof(m_BorderWidths));
544  }
545  return S_OK;
546  }
547  STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) override
548  {
549  // override IOleInPlaceFrame
550  UNREFERENCED_PARAMETER(pActiveObject);
551  UNREFERENCED_PARAMETER(pszObjName);
552  return S_OK;
553  }
554  STDMETHOD(InsertMenus)(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override
555  {
556  // override IOleInPlaceFrame
557  UNREFERENCED_PARAMETER(hmenuShared);
558  UNREFERENCED_PARAMETER(lpMenuWidths);
559  return OnNotImpl();
560  }
561  STDMETHOD(SetMenu)(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) override
562  {
563  // override IOleInPlaceFrame
564  UNREFERENCED_PARAMETER(hmenuShared);
565  UNREFERENCED_PARAMETER(holemenu);
566  UNREFERENCED_PARAMETER(hwndActiveObject);
567  return S_OK;
568  }
569  STDMETHOD(RemoveMenus)(HMENU hmenuShared) override
570  {
571  // override IOleInPlaceFrame
572  UNREFERENCED_PARAMETER(hmenuShared);
573  return OnNotImpl();
574  }
575  STDMETHOD(SetStatusText)(LPCOLESTR pszStatusText) override
576  {
578  UNREFERENCED_PARAMETER(pszStatusText);
579  return S_OK;
580  }
581  STDMETHOD(TranslateAccelerator)(LPMSG lpmsg, WORD wID) override
582  {
584  UNREFERENCED_PARAMETER(lpmsg);
586  return OnNotImpl();
587  }
588  };
589 }
590 
591 #endif
592 #endif
#define GRAYLIB_LINK
Definition: GrayLibBase.h:35
#define IUNKNOWN_DISAMBIG_R(TYPE)
Definition: IUnknown.h:85
#define UNREFERENCED_PARAMETER(P)
< _WIN32 type thing. get rid of stupid warning.
Definition: SysTypes.h:299
INT32 HRESULT
_WIN32 style error codes. INT32
Definition: SysTypes.h:465
#define ASSERT(exp)
Definition: cDebugAssert.h:87
#define HANDLE_NULL
Invalid OS handle for _WIN32. Not invalid OS handle for linux.
Definition: cOSHandle.h:21
STDMETHOD() QueryInterface(const IID &riid, void __RPC_FAR *__RPC_FAR *ppvObject) override
Definition: cRefPtr.h:142
Definition: IUnknown.h:68
Definition: cMesh.h:22
static void Zero(void *pData, size_t nSizeBlock) noexcept
Definition: cMem.h:100
Definition: IUnknown.h:34