-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathembed-browser.c
2028 lines (1633 loc) · 80.9 KB
/
embed-browser.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
embed-browser.c
Embed Internet Explorer browser control to WinAPI program
UI_ShowContextMenu() -> return S_FALSE to enable context menu (right click pop up menu), S_OK to disable
*/
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "shlwapi.lib")
#include <windows.h>
#include <commctrl.h>
#include <exdisp.h>
#include <mshtml.h>
#include <mshtmhst.h>
#include <crtdbg.h>
#include <tchar.h>
#include <oleidl.h>
HFONT hfont_custom;
HWND back_btn, forward_btn, stop_btn;
HWND browser_hwnd;
// Handle of our Main Window.
HWND MainWindow;
// Our font used for buttons
HFONT FontHandle;
// The class name of our Main Window. It can be anything of your choosing.
static const TCHAR ClassName[] = "Browser Example";
// The class name of our Window to host the browser. It can be anything of your choosing.
static const TCHAR BrowserClassName[] = "Browser Object";
// This is used by DisplayHTMLStr(). It can be global because we never change it.
static const SAFEARRAYBOUND ArrayBound = {1, 0};
// Our IOleInPlaceFrame functions that the browser may call
HRESULT STDMETHODCALLTYPE Frame_QueryInterface(IOleInPlaceFrame *This, REFIID riid, LPVOID *ppvObj);
HRESULT STDMETHODCALLTYPE Frame_AddRef(IOleInPlaceFrame *This);
HRESULT STDMETHODCALLTYPE Frame_Release(IOleInPlaceFrame *This);
HRESULT STDMETHODCALLTYPE Frame_GetWindow(IOleInPlaceFrame *This, HWND *lphwnd);
HRESULT STDMETHODCALLTYPE Frame_ContextSensitiveHelp(IOleInPlaceFrame *This, BOOL fEnterMode);
HRESULT STDMETHODCALLTYPE Frame_GetBorder(IOleInPlaceFrame *This, LPRECT lprectBorder);
HRESULT STDMETHODCALLTYPE Frame_RequestBorderSpace(IOleInPlaceFrame *This, LPCBORDERWIDTHS pborderwidths);
HRESULT STDMETHODCALLTYPE Frame_SetBorderSpace(IOleInPlaceFrame *This, LPCBORDERWIDTHS pborderwidths);
HRESULT STDMETHODCALLTYPE Frame_SetActiveObject(IOleInPlaceFrame *This, IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName);
HRESULT STDMETHODCALLTYPE Frame_InsertMenus(IOleInPlaceFrame *This, HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
HRESULT STDMETHODCALLTYPE Frame_SetMenu(IOleInPlaceFrame *This, HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject);
HRESULT STDMETHODCALLTYPE Frame_RemoveMenus(IOleInPlaceFrame *This, HMENU hmenuShared);
HRESULT STDMETHODCALLTYPE Frame_SetStatusText(IOleInPlaceFrame *This, LPCOLESTR pszStatusText);
HRESULT STDMETHODCALLTYPE Frame_EnableModeless(IOleInPlaceFrame *This, BOOL fEnable);
HRESULT STDMETHODCALLTYPE Frame_TranslateAccelerator(IOleInPlaceFrame *This, LPMSG lpmsg, WORD wID);
// Our IOleInPlaceFrame VTable. This is the array of pointers to the above functions in our C
// program that the browser may call in order to interact with our frame window that contains
// the browser object. We must define a particular set of functions that comprise the
// IOleInPlaceFrame set of functions (see above), and then stuff pointers to those functions
// in their respective 'slots' in this table. We want the browser to use this VTable with our
// IOleInPlaceFrame structure.
IOleInPlaceFrameVtbl MyIOleInPlaceFrameTable = {Frame_QueryInterface,
Frame_AddRef,
Frame_Release,
Frame_GetWindow,
Frame_ContextSensitiveHelp,
Frame_GetBorder,
Frame_RequestBorderSpace,
Frame_SetBorderSpace,
Frame_SetActiveObject,
Frame_InsertMenus,
Frame_SetMenu,
Frame_RemoveMenus,
Frame_SetStatusText,
Frame_EnableModeless,
Frame_TranslateAccelerator};
// We need to return an IOleInPlaceFrame struct to the browser object. And one of our IOleInPlaceFrame
// functions (Frame_GetWindow) is going to need to access our window handle. So let's create our own
// struct that starts off with an IOleInPlaceFrame struct (and that's important -- the IOleInPlaceFrame
// struct *must* be first), and then has an extra data field where we can store our own window's HWND.
//
// And because we may want to create multiple windows, each hosting its own browser object (to
// display its own web page), then we need to create a IOleInPlaceFrame struct for each window. So,
// we're not going to declare our IOleInPlaceFrame struct globally. We'll allocate it later using
// GlobalAlloc, and then stuff the appropriate HWND in it then, and also stuff a pointer to
// MyIOleInPlaceFrameTable in it. But let's just define it here.
typedef struct {
IOleInPlaceFrame frame; // The IOleInPlaceFrame must be first!
///////////////////////////////////////////////////
// Here you add any extra variables that you need
// to access in your IOleInPlaceFrame functions.
// You don't want those functions to access global
// variables, because then you couldn't use more
// than one browser object. (ie, You couldn't have
// multiple windows, each with its own embedded
// browser object to display a different web page).
//
// So here is where I added my extra HWND that my
// IOleInPlaceFrame function Frame_GetWindow() needs
// to access.
///////////////////////////////////////////////////
HWND window;
} _IOleInPlaceFrameEx;
// Our IOleClientSite functions that the browser may call
HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite *This, REFIID riid, void ** ppvObject);
HRESULT STDMETHODCALLTYPE Site_AddRef(IOleClientSite *This);
HRESULT STDMETHODCALLTYPE Site_Release(IOleClientSite *This);
HRESULT STDMETHODCALLTYPE Site_SaveObject(IOleClientSite *This);
HRESULT STDMETHODCALLTYPE Site_GetMoniker(IOleClientSite *This, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker ** ppmk);
HRESULT STDMETHODCALLTYPE Site_GetContainer(IOleClientSite *This, LPOLECONTAINER *ppContainer);
HRESULT STDMETHODCALLTYPE Site_ShowObject(IOleClientSite *This);
HRESULT STDMETHODCALLTYPE Site_OnShowWindow(IOleClientSite *This, BOOL fShow);
HRESULT STDMETHODCALLTYPE Site_RequestNewObjectLayout(IOleClientSite *This);
// Our IOleClientSite VTable. This is the array of pointers to the above functions in our C
// program that the browser may call in order to interact with our frame window that contains
// the browser object. We must define a particular set of functions that comprise the
// IOleClientSite set of functions (see above), and then stuff pointers to those functions
// in their respective 'slots' in this table. We want the browser to use this VTable with our
// IOleClientSite structure.
IOleClientSiteVtbl MyIOleClientSiteTable = {Site_QueryInterface,
Site_AddRef,
Site_Release,
Site_SaveObject,
Site_GetMoniker,
Site_GetContainer,
Site_ShowObject,
Site_OnShowWindow,
Site_RequestNewObjectLayout};
// Our IDocHostUIHandler functions that the browser may call
HRESULT STDMETHODCALLTYPE UI_QueryInterface(IDocHostUIHandler *This, REFIID riid, void **ppvObject);
HRESULT STDMETHODCALLTYPE UI_AddRef(IDocHostUIHandler *This);
HRESULT STDMETHODCALLTYPE UI_Release(IDocHostUIHandler *This);
HRESULT STDMETHODCALLTYPE UI_ShowContextMenu(IDocHostUIHandler *This, DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved);
HRESULT STDMETHODCALLTYPE UI_GetHostInfo(IDocHostUIHandler *This, DOCHOSTUIINFO *pInfo);
HRESULT STDMETHODCALLTYPE UI_ShowUI(IDocHostUIHandler *This, DWORD dwID, IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc);
HRESULT STDMETHODCALLTYPE UI_HideUI(IDocHostUIHandler *This);
HRESULT STDMETHODCALLTYPE UI_UpdateUI(IDocHostUIHandler *This);
HRESULT STDMETHODCALLTYPE UI_EnableModeless(IDocHostUIHandler *This, BOOL fEnable);
HRESULT STDMETHODCALLTYPE UI_OnDocWindowActivate(IDocHostUIHandler *This, BOOL fActivate);
HRESULT STDMETHODCALLTYPE UI_OnFrameWindowActivate(IDocHostUIHandler *This, BOOL fActivate);
HRESULT STDMETHODCALLTYPE UI_ResizeBorder(IDocHostUIHandler *This, LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow);
HRESULT STDMETHODCALLTYPE UI_TranslateAccelerator(IDocHostUIHandler *This, LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID);
HRESULT STDMETHODCALLTYPE UI_GetOptionKeyPath(IDocHostUIHandler *This, LPOLESTR *pchKey, DWORD dw);
HRESULT STDMETHODCALLTYPE UI_GetDropTarget(IDocHostUIHandler *This, IDropTarget *pDropTarget, IDropTarget **ppDropTarget);
HRESULT STDMETHODCALLTYPE UI_GetExternal(IDocHostUIHandler *This, IDispatch **ppDispatch);
HRESULT STDMETHODCALLTYPE UI_TranslateUrl(IDocHostUIHandler *This, DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut);
HRESULT STDMETHODCALLTYPE UI_FilterDataObject(IDocHostUIHandler *This, IDataObject *pDO, IDataObject **ppDORet);
// Our IDocHostUIHandler VTable. This is the array of pointers to the above functions in our C
// program that the browser may call in order to replace/set certain user interface considerations
// (such as whether to display a pop-up context menu when the user right-clicks on the embedded
// browser object). We must define a particular set of functions that comprise the
// IDocHostUIHandler set of functions (see above), and then stuff pointers to those functions
// in their respective 'slots' in this table. We want the browser to use this VTable with our
// IDocHostUIHandler structure.
IDocHostUIHandlerVtbl MyIDocHostUIHandlerTable = {UI_QueryInterface,
UI_AddRef,
UI_Release,
UI_ShowContextMenu,
UI_GetHostInfo,
UI_ShowUI,
UI_HideUI,
UI_UpdateUI,
UI_EnableModeless,
UI_OnDocWindowActivate,
UI_OnFrameWindowActivate,
UI_ResizeBorder,
UI_TranslateAccelerator,
UI_GetOptionKeyPath,
UI_GetDropTarget,
UI_GetExternal,
UI_TranslateUrl,
UI_FilterDataObject};
// We'll allocate our IDocHostUIHandler object dynamically with GlobalAlloc() for reasons outlined later.
// Our IOleInPlaceSite functions that the browser may call
HRESULT STDMETHODCALLTYPE InPlace_QueryInterface(IOleInPlaceSite *This, REFIID riid, void **ppvObject);
HRESULT STDMETHODCALLTYPE InPlace_AddRef(IOleInPlaceSite *This);
HRESULT STDMETHODCALLTYPE InPlace_Release(IOleInPlaceSite *This);
HRESULT STDMETHODCALLTYPE InPlace_GetWindow(IOleInPlaceSite *This, HWND *lphwnd);
HRESULT STDMETHODCALLTYPE InPlace_ContextSensitiveHelp(IOleInPlaceSite * This, BOOL fEnterMode);
HRESULT STDMETHODCALLTYPE InPlace_CanInPlaceActivate(IOleInPlaceSite *This);
HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceActivate(IOleInPlaceSite *This);
HRESULT STDMETHODCALLTYPE InPlace_OnUIActivate(IOleInPlaceSite *This);
HRESULT STDMETHODCALLTYPE InPlace_GetWindowContext(IOleInPlaceSite *This, LPOLEINPLACEFRAME *lplpFrame, LPOLEINPLACEUIWINDOW *lplpDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
HRESULT STDMETHODCALLTYPE InPlace_Scroll(IOleInPlaceSite *This, SIZE scrollExtent);
HRESULT STDMETHODCALLTYPE InPlace_OnUIDeactivate(IOleInPlaceSite *This, BOOL fUndoable);
HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceDeactivate(IOleInPlaceSite *This);
HRESULT STDMETHODCALLTYPE InPlace_DiscardUndoState(IOleInPlaceSite *This);
HRESULT STDMETHODCALLTYPE InPlace_DeactivateAndUndo(IOleInPlaceSite *This);
HRESULT STDMETHODCALLTYPE InPlace_OnPosRectChange(IOleInPlaceSite *This, LPCRECT lprcPosRect);
// Our IOleInPlaceSite VTable. This is the array of pointers to the above functions in our C
// program that the browser may call in order to interact with our frame window that contains
// the browser object. We must define a particular set of functions that comprise the
// IOleInPlaceSite set of functions (see above), and then stuff pointers to those functions
// in their respective 'slots' in this table. We want the browser to use this VTable with our
// IOleInPlaceSite structure.
IOleInPlaceSiteVtbl MyIOleInPlaceSiteTable = {InPlace_QueryInterface,
InPlace_AddRef,
InPlace_Release,
InPlace_GetWindow,
InPlace_ContextSensitiveHelp,
InPlace_CanInPlaceActivate,
InPlace_OnInPlaceActivate,
InPlace_OnUIActivate,
InPlace_GetWindowContext,
InPlace_Scroll,
InPlace_OnUIDeactivate,
InPlace_OnInPlaceDeactivate,
InPlace_DiscardUndoState,
InPlace_DeactivateAndUndo,
InPlace_OnPosRectChange};
// We need to pass our IOleClientSite structure to OleCreate (which in turn gives it to the browser).
// But the browser is also going to ask our IOleClientSite's QueryInterface() to return a pointer to
// our IOleInPlaceSite and/or IDocHostUIHandler structs. So we'll need to have those pointers handy.
// Plus, some of our IOleClientSite and IOleInPlaceSite functions will need to have the HWND to our
// window, and also a pointer to our IOleInPlaceFrame struct. So let's create a single struct that
// has the IOleClientSite, IOleInPlaceSite, IDocHostUIHandler, and IOleInPlaceFrame structs all inside
// it (so we can easily get a pointer to any one from any of those structs' functions). As long as the
// IOleClientSite struct is the very first thing in this custom struct, it's all ok. We can still pass
// it to OleCreate() and pretend that it's an ordinary IOleClientSite. We'll call this new struct a
// _IOleClientSiteEx.
//
// And because we may want to create multiple windows, each hosting its own browser object (to
// display its own web page), then we need to create a unique _IOleClientSiteEx struct for
// each window. So, we're not going to declare this struct globally. We'll allocate it later
// using GlobalAlloc, and then initialize the structs within it.
typedef struct {
IOleInPlaceSite inplace; // My IOleInPlaceSite object. Must be first with in _IOleInPlaceSiteEx.
///////////////////////////////////////////////////
// Here you add any extra variables that you need
// to access in your IOleInPlaceSite functions.
//
// So here is where I added my IOleInPlaceFrame
// struct. If you need extra variables, add them
// at the end.
///////////////////////////////////////////////////
_IOleInPlaceFrameEx frame; // My IOleInPlaceFrame object. Must be first within my _IOleInPlaceFrameEx
} _IOleInPlaceSiteEx;
typedef struct {
IDocHostUIHandler ui; // My IDocHostUIHandler object. Must be first.
///////////////////////////////////////////////////
// Here you add any extra variables that you need
// to access in your IDocHostUIHandler functions.
///////////////////////////////////////////////////
} _IDocHostUIHandlerEx;
typedef struct {
IOleClientSite client; // My IOleClientSite object. Must be first.
_IOleInPlaceSiteEx inplace; // My IOleInPlaceSite object. A convenient place to put it.
_IDocHostUIHandlerEx ui; // My IDocHostUIHandler object. Must be first within my _IDocHostUIHandlerEx.
///////////////////////////////////////////////////
// Here you add any extra variables that you need
// to access in your IOleClientSite functions.
///////////////////////////////////////////////////
} _IOleClientSiteEx;
// This is a simple C example. There are lots more things you can control about the browser object, but
// we don't do it in this example. _Many_ of the functions we provide below for the browser to call, will
// never actually be called by the browser in our example. Why? Because we don't do certain things
// with the browser that would require it to call those functions (even though we need to provide
// at least some stub for all of the functions).
//
// So, for these "dummy functions" that we don't expect the browser to call, we'll just stick in some
// assembly code that causes a debugger breakpoint and tells the browser object that we don't support
// the functionality. That way, if you try to do more things with the browser object, and it starts
// calling these "dummy functions", you'll know which ones you should add more meaningful code to.
#define NOTIMPLEMENTED _ASSERT(0); return(E_NOTIMPL)
//////////////////////////////////// My IDocHostUIHandler functions //////////////////////////////////////
// The browser object asks us for the pointer to our IDocHostUIHandler object by calling our IOleClientSite's
// QueryInterface (ie, Site_QueryInterface) and specifying a REFIID of IID_IDocHostUIHandler.
//
// NOTE: You need at least IE 4.0. Previous versions do not ask for, nor utilize, our IDocHostUIHandler functions.
HRESULT STDMETHODCALLTYPE UI_QueryInterface(IDocHostUIHandler *This, REFIID riid, LPVOID *ppvObj)
{
// The browser assumes that our IDocHostUIHandler object is associated with our IOleClientSite
// object. So it is possible that the browser may call our IDocHostUIHandler's QueryInterface()
// to ask us to return a pointer to our IOleClientSite, in the same way that the browser calls
// our IOleClientSite's QueryInterface() to ask for a pointer to our IDocHostUIHandler.
//
// Rather than duplicate much of the code in IOleClientSite's QueryInterface, let's just get
// a pointer to our _IOleClientSiteEx object, substitute it as the 'This' arg, and call our
// our IOleClientSite's QueryInterface. Note that since our _IDocHostUIHandlerEx is embedded right
// inside our _IOleClientSiteEx, and comes immediately after the _IOleInPlaceSiteEx, we can employ
// the following trickery to get the pointer to our _IOleClientSiteEx.
return(Site_QueryInterface((IOleClientSite *)((char *)This - sizeof(IOleClientSite) - sizeof(_IOleInPlaceSiteEx)), riid, ppvObj));
}
HRESULT STDMETHODCALLTYPE UI_AddRef(IDocHostUIHandler *This)
{
return(1);
}
HRESULT STDMETHODCALLTYPE UI_Release(IDocHostUIHandler *This)
{
return(1);
}
// Called when the browser object is about to display its context menu.
HRESULT STDMETHODCALLTYPE UI_ShowContextMenu(IDocHostUIHandler *This, DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
{
// If desired, we can pop up your own custom context menu here. Of course,
// we would need some way to get our window handle, so what we'd probably
// do is like what we did with our IOleInPlaceFrame object. We'd define and create
// our own IDocHostUIHandlerEx object with an embedded IDocHostUIHandler at the
// start of it. Then we'd add an extra HWND field to store our window handle.
// It could look like this:
//
// typedef struct _IDocHostUIHandlerEx {
// IDocHostUIHandler ui; // The IDocHostUIHandler must be first!
// HWND window;
// } IDocHostUIHandlerEx;
//
// Of course, we'd need a unique IDocHostUIHandlerEx object for each window, so
// EmbedBrowserObject() would have to allocate one of those too. And that's
// what we'd pass to our browser object (and it would in turn pass it to us
// here, instead of 'This' being a IDocHostUIHandler *).
// We will return S_OK to tell the browser not to display its default context menu,
// or return S_FALSE to let the browser show its default context menu. For this
// example, we wish to disable the browser's default context menu.
return(S_FALSE);
}
// Called at initialization of the browser object UI. We can set various features of the browser object here.
HRESULT STDMETHODCALLTYPE UI_GetHostInfo(IDocHostUIHandler * This, DOCHOSTUIINFO *pInfo)
{
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
// Set some flags. We don't want any 3D border. You can do other things like hide
// the scroll bar (DOCHOSTUIFLAG_SCROLL_NO), display picture display (DOCHOSTUIFLAG_NOPICS),
// disable any script running when the page is loaded (DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE),
// open a site in a new browser window when the user clicks on some link (DOCHOSTUIFLAG_OPENNEWWIN),
// and lots of other things. See the MSDN docs on the DOCHOSTUIINFO struct passed to us.
pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER;
// Set what happens when the user double-clicks on the object. Here we use the default.
pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
return(S_OK);
}
// Called when the browser object shows its UI. This allows us to replace its menus and toolbars by creating our
// own and displaying them here.
HRESULT STDMETHODCALLTYPE UI_ShowUI(IDocHostUIHandler *This, DWORD dwID, IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
{
// We've already got our own UI in place so just return S_OK to tell the browser
// not to display its menus/toolbars. Otherwise we'd return S_FALSE to let it do
// that.
return(S_OK);
}
// Called when browser object hides its UI. This allows us to hide any menus/toolbars we created in ShowUI.
HRESULT STDMETHODCALLTYPE UI_HideUI(IDocHostUIHandler *This)
{
return(S_OK);
}
// Called when the browser object wants to notify us that the command state has changed. We should update any
// controls we have that are dependent upon our embedded object, such as "Back", "Forward", "Stop", or "Home"
// buttons.
HRESULT STDMETHODCALLTYPE UI_UpdateUI(IDocHostUIHandler *This)
{
// We update our UI in our window message loop so we don't do anything here.
return(S_OK);
}
// Called from the browser object's IOleInPlaceActiveObject object's EnableModeless() function. Also
// called when the browser displays a modal dialog box.
HRESULT STDMETHODCALLTYPE UI_EnableModeless(IDocHostUIHandler *This, BOOL fEnable)
{
return(S_OK);
}
// Called from the browser object's IOleInPlaceActiveObject object's OnDocWindowActivate() function.
// This informs off of when the object is getting/losing the focus.
HRESULT STDMETHODCALLTYPE UI_OnDocWindowActivate(IDocHostUIHandler *This, BOOL fActivate)
{
return(S_OK);
}
// Called from the browser object's IOleInPlaceActiveObject object's OnFrameWindowActivate() function.
HRESULT STDMETHODCALLTYPE UI_OnFrameWindowActivate(IDocHostUIHandler *This, BOOL fActivate)
{
return(S_OK);
}
// Called from the browser object's IOleInPlaceActiveObject object's ResizeBorder() function.
HRESULT STDMETHODCALLTYPE UI_ResizeBorder(IDocHostUIHandler *This, LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
{
return(S_OK);
}
// Called from the browser object's TranslateAccelerator routines to translate key strokes to commands.
HRESULT STDMETHODCALLTYPE UI_TranslateAccelerator(IDocHostUIHandler *This, LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
{
// We don't intercept any keystrokes, so we do nothing here. But for example, if we wanted to
// override the TAB key, perhaps do something with it ourselves, and then tell the browser
// not to do anything with this keystroke, we'd do:
//
// if (pMsg && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB)
// {
// // Here we do something as a result of a TAB key press.
//
// // Tell the browser not to do anything with it.
// return(S_FALSE);
// }
//
// // Otherwise, let the browser do something with this message.
// return(S_OK);
// For our example, we want to make sure that the user can invoke some key to popup the context
// menu, so we'll tell it to ignore all messages.
return(S_FALSE);
}
// Called by the browser object to find where the host wishes the browser to get its options in the registry.
// We can use this to prevent the browser from using its default settings in the registry, by telling it to use
// some other registry key we've setup with the options we want.
HRESULT STDMETHODCALLTYPE UI_GetOptionKeyPath(IDocHostUIHandler *This, LPOLESTR *pchKey, DWORD dw)
{
// Let the browser use its default registry settings.
return(S_FALSE);
}
// Called by the browser object when it is used as a drop target. We can supply our own IDropTarget object,
// IDropTarget functions, and IDropTarget VTable if we want to determine what happens when someone drags and
// drops some object on our embedded browser object.
HRESULT STDMETHODCALLTYPE UI_GetDropTarget(IDocHostUIHandler *This, IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
{
// Return our IDropTarget object associated with this IDocHostUIHandler object. I don't
// know why we don't do this via UI_QueryInterface(), but we don't.
// NOTE: If we want/need an IDropTarget interface, then we would have had to setup our own
// IDropTarget functions, IDropTarget VTable, and create an IDropTarget object. We'd want to put
// a pointer to the IDropTarget object in our own custom IDocHostUIHandlerEx object (like how
// we may add an HWND field for the use of UI_ShowContextMenu). So when we created our
// IDocHostUIHandlerEx object, maybe we'd add a 'idrop' field to the end of it, and
// store a pointer to our IDropTarget object there. Then we could return this pointer as so:
//
// *pDropTarget = ((IDocHostUIHandlerEx *)This)->idrop;
// return(S_OK);
// But for our purposes, we don't need an IDropTarget object, so we'll tell whomever is calling
// us that we don't have one.
return(S_FALSE);
}
// Called by the browser when it wants a pointer to our IDispatch object. This object allows us to expose
// our own automation interface (ie, our own COM objects) to other entities that are running within the
// context of the browser so they can call our functions if they want. An example could be a javascript
// running in the URL we display could call our IDispatch functions. We'd write them so that any args passed
// to them would use the generic datatypes like a BSTR for utmost flexibility.
HRESULT STDMETHODCALLTYPE UI_GetExternal(IDocHostUIHandler *This, IDispatch **ppDispatch)
{
// Return our IDispatch object associated with this IDocHostUIHandler object. I don't
// know why we don't do this via UI_QueryInterface(), but we don't.
// NOTE: If we want/need an IDispatch interface, then we would have had to setup our own
// IDispatch functions, IDispatch VTable, and create an IDispatch object. We'd want to put
// a pointer to the IDispatch object in our custom _IDocHostUIHandlerEx object (like how
// we may add an HWND field for the use of UI_ShowContextMenu). So when we defined our
// _IDocHostUIHandlerEx object, maybe we'd add a 'idispatch' field to the end of it, and
// store a pointer to our IDispatch object there. Then we could return this pointer as so:
//
// *ppDispatch = ((_IDocHostUIHandlerEx *)This)->idispatch;
// return(S_OK);
// But for our purposes, we don't need an IDispatch object, so we'll tell whomever is calling
// us that we don't have one. Note: We must set ppDispatch to 0 if we don't return our own
// IDispatch object.
*ppDispatch = 0;
return(S_FALSE);
}
/* **************************** asciiToNum() ***************************
* Converts the string of digits (expressed in base 10) to a 32-bit
* DWORD.
*
* val = Pointer to the nul-terminated string of digits to convert.
*
* RETURNS: The integer value as a DWORD.
*
* NOTE: Skips leading spaces before the first digit.
*/
DWORD asciiToNum(OLECHAR *val)
{
OLECHAR chr;
DWORD len;
// Result is initially 0
len = 0;
// Skip leading spaces
while (*val == ' ' || *val == 0x09) val++;
// Convert next digit
while (*val)
{
chr = *(val)++ - '0';
if ((DWORD)chr > 9) break;
len += (len + (len << 3) + chr);
}
return(len);
}
unsigned char AppUrl[] = {'a', 0, 'p', 0, 'p', 0, ':', 0};
wchar_t Blank[] = {L"about:blank"};
// Called by the browser object to give us an opportunity to modify the URL to be loaded.
HRESULT STDMETHODCALLTYPE UI_TranslateUrl(IDocHostUIHandler *This, DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
{
unsigned short *src;
unsigned short *dest;
DWORD len;
// Get length of URL
src = pchURLIn;
while ((*(src)++));
--src;
len = src - pchURLIn;
// See if the URL starts with 'app:'
if (len >= 4 && !_wcsnicmp(pchURLIn, (wchar_t *)&AppUrl[0], 4))
{
// Allocate a new buffer to return an "about:blank" URL
if ((dest = (OLECHAR *)CoTaskMemAlloc(12<<1)))
{
HWND hwnd;
*ppchURLOut = dest;
// Return "about:blank"
CopyMemory(dest, &Blank[0], 12<<1);
// Convert the number after the "app:"
len = asciiToNum(pchURLIn + 4);
// Get our host window. That was stored in our _IOleInPlaceFrameEx
hwnd = ((_IOleInPlaceSiteEx *)((char *)This - sizeof(_IOleInPlaceSiteEx)))->frame.window;
// Post a message to this window using WM_APP + 50, and pass the number converted above.
// Do not SendMessage()!. Post instead, since the browser does not like us changing
// the URL within this here callback. Why not WM_APP? Because the browser control appears
// to use messages within the range of WM_APP to WM_APP + 2 (and maybe more). Microsoft
// is a bit careless here. Supposedly, the operating system components, of which
// MSHTML.DLL is now a part, are not supposed to use WM_APP and over, but no...
// What we should probably do is RegisterWindowMessage()
PostMessage(hwnd, WM_APP + 50, (WPARAM)len, 0);
// Tell browser that we returned a URL
return(S_OK);
}
}
// We don't need to modify the URL. Note: We need to set ppchURLOut to 0 if we don't
// return an OLECHAR (buffer) containing a modified version of pchURLIn.
*ppchURLOut = 0;
return(S_FALSE);
}
// Called by the browser when it does cut/paste to the clipboard. This allows us to block certain clipboard
// formats or support additional clipboard formats.
HRESULT STDMETHODCALLTYPE UI_FilterDataObject(IDocHostUIHandler *This, IDataObject *pDO, IDataObject **ppDORet)
{
// Return our IDataObject object associated with this IDocHostUIHandler object. I don't
// know why we don't do this via UI_QueryInterface(), but we don't.
// NOTE: If we want/need an IDataObject interface, then we would have had to setup our own
// IDataObject functions, IDataObject VTable, and create an IDataObject object. We'd want to put
// a pointer to the IDataObject object in our custom _IDocHostUIHandlerEx object (like how
// we may add an HWND field for the use of UI_ShowContextMenu). So when we defined our
// _IDocHostUIHandlerEx object, maybe we'd add a 'idata' field to the end of it, and
// store a pointer to our IDataObject object there. Then we could return this pointer as so:
//
// *ppDORet = ((_IDocHostUIHandlerEx *)This)->idata;
// return(S_OK);
// But for our purposes, we don't need an IDataObject object, so we'll tell whomever is calling
// us that we don't have one. Note: We must set ppDORet to 0 if we don't return our own
// IDataObject object.
*ppDORet = 0;
return(S_FALSE);
}
////////////////////////////////////// My IOleClientSite functions /////////////////////////////////////
// We give the browser object a pointer to our IOleClientSite object when we call OleCreate() or DoVerb().
/************************* Site_QueryInterface() *************************
* The browser object calls this when it wants a pointer to one of our
* IOleClientSite, IDocHostUIHandler, or IOleInPlaceSite structures. They
* are all accessible via the _IOleClientSiteEx struct we allocated in
* EmbedBrowserObject() and passed to DoVerb() and OleCreate().
*
* This = A pointer to whatever _IOleClientSiteEx struct we passed to
* OleCreate() or DoVerb().
* riid = A GUID struct that the browser passes us to clue us as to
* which type of struct (object) it would like a pointer
* returned for.
* ppvObject = Where the browser wants us to return a pointer to the
* appropriate struct. (ie, It passes us a handle to fill in).
*
* RETURNS: S_OK if we return the struct, or E_NOINTERFACE if we don't have
* the requested struct.
*/
HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite *This, REFIID riid, void ** ppvObject)
{
// It just so happens that the first arg passed to us is our _IOleClientSiteEx struct we allocated
// and passed to DoVerb() and OleCreate(). Nevermind that 'This' is declared is an IOleClientSite *.
// Remember that in EmbedBrowserObject(), we allocated our own _IOleClientSiteEx struct, and lied
// to OleCreate() and DoVerb() -- passing our _IOleClientSiteEx struct and saying it was an
// IOleClientSite struct. It's ok. An _IOleClientSiteEx starts with an embedded IOleClientSite, so
// the browser didn't mind. So that's what the browser object is passing us now. The browser doesn't
// know that it's really an _IOleClientSiteEx struct. But we do. So we can recast it and use it as
// so here.
// If the browser is asking us to match IID_IOleClientSite, then it wants us to return a pointer to
// our IOleClientSite struct. Then the browser will use the VTable in that struct to call our
// IOleClientSite functions. It will also pass this same pointer to all of our IOleClientSite
// functions.
//
// Actually, we're going to lie to the browser again. We're going to return our own _IOleClientSiteEx
// struct, and tell the browser that it's a IOleClientSite struct. It's ok. The first thing in our
// _IOleClientSiteEx is an embedded IOleClientSite, so the browser doesn't mind. We want the browser
// to continue passing our _IOleClientSiteEx pointer wherever it would normally pass a IOleClientSite
// pointer.
//
// The IUnknown interface uses the same VTable as the first object in our _IOleClientSiteEx
// struct (which happens to be an IOleClientSite). So if the browser is asking us to match
// IID_IUnknown, then we'll also return a pointer to our _IOleClientSiteEx.
if (!memcmp(riid, &IID_IUnknown, sizeof(GUID)) || !memcmp(riid, &IID_IOleClientSite, sizeof(GUID)))
*ppvObject = &((_IOleClientSiteEx *)This)->client;
// If the browser is asking us to match IID_IOleInPlaceSite, then it wants us to return a pointer to
// our IOleInPlaceSite struct. Then the browser will use the VTable in that struct to call our
// IOleInPlaceSite functions. It will also pass this same pointer to all of our IOleInPlaceSite
// functions (except for Site_QueryInterface, Site_AddRef, and Site_Release. Those will always get
// the pointer to our _IOleClientSiteEx.
//
// Actually, we're going to lie to the browser. We're going to return our own _IOleInPlaceSiteEx
// struct, and tell the browser that it's a IOleInPlaceSite struct. It's ok. The first thing in
// our _IOleInPlaceSiteEx is an embedded IOleInPlaceSite, so the browser doesn't mind. We want the
// browser to continue passing our _IOleInPlaceSiteEx pointer wherever it would normally pass a
// IOleInPlaceSite pointer.
else if (!memcmp(riid, &IID_IOleInPlaceSite, sizeof(GUID)))
*ppvObject = &((_IOleClientSiteEx *)This)->inplace;
// If the browser is asking us to match IID_IDocHostUIHandler, then it wants us to return a pointer to
// our IDocHostUIHandler struct. Then the browser will use the VTable in that struct to call our
// IDocHostUIHandler functions. It will also pass this same pointer to all of our IDocHostUIHandler
// functions (except for Site_QueryInterface, Site_AddRef, and Site_Release. Those will always get
// the pointer to our _IOleClientSiteEx.
//
// Actually, we're going to lie to the browser. We're going to return our own _IDocHostUIHandlerEx
// struct, and tell the browser that it's a IDocHostUIHandler struct. It's ok. The first thing in
// our _IDocHostUIHandlerEx is an embedded IDocHostUIHandler, so the browser doesn't mind. We want the
// browser to continue passing our _IDocHostUIHandlerEx pointer wherever it would normally pass a
// IDocHostUIHandler pointer. My, we're really playing dirty tricks on the browser here. heheh.
else if (!memcmp(riid, &IID_IDocHostUIHandler, sizeof(GUID)))
*ppvObject = &((_IOleClientSiteEx *)This)->ui;
// For other types of objects the browser wants, just report that we don't have any such objects.
// NOTE: If you want to add additional functionality to your browser hosting, you may need to
// provide some more objects here. You'll have to investigate what the browser is asking for
// (ie, what REFIID it is passing).
else
{
*ppvObject = 0;
return(E_NOINTERFACE);
}
return(S_OK);
}
HRESULT STDMETHODCALLTYPE Site_AddRef(IOleClientSite *This)
{
return(1);
}
HRESULT STDMETHODCALLTYPE Site_Release(IOleClientSite *This)
{
return(1);
}
HRESULT STDMETHODCALLTYPE Site_SaveObject(IOleClientSite *This)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE Site_GetMoniker(IOleClientSite *This, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker ** ppmk)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE Site_GetContainer(IOleClientSite *This, LPOLECONTAINER *ppContainer)
{
// Tell the browser that we are a simple object and don't support a container
*ppContainer = 0;
return(E_NOINTERFACE);
}
HRESULT STDMETHODCALLTYPE Site_ShowObject(IOleClientSite *This)
{
return(NOERROR);
}
HRESULT STDMETHODCALLTYPE Site_OnShowWindow(IOleClientSite *This, BOOL fShow)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE Site_RequestNewObjectLayout(IOleClientSite *This)
{
NOTIMPLEMENTED;
}
////////////////////////////////////// My IOleInPlaceSite functions /////////////////////////////////////
// The browser object asks us for the pointer to our IOleInPlaceSite object by calling our IOleClientSite's
// QueryInterface (ie, Site_QueryInterface) and specifying a REFIID of IID_IOleInPlaceSite.
HRESULT STDMETHODCALLTYPE InPlace_QueryInterface(IOleInPlaceSite *This, REFIID riid, LPVOID *ppvObj)
{
// The browser assumes that our IOleInPlaceSite object is associated with our IOleClientSite
// object. So it is possible that the browser may call our IOleInPlaceSite's QueryInterface()
// to ask us to return a pointer to our IOleClientSite, in the same way that the browser calls
// our IOleClientSite's QueryInterface() to ask for a pointer to our IOleInPlaceSite.
//
// Rather than duplicate much of the code in IOleClientSite's QueryInterface, let's just get
// a pointer to our _IOleClientSiteEx object, substitute it as the 'This' arg, and call our
// our IOleClientSite's QueryInterface. Note that since our IOleInPlaceSite is embedded right
// inside our _IOleClientSiteEx, and comes immediately after the IOleClientSite, we can employ
// the following trickery to get the pointer to our _IOleClientSiteEx.
return(Site_QueryInterface((IOleClientSite *)((char *)This - sizeof(IOleClientSite)), riid, ppvObj));
}
HRESULT STDMETHODCALLTYPE InPlace_AddRef(IOleInPlaceSite *This)
{
return(1);
}
HRESULT STDMETHODCALLTYPE InPlace_Release(IOleInPlaceSite *This)
{
return(1);
}
HRESULT STDMETHODCALLTYPE InPlace_GetWindow(IOleInPlaceSite *This, HWND *lphwnd)
{
// Return the HWND of the window that contains this browser object. We stored that
// HWND in our _IOleInPlaceSiteEx struct. Nevermind that the function declaration for
// Site_GetWindow says that 'This' is an IOleInPlaceSite *. Remember that in
// EmbedBrowserObject(), we allocated our own _IOleInPlaceSiteEx struct which
// contained an embedded IOleInPlaceSite struct within it. And when the browser
// called Site_QueryInterface() to get a pointer to our IOleInPlaceSite object, we
// returned a pointer to our _IOleClientSiteEx. The browser doesn't know this. But
// we do. That's what we're really being passed, so we can recast it and use it as
// so here.
*lphwnd = ((_IOleInPlaceSiteEx *)This)->frame.window;
return(S_OK);
}
HRESULT STDMETHODCALLTYPE InPlace_ContextSensitiveHelp(IOleInPlaceSite *This, BOOL fEnterMode)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE InPlace_CanInPlaceActivate(IOleInPlaceSite *This)
{
// Tell the browser we can in place activate
return(S_OK);
}
HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceActivate(IOleInPlaceSite *This)
{
// Tell the browser we did it ok
return(S_OK);
}
HRESULT STDMETHODCALLTYPE InPlace_OnUIActivate(IOleInPlaceSite *This)
{
return(S_OK);
}
HRESULT STDMETHODCALLTYPE InPlace_GetWindowContext(IOleInPlaceSite *This, LPOLEINPLACEFRAME *lplpFrame, LPOLEINPLACEUIWINDOW *lplpDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
// Give the browser the pointer to our IOleInPlaceFrame struct. We stored that pointer
// in our _IOleInPlaceSiteEx struct. Nevermind that the function declaration for
// Site_GetWindowContext says that 'This' is an IOleInPlaceSite *. Remember that in
// EmbedBrowserObject(), we allocated our own _IOleInPlaceSiteEx struct which
// contained an embedded IOleInPlaceSite struct within it. And when the browser
// called Site_QueryInterface() to get a pointer to our IOleInPlaceSite object, we
// returned a pointer to our _IOleClientSiteEx. The browser doesn't know this. But
// we do. That's what we're really being passed, so we can recast it and use it as
// so here.
//
// Actually, we're giving the browser a pointer to our own _IOleInPlaceSiteEx struct,
// but telling the browser that it's a IOleInPlaceSite struct. No problem. Our
// _IOleInPlaceSiteEx starts with an embedded IOleInPlaceSite, so the browser is
// cool with it. And we want the browser to pass a pointer to this _IOleInPlaceSiteEx
// wherever it would pass a IOleInPlaceSite struct to our IOleInPlaceSite functions.
*lplpFrame = (LPOLEINPLACEFRAME)&((_IOleInPlaceSiteEx *)This)->frame;
// We have no OLEINPLACEUIWINDOW
*lplpDoc = 0;
// Fill in some other info for the browser
lpFrameInfo->fMDIApp = FALSE;
lpFrameInfo->hwndFrame = ((_IOleInPlaceFrameEx *)*lplpFrame)->window;
lpFrameInfo->haccel = 0;
lpFrameInfo->cAccelEntries = 0;
// Give the browser the dimensions of where it can draw. We give it our entire window to fill.
// We do this in InPlace_OnPosRectChange() which is called right when a window is first
// created anyway, so no need to duplicate it here.
// GetClientRect(lpFrameInfo->hwndFrame, lprcPosRect);
// GetClientRect(lpFrameInfo->hwndFrame, lprcClipRect);
return(S_OK);
}
HRESULT STDMETHODCALLTYPE InPlace_Scroll(IOleInPlaceSite *This, SIZE scrollExtent)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE InPlace_OnUIDeactivate(IOleInPlaceSite *This, BOOL fUndoable)
{
return(S_OK);
}
HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceDeactivate(IOleInPlaceSite *This)
{
return(S_OK);
}
HRESULT STDMETHODCALLTYPE InPlace_DiscardUndoState(IOleInPlaceSite *This)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE InPlace_DeactivateAndUndo(IOleInPlaceSite *This)
{
NOTIMPLEMENTED;
}
// Called when the position of the browser object is changed, such as when we call the IWebBrowser2's put_Width(),
// put_Height(), put_Left(), or put_Right().
HRESULT STDMETHODCALLTYPE InPlace_OnPosRectChange(IOleInPlaceSite *This, LPCRECT lprcPosRect)
{
IOleObject *browserObject;
IOleInPlaceObject *inplace;
// We need to get the browser's IOleInPlaceObject object so we can call its SetObjectRects
// function.
browserObject = *((IOleObject **)((char *)This - sizeof(IOleObject *) - sizeof(IOleClientSite)));
if (!browserObject->lpVtbl->QueryInterface(browserObject, &IID_IOleInPlaceObject, (void**)&inplace))
{
// Give the browser the dimensions of where it can draw.
inplace->lpVtbl->SetObjectRects(inplace, lprcPosRect, lprcPosRect);
}
return(S_OK);
}
////////////////////////////////////// My IOleInPlaceFrame functions /////////////////////////////////////////
HRESULT STDMETHODCALLTYPE Frame_QueryInterface(IOleInPlaceFrame *This, REFIID riid, LPVOID *ppvObj)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE Frame_AddRef(IOleInPlaceFrame *This)
{
return(1);
}
HRESULT STDMETHODCALLTYPE Frame_Release(IOleInPlaceFrame *This)
{
return(1);
}
HRESULT STDMETHODCALLTYPE Frame_GetWindow(IOleInPlaceFrame *This, HWND *lphwnd)
{
// Give the browser the HWND to our window that contains the browser object. We
// stored that HWND in our IOleInPlaceFrame struct. Nevermind that the function
// declaration for Frame_GetWindow says that 'This' is an IOleInPlaceFrame *. Remember
// that in EmbedBrowserObject(), we allocated our own IOleInPlaceFrameEx struct which
// contained an embedded IOleInPlaceFrame struct within it. And then we lied when
// Site_GetWindowContext() returned that IOleInPlaceFrameEx. So that's what the
// browser is passing us. It doesn't know that. But we do. So we can recast it and
// use it as so here.
*lphwnd = ((_IOleInPlaceFrameEx *)This)->window;
return(S_OK);
}
HRESULT STDMETHODCALLTYPE Frame_ContextSensitiveHelp(IOleInPlaceFrame *This, BOOL fEnterMode)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE Frame_GetBorder(IOleInPlaceFrame *This, LPRECT lprectBorder)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE Frame_RequestBorderSpace(IOleInPlaceFrame *This, LPCBORDERWIDTHS pborderwidths)
{
NOTIMPLEMENTED;
}