下载本文所附源代码
程序运行效果截图:

环境: VC6, MFC
为了实现用鼠标改变控件的大小,通常你需要处理下面一些窗口消息:
WM_SETCURSOR―为控件上不同的区域设置不同的鼠标形状,有以下鼠标供选择。
IDC_SIZEWE―当鼠标在左或右边界时的形状
IDC_SIZENS―当鼠标在上或下边界时的形状
IDC_SIZENWSE―当鼠标在左上角或右下角时的形状
IDC_SIZENESW―当鼠标在右上角或左下角时的形状
IDC_ARROW―当鼠标在控件上但是不在控件边框时的形状
WM_MOUSEMOVE―在鼠标移动时改变控件的大小
WM_NCLBUTTONDOWN―开始控件改变大小的动作
WM_LBUTTONUP―结束控件改变大小的动作
在设计代码的过程中,我发现对于所有的控件改变大小来说,有一些变量或功能是通用的,基于此点,我设计了一个接口-IResizeControl,所有的需要改变大小的控件都可以从这个接口派生。技术上来说,IResizeControl不是一个接口,因为它没有任何的纯虚函数,但是我依然把它当成一个接口,因为在声明IResizeControl实例时,没有作任何的动作。下面是IResizeControl类的声明:
class IResizeControl
{
public:
//Enabling Flags
void EnableNorth(bool bN=true);
void EnableWest(bool bW=true);
void EnableSouth(bool bS=true);
void EnableEast(bool bE=true);
//Change Limits
bool SetWidth(int iMinWidth, int iMaxWidth);
bool SetHeight(int iMinHeight, int iMaxHeight);
//Resize Message
static const UINT UWM_CONTROLRESIZE;
protected:
//Constructor and Destructor declared protected
prevents
//creation of IResizeControl objects
//CONSTRUCTOR
IResizeControl(bool bN, bool bW, bool bS, bool bE,
int iMinWidth, int iMaxWidth,
int iMinHeight, int iMaxHeight, bool bNotify);
//DESTRUCTOR
virtual ~IResizeControl();
//Find the current Mouse Position
virtual int FindPosition(POINT const& rPt, CRect const& roRect);
//Determine the new Dimensions
virtual void NewDimensions(POINT const& rPt,
CRect const& roRect,
int& riLeft, int& riTop,
int& riWidth, int&
riHeight, bool& rbResize);
//Mouse Cursor Positions
enum { POSDEF=0, POSN=1, POSNW=2, POSW=3, POSSW=4, POSS=5,
POSSE=6, POSE=7, POSNE=8 };
//Mouse Cursors
static HCURSOR sm_hWE, sm_hNS, sm_hNWSE, sm_hNESW, sm_hDEF;
//Enabling Flags
bool m_bN, m_bW, m_bS, m_bE;
//Tracking Flag
bool m_bTrack;
//Notification Flag
bool m_bNotify;
//Position
int m_iPosition;
//Limits
int m_iMinWidth, m_iMaxWidth, m_iMinHeight, m_iMaxHeight;
};
成员函数EnableNorth(), EnableWest(), EnableSouth()和EnableEast()在构造函数结束后使用,作用是设置可改变大小的边框。如果设置了两个边框都可以改变大小,那么位于这两个边框的角也可以被鼠标选中,用来改变控件的大小。例如,成员变量m_bN和m_bW为真,那么NW(左上角)也可以被鼠标选中来改变控件的大小。
成员函数SetWidth()和SetHeight(),用来设定控件大小的范围,改变控件的大小不能超出这个范围。
当bNotify(此值在构造函数中被设置)为真时,用户消息UWM_CONTROLRESIZE当控件被改变大小时被发送给父窗口。用户消息UWM_CONTROLRESIZE也可以使用在父窗口中(比如一个对话框),去实现一些特殊的功能。
上面说的方向,大小限制和用户消息可以在构造函数中设置,除了用户消息标记,其他的设置都可以在其他地方更改。
虚成员函数FindPosition()用来找到当前鼠标移动的位置。使用这个函数可以判断当前的鼠标在控件内还是外,或是在边框上还是角上.返回值如下:
enum { POSDEF=0, POSN=1, POSNW=2, POSW=3, POSSW=4, POSS=5, POSSE=6, POSE=7, POSNE=8 };
