打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
从CStatic类派生自己的切分窗口类
//Splitter.h
//小G, 2009.12


#pragma once


// CSplitter

class CSplitter : public CStatic
{
DECLARE_DYNAMIC(CSplitter)

public:
CSplitter();
virtual ~CSplitter();

protected:
DECLARE_MESSAGE_MAP()
public:
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
public:
void OnInvertTracker(const CRect& rect);
public:
int m_nSplitterWidth;
//分割行数及列数,行宽及列宽
int m_nRows;
int m_nColumns;
int m_nCx[2];
int m_nCy[2];
HWND *m_hCtrlWnd;
//最小行高及最小列宽
int m_nMinCx;
int m_nMinCy;
//鼠标位置指示器
int m_nCurX;
int m_nCurY;
//拖动虚框
BOOL m_bTracking;
CRect m_rcHTrack;
CRect m_rcVTrack;
//
bool m_bOver;
bool m_bHasBtn;
//
public:
void HiteTest(CPoint& point);
public:
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
public:
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
public:
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
//public:
// afx_msg void OnTimer(UINT_PTR nIDEvent);
public:
BOOL CreateSplitter(int nRows, int nColumns, CRect& rect, CWnd *pParentWnd, CSize szLimit = CSize(0, 0));
public:
void SetPaneInfo(int nRow, int nColumn, CSize sz, CWnd *pWnd = NULL);
public:
CWnd* GetPane(int nRow, int nColumn);
void GetPanesize(int nRow, int nColumn, CRect &rect);
private:
void CSplitter::ReCalcSize(CRect &rcClient);
public:
void OnDraw();
};

// Splitter.cpp : 实现文件
//小G, 2009.12

#include "stdafx.h"
#include "SplitterWnd.h"
#include "Splitter.h"


// CSplitter

IMPLEMENT_DYNAMIC(CSplitter, CStatic)

CSplitter::CSplitter()
{
m_nSplitterWidth = 7;

m_nRows = 1;
m_nColumns = 1;
m_nCx[0] = 0;
m_nCy[0] = 0;
m_nCx[1] = 0;
m_nCy[1] = 0;

m_nMinCx = 0;
m_nMinCy = 0;

m_hCtrlWnd = NULL;

m_nCurX = -1;
m_nCurY = -1;

m_bOver = false;
m_bHasBtn = true;
m_bTracking = false;
}

CSplitter::~CSplitter()
{
for(int i = 0;i < m_nRows*m_nColumns;i ++)
{
if(m_hCtrlWnd[i] != NULL)
::SendMessage(m_hCtrlWnd[i], WM_DESTROY, 0, 0);
}
}


BEGIN_MESSAGE_MAP(CSplitter, CStatic)
ON_WM_MOUSEMOVE()
ON_WM_SETCURSOR()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
//ON_WM_TIMER()
END_MESSAGE_MAP()



// CSplitter 消息处理程序



void CSplitter::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO:  添加您的代码以绘制指定项
OnDraw();

//移动子窗口
CRect rc = lpDrawItemStruct->rcItem;
ReCalcSize(rc);
for(int i = 0;i < m_nRows;i ++)
{
for(int j = 0;j < m_nColumns;j ++)
{
if(m_hCtrlWnd[i*m_nColumns+j] != NULL)
{
GetPanesize(i, j, rc);
::MoveWindow(m_hCtrlWnd[i*m_nColumns+j], rc.left, rc.top, rc.Width(), rc.Height(), 1);
}
}
}
}

void CSplitter::OnInvertTracker(const CRect& rect)
{
ASSERT_VALID(this);
ASSERT(!rect.IsRectEmpty());
//ASSERT((GetStyle() & WS_CLIPCHILDREN) == 0);

// pat-blt without clip children on
CDC* pDC = GetDC();
// invert the brush pattern (looks just like frame window sizing)
CBrush* pBrush = CDC::GetHalftoneBrush();
HBRUSH hOldBrush = NULL;
if (pBrush != NULL)
hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);
if (hOldBrush != NULL)
SelectObject(pDC->m_hDC, hOldBrush);
ReleaseDC(pDC);
}

void CSplitter::HiteTest(CPoint& point)
{
CRect rc;
this->GetClientRect(&rc);

int nXpos = 0;
int nYpos = 0;

//交叉块
for(int i = 0;i < m_nRows - 1;i ++)
{
nYpos += m_nCy[i];
//pDC->Rectangle(0, nTemp, rc.Width(), nTemp+m_nSplitterWidth);
for(int j = 0;j < m_nColumns - 1;j ++)
{
nXpos += m_nCx[j];
//pDC->Rectangle(nXpos, nYpos, nXpos+m_nSplitterWidth, nYpos+m_nSplitterWidth);
if(point.x>nXpos && point.x<nXpos+m_nSplitterWidth && point.y>nYpos && point.y<nYpos+m_nSplitterWidth)
{
::SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR1));
m_nCurX = i;
m_nCurY = j;
return;
}
nXpos += m_nSplitterWidth;
}
nYpos += m_nSplitterWidth;
nXpos = 0;
}

