티스토리 뷰

 Slider Control 을 드래그 하면 Edit Control에 실시간으로 결과 값을 처리하는 mfc 코드입니다. 가운데 조절 부분을 이용하여 드래그 하였을 때 실시간으로 결과 값을 Edit Control에 처리하게 됩니다.

 slider control에 필요한 별도의 Class를 생성하는 방법을 사용하였습니다.


Project 생성

아래와 같이 다이얼로그로 된 새로운 MFC Project를 생성합니다.


새로운 MFC class를 추가

 아래와 같이 생성된 Project위에서 오른쪽 마우스를 클릭하여 Add -> Class 메뉴로 접근합니다.


새로운 MFC 클래스를 생성합니다. CSliderCtrl을 상속 받는 CMySlider class를 추가합니다.


다이얼로그에 아래와 같이 Slider Control, Edit Control을 추가합니다.


Slider Ctrl을 새로운 변수로 추가합니다.

변수 타입은 위에서 생성한 CMySlider 이고, 카테고리는 Control을 사용합니다. 변수 명은 m_sliderCtrl 로 해주었습니다. Edit Control역시 새로운 변수를 추가합니다. 카테고리는 value, 변수 타입은 CString, 변수 명은 m_strValue 로 지정해주었습니다.


이제 CMySlider 클래스에 아래와 같은 변수와 함수를 추가해주어야 합니다.

bool m_bSelected; //변수 선언
 CSliderCtrl* m_sliderCtrl; //CSliderCtrl* 변수 선언 Dlg에서 넘겨받은 값을 Point로 저장
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point); //마우스 왼쪽 버튼다운
 afx_msg void OnLButtonUp(UINT nFlags, CPoint point);      //마우스 왼쪽 버튼 업
 afx_msg void OnMouseMove(UINT nFlags, CPoint point);  //마우스 드래그

setMySlider 함수를 추가해줍니다. (생성자 함수에 CSliderCtrl* m_pSliderCtrl 를 추가해주어도 됩니다.)

CSliderCtrl* m_pSliderCtrl를 추가하는 함수를 추가합니다.


소스코드 CMySlider.cpp

아래 함수에 다음 내용을 추가합니다.

#include "ex00blogSliderDlg.h" //m_strValue의 값을 실시간으로 변경하기 위해서 h 추가

//마우스가 클릭되었을 경우
void CMySlider::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CRect rect;
	GetThumbRect(&rect);
	if(rect.PtInRect(point)) //사각형 안의 값인지 확인하는 PtlnRect(point);
		m_bSelected = true; //슬라이드의 사각형 안이라면 true
	else
		m_bSelected = false; //슬라이드의 사각형 밖이라면 false

	CSliderCtrl::OnMButtonDown(nFlags, point);
}


void CMySlider::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	m_bSelected = false; //마우스에서 손이 떨어지면 false 처리
	int nPos = GetPos(); //위치 값을 가져옴
	m_sliderCtrl->SetPos(nPos);

	CString str;
	str.Format(_T("%d"), nPos); //str.Fromat() 을 이용하여 int값을 CString으로 변경
	Cex00blogSliderDlg* pMain = (Cex00blogSliderDlg*)AfxGetMainWnd(); //main의 값을 그대로 호출 함
	pMain->m_strValue.SetString(str); //호출 하여 m_strValue에 SetString을 하기 위해서

	CSliderCtrl::OnLButtonUp(nFlags, point);
}


void CMySlider::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	if(m_bSelected && m_sliderCtrl)
	{
		int nPos = GetPos();
		m_sliderCtrl->SetPos(nPos);

                CString str;
                str.Format(_T("%d"), nPos); //str.Fromat() 을 이용하여 int값을 CString으로 변경
                Cex00blogSliderDlg* pMain = (Cex00blogSliderDlg*)AfxGetMainWnd(); //main의 값을 그대로 호출 함
                pMain->m_strValue.SetString(str); //호출 하여 m_strValue에 SetString을 하기 위해서
	}

	CSliderCtrl::OnMouseMove(nFlags, point);
}


