来北航做毕业设计已经有半个月了,由于实验室中,项目组用的是VC,昨天刚好遇到一个细节问题:大家都知道,VC中可以动态或者静态的分割窗口(关于这点许多地方说的已经很清楚了,这里不做讨论)但是实际上,很多时候我们想要的只是静态的分割出窗口,并不想让别人移动改变这个比例,或者是需要限定某个分割出的窗口的范围(比如是小到多少之后就不能再变小了),关于这个问题许多书上都没有解释(PS:莫非是觉得太简单了,直接忽略么?orz...)本人研究了一下,   关于锁定分割大致有两种方法,而如何限制移动范围也可已在此基础上加,特此总结如下:
        锁定的话,其中一种方法是直接截获一个消息,我们知道,其实 CsplitterWnd 是从CWnd 派生出来的,所以其实很容易截获Window的消息,在这里我们应该关注的其实仅仅只有一个消息WM_NCHITTEST ,其作用大致就是当你的鼠标在这个划分出的区域中移动时为CWnd捕捉你的鼠标输入的,所以,换言之,如果我们截获了这个消息,直接返回为HTNOWHERE(参考MSDN),那么当你的鼠标停留在Splitter上时就不会出现任何反应,从而锁定的目的就达到了
        另一种是重载:OnLButtonDown(UINT nFlags, CPoint point),OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 以及OnMouseMove(UINT nFlags, CPoint point)几个函数,前两个函数的重载也可以达到锁定的效果,第三个函数也就是OnMouseMove()的重载则是为了限定移动的范围(这种情况可能需要的更多一些)下面贴上这两种方法的代码:
        两种方法有一个共同点就是需要自己从CSplitterWnd类中派生一个自己的类就叫 MySplitterWnd 好了,先采用第一种方法,来锁定,MySplitterWnd.h中代码如下:
 #if !defined(AFX_MYSPLITTERWND_H__A2E77A4F_BB34_4622_8178_ED5FB394208E__INCLUDED_)
#if !defined(AFX_MYSPLITTERWND_H__A2E77A4F_BB34_4622_8178_ED5FB394208E__INCLUDED_)
 #define AFX_MYSPLITTERWND_H__A2E77A4F_BB34_4622_8178_ED5FB394208E__INCLUDED_
#define AFX_MYSPLITTERWND_H__A2E77A4F_BB34_4622_8178_ED5FB394208E__INCLUDED_

 #if _MSC_VER > 1000
#if _MSC_VER > 1000
 #pragma once
#pragma once
 #endif // _MSC_VER > 1000
#endif // _MSC_VER > 1000
 // MySplitterWnd.h : header file
// MySplitterWnd.h : header file
 //
//


 /**//////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////// // MySplitterWnd frame with splitter
// MySplitterWnd frame with splitter

 #ifndef __AFXEXT_H__
#ifndef __AFXEXT_H__
 #include <afxext.h>
#include <afxext.h>
 #endif
#endif

 class MySplitterWnd : public CSplitterWnd
class MySplitterWnd : public CSplitterWnd


 {
{
 DECLARE_DYNCREATE(MySplitterWnd)
    DECLARE_DYNCREATE(MySplitterWnd)
 protected:
protected:
 // protected constructor used by dynamic creation
        // protected constructor used by dynamic creation

 // Attributes
// Attributes
 protected:
protected:
 CSplitterWnd    m_wndSplitter;
    CSplitterWnd    m_wndSplitter;
 public:
public:

 MySplitterWnd();
    MySplitterWnd();   

 public:
public:

 // Overrides
// Overrides
 // ClassWizard generated virtual function overrides
    // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(MySplitterWnd)
    //{{AFX_VIRTUAL(MySplitterWnd)
 protected:
    protected:
 virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
    virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
 afx_msg UINT    OnNcHitTest(CPoint point);     //新加的
    afx_msg UINT    OnNcHitTest(CPoint point);     //新加的

 //}}AFX_VIRTUAL
    //}}AFX_VIRTUAL

 // Implementation
// Implementation
 public:
public:
 virtual ~MySplitterWnd();
    virtual ~MySplitterWnd();

 // Generated message map functions
    // Generated message map functions
 //{{AFX_MSG(MySplitterWnd)
    //{{AFX_MSG(MySplitterWnd)
 // NOTE - the ClassWizard will add and remove member functions here.
        // NOTE - the ClassWizard will add and remove member functions here.
 //}}AFX_MSG
    //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
    DECLARE_MESSAGE_MAP()
 };
};


 /**//////////////////////////////////////////////////////////////////////////////