//竖条
nXpos = 0;
for(int i = 0;i < m_nColumns - 1;i ++)
{
nXpos += m_nCx[i];
//pDC->Rectangle(nXpos, 0, nXpos+m_nSplitterWidth, rc.Height());
if(point.x>nXpos && point.x<nXpos+m_nSplitterWidth)
{
if(m_bHasBtn)
{
if(point.y > rc.Height()/2-25 && point.y < rc.Height()/2+25)
{
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
m_nCurX = -1;
m_nCurY = -2;
if(!m_bOver)
{
m_bOver = true;
OnDraw();
}
return;
}
else
{
if(m_bOver)
{
m_bOver = false;
OnDraw();
}
//return;
}
}
::SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR2));
m_nCurX = -1;
m_nCurY = i;
return;
}
nXpos += m_nSplitterWidth;
}

//横条
nYpos = 0;
for(int i = 0;i < m_nRows - 1;i ++)
{
nYpos += m_nCy[i];
//pDC->Rectangle(0, nYpos, rc.Width(), nYpos+m_nSplitterWidth);
if(point.y>nYpos && point.y<nYpos+m_nSplitterWidth)
{
if(m_bHasBtn)
{
if(point.x > rc.Width()/2-25 && point.x < rc.Width()/2+25)
{
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
m_nCurX = -2;
m_nCurY = -1;
if(!m_bOver)
{
m_bOver = true;
OnDraw();
}
return;
}
else
{
if(m_bOver)
{
m_bOver = false;
OnDraw();
}
//return;
}
}
::SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR3));
m_nCurX = i;
m_nCurY = -1;
return;
}
nYpos += m_nSplitterWidth;
}

::SetCursor(::LoadCursor(NULL, IDC_ARROW));
m_nCurX = -1;
m_nCurY = -1;
}

void CSplitter::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(nFlags & MK_LBUTTON)
{
if(m_bTracking)
{
CRect rc;
this->GetClientRect(&rc);

if(m_nCurX != -1)
{
OnInvertTracker(m_rcHTrack);
//横条移动范围限制
if(point.y > m_nMinCy+m_nSplitterWidth/2-2 && point.y < rc.Height()-m_nMinCy-m_nSplitterWidth/2-2)
m_rcHTrack.MoveToY(point.y-2);
else if(point.y <= m_nMinCy+m_nSplitterWidth/2-2)
m_rcHTrack.MoveToY(m_nMinCy+m_nSplitterWidth/2-2);
else
m_rcHTrack.MoveToY(rc.Height()-m_nMinCy-m_nSplitterWidth/2-2);
OnInvertTracker(m_rcHTrack);
}
if(m_nCurY != -1)
{
OnInvertTracker(m_rcVTrack);
//竖条移动范围限制
if(point.x > m_nMinCx+m_nSplitterWidth/2-2 && point.x < rc.Width()-m_nMinCx-m_nSplitterWidth/2-2)
m_rcVTrack.MoveToX(point.x-2);
else if(point.x <= m_nMinCx+m_nSplitterWidth/2-2)
m_rcVTrack.MoveToX(m_nMinCx+m_nSplitterWidth/2-2);
else
m_rcVTrack.MoveToX(rc.Width()-m_nMinCx-m_nSplitterWidth/2-2);
OnInvertTracker(m_rcVTrack);
}
}
}
else
HiteTest(point);

CStatic::OnMouseMove(nFlags, point);
}

BOOL CSplitter::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(pWnd == this)
{
if(m_bOver || m_nCurX != -1 || m_nCurY != -1)
return true;
}
if(m_bHasBtn && m_bOver)
{
m_bOver = false;
OnDraw();
}

return CStatic::OnSetCursor(pWnd, nHitTest, message);
}

void CSplitter::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
static int nOrginal = 0;
HiteTest(point);

