wxWidgets wrap wtl browser

首先我们必须了解wxWidgets框架有自己的消息处理体系,WTL也有自己的消息处理体系,现在我们是wxWidgets wrap wtl,主消息循环是wxwidgets的,我们可以通过一个线程启动wtl消息循环,我们看下atlapp.h里面CAppModule一个函数的代码就会了解:

 BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
 {
  CStaticDataInitCriticalSectionLock lock;
  if(FAILED(lock.Lock()))
  {
   ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));
   ATLASSERT(FALSE);
   return FALSE;
  }

  ATLASSERT(pMsgLoop != NULL);
  ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL);   // not in map yet

  BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);

  lock.Unlock();

  return bRet;
 }

再看WTL SDK sample中例子工程TabBrowser里面的启动函数:

int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
 CMessageLoop theLoop;
 _Module.AddMessageLoop(&theLoop);

 CMainFrame wndMain;

 if(wndMain.CreateEx() == NULL)
 {
  ATLTRACE(_T("Main window creation failed!\n"));
  return 0;
 }

 wndMain.ShowWindow(nCmdShow);

 int nRet = theLoop.Run();

 _Module.RemoveMessageLoop();
 return nRet;
}

标注红色的第一行代码表示wtl的消息循环是线程安全的,也就是说我们不能从wxwidgets主线程中直接使用wtl体系里面的UI。另外又由于CAppModule派生于ATL::CComModule,我们把有关WTL的功能封装成一个独立的DLL。

下面我们介绍wrap wtl browser的详细步骤:

我们先新建一个DLL工程,然后把WTL SDK sample中例子工程TabBrowser中的两个文件TabBrowser.cpp和BrowserView.h拷贝过来使用,注意,我们要继续使用CBrowserView来实现browser的视图展现。

1、设计dll接口

1)启动wtl消息循环接口

该接口实现是创建一个线程,通过这个线程启动wtl消息循环,线程函数实现很简单,我们只要稍微修改一下TabBrowser.cpp里面的_tWinMain入口函数就可以了,首先,把函数名改掉如改为InitWTL,参数只保留第一个参数,如下:

int InitWTL(HINSTANCE hInstance)
{
 HRESULT hRes = ::CoInitialize(NULL);
 ATLASSERT(SUCCEEDED(hRes));

 AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_USEREX_CLASSES);

 hRes = _Module.Init(NULL, hInstance);
 ATLASSERT(SUCCEEDED(hRes));

 AtlAxWinInit();

 int nRet = Run();

 _Module.Term();
 ::CoUninitialize();

 return nRet;
}

当然。Run函数也要修改一下,如下:

static CBrowserView* G_View= NULL;

int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
 CMessageLoop theLoop;
 _Module.AddMessageLoop(&theLoop);

G_View = new CBrowserView;
G_View->Create(NULL, rcDefault, NULL,  WS_DISABLED);

 int nRet = theLoop.Run();

 _Module.RemoveMessageLoop();
 return nRet;
}

注意红色字体的部分,我们通过这个隐藏的window来实现与wxwidgets交互的消息。

另外要注意CBrowserView要添加一个基类CMessageFilter,OnCreate函数里面添加如下代码:

// register object for message filtering and idle updates
  CMessageLoop* pLoop = _Module.GetMessageLoop();
  ATLASSERT(pLoop != NULL);
  pLoop->AddMessageFilter(this);

OnDestroy函数里面添加如下代码:

CMessageLoop* pLoop = _Module.GetMessageLoop();
  ATLASSERT(pLoop != NULL);
  pLoop->RemoveMessageFilter(this);

该接口调用可以放在dll attach的时候,也可以在wxwidgets程序里面调用。

2)创建browser的接口

首先该接口要有一个参数就是HWND类型的,作为我们new CBrowserView 的父窗口句柄;第二个参数就是RECT类型的,视图的位置大小;第三个参数就是URL,我们要打开的网页的地址。有这三个参数就足够了,当然你也可以添加其他参数如果必要。

该函数的实现要注意了,由于我们是要new一个CBrowserView ,该函数要有wxwidgets程序调用,所以我们不能直接在该函数里面New,要通过发送windows的消息,首先我们在BrowserView.h里面自定义一个windows消息(先前已经有两个自定义消息了):

#define WM_BROWSERSCREATE   (WM_APP + 3)

接口实现如下:

void CreateWtlBrowser(HWND parent, RECT& rect, LPCTSTR strURL)

{

if (G_View && G_View->IsWindow())

{

WTLPARAMINFO *info = new WTLPARAMINFO;//我们定义的一个传递参数的结构体,使用后不要忘记delete

info->m_hWnd = parent;

info->rect = rect;

info->m_url = strURL;

::PostMessage(G_View->m_hWnd, WM_BROWSERSCREATE, (WPARAM)info ,0);//注意,此处只能用Post,不能用send,否则等于是直接调用了

}

}

然后我们在BrowserView.h里来添加实现WM_BROWSERSCREATE消息的映射函数就可以了,如:

LRESULT OnBrowserCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {

WTLPARAMINFO *info = (WTLPARAMINFO *)wParam;

if (info)

{

   CBrowserView* pView = new CBrowserView;
   pView->Create(info->m_hWnd, info->rect, info->m_url, WS_CHILD | WS_VISIBLE |  WS_VSCROLL | WS_HSCROLL);

}

  bHandled=FALSE;
  return 1;
 }

实际上,在wxwidgets程序里面,我们仅仅知道一个父窗口的句柄,其他都封装在了一个DLL里面,wxwidgets里面对browser的所有操作只能通过这个窗口句柄,所以我们要在DLL里面保持一个hash表,用来可以通过这个消息句柄找到对应的CBrowserView实例。

OK了,其他诸如重新刷新窗口大小,前进,后退,刷新,停止等接口照着这个接口实现就可以了。

2、消息接口设计

这个消息接口指的是从dll里面反映到wxwidgets程序里面的消息,例如浏览器状态,标题变化及NewWindow事件等的通知。当然,这个实现我们也通过自定义windows消息,通过在wxWidgets里面接收消息就OK了。

 

介绍结束,只要注意关键的几个点就不会有难度了!

转载于:https://my.oschina.net/u/2332347/blog/637837

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值