/**//////////////////////////////////////////////////////////////////////////////
 //{{AFX_INSERT_LOCATION}}
//{{AFX_INSERT_LOCATION}}
 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

 #endif // !defined(AFX_MYSPLITTERWND_H__A2E77A4F_BB34_4622_8178_ED5FB394208E__INCLUDED_)
#endif // !defined(AFX_MYSPLITTERWND_H__A2E77A4F_BB34_4622_8178_ED5FB394208E__INCLUDED_)

其中关键的语句就是 加一句  afx_msg UINT    OnNcHitTest(CPoint point)的定义,然后再在MySplitterWnd.cpp具体实现这个函数,如下
 // MySplitterWnd.cpp : implementation file
// MySplitterWnd.cpp : implementation file
 //
//

 #include "stdafx.h"
#include "stdafx.h"
 #include "GL.h"
#include "GL.h"
 #include "MySplitterWnd.h"
#include "MySplitterWnd.h"

 #ifdef _DEBUG
#ifdef _DEBUG
 #define new DEBUG_NEW
#define new DEBUG_NEW
 #undef THIS_FILE
#undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
static char THIS_FILE[] = __FILE__;
 #endif
#endif


 /**//////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////// // MySplitterWnd
// MySplitterWnd

 IMPLEMENT_DYNCREATE(MySplitterWnd, CSplitterWnd)
IMPLEMENT_DYNCREATE(MySplitterWnd, CSplitterWnd)

 MySplitterWnd::MySplitterWnd()
MySplitterWnd::MySplitterWnd()


 {
{
 }
}

 MySplitterWnd::~MySplitterWnd()
MySplitterWnd::~MySplitterWnd()


 {
{
 }
}


 BOOL MySplitterWnd::OnCreateClient(LPCREATESTRUCT /**//*lpcs*/, CCreateContext* pContext)
BOOL MySplitterWnd::OnCreateClient(LPCREATESTRUCT /**//*lpcs*/, CCreateContext* pContext)


 {
{
 return m_wndSplitter.Create(this,
    return m_wndSplitter.Create(this,
 2, 2,       // TODO: adjust the number of rows, columns
        2, 2,       // TODO: adjust the number of rows, columns
 CSize(10, 10),  // TODO: adjust the minimum pane size
        CSize(10, 10),  // TODO: adjust the minimum pane size
 pContext);
        pContext);
 }
}


 afx_msg UINT MySplitterWnd::OnNcHitTest(CPoint /**//*point*/)
afx_msg UINT MySplitterWnd::OnNcHitTest(CPoint /**//*point*/)


 {
{
 return HTNOWHERE;
    return HTNOWHERE;
 }
}



 /**//*BEGIN_MESSAGE_MAP(MySplitterWnd, CSplitterWnd)
/**//*BEGIN_MESSAGE_MAP(MySplitterWnd, CSplitterWnd)
 //{{AFX_MSG_MAP(MySplitterWnd)
    //{{AFX_MSG_MAP(MySplitterWnd)
 // NOTE - the ClassWizard will add and remove mapping macros here.
        // NOTE - the ClassWizard will add and remove mapping macros here.
 //}}AFX_MSG_MAP
    //}}AFX_MSG_MAP
 END_MESSAGE_MAP()*/
END_MESSAGE_MAP()*/


 BEGIN_MESSAGE_MAP(MySplitterWnd, CSplitterWnd)
BEGIN_MESSAGE_MAP(MySplitterWnd, CSplitterWnd)
 ON_WM_NCHITTEST()
ON_WM_NCHITTEST()
 END_MESSAGE_MAP()
END_MESSAGE_MAP()



 /**//////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////// // MySplitterWnd message handlers
// MySplitterWnd message handlers