if(m_bOver)
{
if(m_nCurX == -2)
{
m_nCurX = -1;
//MessageBox(L"Clicked H.");
CRect rc;
this->GetClientRect(&rc);
if(m_nCy[0] == rc.Height()-m_nSplitterWidth-20)
m_nCy[0] = nOrginal;
else
{
nOrginal = m_nCy[0];
m_nCy[0] = rc.Height()-m_nSplitterWidth-20;
}
}
if(m_nCurY == -2)
{
m_nCurY = -1;
//MessageBox(L"Clicked V.");
if(m_nCx[0] == 0)
m_nCx[0] = nOrginal;
else
{
nOrginal = m_nCx[0];
m_nCx[0] = 0;
}
}
this->Invalidate();
this->UpdateWindow();
}

if(m_nCurX != -1 || m_nCurY != -1)
{
CRect rc;
this->GetClientRect(&rc);

int nPos = -m_nSplitterWidth;
if(m_nCurX != -1)
{
m_rcHTrack.SetRect(0, point.y-2, rc.Width(), point.y+2);
OnInvertTracker(m_rcHTrack);
}
nPos = -m_nSplitterWidth;
if(m_nCurY != -1)
{
m_rcVTrack.SetRect(point.x-2, 0, point.x+2, rc.Height());
OnInvertTracker(m_rcVTrack);
}
m_bTracking = true;
//SetTimer(110, 10, NULL);
//让当前窗口捕获鼠标消息
SetCapture();
}

CStatic::OnLButtonDown(nFlags, point);
}

void CSplitter::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(m_bTracking)
{
m_bTracking = false;
//KillTimer(110);
//停止捕获鼠标消息
ReleaseCapture();

if(m_nCurX != -1)
{
OnInvertTracker(m_rcHTrack);
for(int i = 0;i < m_nCurX;i ++)
m_rcHTrack.top -= m_nCy[i]+m_nSplitterWidth;
m_nCy[m_nCurX] = m_rcHTrack.top - m_nSplitterWidth/2 + 2;
}
if(m_nCurY != -1)
{
OnInvertTracker(m_rcVTrack);
for(int i = 0;i < m_nCurY;i ++)
m_rcVTrack.left -= m_nCx[i]+m_nSplitterWidth;
m_nCx[m_nCurY] = m_rcVTrack.left - m_nSplitterWidth/2 + 2;
}
HiteTest(point);

this->Invalidate();
this->UpdateData();
}

CStatic::OnLButtonUp(nFlags, point);
}

//void CSplitter::OnTimer(UINT_PTR nIDEvent)
//{
// // TODO: 在此添加消息处理程序代码和/或调用默认值
// //控制鼠标位置==================================
// CRect rc;
// this->GetClientRect(&rc);
//
// CPoint ptWnd, ptCursor;
// ptWnd.SetPoint(0, 0);
// ClientToScreen(&ptWnd);
// ::GetCursorPos(&ptCursor);
// if(ptCursor.x < ptWnd.x + m_nMinCx+m_nSplitterWidth/2+4)
// ::SetCursorPos(ptWnd.x + m_nMinCx+m_nSplitterWidth/2+4, ptCursor.y);
// if(ptCursor.x > ptWnd.x + rc.Width() - 2)
// ::SetCursorPos(ptWnd.x + rc.Width() - 2, ptCursor.y);
// if(ptCursor.y < ptWnd.y + m_nMinCy+m_nSplitterWidth/2+4)
// ::SetCursorPos(ptCursor.x, ptWnd.y + m_nMinCy+m_nSplitterWidth/2+4);
// if(ptCursor.y > ptWnd.y + rc.Height() - 2)
// ::SetCursorPos(ptCursor.x, ptWnd.y + rc.Height() - 2);
// //==============================================
//
// CStatic::OnTimer(nIDEvent);
//}

BOOL CSplitter::CreateSplitter(int nRows, int nColumns, CRect& rect, CWnd *pParentWnd, CSize szLimit)
{
ASSERT(pParentWnd != NULL);

m_nRows = nRows;
m_nColumns = nColumns;

m_nMinCx = szLimit.cx;
m_nMinCy = szLimit.cy;

m_hCtrlWnd = new HWND[m_nRows*m_nColumns];
memset((void*)m_hCtrlWnd, 0, sizeof(HWND)*m_nRows*m_nColumns);

return this->Create(NULL, SS_NOTIFY|SS_OWNERDRAW|WS_VISIBLE|WS_CHILD, rect, pParentWnd);
}

void CSplitter::SetPaneInfo(int nRow, int nColumn, CSize sz, CWnd *pWnd)
{
m_nCx[nColumn] = sz.cx;
m_nCy[nRow] = sz.cy;

if(pWnd != NULL)
{
pWnd->SetParent(this);
m_hCtrlWnd[nRow*m_nColumns+nColumn] = pWnd->m_hWnd;
}
}

