하나의 View 영역을 분할하여 사용할 수 있는 윈도우를 의미합니다.
여기서 분할이라는 의미는 화면 영역을 나누어 사용한다는 의미로 각 영역은 동일한 데이터를 공유할 수 있으며 화면에 표시되는 방식에만 차이가 있는 것을 의미합니다.
분할윈도우를 컨트롤하는 윈도우 클래스는 CSplitterWnd입니다.
이 클래스가 프레임윈도우에 설정되고 이 윈도우위에 여러 개의 View윈도우들이 설정될 수 있는 것 입니다.
분할윈도우를 설정하고자 할 때는 AppWizard Step4에서 Advance항목을 선택하고 분할윈도우 스타일을 설정해 주어야 합니다.
1) 분할 윈도우의 종류
정적 분할 윈도우 | 프로그램이 실행 될 때 영역이 분할된 상태로 실행되며 영역의 크기를 조절할 수는 있지만 분할된 영역을 제거할 수는 없는 분할 윈도우 |
동적 분할 윈도우 | 분할된 영역의 크기를 조절할 수 있을 뿐 아니라 분할된 영역을 제거할 수 있는 윈도우 |
2) CSplitterWnd 클래스의 멤버함수
Create() | 동적 분할 윈도우 생성 |
CreateStatic() | 정적 분할 윈도우 생성 |
CreateView() | 정적 분할 윈도우의 영역 생성 |
GetColumnCount() | 가로로 분할 된 영역의 수를 구함 |
GetColumnInfo() | 지정된 분할 영역의 정보(가로길이, 최소길이)를 구함 |
GetRowCount() | 세로로 분할 된 영역의 수를 구함 |
GetRowInfo() | 지정된 분할 영역의 정보(세로길이, 최소길이)를 구함 |
RecalcLayout() | 분할 윈도우를 다시 표시 |
DeleteColumn() | 지정된 가로 영역을 제거 |
DeleteRow() | 지정된 세로 영역을 제거 |
4.1. 다중 분할 윈도우 만들기
상/하, 좌/우가 복합적으로 분할된 다중 분할 윈도우를 생성하는 소스 코드 (아래의 그림과 같이 분할하는 코드).
-
// 분할 윈도우 객체 선언{protected: CSplitterWnd m_wndSplitterSub; // 상/하 분할};// 분할 윈도우 생성 코드 구현 CCreateContext* pContext) // 윈도우 클라이언트 영역 크기 얻기 GetClientRect( &rect ); // STEP 1: 메인 윈도우의 좌/우 분할
// m_wndSplitterMain.SetColumnInfo( 0, 250, 10 );
m_wndSplitterMain.CreateView( 0, 0, RUNTIME_CLASS( CViewA ),
m_wndSplitterSub.CreateStatic( &m_wndSplitterMain, 2, 1, m_wndSplitterMain.IdFromRowCol( 0, 1 ) ); // 참고 2 : 상/하 윈도우 크기 지정 // m_wndSplitterSub.SetRowInfo( 1, 250, 10 ); // SETP 2-1: 상/하 분할 윈도우의 View 생성 m_wndSplitterSub.CreateView( 0, 0, RUNTIME_CLASS( CViewB ), m_wndSplitterSub.CreateView( 1, 0, RUNTIME_CLASS( CViewC ),
}// 분할 윈도우의 스크롤바 없애기BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/,{ 2, 1, // 행 및 열의 개수를 지정 pContext,}// 분할 윈도우의 크기 조절하기{
{ m_wndSplitter.GetClientRect( &rect ); m_wndSplitter.SetRowInfo( 0, rect.Height() / 2, 10 ); // 첫번째 행의 크기를 지정
}
분할 윈도우의 Client Edge 는 CWnd 클래스를 상속 받은 다른 클래스와 달리 윈도우 스타일을 사용하지 않고 CSplitterWnd 클래스에서 직접 그린다. 따라서 CSplitterWnd 클래스를 상속 받아서 Client Edge 를 그리는 함수(가상 함수)를 재정의해야 한다.DrawAllSplitBars() 함수참고> 두 함수의 자세한 코드는 아래의 파일을 참고한다.$(VCInstallDir)atlmfc\include\afxext.h
//#pragma once
class CSplitterWndEx : public CSplitterWnd DECLARE_DYNAMIC( CSplitterWndEx )public: virtual ~CSplitterWndEx(); // 가상함수 재정의 virtual void OnDrawSplitter( CDC* pDC, ESplitType nType, const CRect& rect ); // 특정 View 의 Client Edge 를 지워야 될 경우 재정의 한다.
DECLARE_MESSAGE_MAP()public:// afx_msg void OnPaint();
//#include "StdAfx.h"
#define CX_BORDER (1)
{
{
END_MESSAGE_MAP()void CSplitterWndEx::OnDrawSplitter( CDC* pDC, ESplitType nType, const CRect& rectArg ) if( ( 0 == rectArg.left ) && ( 0 == rectArg.top ) ) // 좌상단(0,0) 에서 시작하는 View 에 대하여 Client Edge 를 지운다.
{ return; ASSERT_VALID(pDC); //-------------------------------------------------------------- CRect rect = rectArg; pDC->Draw3dRect( rect, ::GetSysColor( COLOR_BTNFACE ), ::GetSysColor( COLOR_BTNFACE ) ); pDC->Draw3dRect( rect, ::GetSysColor( COLOR_BTNFACE ), ::GetSysColor( COLOR_BTNFACE ) ); return;
CSplitterWnd::OnDrawSplitter( pDC, nType, rectArg ); - }
- // 다른 View 는 동일하게 동작하도록 OnDrawSplitter() 함수를 호출한다.
- }
- rect.InflateRect( -CX_BORDER, -CY_BORDER );
- }
- RedrawWindow( rectArg, NULL, RDW_INVALIDATE | RDW_NOCHILDREN );
- if( NULL == pDC )
- // - 원리: 창의 기본색과 동일한게 Client Edge 를 그린다.
- {
- {
- BEGIN_MESSAGE_MAP( CSplitterWndEx, CSplitterWnd )
- }
- CSplitterWndEx::~CSplitterWndEx()
- }
- CSplitterWndEx::CSplitterWndEx()
- IMPLEMENT_DYNAMIC( CSplitterWndEx, CSplitterWnd )
- // CSplitterWndEx 클래스
- #define CY_BORDER (1)
- // 상수 선언
- #include "SplitterWndEx.h"
- // SplitterWndEx.cpp : CSplitterWndEx 클래스 구현
- };
- // 특정 View 의 Client Edge 를 지워야 될 경우 재정의 한다.
- protected:
- // virtual void DrawAllSplitBars(CDC* pDC, int cxInside, int cyInside);
- protected:
- CSplitterWndEx();
- {
- // CSplitterWndEx 클래스
- // SplitterWndEx.h : CSplitterWndEx 클래스 선언
- */
- $(VCInstallDir)atlmfc\src\mfc\winsplit.cpp
- OnPaint() 함수 (WM_PAINT 메시지 재정의)
- 특정 Pane (View) 의 Client Edge 를 지워야 될 경우, 다음의 두 함수를 재정의 한다.
- /*
- // 분할 윈도우의 Client Edge 지우기
- }
- m_wndSplitter.RecalcLayout();
- // 열의 크기를 지정할 경우 SetColumnInfo() 함수 사용
- m_wndSplitter.SetRowInfo( 1, rect.Height() / 2, 10 ); // 두번째 행의 크기를 지정
- CRect rect;
- if( m_bSplitterCreated ) // 주의> 창이 열린 경우에만 적용 가능하다.
- CFrameWnd::OnSize( nType, cx, cy );
- void CMainFrame::OnSize( UINT nType, int cx, int cy )
- WS_CHILD | WS_VISIBLE | SPLS_DYNAMIC_SPLIT ); // 기본 스타일 중에서 WS_HSCROLL 와 WS_VSCROLL 를 제거
- CSize(100, 100), // 최소 창 크기를 지정
- return m_wndSplitter.Create( this,
- CCreateContext* pContext )
- return TRUE;
- CSize( 0, nHeight ), pContext );
- CSize( 0, nHeight ), pContext );
- int nHeight = rect.Height() / 2;
- // m_wndSplitterSub.SetRowInfo( 0, 250, 10 );
- WS_CHILD | WS_VISIBLE,
- // STEP 2: 우측 분할 윈도우의 상/하 분할
- CSize( 200, 0 ), pContext )
- // STEP 1-1: 좌측 분할 윈도우의 View 생성
- // m_wndSplitterMain.SetColumnInfo( 1, 250, 10 );
- // 참고 1: 좌/우 윈도우 크기 지정
- m_wndSplitterMain.CreateStatic( this, 1, 2 );
- CRect rect;
- {
- BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
- CSplitterWnd m_wndSplitterMain; // 좌/우 분할
- // 특성입니다.
- class CMainFrame : public CFrameWnd
-
[Dialog / Splitter Bar] Splitter Bar 를 고정시킬 수 있는 CSplitterWnd 클래스 C & C++/MFC Dialog Splitter Bar 를 고정시킬 수 있는 방법이 MFC 의 CSplitterWnd 클래스에는 존재하는지 찾아 보았지만 존재하지 않더군요. 그래서, CSplitterWnd 를 상속받아서 Splitter Bar 를 고정시킬 수 있는 클래스를 작성해 보았습니다. 아래는 Splitter Bar 를 고정시킬 수 있는 CMySplitterWnd 클래스 소스 코드입니다. // Header File class CMySplitterWnd : public CSplitterWnd { DECLARE_DYNAMIC(CMySplitterWnd) public: CMySplitterWnd(); virtual ~CMySplitterWnd(); void LockBar( ); void UnlockBar( ); protected: DECLARE_MESSAGE_MAP() bool m_bLockBar; public: 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); }; // Source File IMPLEMENT_DYNAMIC(CMySplitterWnd, CSplitterWnd) CMySplitterWnd::CMySplitterWnd() : m_bLockBar(false) { } CMySplitterWnd::~CMySplitterWnd() { } BEGIN_MESSAGE_MAP(CMySplitterWnd, CSplitterWnd) ON_WM_LBUTTONDOWN() ON_WM_SETCURSOR() ON_WM_MOUSEMOVE() END_MESSAGE_MAP() /** * @brief Splitter Bar 를 고정시킨다. */ void CMySplitterWnd::LockBar( ) { m_bLockBar = true; } /** * @brief Splitter Bar 를 움직일 수 있게 한다. */ void CMySplitterWnd::UnlockBar( ) { m_bLockBar = false; } void CMySplitterWnd::OnLButtonDown(UINT nFlags, CPoint point) { if( m_bLockBar == false ) { CSplitterWnd::OnLButtonDown(nFlags, point); } } BOOL CMySplitterWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if( m_bLockBar ) { return CWnd::OnSetCursor(pWnd, nHitTest, message); } return CSplitterWnd::OnSetCursor(pWnd, nHitTest, message); } void CMySplitterWnd::OnMouseMove(UINT nFlags, CPoint point) { if( m_bLockBar ) { CWnd::OnMouseMove(nFlags, point); } else { CSplitterWnd::OnMouseMove(nFlags, point); } }
'C & C++ > MFC 컨트롤' 카테고리의 다른 글
다이얼로그 최대화 하는 2가지 방법 (0) | 2012.11.28 |
---|---|
시스템 캡션 깜빡거리게 만들기 (0) | 2012.10.05 |
Tree 와 List 가 합쳐진 트리 (0) | 2012.08.31 |
스크롤바 꾸미기(색상표) (0) | 2012.08.21 |
Time Picker - 시간 컨트롤러 (0) | 2012.06.26 |
댓글