mfc链接
第三步添加事件关联关联一个左键双击事件
在CView.h中添加
afx_msg void OnTreeDblClk(LPNMHDR,LRESULT* pResult);
在.cpp文件的消息映射中添加
BEGIN_MESSAGE_MAP(CView1, CView)
//{{AFX_MSG_MAP(CView1)
ON_NOTIFY(NM_DBLCLK,ID_TREERECORD,OnTreeDblClk) //此行为自己添加.其余是生成的.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
然后在写OnTreeDblClk(LPNMHDR,LRESULT* pResult)的代码就可以了.
第四步实现通信
其实实现通信很简单,只要有一个关联就可以了网上有很多方法就不一一说了我的实现是这样的
void CView1::OnTreeDblClk(LPNMHDR,LRESULT* pResult)
{
HTREEITEM m_hTreeSel = m_TreeCtrl.GetSelectedItem();
if (m_TreeCtrl.GetChildItem( m_hTreeSel )==NULL) {
//获取CMainFrame指针,然后通过这个指针取得里面的数据成员也就是我们切分窗口时用的变量
//然后用它来获取view类的指针.有了指针我们就可以随便做了
CMainFrame * pMainFrm = (CMainFrame*)AfxGetMainWnd();
CDilView1 *m_divew = (CDilView1*)pMainFrm->m_wndSpli2.GetPane(1,0);
CDesktop2View *m_this = (CDesktop2View*)pMainFrm->m_wndSpli1.GetPane(0,1);
m_this->DrawText(m_TreeCtrl.GetItemText(m_hTreeSel));//为CDesktop2View设置显示文字,当然了要在CDesktop2View类中添加
//一个DrawText(CString str)函数.
m_divew->SetDlgItemText(IDC_EDIT1,m_TreeCtrl.GetItemText(m_hTreeSel));//为CDilView1设置显示文字
}
}
DrawText函数实现
void CDesktop2View::DrawText(CString str)
{
CDC *pDC;
pDC = this->GetDC();
CRect rect;
pDC->Rectangle(10,10,100,100);
rect.top=100;
rect.left=100;
rect.right=250;
rect.bottom=250;
pDC->TextOut(15,15,str);
ReleaseDC(pDC);
}
2.3实现各个分割区域的通信
■有文档相连的视图之间的通信
由AppWizard生成的CCuteFTPView是与文档相连的,同时我们也让CView2与文档相连,因此我们需要修改CCuteFTPApp的InitInstance()函数,我们将增加下面的部分。
view sourceprint?
1.AddDocTemplate (new CMultiDocTemplate(IDR_VIEW2TYPE,
2.
3.
RUNTIME_CLASS(CMainDoc),
4.
RUNTIME_CLASS(CMDIChildWnd),
5.
RUNTIME_CLASS(CView2)));我们现在来实现CCuteFTPView与CView2之间的通信。由于跟文档类相连的视图类 是不能安全的与除文档类之外的其余的视图类通信的。因此我们只能让他们都与文档 类通信。在文档中我们设置相应的指针以用来获的各个视图。我们重载 CCuteFTPView::OnOpenDocument()函数;
view sourceprint?
01.CCuteFTPView* pCuteFTPView;
02.CView2* pView2;
03.POSITION pos;
04.CView* pView;
05.while(pos!=NULL)
06.{
07.
pView=GetNextView(pos);
08.
if(pView->IsKindOf(RUNTIME_CLASS(CCuteFTPView))==NULL)
09.
pCuteFTPView=(CCuteFTPView*)pView;
10.
else(pView->IsKindOf(RUNTIME_CLASS(CCuteFTPView))==NULL)
11.
pView2=(CView2*)pView;
12.}这样我们在文档类中就获的了跟它相连的所有的视图的指针。
如果需要在 CCuteFTPView中调用CView2中的一个方法DoIt()则代码如下:
view sourceprint?
1.CCuteFTPDoc* pDoc=GetDocument();
2.CView2* pView2=pDoc->pView3;
3.pView3.DoIt();■无文档视图与文档关联视图之间的通信
CView3和CView4都是不与文档相关联的。我们现在实现CView3与CView2的通信.正如前面所说,CView2只能安全的与CCuteFTPDoc通信,因此,CView3如果需要跟CView2通信,也必须借助于文档类。因此程序的关键是如何在CView3中获得文档的指针。视图类中没有这样的类成员可以用来直接访问文档类。但是我们知道在主窗口类MainFrame中我们可以获得程序的任意窗口类的指针。因此我们只要获得程序主窗口了的指针,就可以解决问题了。代码实现在CView3中访问CView2中的DoIt()方法。
CView3中的代码如下:
view sourceprint?
01.CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();
02.
03.
CCuteFTPDoc* Doc=(CCuteFTPDoc*)MainFrame->GetActiveDocument();
04.
if(Doc!=NULL) Doc->DoIt();
05.
06.
CCuteFTPDoc中的相应的处理函数DoIt()代码如下:
07.
08.
CView2* pView2;
09.
POSITION pos;
10.
CView* pView;
11.
while(pos!=NULL)
12.
{
13.
pView=GetNextView(pos);
14.
if(pView->IsKindOf(RUNTIME_CLASS(CView2))==NULL)
15.
pView2=(CView2*)pView;
16.
}
17.
pView2->DoIt();■无文档关联视图之间的通信
CView3和CView4都是不跟文档相连的,如何实现他们之间的通信呢。 正如我们在上面所说的那样,由于在主框架中我们可以访问任意的视图,因此我们的主要任 务还是在程序中获得主框架的指针。在CView3中访问CView4中的方法DoIt()。
view sourceprint?
1.CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();
2.
3.
CView4* View4=(CView4*)MainFrame->m_wndSplitter1.GetPane(2,0);
4.
View4->DoIt();到现在我们已经实现了CuteFTP的主窗口的框架并且能够实现他们之间相互通信的框架。 同样的我们可以实现其他的一些流行界面例如NetAnts,Foxmail的分割。
三、关于对话框的分割
到目前为止,只有基于文档/视图的程序才能使用CSplitterWnd,而基于对话框的应用程序却不支持CSplitterWnd,但是如果我们在继承类中重载一些虚拟方法,也能使CSplitterWnd 在对话框程序中使用。从MFC的源程序WinSplit.cpp中可以看出,为了获得父窗口的地方程序都调用了虚拟方法GetParentFrame(),因此如果在对话框中使用,我们必须将它改为GetParent();因此我们将CSplitterWnd的下面几个方法重载。
view sourceprint?
1.virtual void StartTracking(int ht);
2.virtual CWnd* GetActivePane(int* pRow = NULL, int* pCol = NULL);
3.virtual void SetActivePane( int row, int col, CWnd* pWnd = NULL );
4.virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
5.virtual BOOL OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult );
6.virtual BOOL OnWndMsg( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult );具体实现如下,实现中我将给出原有代码的主要部分以及修改后的代码以作对比。
在cpp文件中加入下面的枚举类型。
view sourceprint?
001.enum HitTestValue
002.{
003.
noHit = 0,//表示没有选中任何对象
004.
vSplitterBox = 1,
005.
hSplitterBox = 2,
006.
bothSplitterBox = 3,
007.
vSplitterBar1 = 101,//代表各个方向的水平分割条
008.
vSplitterBar15 = 115,
009.
hSplitterBar1 = 201,//代表垂直方向的各个分割条
010.
hSplitterBar15 = 215,
011.
splitterIntersection1 = 301,//代表各个交叉点
012.
splitterIntersection225 = 525
013.};
014.
015.
016.CWnd* CxSplitterWnd::GetActivePane(int* pRow, int* pCol)
017.
{
018.
ASSERT_VALID(this);
019.
//获得当前的获得焦点的窗口
020.
//下面注释粗体的是原有的代码的主要部分。
021.
// CWnd* pView = NULL;
022.
//CFrameWnd* pFrameWnd = GetParentFrame();
023.
//ASSERT_VALID(pFrameWnd);
024.
//pView = pFrameWnd->GetActiveView();
025.
//if (pView == NULL)
026.
// pView = GetFocus();
027.
CWnd* pView = GetFocus();
028.
if (pView != NULL && !IsChildPane(pView, pRow, pCol))
029.
pView = NULL;
030.
return pView;
031.}
032.
033.void CxSplitterWnd::SetActivePane( int row, int col, CWnd* pWnd)
034.{
035.
CWnd* pPane = pWnd == NULL ? GetPane(row, col) : pWnd;
036.
//下面加注释粗体的是原有代码的主要部分。
037.
//FrameWnd* pFrameWnd = GetParentFrame();
038.
//ASSERT_VALID(pFrameWnd);
039.
//pFrameWnd->SetActiveView((CView*)pPane);
040.
pPane->SetFocus();//修改后的语句
041.}
042.
043.void CxSplitterWnd::StartTracking(int ht)
044.{
045.
ASSERT_VALID(this);
046.
if (ht == noHit)
047.
return;
048.
// GetHitRect will restrict ''''m_rectLimit'''' as appropriate
049.
050.
GetInsideRect(m_rectLimit);
051.
if (ht >= splitterIntersection1 && ht <= splitterIntersection225)
052.
053.
{
054.
// split two directions (two tracking rectangles)
055.
056.
int row = (ht - splitterIntersection1) / 15;
057.
058.
int col = (ht - splitterIntersection1) % 15;
059.
060.
GetHitRect(row + vSplitterBar1, m_rectTracker);
061.
062.
int yTrackOffset = m_ptTrackOffset.y;
063.
m_bTracking2 = TRUE;
064.
GetHitRect(col + hSplitterBar1, m_rectTracker2);
065.
066.
m_ptTrackOffset.y = yTrackOffset;
067.
}
068.
else if (ht == bothSplitterBox)
069.
{
070.
// hit on splitter boxes (for keyboard)
071.
GetHitRect(vSplitterBox, m_rectTracker);
072.
int yTrackOffset = m_ptTrackOffset.y;
073.
m_bTracking2 = TRUE;
074.
GetHitRect(hSplitterBox, m_rectTracker2);
075.
m_ptTrackOffset.y = yTrackOffset; // center it
076.
m_rectTracker.OffsetRect(0, m_rectLimit.Height()/2); m_rectTracker2.OffsetRect(m_rectLimit.Width()/2,
077.
0);
078.
}
079.
else
080.
{
081.
// only hit one bar
082.
GetHitRect(ht, m_rectTracker);
083.
}
084.
085.
//下面加注释的将从程序中删去。
086.
//CView* pView = (CView*)GetActivePane();
087.
//if (pView != NULL && pView->IsKindOf(RUNTIME_CLASS(CView)))
088.
//{
089.
// ASSERT_VALID(pView);
090.
// CFrameWnd* pFrameWnd = GetParentFrame();
091.
//ASSERT_VALID(pFrameWnd);
092.
//pView->OnActivateFrame(WA_INACTIVE, pFrameWnd);
093.
// }
094.
// steal focus and capture
095.
SetCapture();
096.
SetFocus();
097.
// make sure no updates are pending
098.
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
099.
100.
// set tracking state and appropriate cursor
101.
m_bTracking = TRUE;
102.
OnInvertTracker(m_rectTracker);
103.
if (m_bTracking2)
104.
OnInvertTracker(m_rectTracker2);
105.
m_htTrack = ht;
106.
SetSplitCursor(ht);
107.}
108.
109.BOOL CxSplitterWnd::OnCommand(WPARAM wParam, LPARAM lParam)
110.{
111.
if (CWnd::OnCommand(wParam, lParam))
112.
return TRUE;
113.
//下面粗体的是原程序的语句
114.
//return GetParentFrame()->SendMessage(WM_COMMAND, wParam, lParam);
115.
return GetParent()->SendMessage(WM_COMMAND, wParam, lParam);
116.
117.}
118.BOOL CxSplitterWnd::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult )
119.{
120.
if (CWnd::OnNotify(wParam, lParam, pResult))
121.
return TRUE;
122.
//下面粗体的是源程序的语句
123.
//*pResult = GetParentFrame()->SendMessage(WM_NOTIFY,
124.
wParam, lParam); *pResult = GetParent()->SendMessage(WM_NOTIFY, wParam, lParam);
125.
return TRUE;
126.}
127.
128.BOOL CxSplitterWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
129.{
130.
// The code line below is necessary if using CxSplitterWnd
131.
in a regular dll
132.
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
133.
return CWnd::OnWndMsg(message, wParam, lParam, pResult);
134.
135.}这样我们就可以在对话框中使用CxSplitterWnd类了。
四、CSplitterWnd的扩展
CSplitterWnd扩展话题是很多的,我们可以通过对原有方法的覆盖或者增加新的方法来扩展CSplitterWnd。我们在此仅举两个方面的例子。
4.1锁定切分条
当用户创建好分割窗口后,有时并不希望通过拖动切分条来调节窗口的大小。这时就必须锁定切分条。锁定切分条的最简单的方法莫过于不让CSplitterWnd来处理WM_LBUTTONDOWN,WM_MOUSEMOVE,WM_SETCURSOR消息,而是将这些消息交给CWnd窗口进行处理,从而屏蔽掉这些消息。拿WM_LBUTTONDOWN处理过程来说。修改为如下:
view sourceprint?
1.void CXXSplitterWnd::OnLButtonDown(UINT nFlags,CPoint point)
2.{
3.
CWnd::OnLButtonDown(nFlags,point);
4.}其余的处理方法类似。
4.2切分条的定制
由Window自己生成的切分条总是固定的,没有任何的变化,我们在使用一些软件比如ACDSee的时候却能发现它们的切分条却是和自动生成的切分条不一样的。那么如何定制自己的切分条呢?通过重载CSplitterWnd的虚方法OnDrawSplitter和OnInvertTracker可以达到这样的目的。下面的代码生成的效果是分割窗口的边界颜色为红色,分割条的颜色为绿色.代码如下:
view sourceprint?01.void CSplitterWndEx::OnDrawSplitter(CDC *pDC, ESplitType nType, const CRect &rectArg)
02.{
03.
if(pDC==NULL)
04.
{
05.
RedrawWindow(rectArg,NULL,RDW_INVALIDATE|RDW_NOCHILDREN);
06.
return;
07.
}
08.
ASSERT_VALID(pDC);
09.
CRect rc=rectArg;
10.
switch(nType)
11.
{
12.
case splitBorder:
13.
//重画分割窗口边界,使之为红色
14.
pDC->Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0));
15.
rc.InflateRect(-CX_BORDER,-CY_BORDER);
16.
pDC->Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0));
17.
18.
return;
19.
case splitBox:
20.
pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0));
21.
rc.InflateRect(-CX_BORDER,-CY_BORDER);
22.
pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0));
23.
rc.InflateRect(-CX_BORDER,-CY_BORDER);
24.
pDC->FillSolidRect(rc,RGB(0,0,0));
25.
pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0));
26.
return;
27.
case splitBar:
28.
//重画分割条,使之为绿色
29.
pDC->FillSolidRect(rc,RGB(255,255,255));
30.
rc.InflateRect(-5,-5);
31.
pDC->Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0));
32.
33.
return;
34.
default:
35.
ASSERT(FALSE);
36.
}
37.
pDC->FillSolidRect(rc,RGB(0,0,255));
38.}
39.void CSplitterWndEx::OnInvertTracker(CRect &rect)
40.{
41.
ASSERT_VALID(this);
42.
ASSERT(!rect.IsRectEmpty());
43.
ASSERT((GetStyle()&WS_CLIPCHILDREN)==0);
44.
CRect rc=rect;
45.
rc.InflateRect(2,2);
46.
CDC* pDC=GetDC();
47.
CBrush* pBrush=CDC::GetHalftoneBrush();
48.
HBRUSH hOldBrush=NULL;
49.
if(pBrush!=NULL) hOldBrush=(HBRUSH)SelectObject(pDC->m_hDC,pBrush->m_hObject);
50.
pDC->PatBlt(rc.left,rc.top,rc.Width(),rc.Height(),BLACKNESS);
51.
52.
if(hOldBrush!=NULL)
53.
SelectObject(pDC->m_hDC,hOldBrush);
54.
ReleaseDC(pDC);
55.}