CWnd* CSplitter::GetPane(int nRow, int nColumn)
{
return CWnd::FromHandle(m_hCtrlWnd[nRow*m_nColumns+nColumn]);
}

void CSplitter::GetPanesize(int nRow, int nColumn, CRect &rect)
{
rect.SetRect(0, 0, 0, 0);
for(int i = 0;i < nColumn;i ++)
rect.left += m_nCx[i] + m_nSplitterWidth;
rect.right = rect.left + m_nCx[nColumn];
for(int i = 0;i < nRow;i ++)
rect.top += m_nCy[i] + m_nSplitterWidth;
rect.bottom = rect.top + m_nCy[nRow];
}

void CSplitter::ReCalcSize(CRect &rcClient)
{
m_nCx[m_nColumns - 1] = rcClient.Width();
for(int i = 0;i < m_nColumns - 1;i ++)
m_nCx[m_nColumns - 1] -= m_nCx[i] + m_nSplitterWidth;
m_nCy[m_nRows - 1] = rcClient.Height();
for(int i = 0;i < m_nRows - 1;i ++)
m_nCy[m_nRows - 1] -= m_nCy[i] + m_nSplitterWidth;
}

void CSplitter::OnDraw()
{
CDC *pDC = this->GetDC();
CRect rc;
this->GetClientRect(&rc);

int nXpos = 0;
int nYpos = 0;

//
//CPen pen;
//pen.CreatePen(PS_SOLID, 1, RGB(167, 166, 170));
//CBrush brush;
//brush.CreateSolidBrush(RGB(239, 237, 241));
//CPen *pOldPen = pDC->SelectObject(&pen);
//CBrush *pOldBrush = pDC->SelectObject(&brush);
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);

CDC compDC;
compDC.CreateCompatibleDC(pDC);
compDC.SelectObject(&bitmap);
//

//竖条
for(int i = 0;i < m_nColumns - 1;i ++)
{
nXpos += m_nCx[i];
//pDC->Rectangle(nXpos, 0, nXpos+m_nSplitterWidth, rc.Height());
if(!m_bHasBtn)
pDC->StretchBlt(nXpos, 0, m_nSplitterWidth, rc.Height(), &compDC, 0, 0, 7, 7, SRCCOPY);
else
{
pDC->StretchBlt(nXpos, 0, m_nSplitterWidth, rc.Height()/2-25, &compDC, 0, 0, 7, 7, SRCCOPY);
pDC->StretchBlt(nXpos, rc.Height()/2+25, m_nSplitterWidth, rc.Height()/2-24, &compDC, 0, 0, 7, 7, SRCCOPY);
//button===================================================================================
if(m_bOver && m_nCurY == -2)
{
pDC->StretchBlt(nXpos, rc.Height()/2-25, m_nSplitterWidth, 50, &compDC, 0, 15, 7, 8, SRCCOPY);
if(m_nCx[0] == 0)
pDC->StretchBlt(nXpos, rc.Height()/2-4, m_nSplitterWidth, 8, &compDC, 14, 15, 7, 8, SRCCOPY);
else
pDC->StretchBlt(nXpos, rc.Height()/2-4, m_nSplitterWidth, 8, &compDC, 7, 15, 7, 8, SRCCOPY);
}
else
{
pDC->StretchBlt(nXpos, rc.Height()/2-25, m_nSplitterWidth, 50, &compDC, 0, 7, 7, 8, SRCCOPY);
if(m_nCx[0] == 0)
pDC->StretchBlt(nXpos, rc.Height()/2-4, m_nSplitterWidth, 8, &compDC, 14, 7, 7, 8, SRCCOPY);
else
pDC->StretchBlt(nXpos, rc.Height()/2-4, m_nSplitterWidth, 8, &compDC, 7, 7, 7, 8, SRCCOPY);
}
}
nXpos += m_nSplitterWidth;
}

