Export a splitter view from a DLL using WTL.
WTL library shows the codes below:
// Constructor
CSplitterImpl() :
m_xySplitterPos(-1), m_nDefActivePane(SPLIT_PANE_NONE),
m_cxySplitBar(0), m_cxyMin(0), m_cxyBarEdge(0),
m_bFullDrag(true),
m_cxyDragOffset(0), m_nProportionalPos(0),
m_bUpdateProportionalPos(true),
m_dwExtendedStyle(SPLIT_PROPORTIONAL),
m_nSinglePane(SPLIT_PANE_NONE)
{
m_hWndPane[SPLIT_PANE_LEFT] = NULL;
m_hWndPane[SPLIT_PANE_RIGHT] = NULL;
::SetRectEmpty(&m_rcSplitter);
if(m_hCursor == NULL)
{
CStaticDataInitCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical
section
in CSplitterImpl::CSplitterImpl.\n"));
ATLASSERT(FALSE);
return;
}
if(m_hCursor == NULL)
m_hCursor = ::LoadCursor(NULL, t_bVertical ? IDC_SIZEWE :
IDC_SIZENS);
lock.Unlock();
}
}
The constrctor uses CStaticDataInitCriticalSectionLock lock; to
control
synchronous resource loading. I found that this caused a crash problem
when I load a CSplitterWindow from a DLL file. After commented the
lock
related bold lines, it works fine. I wonder if it will affect the
application in the future if I comment these lines. Can we remove
these
lines forever? If not, how can we handle the crash problem?
My demo application creates a SDI project without any view, only load
a
dll and create a CSplitterWindow exported from DLL. Below shows my
code.
MainFrame Code:
void CMainFrame::LoadDLL(LPCTSTR lpPath)
{
typedef void (*PFN_MERGEVIEW)(WDLLView**);
HMODULE hDLLInst = ::LoadLibrary((LPCTSTR)strDLLFile);
pfnMergeView = (PFN_MERGEVIEW)::GetProcAddress(hDLLInst,
"MergeView");
if (item.m_pfnMergeView)
{
pfnMergeView(&m_pDLLView);
m_hWndClient = m_pDLLView->Initialize(this->m_hWnd);
}
return nRet;
}
LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM
/*lParam*/, BOOL& /*bHandled*/)
{
.........
this->LoadDLL(_T("TestDLL.dll"));
return 0;
}
DLL view code:
struct WDLLView
{
virtual ~WDLLView() { } // we intend
on
deriving from this,
virtual HWND Initialize(HWND hParentWnd) = 0; // Use this
to
initialize the object
virtual void Destroy() = 0; // Use this
to
destroy the object
virtual TCHAR* Description() = 0; // What this
thing does
};
extern "C" WTLTEST_API void __cdecl MergeView(WDLLView** ppOutView);
class CReplaceSplitView : public WDLLView,
public CWindowImpl<CReplaceSplitView>,
public CSplitterImpl<CReplaceSplitView,
true>
{
public:
CReplaceSplitView(){};
~CReplaceSplitView(){};
HWND m_hWndParent;
HWND Initialize(HWND hParentWnd)
{
m_hWndParent = hParentWnd;
return this->Create(hParentWnd, rcDefault);
}
void Destroy()
{ // nothing to destroy
}
TCHAR* Description()
{
return (_T("Test loading a WTL Split View from DLL"));
}
BEGIN_MSG_MAP(CReplaceSplitView)
END_MSG_MAP()
};
extern "C" WTLTEST_API void __cdecl MergeView(WDLLView** ppOutView)
{
*ppOutView = new CReplaceSplitView;
}