it seems csplitterwnd is designed to be used in document/view-based applications only.
but by overriding some virtual methods in a derived class, you can make splitter windows based on csplitterwnd be used in dialog based application, activex-controls using mfc:
all virtual methods that call getparentframe() in its implementation have to be overridden.
i have done this by using existing code except
- that i replaced the call to getparentframe() by a call to getparent().
- all references or pointers to cframewnd were changed to references or pointers to cwnd.
i derived a class cxsplitterwnd from the class csplitterwnd and proceeded as stated above.
then i used this class in a dialog based application in the same way as any other cwnd derived class.
for example:
but by overriding some virtual methods in a derived class, you can make splitter windows based on csplitterwnd be used in dialog based application, activex-controls using mfc:
all virtual methods that call getparentframe() in its implementation have to be overridden.
i have done this by using existing code except
- that i replaced the call to getparentframe() by a call to getparent().
- all references or pointers to cframewnd were changed to references or pointers to cwnd.
i derived a class cxsplitterwnd from the class csplitterwnd and proceeded as stated above.
then i used this class in a dialog based application in the same way as any other cwnd derived class.
for example:
class csampledialog : public cdialog
{
...
cxsplitterwnd m_wndsplitter;
....
}
bool csampledlg::oninitdialog()
{
...
// todo: add extra initialization here
m_wndsplitter.createstatic(this, 1, 2);
m_wndsplitter.createview(0,0,runtime_class(csampleview), csize(50,0), null);
m_wndsplitter.createview(0,1,runtime_class(csampleview), csize(0,0), null);
crect rect = ...;
m_wndsplitter.movewindow(&rect);
...
}
the sample attached is a dialog based application and demonstrates the use of cxsplitterwnd. it does
nothing useful.
this is the new class declaration:
// splitwnd.h : implementation file
//
class cxsplitterwnd : public csplitterwnd
{
// construction
public:
cxsplitterwnd() {};
virtual ~cxsplitterwnd() {};
// operations
public:
// overrides
// classwizard generated virtual function overrides
//{{afx_virtual(cxsplitterwnd)
//}}afx_virtual
// implementation
public:
// these are the methods to be overridden
virtual void starttracking(int ht);
virtual cwnd* getactivepane(int* prow = null, int* pcol = null);
virtual void setactivepane( int row, int col, cwnd* pwnd = null );
virtual bool oncommand(wparam wparam, lparam lparam);
virtual bool onnotify( wparam wparam, lparam lparam, lresult* presult );
virtual bool onwndmsg( uint message, wparam wparam, lparam lparam, lresult* presult );
// generated message map functions
protected:
//{{afx_msg(cxsplitterwnd)
// note - the classwizard will add and remove member functions here.
//}}afx_msg
declare_message_map()
};
and here the implementation file:
// splitwnd.cpp : implementation file
//
#include "stdafx.h"
#include "splitwnd.h"
#ifdef _debug
#define new debug_new
#undef this_file
static char this_file[] = __file__;
#endif
// hittest return values (values and spacing between values is important)
// had to adopt this because it has module scope
enum hittestvalue
{
nohit = 0,
vsplitterbox = 1,
hsplitterbox = 2,
bothsplitterbox = 3, // just for keyboard
vsplitterbar1 = 101,
vsplitterbar15 = 115,
hsplitterbar1 = 201,
hsplitterbar15 = 215,
splitterintersection1 = 301,
splitterintersection225 = 525
};
/////////////////////////////////////////////////////////////////////////////
// cxsplitterwnd
begin_message_map(cxsplitterwnd, csplitterwnd)
//{{afx_msg_map(cxsplitterwnd)
// note - the classwizard will add and remove mapping macros here.
//}}afx_msg_map
end_message_map()
cwnd* cxsplitterwnd::getactivepane(int* prow, int* pcol)
{
assert_valid(this);
cwnd* pview = getfocus();
// make sure the pane is a child pane of the splitter
if (pview != null && !ischildpane(pview, prow, pcol))
pview = null;
return pview;
}
void cxsplitterwnd::setactivepane( int row, int col, cwnd* pwnd)
{
// set the focus to the pane
cwnd* ppane = pwnd == null ? getpane(row, col) : pwnd;
ppane->setfocus();
}
void cxsplitterwnd::starttracking(int ht)
{
assert_valid(this);
if (ht == nohit)
return;
// gethitrect will restrict 'm_rectlimit' as appropriate
getinsiderect(m_rectlimit);
if (ht >= splitterintersection1 && ht <= splitterintersection225)
{
// split two directions (two tracking rectangles)
int row = (ht - splitterintersection1) / 15;
int col = (ht - splitterintersection1) % 15;
gethitrect(row + vsplitterbar1, m_recttracker);
int ytrackoffset = m_pttrackoffset.y;
m_btracking2 = true;
gethitrect(col + hsplitterbar1, m_recttracker2);
m_pttrackoffset.y = ytrackoffset;
}
else if (ht == bothsplitterbox)
{
// hit on splitter boxes (for keyboard)
gethitrect(vsplitterbox, m_recttracker);
int ytrackoffset = m_pttrackoffset.y;
m_btracking2 = true;
gethitrect(hsplitterbox, m_recttracker2);
m_pttrackoffset.y = ytrackoffset;
// center it
m_recttracker.offsetrect(0, m_rectlimit.height()/2);
m_recttracker2.offsetrect(m_rectlimit.width()/2, 0);
}
else
{
// only hit one bar
gethitrect(ht, m_recttracker);
}
// steal focus and capture
setcapture();
setfocus();
// make sure no updates are pending
redrawwindow(null, null, rdw_allchildren | rdw_updatenow);
// set tracking state and appropriate cursor
m_btracking = true;
oninverttracker(m_recttracker);
if (m_btracking2)
oninverttracker(m_recttracker2);
m_httrack = ht;
setsplitcursor(ht);
}
/////////////////////////////////////////////////////////////////////////////
// csplitterwnd command routing
bool cxsplitterwnd::oncommand(wparam wparam, lparam lparam)
{
if (cwnd::oncommand(wparam, lparam))
return true;
// route commands to the splitter to the parent frame window
return getparent()->sendmessage(wm_command, wparam, lparam);
}
bool cxsplitterwnd::onnotify( wparam wparam, lparam lparam, lresult* presult )
{
if (cwnd::onnotify(wparam, lparam, presult))
return true;
// route commands to the splitter to the parent frame window
*presult = getparent()->sendmessage(wm_notify, wparam, lparam);
return true;
}
bool cxsplitterwnd::onwndmsg(uint message, wparam wparam, lparam lparam, lresult* presult)
{
// the code line below is necessary if using cxsplitterwnd in a regular dll
// afx_manage_state(afxgetstaticmodulestate());
return cwnd::onwndmsg(message, wparam, lparam, presult);
}
本文介绍如何通过覆盖CSplitterWnd类的虚拟方法,实现在MFC对话框应用程序中使用分隔窗口。通过创建CXSplitterWnd类,并重写特定方法,可以避免调用GetParentFrame(),从而使分隔窗口能在非文档视图架构的应用中正常工作。
3200

被折叠的 条评论
为什么被折叠?



