【前言】
使用Delphi和VB的好处就是拖拉控件。使用方便。
我就一直和奇怪,这个功能vc也有,但是为什么他不扩展呢 ?在编写MFC应用程序的时候,我们就可以拖拉几个简单的控件,例如:输入框,静态文本,树型图,等等。而他也提供给我们程序员来自己编写控件的功能。但是终究他还是牵拉着MFC这个东东,显得很累赘。所以被部分程序员所不屑。
现在有个方法,可以不用MFC的库,也可以使用到系统中的 com 。
先做一个简单的示例认识ActiveX控件。新建一个MFC (.exe),在vc下->工程 ->增加到工程 -> component and Control
选择一个控件,就可以在你的MFC控件对话框上看到新增的控件了。
发现原来不用MFC的东西,我们也可以使用AciveX控件。就是下面的办法
【代码】
用ATL是一个简便的办法,你的工程无须改成ATL COM,下面是实现方法:
#include
// Required ATL module
CComModule _Module;
#include
#include
#include
#include
在WinMain里面一开始加上:
CoInitialize(0);
_Module.Init(0, hInstance); //hInstance是WinMain的参数
AtlAxWinInit();
然后做你WinMain里面该做的事。在函数退出前调用以下代码:
_Module.Term();
CoUninitialize();
这只是初始化,然后才是代码核心:
CAxWindow2 Container;
BOOL CreateContainer(HWND m_hWnd,LPCOLESTR ocxName)
{
RECT rect;
GetClientRect(m_hWnd,&rect);
HWND hwndContainer = Container.Create(m_hWnd,&rect,0,WS_CHILDWS_VISIBLEWS_HSCROLLWS_VSCROLL);
if(!hwndContainer) return FALSE;
HRESULT hr = Container.CreateControl(ocxName);
return SUCCEEDED(hr);
}
template
class CAxWindowT2 : public CAxWindowT
{
public:
CAxWindowT2(HWND hwnd = 0) : CAxWindowT(hwnd) {}
HRESULT CreateControl(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL)
{
return CreateControlEx(lpszName, pStream, ppUnkContainer);
}
HRESULT CreateControl(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL)
{
return CreateControlEx(dwResID, pStream, ppUnkContainer);
}
HRESULT CreateControlEx(DWORD dwResID, IStream* pStream = NULL,
IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL,
REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL)
{
TCHAR szModule[_MAX_PATH];
GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
CComBSTR bstrURL(OLESTR(;res://;));
bstrURL.Append(szModule);
bstrURL.Append(OLESTR(;/;));
TCHAR szResID[11];
wsprintf(szResID, _T(;%0d;), dwResID);
bstrURL.Append(szResID);
return CreateControlEx(bstrURL, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink);
}
HRESULT CreateControlEx(LPCOLESTR lpszName, IStream* pStream = NULL,
IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL,
REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL)
{
ATLASSERT(::IsWindow(m_hWnd));
HRESULT hr = E_FAIL;
CComPtr spAxWindow;
// Reuse existing CAxHostWindow
hr = QueryHost(&spAxWindow);
if( SUCCEEDED(hr) )
{
CComPtr spunkControl;
hr = spAxWindow->CreateControlEx(lpszName, m_hWnd, pStream, &spunkControl, iidSink, punkSink);
if( FAILED(hr) ) return hr;
if( ppUnkControl ) (*ppUnkControl = spunkControl)->AddRef();
if( ppUnkContainer ) (*ppUnkContainer = spAxWindow)->AddRef();
}
// Create a new CAxHostWindow
else
{
return AtlAxCreateControlEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink);
}
return S_OK;
}
HRESULT AttachControl(IUnknown* pControl, IUnknown** ppUnkContainer = 0)
{
ATLASSERT(::IsWindow(m_hWnd));
HRESULT hr = E_FAIL;
CComPtr spAxWindow;
// Reuse existing CAxHostWindow
hr = QueryHost(&spAxWindow);
if( SUCCEEDED(hr) )
{
hr = spAxWindow->AttachControl(pControl, m_hWnd);
if( FAILED(hr) ) return hr;
if( ppUnkContainer ) (*ppUnkContainer = spAxWindow)->AddRef();
}
// Create a new CAxHostWindow
else
{
return AtlAxAttachControl(pControl, m_hWnd, ppUnkContainer);
}
return S_OK;
}
};
typedef CAxWindowT2 CAxWindow2;
// 然后在你窗口过程的WM_CREATE中调用:
CreateContainer(hWnd,OLESTR(;http://www.csdn.net;));
就OK了。|||需要把template 及以下的代码移到前面。
这只是实现了最简单的功能,不能与网页交互,需要交互的话,必须得到IWebBrowser2对象:
CComPtr m_Browser;
HRESULT hr=Container.QueryControl(IID_IWebBrowser2,(void**)&m_Browser);
成功后就可以调用IWebBrowser2的接口方法等了,比如接受输入网址:
没有怎么做错误检查,你可以自己改并做完善。
原文链接 :http://www.hxzi.com/article/wangluoshouji/ATL_ActiveX_COM/2009-06-23/21991_4.html
从上面看以看到怎么将一个控件嵌入到窗口上去。
同样的我们就可以举一反三的。对一个控件进行重构了。
例如:
在编辑框里面加入一个按钮。在数据报表上加入一个头combox用来过滤的。