Files
2026-06-01 12:46:52 +02:00

407 lines
13 KiB
C++

#include "stdafx.h"
#include "KUIControlSlider.h"
#include "KUIWndManager.h"
#include "KUIControlButton.h"
//#include "Util.h"
#include "KResourceManager.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// KUIControlSlider Implement
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using namespace KUI_MESSAGE;
namespace
{
const std::string SLIDER_OPTION_CTR = "button_option_control";
const std::string SLIDER_DOWN_BTN = "button_scrollbar_down";
const std::string SLIDER_UP_BTN = "button_scrollbar_up";
const std::string SLIDER_LEFT_BTN = "button_common_left";
const std::string SLIDER_RIGHT_BTN = "button_common_right";
const std::string SLIDER_VERTICAL_BACK = "static_scrollbar_backgroundable";
const std::string SLIDER_HORIZONTAL_BACK = "static_scrollbar_backgroundable";
const int SLIDER_BTN_GAP = 3;
const float SLIDER_BAR_UNIT_DEVIDER = 20.f;
const char* c_lpBackGrondCtr0 = "option_bcakground00_%02d";
const char* c_lpBackGrondCtr1 = "option_bcakground01_%02d";
}
KUIControlSlider::KUIControlSlider()
{
m_dwMaxRange = 1;
m_bMouseDrag = false;
m_nCurrentPos = 0;
m_pOptionCtrBt = NULL;
memset(m_pSliderBarBtn, 0 ,sizeof(m_pSliderBarBtn));
}
KUIControlSlider::~KUIControlSlider()
{
}
void KUIControlSlider::_initControl()
{
KUIWnd::_ClearChildList();
KRect rcOrigin = m_rcRegion;
KUIControl::_initControl();
}
void KUIControlSlider::SetSliderRange(DWORD dwMaxRange)
{
if( dwMaxRange < 1 || m_dwMaxRange == dwMaxRange ) return;
m_dwMaxRange = dwMaxRange;
if(m_nCurrentPos >= dwMaxRange)
SetPosition(dwMaxRange - 1);
_CopyRangeStaticCtr();
InvalidateWnd();
}
void KUIControlSlider::SetPosition(int nPos)
{
if( m_nCurrentPos == nPos ) return;
if(nPos <= 0)
nPos = 0;
else if(nPos >= m_dwMaxRange-1)
nPos = m_dwMaxRange-1;
m_nCurrentPos = nPos;
KUIWnd* pWnd = GetChild("option_control");
if( pWnd )
{
KRect rc = pWnd->GetRect();
int nCrrPos = m_rcRegion.left + nPos*_GetOptionControlGap();
rc.left = nCrrPos - rc.GetWidth()/2;
rc.right = rc.left + rc.GetWidth();
SetMovePos( "option_control", rc.left, rc.top);
}
_BackGroundCtrUpdate(nPos);
InvalidateWnd();
}
DWORD KUIControlSlider::OnKeyMessage(DWORD dwMessage, DWORD dwKeyCode)
{
DWORD dwRet = KUIControl::OnKeyMessage(dwMessage, dwKeyCode);
if(KMR_NO_GET & dwRet) return dwRet;
if( IsDisable() ) return dwRet;
// 여기에 처리
return dwRet;
}
void KUIControlSlider::PumpUpMessage(LPCSTR lpszControlID, DWORD dwMessage, DWORD lParam, DWORD wParam)
{
if( IsDisable() ) return;
if(KBUTTON_CLICK == dwMessage)
{
int nOldPos = m_nCurrentPos;
if( _ButtonClickUpdate(lpszControlID) )
{
PumpUpMessage(GetID(), SLIDER_CHANGE, nOldPos, 0);
}
PumpUpMessage(GetID(), SLIDER_SELECT, m_nCurrentPos, 0);
InvalidateWnd();
}
KUIControl::PumpUpMessage( lpszControlID, dwMessage, lParam, wParam);
}
DWORD KUIControlSlider::OnMouseMessage( DWORD dwMessage, int x, int y )
{
DWORD dwRet = KUIControl::OnMouseMessage(dwMessage,x,y);
if(KMR_NO_GET & dwRet) return dwRet;
if( IsDisable() ) return dwRet;
if(KMR_NO_GET & dwRet)
return dwRet;
// 여기에 처리
int nOldPos = m_nCurrentPos;
// Drag 처리
if( m_bMouseDrag )
{
switch( dwMessage )
{
case KMOUSE_MOVE:
if( IsInRect(x,y) ) //SetCapture를 해서 윈도우 벗어나도 오는데 벗어날때는 MOVE를 무시한다 KLBUTTON_UP를 받기 위해서 SetCapture한 것
{
_OffsetOptionCtrBt( x-m_OldClickPoint.x, y-m_OldClickPoint.y );
_BackGroundCtrUpdate( _GetPos(x,y) );
m_OldClickPoint.x = x; m_OldClickPoint.y = y;
}
break;
case KLBUTTON_UP:
{
SetPosition( _GetPos(x,y) );
m_pManager->ReleaseCapture(this);
m_bMouseDrag = false;
break;
}
default:
break;
}
}
// Scroll 이동범위 체크
else if(IsInRect(x,y) )
{
switch(dwMessage)
{
case KLBUTTON_DOWN:
if(m_pOptionCtrBt->IsInRect(x,y) )
{
m_OldClickPoint = KPoint(x, y);
m_bMouseDrag = true;
m_pManager->SetCapture(this);
}
else
{
SetPosition( _GetPos(x,y) );
}
break;
case KLBUTTON_UP:
break;
default:
break;
}
}
if(nOldPos != m_nCurrentPos )
{
PumpUpMessage(GetID(), SLIDER_CHANGE, nOldPos, 0);
PumpUpMessage(GetID(), SLIDER_SELECT, m_nCurrentPos, 0);
}
return dwRet;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// KUIControlHSlider Implement
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace
{
KUIWnd* HSliderCreator()
{
return new KUIControlHSlider;
}
bool bHSliderRegister = KUIFactory::GetInstance()->RegisterCreator( HSliderCreator, "h_slider");
const int c_nButtonUpGap = -5;
const int c_nButtonDownGap = 3;
const int c_nButtonSize = 3;
}
KUIControlHSlider::KUIControlHSlider(void)
{}
KUIControlHSlider::~KUIControlHSlider(void)
{}
void KUIControlHSlider::_initControl()
{
if ( m_sAniName.empty() )
m_sAniName = SLIDER_HORIZONTAL_BACK;
KUIControlSlider::_initControl();
_CopyRangeStaticCtr();
// 컨트롤 버튼 생성
KUIWND_CREATE_ARG arg;
arg.lpszSprName = m_sSprName.c_str();
arg.lpszAniName = SLIDER_OPTION_CTR.c_str();
arg.lpszClassName = "simplebutton";
arg.lpszID = "option_control";
arg.pParent = this;
arg.dwStyle = 0;
arg.rcRect.left = m_rcRegion.left - c_nButtonSize/2;
arg.rcRect.right = m_rcRegion.left + c_nButtonSize;
arg.rcRect.top = m_rcRegion.top +c_nButtonUpGap;
arg.rcRect.bottom = m_rcRegion.bottom +c_nButtonDownGap;
m_pOptionCtrBt = reinterpret_cast<KUIControlButton*>( m_pManager->CreateControl( arg ));
m_pOptionCtrBt->SetCorrectionRect(KRect(-1,-1,1,1), false); //컨트롤 버튼 좀더 클릭하기 쉽게 1픽셀씩 영역 확장
//기본 슬라이드 윈도우의 클릭 영역도 확장, 버튼은 길지만 윈도우 자체가 작아서 메세지 안오는 것 때문
SetCorrectionRect( KRect(-SLIDER_BTN_GAP, c_nButtonUpGap, SLIDER_BTN_GAP, c_nButtonDownGap), false );
// Slider Left Btn 생성
arg.lpszClassName = "simplebutton";
arg.lpszSprName = m_sSprName.c_str();
arg.lpszAniName = SLIDER_LEFT_BTN.c_str();
arg.lpszID = "slider_btn_left";
arg.dwStyle = 0;
KResSprite * pFrameLeft = KSpriteManager::GetManager()->GetResSprite(m_sSprName.c_str(), SLIDER_LEFT_BTN.c_str() , 0);
if(NULL == pFrameLeft)
assert( false && "Cannot Find Res Frame");
int nSizeXBt(0);
nSizeXBt = pFrameLeft->GetSizeX();
arg.rcRect = KRect(m_rcRegion.left - nSizeXBt - SLIDER_BTN_GAP, m_rcRegion.top-3,-1, -1);
m_pSliderBarBtn[SLIDER_BAR_LEFT] = reinterpret_cast<KUIControlSimpleButton*>( m_pManager->CreateControl( arg ) );
// Slider Right Btn 생성
arg.lpszAniName = SLIDER_RIGHT_BTN.c_str();
arg.lpszID = "slider_btn_right";
arg.rcRect = KRect(m_rcRegion.right + SLIDER_BTN_GAP, m_rcRegion.top-3,-1,-1);
m_pSliderBarBtn[SLIDER_BAR_RIGHT] = reinterpret_cast<KUIControlSimpleButton*>( m_pManager->CreateControl( arg ) );
//미확인 -N4-
//이것은 무엇을 하는 함수인지 모르겠다. 우선 Scroll에 있어서 넣었는데 확인해보고 지우던지 두던지 결정하자
// 가로로 세조각
_reArrangeRect( true );
}
//Range에 마춰서 생성한 컨트롤들 삭제
//처음에는 디폴트인 option_bcakground00_00 과 option_bcakground01_00를 삭제 안했지만 이러면 다시 Range쎄팅할때 문제 있어서 모두 삭제
void KUIControlHSlider::RemoveCopyStaticCtr()
{
for( int i(0); i<m_dwMaxRange-1; ++i )
{
RemoveControl( CStringUtil::StringFormat(c_lpBackGrondCtr0, i).c_str() );
RemoveControl( CStringUtil::StringFormat(c_lpBackGrondCtr1, i).c_str() );
}
}
//Range에 마춰 컨트롤들을 생성하는 함수
//처음에는 디폴트인 option_bcakground00_00 과 option_bcakground01_00를 위치 이동만 하고 나머지를 생성했지만 문제 있어서 지우고 다시 생성
void KUIControlHSlider::_CopyRangeStaticCtr()
{
if( m_dwMaxRange <= 1 ) return;
RemoveCopyStaticCtr(); //기존에 생성되있는 컨트롤 삭제 (여기서 삭제하는 것들은 Range에 따라 생성되는 컨트롤들)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 가장 앞의 최초 컨트롤 생성
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//기존 option_bcakground00_00 과 option_bcakground01_00 을 삭제하지 않고 이놈들의 싸이즈만 변경해서
//나머지 컨트롤들을 복사하니 기존 option_bcakground00_00 과 option_bcakground01_00의 랜더링이 이상한 현상이 있었다.
//속편하고 안전하게 모두 삭제하고 다시 생성하자.
KUIWND_CREATE_ARG arg;
arg.lpszSprName = m_sSprName.c_str();
arg.lpszAniName = "static_option_bcakground00_00";
arg.lpszClassName = "static";
arg.lpszID = CStringUtil::StringFormat(c_lpBackGrondCtr0, 0).c_str();
arg.pParent = this;
arg.dwStyle = 0;
int nWidth = _GetOptionControlGap();
arg.rcRect = m_rcRegion;
arg.rcRect.right = m_rcRegion.left+nWidth;
m_pManager->CreateControl( arg );
//현재 슬라이더의 위치까지 칠해줄 컨트롤 생성
arg.lpszAniName = "static_option_bcakground01_00";
arg.lpszID = CStringUtil::StringFormat(c_lpBackGrondCtr1, 0).c_str();
m_pManager->CreateControl( arg );
SetChildShow( CStringUtil::StringFormat(c_lpBackGrondCtr1, 0).c_str(), false );
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//이제 나머지 것들을 생성
RECT OffsetRt; OffsetRt.left = nWidth; OffsetRt.top = 0; OffsetRt.right = nWidth; OffsetRt.bottom = 0;
//Range가 5라는 것은 칸수가 아닌 라인수이다. 즉, 5이면 생성할 윈도우는 4개 따라서 이미 하나 있으니 여기는 -2
for( int i(0); i<m_dwMaxRange-2; ++i )
{
std::string strBackGroundControl = CStringUtil::StringFormat(c_lpBackGrondCtr0, i+1);
CopyControl( CStringUtil::StringFormat(c_lpBackGrondCtr0, i).c_str(), strBackGroundControl.c_str(), OffsetRt );
std::string strOverControl = CStringUtil::StringFormat(c_lpBackGrondCtr1, i+1);
CopyControl( CStringUtil::StringFormat(c_lpBackGrondCtr1, i).c_str(), strOverControl.c_str(), OffsetRt );
SetChildShow( strOverControl.c_str(), false );
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SetChildAsTop("option_control"); //여기서 컨트롤 생성하면 버튼위로 덮어지기 때문에 Top설정
SetPosition(m_nCurrentPos); //새로 만들어진 컨트롤에 버튼 위치 다시 설정 ( 이부분은 무조건 m_nCurrentPos을 0으로 할지 추후 결정 )
}
//Pos위치에 맞게 칠해줘야할 것들 갱신
void KUIControlHSlider::_BackGroundCtrUpdate(int nPos)
{
for( int i(0); i<m_dwMaxRange-1; ++i )
{
if( i<nPos ) SetChildShow( CStringUtil::StringFormat(c_lpBackGrondCtr1, i).c_str(), true );
else SetChildShow( CStringUtil::StringFormat(c_lpBackGrondCtr1, i).c_str(), false );
}
InvalidateWnd();
}
//마우스 위치로 슬라이드바의 버튼을 어디에 올려야 하는지 얻어주는 함수
int KUIControlHSlider::_GetPos( int x, int y )
{
int nWidth = _GetOptionControlGap();
int nStartWidth = m_rcRegion.left + nWidth/2;
int i(0);
for( i; i<m_dwMaxRange; ++i )
{
if(nStartWidth > x) return i;
nStartWidth += nWidth;
}
return i;
}
//옵션 컨트롤 Offset ( KMOUSE_MOVE에서 Delta만큼 이동시키기 위해 필요 )
void KUIControlHSlider::_OffsetOptionCtrBt( int OffsetX, int OffsetY )
{
KRect PrtRt, ChildRt;
PrtRt = GetRect();
KUIWnd* pWnd = GetChild( "option_control" );
if( pWnd )
{
ChildRt = pWnd->GetRect();
if( ChildRt.left + OffsetX < PrtRt.left ) return;
if( ChildRt.right + OffsetX > PrtRt.right ) return;
SetMovePosOffset("option_control", OffsetX, 0);
}
InvalidateWnd();
}
//확장요망 -N4-
//슬라이드바의 양쪽끝에 있는 버튼을 클릭했을때 한칸씩이동하게 하는 함수
//추후에 한칸이 아닌 Tick을 변수로 지니고 그 수만큼 이동하게 확장하자.
bool KUIControlHSlider::_ButtonClickUpdate( const char* lpszControlID )
{
int OldPos = m_nCurrentPos;
if(strcmp(lpszControlID, "slider_btn_left") == 0)
{
SetPosition(m_nCurrentPos-1);
if( OldPos != m_nCurrentPos )
return true;
}
else if(strcmp(lpszControlID, "slider_btn_right") == 0)
{
SetPosition(m_nCurrentPos+1);
if( OldPos != m_nCurrentPos )
return true;
}
return false;
}