void CMySlider::setMySlider(CSliderCtrl* m_pSliderCtrl)
{
	m_sliderCtrl = m_pSliderCtrl;
}

메인 코드 처리 ex00blogSliderDlg.h

 Head 부분에 아래와 같이 import 함수를 추가하시면 됩니다.

#include "MySlider.h"


메인 코드 처리 ex00blogSliderDlg.cpp

BOOL Cex00blogSliderDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	m_sliderCtrl.SetRange(0, 100);
	m_sliderCtrl.SetPos(30);

	int nPos = m_sliderCtrl.GetPos(); //처음 실행될 부분을 위해서 m_sliderCtrl.GetPos(); 를 사용
	CString str;
	str.Format(_T("%d"), nPos); //Format을 이용하여 int값을 변경
	m_strValue.SetString(str);
	UpdateData(false); //set을 해주기 위해서 UpdateData(false); 를 사용

	m_sliderCtrl.setMySlider(&m_sliderCtrl);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

이렇게 사용하시면 실시간으로 값을 처리하게 됩니다.


2번째 방법

 위와 같이 별도의 함수를 사용하지만 "ex00blogSliderDlg.h" 함수에서 실시간 값을 처리하는 방법입니다. 

 OnHScroll 함수를 추가 합니다. 이 함수는 ScrollBar의 값을 불러와 Edit Control에 정의할 때 사용가능합니다. 코드는 아래와 같습니다. 이때에는 CMySlider의 MouseMove에 중복 코드를 제거하시면 됩니다.

 코드 설명 UINT nPos 의 nPos 변수를 사용할 경우 실시간으로는 처리되지만 마우스를 때고 나서는 0으로 변경됩니다. 그렇기에 별도의 변수를 추가하여 작성하였습니다.

void Cex00blogSliderDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: Add your message handler code here and/or call default
	int npos = m_slider.GetPos();
	CString str;
	str.Format(_T("%d"), npos);
	m_strValue.SetString(str);
	UpdateData(false); //Edit Control에 값을 내보내기 위해서 작성
	CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}

위 코드를 추가해주셔도 위와 같이 동일하게 구성됩니다. 편하신 코드와 이해하기 쉬운 코드를 작성하시는 게 좋은 듯합니다.


참고

 처음에는 위와 같은 소스코드가 아니라 아래와 같은 일부 코드였습니다. CMySlider.cpp 의 setMySlider에 CSliderCtrl* 을 넘겨주고, CString* 도 역시 넘겨주었습니다. Dlg.cpp의 윗부분에는 아래와 같은 코드가 정의되어 있기에 당연히 될 것이라고 생각하여 이렇게 처리하였습니다.

	DDX_Control(pDX, IDC_LIST1, m_listBox);
	DDX_Text(pDX, IDC_EDIT2, m_strDay);

이 부분을 처리하기 UpdateData(false)를 처리해야 했습니다. 처리 방법은 아래와 같았습니다.

void CMySlider::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	if(m_bSelected && m_sliderCtrl)
	{
		int nPos = GetPos();
		m_sliderCtrl->SetPos(nPos);

                CString str;
	        str.Format(_T("%d"), npos);
	        m_strValue.SetString(str);
	        UpdateData(false); //Edit Control에 값을 내보내기 위해서 작성
	}

	CSliderCtrl::OnMouseMove(nFlags, point);
}

 디버깅을 통해서 확인해봤지만 모든 값이 처리되고 있었습니다. 문제는 UpdateData(false); 부분을 처리하지 못한 게 문제였습니다. 이유는 UpdateData() 함수는 Dlg의 DDX 부분을 처리하기 위함인데 여기서는 DDX 부분을 찾지 못하기 때문에 값을 처리하지 못하는 문제가 발생하였습니다. 그래서 책을 찾아서 위의 코드와 같이 해결하여 작성된 글입니다.






댓글