//横条
nYpos = 0;
for(int i = 0;i < m_nRows - 1;i ++)
{
nYpos += m_nCy[i];
//pDC->Rectangle(0, nYpos, rc.Width(), nYpos+m_nSplitterWidth);
if(!m_bHasBtn)
pDC->StretchBlt(0, nYpos, rc.Width(), m_nSplitterWidth, &compDC, 7, 0, 7, 7, SRCCOPY);
else
{
pDC->StretchBlt(0, nYpos, rc.Width()/2-25, m_nSplitterWidth, &compDC, 7, 0, 7, 7, SRCCOPY);
pDC->StretchBlt(rc.Width()/2+25, nYpos, rc.Width()/2-24, m_nSplitterWidth, &compDC, 7, 0, 7, 7, SRCCOPY);
//button===================================================================================
if(m_bOver && m_nCurX == -2)
{
pDC->StretchBlt(rc.Width()/2-25, nYpos, 50, m_nSplitterWidth, &compDC, 0, 30, 4, 7, SRCCOPY);
if(m_nCy[0] == rc.Height()-m_nSplitterWidth-20)
pDC->StretchBlt(rc.Width()/2-4, nYpos, 8, m_nSplitterWidth, &compDC, 13, 30, 8, 7, SRCCOPY);
else
pDC->StretchBlt(rc.Width()/2-4, nYpos, 8, m_nSplitterWidth, &compDC, 5, 30, 8, 7, SRCCOPY);
}
else
{
pDC->StretchBlt(rc.Width()/2-25, nYpos, 50, m_nSplitterWidth, &compDC, 0, 23, 4, 7, SRCCOPY);
if(m_nCy[0] == rc.Height()-m_nSplitterWidth-20)
pDC->StretchBlt(rc.Width()/2-4, nYpos, 8, m_nSplitterWidth, &compDC, 13, 23, 8, 7, SRCCOPY);
else
pDC->StretchBlt(rc.Width()/2-4, nYpos, 8, m_nSplitterWidth, &compDC, 5, 23, 8, 7, SRCCOPY);
}
}
nYpos += m_nSplitterWidth;
}

//交叉块
nXpos = 0;
nYpos = 0;
for(int i = 0;i < m_nRows - 1;i ++)
{
nYpos += m_nCy[i];
//pDC->Rectangle(0, nTemp, rc.Width(), nTemp+m_nSplitterWidth);
for(int j = 0;j < m_nColumns - 1;j ++)
{
nXpos += m_nCx[j];
//pDC->Rectangle(nXpos, nYpos, nXpos+m_nSplitterWidth, nYpos+m_nSplitterWidth);
pDC->StretchBlt(nXpos, nYpos, m_nSplitterWidth, m_nSplitterWidth, &compDC, 14, 0, 7, 7, SRCCOPY);
nXpos += m_nSplitterWidth;
}
nYpos += m_nSplitterWidth;
nXpos = 0;
}
//pDC->SelectObject(pOldPen);
//pDC->SelectObject(pOldBrush);
compDC.DeleteDC();
bitmap.DeleteObject();
ReleaseDC(pDC);
}

 在OnInitDialog()中做如下初始化

 CRect rc;
 this->GetClientRect(&rc);
 if(!m_splitter.CreateSplitter(2, 2, rc, this, CSize(100, 100)))
  return false;
 m_splitter.SetPaneInfo(0, 0, CSize(100, 150), GetDlgItem(IDC_EDIT1));
 m_splitter.SetPaneInfo(0, 1, CSize(100, 150), GetDlgItem(IDC_EDIT2));
 m_splitter.SetPaneInfo(1, 0, CSize(100, 150), GetDlgItem(IDC_EDIT3));
 m_splitter.SetPaneInfo(1, 1, CSize(100, 150), GetDlgItem(IDC_EDIT4));

 

 在OnInitDialog()中做如下初始化

 CRect rc;
 this->GetClientRect(&rc);
 if(!m_splitter.CreateSplitter(1, 2, rc, this, CSize(100, 100)))
  return false;
 if(!m_splitter1.CreateSplitter(2, 1, rc, this, CSize(100, 100)))
  return false;
 if(!m_splitter2.CreateSplitter(2, 1, rc, this, CSize(100, 100)))
  return false;
 m_splitter.SetPaneInfo(0, 0, CSize(200, 0), CWnd::FromHandle(m_splitter1.m_hWnd));
 m_splitter.SetPaneInfo(0, 1, CSize(0, 150), CWnd::FromHandle(m_splitter2.m_hWnd));
 m_splitter1.SetPaneInfo(0, 0, CSize(200, 200), GetDlgItem(IDC_EDIT1));
 m_splitter1.SetPaneInfo(1, 0, CSize(0, 0), GetDlgItem(IDC_EDIT2));
 m_splitter2.SetPaneInfo(0, 0, CSize(100, 300), GetDlgItem(IDC_EDIT3));
 m_splitter2.SetPaneInfo(1, 0, CSize(0, 0), GetDlgItem(IDC_EDIT4));

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
在MFC应用程序中显示JPG/GIF图像文件
使用duilib出现“error C2872: 'CRect' : ambiguous symbol”等错误
SplitterCtrl-用于将某些窗口划分为几个部分的控件
MFC中CDC的使用?绘图
CPoint,CSize,CRect类说明收藏
MFC常用类、成员函数、数组类、Cstring类、CTime类、CPoint类
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服