1.
(1) InfoPath自定义控件的开发
本测试控件是基于ATL框架之上开发。创建一个ATL Project工程TestProject,并在此工程里添加了一个ATL Control类CTestControl。
① 在CTestControl类的创建过程中,按照下列步骤:
步骤一、添加TestControl控件类;
步骤二、进入Options页,勾选Connection points使控件支持连接点;
步骤三、进入Interfaces页,把IPorpertyNotifySink加入Supported;
步骤四、进入Stock Properties,把Enabled和Text加入Supported;
② 在完成CTestControl类的创建后,打开TestControl.h文件,在CTestControl类的定义中添加IObjectSafetyImpl,IPersistPropertyBagImpl这两个接口,使CTestControl类继承这两个接口。并加入以下代码,使控件可以安全初始化。
BEGIN_CATEGORY_MAP(ICTestControl)
IMPLEMENTED_CATEGORY(CATID_SafeForScripting)
IMPLEMENTED_CATEGORY(CATID_SafeForInitializing)
END_CATEGORY_MAP()
③ 添加一个ATL Property Page类CPropPage,按默认方式创建即可。在资源视图内,找到ID为IDD_PROPPAGE的对话框,在对话框内加入一个ID为IDC_MY_EDIT的Edit Control控件(注:可以根据需求添加控件),并创建EN_CHANGE事件处理函数OnEnChangeMyEdit,在函数OnEnChangeMyEdit内添加语句IPropertyPageImpl::SetDirty(1); 同时,加入以下几个函数:
public:
CComBSTR m_bstr; // The original name
CComBSTR m_Curbstr;
typedef IPropertyPageImpl<CPropPage> PPGBaseClass;
STDMETHOD(SetObjects)(ULONG nObjects, IUnknown** ppUnk)
{
HRESULT hr = E_INVALIDARG;
if (nObjects == 1)
{
CComQIPtr<ITestControl> pDoc(ppUnk[0]);
if (pDoc)
hr = PPGBaseClass::SetObjects(nObjects, ppUnk);
}
return hr;
}
STDMETHOD(Activate)(HWND hWndParent, LPCRECT prc, BOOL bModal)
{
// If we don't have any objects, this method should not be called
// Note that OleCreatePropertyFrame will call Activate even if
// a call to SetObjects fails, so this check is required
if (!m_ppUnk)
return E_UNEXPECTED;
// Use Activate to update the property page's UI with information
// obtained from the objects in the m_ppUnk array
// We update the page to display the Name and ReadOnly properties
// of the document
// Call the base class
HRESULT hr = PPGBaseClass::Activate(hWndParent, prc, bModal);
if (FAILED(hr))
return hr;
// Get the ITestControl pointer
CComQIPtr<ITestControl> pDoc(m_ppUnk[0]);
if (!pDoc)
return E_UNEXPECTED;
// Get the “Text” property
hr = pDoc->get_Text(&m_bstr.m_str);
if (FAILED(hr))
return hr;
// Set the text box so that the user can see the document name
USES_CONVERSION;
SetDlgItemText(IDC_MY_EDIT, CW2CT(m_bstr.m_str));
return hr;
}
STDMETHOD(Apply)(void)
{
// If we don't have any objects, this method should not be called
if (!m_ppUnk)
return E_UNEXPECTED;
// Use Apply to validate the user's settings and update the objects'
// properties
// Check whether we need to update the object
// Quite important since standard property frame calls Apply
// when it doesn't need to
if (!m_bDirty)
return S_OK;
HRESULT hr = E_UNEXPECTED;
// Get a pointer to the document
// Get the file name
if (!GetDlgItemText(IDC_MY_EDIT, m_Curbstr.m_str))
return E_FAIL;
// Save the document
if (m_Curbstr != m_bstr)
{
CComQIPtr<ITestControl> pDoc(m_ppUnk[0]);
if (!pDoc)
return hr;
//set the property “Text”;
hr = pDoc->put_Text(m_Curbstr.m_str);
//hr = pDoc->Save(bstrName, &status);
if (FAILED(hr))
return hr;
}
// Clear the dirty status of the property page
SetDirty(false);
return S_OK;
}
④ 打开CTestControl类的头文件,在宏BEGIN_PROP_MAP内添加“PROP_PAGE( CLSID_PropPage) “,把CPropPage类加入到控件属性页内。
⑤ 编译工程TestProject。
至此,自定义控件开发完成,接下来的任务就是把自定义控件加入 InfoPath 中,对控件进行测试,看是否满足需求。