可以看到,具体实现就一句话,return HTNOWHERE。现在就OK了,我的表述已经尽可能清楚了,如果实在不理解也没关系,你们可以直接将上面的.h和.cpp直接复制过去,直接加入到你的工程中,到时候用的时候直接 定义用 MySplitterWnd这个类定义 自己的变量,如  MySplitterWnd  XXX(自己随便取名)
下面介绍另一种方法,也是同上面一样需要自己建立一个类,还是叫MySplitterWnd好了,基类还是CSplitterWnd
然后 在MySplitterWnd.h中添加如下代码(位置 和添加OnNcHitTest(...)函数一样)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
在MySplitterWnd.cpp中添加三个函数的具体实现代码如下:
void MySplitterWnd::OnLButtonDown(UINT nFlags, CPoint point)
{     
    // 直接返回,不处理
 return;
}
BOOL MySplitterWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{   
    // 当光标进入分割窗口时,不允许改变样子,不处理
 return FALSE;
}
void MySplitterWnd::OnMouseMove(UINT nFlags, CPoint point)
{       
 //将CSplitter类的处理改为由CWnd处理
 //CSplitterWnd::OnMouseMove(nFlags, point); 
 if(point.x<250||point.x>500) CWnd::OnMouseMove(nFlags, point); 
 else  CSplitterWnd::OnMouseMove(nFlags, point); 
 }
好了,其实到了这里还没有完,刚说到锁定的问题,大家可以发现如果三个函数这样子写你的分隔条直接不能动了,和刚才的截取消息的锁定效果一摸一样,但是关于第三个函数OnMouseMove()的实际作用其实是限定范围,if(point.x<250||point.x>500) CWnd::OnMouseMove(nFlags, point); 
 else  CSplitterWnd::OnMouseMove(nFlags, point); 这两句的意思是说将移动范围锁定在250和500之间(这个数值大家可以随便设置),为了要使得这个函数生效,大家可以把前面两个也就是OnLButtonDown()和OnSetCursor()屏蔽掉,只留下第三个OnMouseMove()就可以达到限制范围的效果了,当然只屏蔽掉OnLButtonDown()函数也是可以的,因为OnSetCursor()函数只是改变光标样子用的,(锁定的另一个方法其实就是只用前面两个,既屏蔽掉OnMouseMove(),这个函数,大家可以自己试试,分别屏蔽看会出现什么效果)
MySplitterWnd.h和MySplitterWnd.cpp分别如下:
MySplitterWnd.h:
 #if !defined(AFX_MYSPLITTERWND_H__7AA280DC_82F5_4FF5_95A6_036C8A20B50D__INCLUDED_)
#if !defined(AFX_MYSPLITTERWND_H__7AA280DC_82F5_4FF5_95A6_036C8A20B50D__INCLUDED_)
 #define AFX_MYSPLITTERWND_H__7AA280DC_82F5_4FF5_95A6_036C8A20B50D__INCLUDED_
#define AFX_MYSPLITTERWND_H__7AA280DC_82F5_4FF5_95A6_036C8A20B50D__INCLUDED_

 #if _MSC_VER > 1000
#if _MSC_VER > 1000
 #pragma once
#pragma once
 #endif // _MSC_VER > 1000
#endif // _MSC_VER > 1000
 // MySplitterWnd.h : header file
// MySplitterWnd.h : header file
 //
//


 /**//////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////// // MySplitterWnd frame with splitter
// MySplitterWnd frame with splitter

 #ifndef __AFXEXT_H__
#ifndef __AFXEXT_H__
 #include <afxext.h>
#include <afxext.h>
 #endif
#endif

 class MySplitterWnd : public CSplitterWnd
class MySplitterWnd : public CSplitterWnd


 {
{

 
  
 public:
public:

 MySplitterWnd();
    MySplitterWnd(); 
 // Operations
// Operations
 public:
public:

 // Overrides
// Overrides
 // ClassWizard generated virtual function overrides
    // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(MySplitterWnd)
    //{{AFX_VIRTUAL(MySplitterWnd)
 
    


 //}}AFX_VIRTUAL
    //}}AFX_VIRTUAL

 // Implementation
// Implementation
 public:
public:
 virtual ~MySplitterWnd();
    virtual ~MySplitterWnd();
 
    

 
        
 DECLARE_DYNCREATE(MySplitterWnd)
    DECLARE_DYNCREATE(MySplitterWnd)

 
    
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);     //新加的
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);     //新加的
 afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); //新加的
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); //新加的
 afx_msg void OnMouseMove(UINT nFlags, CPoint point); //新加的
    afx_msg void OnMouseMove(UINT nFlags, CPoint point); //新加的
 
    
 DECLARE_MESSAGE_MAP()     //后加的
    DECLARE_MESSAGE_MAP()     //后加的


 };
};


 /**//////////////////////////////////////////////////////////////////////////////
/**//////////////////////////////////////////////////////////////////////////////
 //{{AFX_INSERT_LOCATION}}
