这是一个从C移植到D的代码,原文请见“
Embed an HTML control in your own window using plain C”,它用C结构模拟了虚表,并且实现了多个接口以完成对Web Browser控件的调用。
在看完他的代码之后,我对于COM/OLE的了解加深了一些,以前使用VC做过COM方面的应用,也看过不少COM方面的书,不过没有涉及到界面,所以一直不知道如何把ActiveX嵌入到自己的项目中,我指的是纯手工实现,不依赖MFC/ATL。
既然是理解了,当然要把它作出来才算数,以日久又忘了。
另外要解释一下使用D语言的原因。实际上使用C++也可达到一样的效果,只是最近突然觉得使用C++很烦,而D语言又是一个很好的补充,又一直仰慕D语言作者的大名,再加上想检验D语言实际开发能力,所以这次就用它做刀了。
注:对C++觉得烦的一个重要原因,是在阅读很多优秀的C++库时,被那些宏搞得火冒三丈,难道代码非得这样写?现代的计算机语言只需要处理记号,而不是字符串,而宏却是字符串的典型,这也影响了C++程序的编译速度。或许D语言不能真正解决这个问题,但暂时还没看到令我特别不爽的东西,所以将就着用吧,反正还在Alpha阶段,也就是说语言本身也一直在改进,也一直有人在提一些改进意见,还是有些希望的。D语言作者作为优秀的Symantic C++编译器的作者,把C++的高效也带进D里面,所以我对D语言还是有很大期望的。言规正传,先来看看要在自己在窗口里嵌入HTML control要做哪些事。简单罗列如下:
1、初始化OLE环境
2、创建一个窗口,作为ActiveX的宿主窗口
3、实现一个IStorage对象,实际上不用它来做任何事,只是OleCreate函数需要这样一个对象
4、实现IOleInPlaceSite, IOleInPlaceFrame, IOleClientSite, IDocHostUIHandler接口
5、其它就是调用了。。。
这里所列的项目没有明确的分类标准,大概同时讲了要实现的接口和代码处理过程,具体看代码吧。
由于D语言的标准库phobos没有列出我们所需要的大部分COM接口,所以需要core32,可以从
http://www.dsource.org/projects/core32/下载(或SVN)。这个也不是很完整,所以在程序里我还是要定义几个变量:
static const IID IID_IWebBrowser2 =
{0xD30C1661, 0xCDAF, 0x11d0, [0x8A, 0x3E, 0x0, 0xC0, 0x4F, 0xC9, 0xE2, 0x6E]};
static const CLSID CLSID_WebBrowser =
{0x8856F961, 0x340A, 0x11D0, [0xA9, 0x6B, 0x0, 0xC0, 0x4F, 0xD7, 0x05, 0xA2]};
static const IID IID_IDocHostUIHandler =
{0xbd3f23c0, 0xd43e, 0x11cf, [0x89, 0x3b, 0x0, 0xaa, 0x0, 0xbd, 0xce, 0x1a]};
下面是完整代码:
private import std.stdio;
private import std.string;
private import win32.ole2;
private import win32.com.OAIDL;
private import win32.com.OLEIDL;
private import win32.com.EXDISP;
private import win32.com.MSHTMHST;
char[] ClassName = "Test Wnd Class";
static const IID IID_IWebBrowser2 =
{0xD30C1661, 0xCDAF, 0x11d0, [0x8A, 0x3E, 0x0, 0xC0, 0x4F, 0xC9, 0xE2, 0x6E]};
static const CLSID CLSID_WebBrowser =
{0x8856F961, 0x340A, 0x11D0, [0xA9, 0x6B, 0x0, 0xC0, 0x4F, 0xD7, 0x05, 0xA2]};
static const IID IID_IDocHostUIHandler =
{0xbd3f23c0, 0xd43e, 0x11cf, [0x89, 0x3b, 0x0, 0xaa, 0x0, 0xbd, 0xce, 0x1a]};
extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleDtor();
extern (C) void _moduleUnitTests();
extern (Windows)
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
int result;
gc_init(); // initialize garbage collector
_minit(); // initialize module constructor table
try
{
_moduleCtor(); // call module constructors
_moduleUnitTests(); // run unit tests (optional)
result = myWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
_moduleDtor(); // call module destructors
}
catch (Object o) // catch any uncaught exceptions
{
MessageBoxA(null, cast(char *)o.toString(), "Error",
MB_OK | MB_ICONEXCLAMATION);
result = 0; // failed
}
gc_term(); // run finalizers; terminate garbage collector
return result;
}
// A running count of how many windows we have open that contain a browser object
uint WindowCount = 0;
// This is used by DisplayHTMLStr(). It can be global because we never change it.
static const SAFEARRAYBOUND ArrayBound = {1, 0};
IOleObject g_browserObject = null;
class MyStorage : IStorage
{
this ()
in {writefln ("In MyStorage.this");}
out {writefln ("Out MyStorage.this");}
body{
}
~this()
in {writefln ("In MyStorage.~this");}
out {writefln ("Out MyStorage.~this");}
body{
}
HRESULT QueryInterface(IID* riid, void** pvObject)
in {writefln ("In MyStorage.QueryInterface");}
out {writefln ("Out MyStorage.QueryInterface");}
body{
return E_NOTIMPL;
}
ULONG AddRef ()
in {writefln ("In MyStorage.AddRef");}
out {writefln ("Out MyStorage.AddRef");}
body {
return 1;
}
ULONG Release ()
in {writefln ("In MyStorage.Release");}
out {writefln ("Out MyStorage.Release");}
body {
return 1;
}
HRESULT CreateStream( OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream * ppstm)
in {writefln ("In MyStorage.CreateStream");}
out {writefln ("Out MyStorage.CreateStream");}
body {
return E_NOTIMPL;
}
HRESULT OpenStream( OLECHAR *pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream * ppstm)
in {writefln ("In MyStorage.OpenStream");}
out {writefln ("Out MyStorage.OpenStream");}
body {
return E_NOTIMPL;
}
HRESULT CreateStorage( OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStorage * ppstg)
in {writefln ("In MyStorage.CreateStorage");}
out {writefln ("Out MyStorage.CreateStorage");}
body {
return E_NOTIMPL;
}
HRESULT OpenStorage( OLECHAR *pwcsName, IStorage pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage * ppstg )
in {writefln ("In MyStorage.OpenStorage");}
out {writefln ("Out MyStorage.OpenStorage");}
body {
return E_NOTIMPL;
}
HRESULT CopyTo( DWORD ciidExclude, IID *rgiidExclude, SNB snbExclude, IStorage pstgDest )
in {writefln ("In MyStorage.CopyTo");}
out {writefln ("Out MyStorage.CopyTo");}
body {
return E_NOTIMPL;
}
HRESULT MoveElementTo( OLECHAR * pwcsName, IStorage pstgDest, OLECHAR *pwcsNewName, DWORD grfFlags )
in {writefln ("In MyStorage.MoveElementTo");}
out {writefln ("Out MyStorage.MoveElementTo");}
body {
return E_NOTIMPL;
}
HRESULT Commit( DWORD grfCommitFlags )
in {writefln ("In MyStorage.Commit");}
out {writefln ("Out MyStorage.Commit");}
body {
return E_NOTIMPL;
}
HRESULT Revert()
in {writefln ("In MyStorage.Revert");}
out {writefln ("Out MyStorage.Revert");}
body {
return E_NOTIMPL;
}
HRESULT EnumElements( DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG * ppenum)
in {writefln ("In MyStorage.EnumElements");}
out {writefln ("Out MyStorage.EnumElements");}
body {
return E_NOTIMPL;
}
HRESULT DestroyElement( OLECHAR * pwcsName )
in {writefln ("In MyStorage.DestroyElement");}
out {writefln ("Out MyStorage.DestroyElement");}
body {
return E_NOTIMPL;
}
HRESULT RenameElement( OLECHAR *pwcsOldName, OLECHAR *pwcsNewName )
in {writefln ("In MyStorage.RenameElement");}
out {writefln ("Out MyStorage.RenameElement");}
body {
return E_NOTIMPL;
}
HRESULT SetElementTimes( OLECHAR * pwcsName, FILETIME * pctime, FILETIME *patime, FILETIME *pmtime )
in {writefln ("In MyStorage.SetElementTimes");}
out {writefln ("Out MyStorage.SetElementTimes");}
body {
return E_NOTIMPL;
}
HRESULT SetClass( REFCLSID clsid )
in {writefln ("In MyStorage.SetClass");}
out {writefln ("Out MyStorage.SetClass");}
body {
return S_OK;
}
HRESULT SetStateBits( DWORD grfStateBits, DWORD grfMask )
in {writefln ("In MyStorage.SetStateBits");}
out {writefln ("Out MyStorage.SetStateBits");}
body {
return E_NOTIMPL;
}
HRESULT Stat( STATSTG *pstatstg, DWORD grfStatFlag )
in {writefln ("In MyStorage.Stat");}
out {writefln ("Out MyStorage.Stat");}
body {
return E_NOTIMPL;
}
}
bool compare(IID* iid1, IID* iid2)
{
return !memcmp(iid1, iid2, IID.sizeof);
}
class OleInPlaceSite : IOleInPlaceSite, IOleInPlaceFrame, IOleClientSite, IDocHostUIHandler
{
private:
HWND hWnd;
public:
this (HWND hwnd)
in {writefln ("In OleInPlaceSite.this");}
out {writefln ("Out OleInPlaceSite.this");}
body {
this.hWnd = hwnd;
}
~this ()
in {writefln ("In OleInPlaceSite.~this");}
out {writefln ("Out OleInPlaceSite.~this");}
body {
}
protected:
ULONG AddRef ()
in {writefln ("In OleInPlaceSite.AddRef");}
out {writefln ("Out OleInPlaceSite.AddRef");}
body {
return 1;
}
ULONG Release ()
in {writefln ("In OleInPlaceSite.Release");}
out {writefln ("Out OleInPlaceSite.Release");}
body {
return 1;
}
HRESULT QueryInterface (IID* riid, void ** ppvObject)
in {writefln ("In OleInPlaceSite.QueryInterface");}
out {writefln ("Out OleInPlaceSite.QueryInterface");}
body {
if (compare(riid, &IID_IUnknown))
*ppvObject = cast(IUnknown)this;
else if (compare(riid, &IID_IOleClientSite))
*ppvObject = cast(IOleClientSite)this;
else if (compare(riid, &IID_IOleInPlaceSite))
{
writefln ("Ole In Place Site");
*ppvObject = cast(IOleInPlaceSite)this;
}
//else if (compare(riid, &IID_IOleInPlaceFrame))
// *ppvObject = cast(IOleInPlaceFrame)this;
else if (compare(riid, &IID_IDocHostUIHandler))
*ppvObject = cast(IDocHostUIHandler)this;
else
return E_NOINTERFACE;
return S_OK;
}
// IOleInPlaceFrame
HRESULT InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths )
in {writefln ("In OleInPlaceSite.InsertMenus");}
out {writefln ("Out OleInPlaceSite.InsertMenus");}
body{
return E_NOTIMPL;
}
HRESULT SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject )
in {writefln ("In OleInPlaceSite.SetMenu");}
out {writefln ("Out OleInPlaceSite.SetMenu");}
body{
return S_OK;
}
HRESULT RemoveMenus( HMENU hmenuShared )
in {writefln ("In OleInPlaceSite.RemoveMenus");}
out {writefln ("Out OleInPlaceSite.RemoveMenus");}
body{
return E_NOTIMPL;
}
HRESULT SetStatusText( LPCOLESTR pszStatusText )
in {writefln ("In OleInPlaceSite.SetStatusText");}
out {writefln ("Out OleInPlaceSite.SetStatusText");}
body{
return S_OK;
}
HRESULT TranslateAccelerator( LPMSG lpmsg, WORD wID )
in {writefln ("In OleInPlaceSite.TranslateAccelerator");}
out {writefln ("Out OleInPlaceSite.TranslateAccelerator");}
body{
return E_NOTIMPL;
}
// IOleInPlaceUIWindow
HRESULT GetBorder( LPRECT lprectBorder )
in {writefln ("In OleInPlaceSite.GetBorder");}
out {writefln ("Out OleInPlaceSite.GetBorder");}
body{
return E_NOTIMPL;
}
HRESULT RequestBorderSpace( LPCBORDERWIDTHS pborderwidths )
in {writefln ("In OleInPlaceSite.RequestBorderSpace");}
out {writefln ("Out OleInPlaceSite.RequestBorderSpace");}
body{
return E_NOTIMPL;
}
HRESULT SetBorderSpace( LPCBORDERWIDTHS pborderwidths )
in {writefln ("In OleInPlaceSite.SetBorderSpace");}
out {writefln ("Out OleInPlaceSite.SetBorderSpace");}
body{
return E_NOTIMPL;
}
HRESULT SetActiveObject( IOleInPlaceActiveObject pActiveObject, LPCOLESTR pszObjName )
in {writefln ("In OleInPlaceSite.SetActiveObject");}
out {writefln ("Out OleInPlaceSite.SetActiveObject");}
body{
return S_OK;
}
// IOleWindow
HRESULT GetWindow( HWND * phwnd )
in {writefln ("In OleInPlaceSite.GetWindow");}
out {writefln ("Out OleInPlaceSite.GetWindow");}
body{
*phwnd = hWnd;
return S_OK;
}
HRESULT ContextSensitiveHelp( BOOL fEnterMode )
in {writefln ("In OleInPlaceSite.ContextSensitiveHelp");}
out {writefln ("Out OleInPlaceSite.ContextSensitiveHelp");}
body{
return E_NOTIMPL;
}
// IOleInPlaceFrame
HRESULT CanInPlaceActivate()
in {writefln ("In OleInPlaceSite.CanInPlaceActivate");}
out {writefln ("Out OleInPlaceSite.CanInPlaceActivate");}
body{
return S_OK;
}
HRESULT OnInPlaceActivate()
in {writefln ("In OleInPlaceSite.OnInPlaceActivate");}
out {writefln ("Out OleInPlaceSite.OnInPlaceActivate");}
body{
return S_OK;
}
HRESULT OnUIActivate()
in {writefln ("In OleInPlaceSite.OnUIActivate");}
out {writefln ("Out OleInPlaceSite.OnUIActivate");}
body{
return S_OK;
}
HRESULT GetWindowContext( IOleInPlaceFrame * ppFrame, IOleInPlaceUIWindow * ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo )
in {writefln ("In OleInPlaceSite.GetWindowContext");}
out {writefln ("Out OleInPlaceSite.GetWindowContext");}
body{
*ppFrame = cast(IOleInPlaceFrame)this;
*ppDoc = null;
// Fill in some other info for the browser
lpFrameInfo.cb = lpFrameInfo.sizeof;
lpFrameInfo.fMDIApp = FALSE;
lpFrameInfo.hwndFrame = hWnd;
lpFrameInfo.haccel = null;
lpFrameInfo.cAccelEntries = 0;
return S_OK;
}
HRESULT Scroll( SIZE scrollExtant )
in {writefln ("In OleInPlaceSite.Scroll");}
out {writefln ("Out OleInPlaceSite.Scroll");}
body{
return E_NOTIMPL;
}
HRESULT OnUIDeactivate( BOOL fUndoable )
in {writefln ("In OleInPlaceSite.OnUIDeactivate");}
out {writefln ("Out OleInPlaceSite.OnUIDeactivate");}
body{
return S_OK;
}
HRESULT OnInPlaceDeactivate()
in {writefln ("In OleInPlaceSite.OnInPlaceDeactivate");}
out {writefln ("Out OleInPlaceSite.OnInPlaceDeactivate");}
body{
return S_OK;
}
HRESULT DiscardUndoState()
in {writefln ("In OleInPlaceSite.DiscardUndoState");}
out {writefln ("Out OleInPlaceSite.DiscardUndoState");}
body{
return E_NOTIMPL;
}
HRESULT DeactivateAndUndo()
in {writefln ("In OleInPlaceSite.DeactivateAndUndo");}
out {writefln ("Out OleInPlaceSite.DeactivateAndUndo");}
body{
return E_NOTIMPL;
}
HRESULT OnPosRectChange( LPCRECT lprcPosRect )
in {writefln ("In OleInPlaceSite.OnPosRectChange");}
out {writefln ("Out OleInPlaceSite.OnPosRectChange");}
body{
IOleInPlaceObject inplace;
if (!g_browserObject.QueryInterface(&IID_IOleInPlaceObject, cast(void**)&inplace))
{
// Give the browser the dimensions of where it can draw.
inplace.SetObjectRects(lprcPosRect, lprcPosRect);
inplace.Release();
}
return S_OK;
}
// IDocHostUIHandler
HRESULT ShowContextMenu( DWORD dwID, POINT* ppt, IUnknown pcmdtReserved, IDispatch pdispReserved)
in {writefln ("In OleInPlaceSite.ShowContextMenu");}
out {writefln ("Out OleInPlaceSite.ShowContextMenu");}
body {
return S_OK;
}
HRESULT GetHostInfo( DOCHOSTUIINFO * pInfo )
in {writefln ("In OleInPlaceSite.GetHostInfo");}
out {writefln ("Out OleInPlaceSite.GetHostInfo");}
body {
pInfo.cbSize = DOCHOSTUIINFO.sizeof;
pInfo.dwFlags = DOCHOSTUIFLAG_NO3DBORDER;
pInfo.dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
return(S_OK);
}
HRESULT ShowUI( DWORD dwID, IOleInPlaceActiveObject pActiveObject, IOleCommandTarget pCommandTarget, IOleInPlaceFrame pFrame, IOleInPlaceUIWindow pDoc )
in {writefln ("In OleInPlaceSite.ShowUI");}
out {writefln ("Out OleInPlaceSite.ShowUI");}
body {
return S_OK;
}
HRESULT HideUI()
in {writefln ("In OleInPlaceSite.HideUI");}
out {writefln ("Out OleInPlaceSite.HideUI");}
body{
return S_OK;
}
HRESULT UpdateUI()
in {writefln ("In OleInPlaceSite.UpdateUI");}
out {writefln ("Out OleInPlaceSite.UpdateUI");}
body{
return S_OK;
}
HRESULT EnableModeless( BOOL fEnable )
in {writefln ("In OleInPlaceSite.EnableModeless");}
out {writefln ("Out OleInPlaceSite.EnableModeless");}
body{
return S_OK;
}
HRESULT OnDocWindowActivate( BOOL fActivate )
in {writefln ("In OleInPlaceSite.OnDocWindowActivate");}
out {writefln ("Out OleInPlaceSite.OnDocWindowActivate");}
body{
return S_OK;
}
HRESULT OnFrameWindowActivate( BOOL fActivate )
in {writefln ("In OleInPlaceSite.OnFrameWindowActivate");}
out {writefln ("Out OleInPlaceSite.OnFrameWindowActivate");}
body{
return S_OK;
}
HRESULT ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow pUIWindow, BOOL fRameWindow )
in {writefln ("In OleInPlaceSite.ResizeBorder");}
out {writefln ("Out OleInPlaceSite.ResizeBorder");}
body{
return S_OK;
}
HRESULT TranslateAccelerator( LPMSG lpMsg, GUID * pguidCmdGroup, DWORD nCmdID )
in {writefln ("In OleInPlaceSite.TranslateAccelerator");}
out {writefln ("Out OleInPlaceSite.TranslateAccelerator");}
body{
return S_FALSE;
}
HRESULT GetOptionKeyPath( LPOLESTR * pchKey, DWORD dw )
in {writefln ("In OleInPlaceSite.GetOptionKeyPath");}
out {writefln ("Out OleInPlaceSite.GetOptionKeyPath");}
body{
return S_FALSE;
}
HRESULT GetDropTarget( IDropTarget pDropTarget, IDropTarget * ppDropTarget )
in {writefln ("In OleInPlaceSite.GetDropTarget");}
out {writefln ("Out OleInPlaceSite.GetDropTarget");}
body{
return S_FALSE;
}
HRESULT GetExternal( IDispatch * ppDispatch )
in {writefln ("In OleInPlaceSite.GetExternal");}
out {writefln ("Out OleInPlaceSite.GetExternal");}
body{
*ppDispatch = null;
return S_FALSE;
}
HRESULT TranslateUrl( DWORD dwTranslate, OLECHAR * pchURLIn, OLECHAR ** ppchURLOut )
in {writefln ("In OleInPlaceSite.TranslateUrl");}
out {writefln ("Out OleInPlaceSite.TranslateUrl");}
body{
*ppchURLOut = null;
return S_FALSE;
}
HRESULT FilterDataObject( IDataObject pDO, IDataObject * ppDORet )
in {writefln ("In OleInPlaceSite.FilterDataObject");}
out {writefln ("Out OleInPlaceSite.FilterDataObject");}
body{
*ppDORet = null;
return S_FALSE;
}
// IStorage
HRESULT CreateStream( OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream * ppstm)
in {writefln ("In OleInPlaceSite.CreateStream");}
out {writefln ("Out OleInPlaceSite.CreateStream");}
body{
return E_NOTIMPL;
}
HRESULT OpenStream( OLECHAR *pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream * ppstm)
in {writefln ("In OleInPlaceSite.OpenStream");}
out {writefln ("Out OleInPlaceSite.OpenStream");}
body{
return E_NOTIMPL;
}
HRESULT CreateStorage( OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStorage * ppstg)
in {writefln ("In OleInPlaceSite.CreateStorage");}
out {writefln ("Out OleInPlaceSite.CreateStorage");}
body{
return E_NOTIMPL;
}
HRESULT OpenStorage( OLECHAR *pwcsName, IStorage pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage * ppstg )
in {writefln ("In OleInPlaceSite.OpenStorage");}
out {writefln ("Out OleInPlaceSite.OpenStorage");}
body{
return E_NOTIMPL;
}
HRESULT CopyTo( DWORD ciidExclude, IID *rgiidExclude, SNB snbExclude, IStorage pstgDest )
in {writefln ("In OleInPlaceSite.CopyTo");}
out {writefln ("Out OleInPlaceSite.CopyTo");}
body{
return E_NOTIMPL;
}
HRESULT MoveElementTo( OLECHAR * pwcsName, IStorage pstgDest, OLECHAR *pwcsNewName, DWORD grfFlags )
in {writefln ("In OleInPlaceSite.MoveElementTo");}
out {writefln ("Out OleInPlaceSite.MoveElementTo");}
body{
return E_NOTIMPL;
}
HRESULT Commit( DWORD grfCommitFlags )
in {writefln ("In OleInPlaceSite.Commit");}
out {writefln ("Out OleInPlaceSite.Commit");}
body{
return E_NOTIMPL;
}
HRESULT Revert()
in {writefln ("In OleInPlaceSite.Revert");}
out {writefln ("Out OleInPlaceSite.Revert");}
body{
return E_NOTIMPL;
}
HRESULT EnumElements( DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG * ppenum)
in {writefln ("In OleInPlaceSite.EnumElements");}
out {writefln ("Out OleInPlaceSite.EnumElements");}
body{
return E_NOTIMPL;
}
HRESULT DestroyElement( OLECHAR * pwcsName )
in {writefln ("In OleInPlaceSite.DestroyElement");}
out {writefln ("Out OleInPlaceSite.DestroyElement");}
body{
return E_NOTIMPL;
}
HRESULT RenameElement( OLECHAR *pwcsOldName, OLECHAR *pwcsNewName )
in {writefln ("In OleInPlaceSite.RenameElement");}
out {writefln ("Out OleInPlaceSite.RenameElement");}
body{
return E_NOTIMPL;
}
HRESULT SetElementTimes( OLECHAR * pwcsName, FILETIME * pctime, FILETIME *patime, FILETIME *pmtime )
in {writefln ("In OleInPlaceSite.SetElementTimes");}
out {writefln ("Out OleInPlaceSite.SetElementTimes");}
body{
return E_NOTIMPL;
}
HRESULT SetClass( REFCLSID clsid )
in {writefln ("In OleInPlaceSite.SetClass");}
out {writefln ("Out OleInPlaceSite.SetClass");}
body{
return S_OK;
}
HRESULT SetStateBits( DWORD grfStateBits, DWORD grfMask )
in {writefln ("In OleInPlaceSite.SetStateBits");}
out {writefln ("Out OleInPlaceSite.SetStateBits");}
body{
return E_NOTIMPL;
}
HRESULT Stat( STATSTG *pstatstg, DWORD grfStatFlag )
in {writefln ("In OleInPlaceSite.Stat");}
out {writefln ("Out OleInPlaceSite.Stat");}
body{
return E_NOTIMPL;
}
// IOleClientSite
HRESULT SaveObject()
in {writefln ("In OleInPlaceSite.SaveObject");}
out {writefln ("Out OleInPlaceSite.SaveObject");}
body{
return E_NOTIMPL;
}
HRESULT GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker, IMoniker * ppmk )
in {writefln ("In OleInPlaceSite.GetMoniker");}
out {writefln ("Out OleInPlaceSite.GetMoniker");}
body{
return E_NOTIMPL;
}
HRESULT GetContainer( IOleContainer * ppContainer )
in {writefln ("In OleInPlaceSite.GetContainer");}
out {writefln ("Out OleInPlaceSite.GetContainer");}
body{
*ppContainer = null;
return E_NOINTERFACE;
}
HRESULT ShowObject()
in {writefln ("In OleInPlaceSite.ShowObject");}
out {writefln ("Out OleInPlaceSite.ShowObject");}
body{
return S_OK;
}
HRESULT OnShowWindow( BOOL fShow )
in {writefln ("In OleInPlaceSite.OnShowWindow");}
out {writefln ("Out OleInPlaceSite.OnShowWindow");}
body{
return E_NOTIMPL;
}
HRESULT RequestNewObjectLayout()
in {writefln ("In OleInPlaceSite.RequestNewObjectLayout");}
out {writefln ("Out OleInPlaceSite.RequestNewObjectLayout");}
body{
return E_NOTIMPL;
}
}
/*************************** UnEmbedBrowserObject() ************************
* Called to detach the browser object from our host window, and free its
* resources, right before we destroy our window.
*
* hwnd = Handle to the window hosting the browser object.
*
* NOTE: The pointer to the browser object must have been stored in the
* window's USERDATA field. In other words, don't call UnEmbedBrowserObject().
* with a HWND that wasn't successfully passed to EmbedBrowserObject().
*/
void UnEmbedBrowserObject(HWND hwnd)
{
// Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
// we initially attached the browser object to this window.
if (g_browserObject != null)
{
// Unembed the browser object, and release its resources.
g_browserObject.Close(OLECLOSE.OLECLOSE_NOSAVE);
g_browserObject.Release();
return;
}
assert (false);
}
enum {
WEBPAGE_GOBACK,
WEBPAGE_GOFORWARD,
WEBPAGE_GOHOME,
WEBPAGE_SEARCH,
WEBPAGE_REFRESH,
WEBPAGE_STOP
}
/******************************* DoPageAction() **************************
* Implements the functionality of a "Back". "Forward", "Home", "Search",
* "Refresh", or "Stop" button.
*
* hwnd = Handle to the window hosting the browser object.
* action = One of the following:
* 0 = Move back to the previously viewed web page.
* 1 = Move forward to the previously viewed web page.
* 2 = Move to the home page.
* 3 = Search.
* 4 = Refresh the page.
* 5 = Stop the currently loading page.
*
* NOTE: EmbedBrowserObject() must have been successfully called once with the
* specified window, prior to calling this function. You need call
* EmbedBrowserObject() once only, and then you can make multiple calls to
* this function to display numerous pages in the specified window.
*/
void DoPageAction(HWND hwnd, DWORD action)
{
IWebBrowser2 webBrowser2;
// We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser
// object, so we can call some of the functions in the former's table.
if (!g_browserObject.QueryInterface(&IID_IWebBrowser2, cast(void**)&webBrowser2))
{
// Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is
// webBrowser2->lpVtbl.
// Call the desired function
switch (action)
{
case WEBPAGE_GOBACK:
{
// Call the IWebBrowser2 object's GoBack function.
webBrowser2.GoBack();
break;
}
case WEBPAGE_GOFORWARD:
{
// Call the IWebBrowser2 object's GoForward function.
webBrowser2.GoForward();
break;
}
case WEBPAGE_GOHOME:
{
// Call the IWebBrowser2 object's GoHome function.
webBrowser2.GoHome();
break;
}
case WEBPAGE_SEARCH:
{
// Call the IWebBrowser2 object's GoSearch function.
webBrowser2.GoSearch();
break;
}
case WEBPAGE_REFRESH:
{
// Call the IWebBrowser2 object's Refresh function.
webBrowser2.Refresh();
}
case WEBPAGE_STOP:
{
// Call the IWebBrowser2 object's Stop function.
webBrowser2.Stop();
}
}
// Release the IWebBrowser2 object.
webBrowser2.Release();
}
}
long DisplayHTMLPage(HWND hwnd, wchar[] webPageName)
{
IWebBrowser2 webBrowser2;
VARIANT myURL;
if (!g_browserObject.QueryInterface(&IID_IWebBrowser2, cast(void**)&webBrowser2))
{
myURL.n1.n2.vt = VT_BSTR;
myURL.n1.n2.n3.bstrVal = webPageName;
if (!myURL.n1.n2.n3.bstrVal)
{
webBrowser2.Release();
return(-6);
}
webBrowser2.Navigate2(&myURL, null, null, null, null);
webBrowser2.Release();
writefln ("display html page success");
return(0);
}
writefln ("display html page failed");
return(-5);
}
void ResizeBrowser(HWND hwnd, DWORD width, DWORD height)
{
IWebBrowser2 webBrowser2;
if (!g_browserObject.QueryInterface(&IID_IWebBrowser2, cast(void**)&webBrowser2))
{
webBrowser2.Put_Width(width);
webBrowser2.Put_Height(height);
webBrowser2.Release();
}
}
long EmbedBrowserObject(HWND hwnd)
{
IWebBrowser2 webBrowser2;
RECT rect;
IStorage storage = new MyStorage;
IOleClientSite _iOleClientSite = new OleInPlaceSite(hwnd);
if (!OleCreate(cast(REFCLSID)&CLSID_WebBrowser, cast(REFIID)&IID_IOleObject, OLERENDER.OLERENDER_DRAW,
null, _iOleClientSite, storage, cast(void**)&g_browserObject))
{
writefln("create ole object success");
g_browserObject.SetHostNames("My Host Name"w, null);
GetClientRect(hwnd, &rect);
// Let browser object know that it is embedded in an OLE container.
if (!OleSetContainedObject(g_browserObject, TRUE))
{
writefln("set contained object success");
if(!g_browserObject.DoVerb(OLEIVERB_SHOW, null, _iOleClientSite, -1, hwnd, &rect))
{
writefln("do verb success");
if(!g_browserObject.QueryInterface(&IID_IWebBrowser2, cast(void**)&webBrowser2))
{
writefln("query IID_IWebBrowser2 interface success");
webBrowser2.Put_Left(0);
webBrowser2.Put_Top(0);
webBrowser2.Put_Width(rect.right);
webBrowser2.Put_Height(rect.bottom);
webBrowser2.Release();
// Success
return(0);
}
else
{
writefln("query IID_IWebBrowser2 interface failed");
}
}
else
{
writefln("do verb failed");
}
}
else
{
writefln("set contained object failed");
}
writefln("embed failed");
// Something went wrong!
UnEmbedBrowserObject(hwnd);
return(-3);
}
return(-2);
}
/****************************** WindowProc() ***************************
* Our message handler for our window to host the browser.
*/
extern(Windows)
LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
{
// Resize the browser object to fit the window
//ResizeBrowser(hwnd, LOWORD(lParam), HIWORD(lParam));
return(0);
}
case WM_CREATE:
{
// Embed the browser object into our host window. We need do this only
// once. Note that the browser object will start calling some of our
// IOleInPlaceFrame and IOleClientSite functions as soon as we start
// calling browser object functions in EmbedBrowserObject().
if (EmbedBrowserObject(hwnd)) return(-1);
// Another window created with an embedded browser object
++WindowCount;
// Success
return(0);
}
case WM_DESTROY:
{
// Detach the browser object from this window, and free resources.
UnEmbedBrowserObject(hwnd);
// One less window
--WindowCount;
// If all the windows are now closed, quit this app
if (!WindowCount) PostQuitMessage(0);
return(TRUE);
}
default:
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}
}
/****************************** WinMain() ***************************
* C program entry point.
*
* This creates a window to host the web browser, and displays a web
* page.
*/
int myWinMain(HINSTANCE hInstance, HINSTANCE hInstNULL, LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
// Initialize the OLE interface. We do this once-only.
if (OleInitialize(null) == S_OK)
{
WNDCLASSEX wc;
// Register the class of our window to host the browser. 'WindowProc' is our message handler
// and 'ClassName' is the class name. You can choose any class name you want.
wc.cbSize = WNDCLASSEX.sizeof;
wc.hInstance = hInstance;
wc.lpfnWndProc = &WindowProc;
wc.lpszClassName = &ClassName[0];
RegisterClassEx(&wc);
// Create a window. NOTE: We embed the browser object duing our WM_CREATE handling for
// this window.
msg.hwnd = CreateWindowEx(0, ClassName, "An HTML string", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
HWND_DESKTOP, null, hInstance, null);
if (msg.hwnd == null)
{
writefln ("create window failed");
OleUninitialize();
return -2;
}
// For this window, display a URL. This could also be a HTML file on disk such as "c:\\myfile.htm".
DisplayHTMLPage(msg.hwnd, "http://www.microsoft.com");
// Show the window.
ShowWindow(msg.hwnd, nCmdShow);
UpdateWindow(msg.hwnd);
// Do a message loop until WM_QUIT.
while (GetMessage(&msg, null, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Free the OLE library.
OleUninitialize();
return(0);
}
writefln("Can't open OLE!");
return(-1);
}