//{{AFX_INSERT_LOCATION}}
 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

 #endif // !defined(AFX_MYSPLITTERWND_H__7AA280DC_82F5_4FF5_95A6_036C8A20B50D__INCLUDED_)
#endif // !defined(AFX_MYSPLITTERWND_H__7AA280DC_82F5_4FF5_95A6_036C8A20B50D__INCLUDED_)

MySplitterWnd.cpp:
 // MySplitterWnd.cpp : implementation file
// MySplitterWnd.cpp : implementation file
 //
//

 #include "stdafx.h"
#include "stdafx.h"
 #include "GL.h"
#include "GL.h"
 #include "MySplitterWnd.h"
#include "MySplitterWnd.h"

 #ifdef _DEBUG
#ifdef _DEBUG
 #define new DEBUG_NEW
#define new DEBUG_NEW
 #undef THIS_FILE
#undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
static char THIS_FILE[] = __FILE__;
 #endif
#endif


 /**//////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////// // MySplitterWnd
// MySplitterWnd


 IMPLEMENT_DYNCREATE(MySplitterWnd, CSplitterWnd)
IMPLEMENT_DYNCREATE(MySplitterWnd, CSplitterWnd)


 BEGIN_MESSAGE_MAP(MySplitterWnd, CSplitterWnd)
BEGIN_MESSAGE_MAP(MySplitterWnd, CSplitterWnd)
 //ON_WM_LBUTTONDOWN()
//ON_WM_LBUTTONDOWN()
 //ON_WM_SETCURSOR()
//ON_WM_SETCURSOR()
 ON_WM_MOUSEMOVE()
ON_WM_MOUSEMOVE()

 END_MESSAGE_MAP()
END_MESSAGE_MAP()




 MySplitterWnd::MySplitterWnd()
MySplitterWnd::MySplitterWnd()


 {
{
 }
}

 MySplitterWnd::~MySplitterWnd()
MySplitterWnd::~MySplitterWnd()


 {
{
 }
}


 /**//*void MySplitterWnd::OnLButtonDown(UINT nFlags, CPoint point)
/**//*void MySplitterWnd::OnLButtonDown(UINT nFlags, CPoint point)
 {
{     
 // 直接返回,不处理
    // 直接返回,不处理
 return;
    return;
 }
}

 BOOL MySplitterWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
BOOL MySplitterWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
 {
{   
 // 当光标进入分割窗口时,不允许改变样子,不处理
    // 当光标进入分割窗口时,不允许改变样子,不处理
 return FALSE;
    return FALSE;
 }*/
}*/

 void MySplitterWnd::OnMouseMove(UINT nFlags, CPoint point)
void MySplitterWnd::OnMouseMove(UINT nFlags, CPoint point)


 {
{       
 
    
 //将CSplitter类的处理改为由CWnd处理
    //将CSplitter类的处理改为由CWnd处理
 //CSplitterWnd::OnMouseMove(nFlags, point);
    //CSplitterWnd::OnMouseMove(nFlags, point); 

 if(point.x<250||point.x>500) CWnd::OnMouseMove(nFlags, point);
    if(point.x<250||point.x>500) CWnd::OnMouseMove(nFlags, point); 
 else  CSplitterWnd::OnMouseMove(nFlags, point);
    else  CSplitterWnd::OnMouseMove(nFlags, point); 

 }
}





 /**//*
/**//*
 BEGIN_MESSAGE_MAP(MySplitterWnd, CSplitterWnd)
BEGIN_MESSAGE_MAP(MySplitterWnd, CSplitterWnd)
 //{{AFX_MSG_MAP(MySplitterWnd)
    //{{AFX_MSG_MAP(MySplitterWnd)
 // NOTE - the ClassWizard will add and remove mapping macros here.
        // NOTE - the ClassWizard will add and remove mapping macros here.
 //}}AFX_MSG_MAP
    //}}AFX_MSG_MAP
 END_MESSAGE_MAP()*/
END_MESSAGE_MAP()*/


 /**//////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////// // MySplitterWnd message handlers
// MySplitterWnd message handlers

说的可能有些不清楚,不清楚的也没关系,可以直接将上面的MySplitterWnd.h和MySplitterWnd.cpp导入到自己的工程中,直接用就行了,将你要锁定或者限制移动范围的分割区域用MySplitterWnd定义,不做限制,锁定的区域用CSplitterWnd类定义,这样子就可以做到有选择的限制锁定某几个分割区域的效果.