#include "stdafx.h" #include "KUITextureManager.h" #include "KUIWndManager.h" #include "KUIWnd.h" #include "./Controls/KUIControl.h" #include "./Controls/KUIControlEdit.h" #include "./Controls/KUIMsgControl.h" #include "KUIImeObject.h" #include "KUIDragAndDrop.h" #include "KUITipControl.h" // { [sonador] #ifdef _KUI_INVALIDATION #include "KViewport.h" #endif // } namespace { const char * c_szDEF_SPR_NAME = "ui_frame.spr"; } #ifdef _KUI_INVALIDATION // { [sonador] namespace { struct SmartInvalidator { SmartInvalidator() : dirtyRect( 0, 0, 0, 0 ) {} void operator () ( KUIWnd* pWnd ) { if( pWnd->IsShow() && pWnd->IsValidWnd() && dirtyRect.IsIntersect( pWnd->GetRect() ) ) { pWnd->InvalidateWnd(); invalidRects.push_back( pWnd->GetRect() ); } } void SetDirtyRect( const KRect& rect ) { dirtyRect = rect; invalidRects.push_back( dirtyRect ); } void Clear() { invalidRects.clear(); } const KRect* GetRectArray() { if( GetRectCount() ) return &(*invalidRects.begin()); return 0; } int GetRectCount() { return invalidRects.size(); } typedef std::vector< KRect > rectarray_t; KRect dirtyRect; rectarray_t invalidRects; }; } // } #endif //#include "Util.h" ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KUIwndManager Implement ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef WM_MOUSEWHEEL #define WM_MOUSEWHEEL 0x020A #endif HWND KUIWndManager::m_sHWnd = NULL; HINSTANCE KUIWndManager::m_sInstance = NULL; KSize KUIWndManager::m_sizeResolution = KSize(1024,768); bool KUIWndManager::s_bIsEnterChatMode = false; KUIWndManager::KUIWndManager() // { [sonador] #ifdef _KUI_INVALIDATION : m_pUIViewport ( 0 ) //, m_pUISpritePrimitive ( 0 ) //, m_pSmartInvalidator ( new SmartInvalidator ) //, m_bValidation ( true ) //, m_bLockedToInvalidate ( false ) #endif // } { m_bRenderFlag = true; m_bInputDisable = false; m_pCaptureWnd = NULL; m_pDragObject = NULL; m_pDragIconRenderer = NULL ; m_ptDragRendererOffset = KPoint(0,0); m_dwTime = 0; //m_pImeObject = new KUIIMEObject; m_pMouseFocusWnd = NULL; m_pMouseClickWnd = NULL; #ifdef _KUI_INVALIDATION //m_pUISpritePrimitive = new KSpritePrimitive(); //m_pUISpritePrimitive->SetRes( new KResSprite() ); #endif } KUIWndManager::~KUIWndManager() { Clear(); //SAFE_DELETE( m_pImeObject ); // { [sonador] #ifdef _KUI_INVALIDATION SAFE_DELETE( m_pUIViewport ); //SAFE_DELETE( m_pUISpritePrimitive ); //SAFE_DELETE( m_pSmartInvalidator ); #endif // } } void KUIWndManager::Clear() { CloseAllMessageBox(); m_listSortedWnd.clear(); m_listWnd.clear(); /// 2011.06.14 mantis 13132 - prodongi m_listWebWnd.clear(); m_pDragObject = NULL; m_pDragIconRenderer = NULL ; m_bInputDisable = false; m_pCaptureWnd = NULL; m_ptDragRendererOffset = KPoint(0,0); m_dwTime = 0; m_pMouseFocusWnd = NULL; m_pMouseClickWnd = NULL; } void KUIWndManager::AddWnd( KUIWnd *pWnd, bool bSetFocus/* = true*/, bool bBack ) { // MJ 2004/12/01 // alpha pWnd->SetAlphaOpen(m_dwTime); std::list< KUIWnd* >::iterator it = std::find( m_listWnd.begin(), m_listWnd.end(), pWnd ); if( it != m_listWnd.end() ) return; if(bBack) { m_listWnd.push_front( pWnd ); } else { if( !IsEnterChatMode() ) { if( bSetFocus ) { KillFocus(); pWnd->SetFocus( true ); m_listWnd.push_back( pWnd ); } else m_listWnd.push_front( pWnd ); } else { //우선 순위 문제 때문에 위로 올려 준다. m_listWnd.push_back( pWnd ); } } } void KUIWndManager::addWndForceBack(KUIWnd* wnd) { // MJ 2004/12/01 // alpha wnd->SetAlphaOpen(m_dwTime); std::list< KUIWnd* >::iterator it = std::find( m_listWnd.begin(), m_listWnd.end(), wnd ); if( it != m_listWnd.end() ) return; m_listWnd.push_back(wnd); } void KUIWndManager::MouseFocusWndRemoveCheck( KUIWnd *pWnd ) { if( m_pMouseFocusWnd && pWnd && pWnd == m_pMouseFocusWnd ) { m_pMouseFocusWnd->SetTooltipOff(); m_pMouseFocusWnd->InitFocusWnd(); m_pMouseFocusWnd = NULL; } } void KUIWndManager::RemoveWnd( KUIWnd *pWnd ) { //pWnd->SetAlphaClose(m_dwTime); std::list< KUIWnd* >::iterator it = std::find( m_listWnd.begin(), m_listWnd.end(), pWnd ); if( it != m_listWnd.end() ) { //사라지는 윈도우에 m_pCaptureWnd 있을 경우, m_pCaptureWnd 를 NULL 로 설정 if( m_pCaptureWnd && ( _stricmp( (*it)->GetID(), m_pCaptureWnd->GetID() ) == 0 ) ) m_pCaptureWnd = NULL; if( m_pCaptureWnd && m_pCaptureWnd->GetParent() && ( _stricmp( (*it)->GetID(), m_pCaptureWnd->GetParent()->GetID() ) == 0 ) ) m_pCaptureWnd = NULL; (*it)->SetFocus( false ); m_listWnd.erase( it ); } it = std::find( m_listSortedWnd.begin(), m_listSortedWnd.end(), pWnd ); if( it != m_listSortedWnd.end() ) { m_listSortedWnd.erase( it ); } } void KUIWndManager::DestroyWnd( KUIWnd* pWnd ) { std::list< KUIWnd* >::iterator it = std::find( m_listWnd.begin(), m_listWnd.end(), pWnd ); if( it != m_listWnd.end() ) { (*it)->SetFocus( false ); m_listWnd.erase( it ); } } KUIWnd* KUIWndManager::GetModalWnd(LPCSTR lpszboxID) { KUIWnd* pUIWnd = NULL; for( std::list::const_iterator it = m_listModal.begin(); it != m_listModal.end(); ++it ) { pUIWnd = (*it); if( strncmp( pUIWnd->GetClassName().c_str() , "msgwnd", 6) != 0) continue; // 같은놈 if( strcmp( pUIWnd->GetID(), lpszboxID) == 0) return pUIWnd; } return pUIWnd; } KUIWnd* KUIWndManager::GetModalessWnd(LPCSTR lpszboxID) { KUIWnd* pUIWnd = NULL; for( std::list::const_iterator it = m_listModaless.begin(); it != m_listModaless.end(); ++it ) { pUIWnd = (*it); if( strncmp( pUIWnd->GetClassName().c_str() , "msgwnd", 6) != 0) continue; // 같은놈 if( strcmp( pUIWnd->GetID(), lpszboxID) == 0) return pUIWnd; } return pUIWnd; } void KUIWndManager::AddModalWnd(KUIWnd* pWnd) { m_listModal.push_back( pWnd ); } void KUIWndManager::RemoveModalWnd(KUIWnd* pWnd) { std::list< KUIWnd* >::iterator it = std::find( m_listModal.begin(), m_listModal.end(), pWnd ); if( it != m_listModal.end() ) m_listModal.erase( it ); } void KUIWndManager::SetFocus( KUIWnd *pWnd ) { #ifdef _DEV /// 2011.11.24 - prodongi if (KUIValidChecker::getIsProcessingMsg()) { _oprint("\n***************************************************\n"); _oprint("current is processing message!!!!!!(%s)\n", pWnd->GetID()); _oprint("***************************************************\n\n"); //char str[MAX_PATH]; //sprintf(str, "current is processing message!!!!!!(%s)", pWnd->GetID()); //::MessageBox(HWND_DESKTOP, str, "warning", MB_OK); } #endif std::list< KUIWnd* >::iterator it = std::find( m_listWnd.begin(), m_listWnd.end(), pWnd ); if( it != m_listWnd.end() ) { if( !pWnd->HasFocus() ) { m_listWnd.erase( it ); KillFocus(); pWnd->SetFocus( true ); m_listWnd.push_back( pWnd ); return; } } it = std::find( m_listModaless.begin(), m_listModaless.end(), pWnd ); if( it != m_listModaless.end() ) { if( !pWnd->HasFocus() ) { m_listModaless.erase( it ); KillFocus(); pWnd->SetFocus( true ); m_listModaless.push_back( pWnd ); } } } KUIWnd* KUIWndManager::GetFocusWnd() { return (!m_listWnd.empty() && m_listWnd.back()->HasFocus()) ? m_listWnd.back() : NULL; } //servantes 2010.12.06 수입력기를 ESC를 눌렀을 때, 맨위의 포커스 창이 닫히도록 수정 void KUIWndManager::SetMouseClickWnd(KUIWnd* pWnd) { m_pMouseClickWnd = m_pMouseFocusWnd = pWnd; } void KUIWndManager::KillFocus() { if( !m_listModaless.empty() ) { m_listModaless.back()->OnKillFocusNotify(); //포커스 잃어버리면서 포커스 잃었다고 윈도우에 통보 -N4- m_listModaless.back()->SetFocus( false ); } if( !m_listWnd.empty() ) { m_listWnd.back()->OnKillFocusNotify(); //포커스 잃어버리면서 포커스 잃었다고 윈도우에 통보 -N4- m_listWnd.back()->SetFocus( false ); } } #ifdef _KUI_INVALIDATION // { [sonador] void KUIWndManager::SetViewportObject( KViewportObject* viewport ) { SAFE_DELETE( m_pUIViewport ); m_pUIViewport = viewport; } /*K3DRenderTarget* KUIWndManager::GetRenderTarget() { if( m_spRenderTarget == 0 ) { InitRenderTarget(); } return m_spRenderTarget; } void KUIWndManager::InitRenderTarget() { m_pUISpritePrimitive->GetRes()->SetTexture( 0, 0 ); m_spRenderTarget = 0; int nW, nH; K3DRenderDevice::GetSquareSize( m_sizeResolution.width, m_sizeResolution.height, nW, nH ); m_spRenderTarget = KUICachedTextureManager::GetManager() ->GetRenderTarget( nW, nH, 1, K3DRenderTarget::DEPTH_ENABLE ); if( m_spRenderTarget ) { // clear render target m_pUIViewport->Render( m_spRenderTarget, 0, true, 0, 0 ); } m_pSmartInvalidator->Clear(); }*/ void KUIWndManager::InvalidateAllWnd() { //std::for_each( m_listSortedWnd.begin(), m_listSortedWnd.end(), // std::mem_fun( &KUIWnd::InvalidateWnd ) ); std::for_each( m_listWnd.begin(), m_listWnd.end(), std::mem_fun( &KUIWnd::InvalidateWnd ) ); std::for_each( m_listModal.begin(), m_listModal.end(), std::mem_fun( &KUIWnd::InvalidateWnd ) ); std::for_each( m_listModaless.begin(), m_listModaless.end(), std::mem_fun( &KUIWnd::InvalidateWnd ) ); } void KUIWndManager::ValidateAllWnd() { //std::for_each( m_listSortedWnd.begin(), m_listSortedWnd.end(), // std::mem_fun( &KUIWnd::ValidateWnd ) ); std::for_each( m_listWnd.begin(), m_listWnd.end(), std::mem_fun( &KUIWnd::ValidateWnd ) ); std::for_each( m_listModal.begin(), m_listModal.end(), std::mem_fun( &KUIWnd::ValidateWnd ) ); std::for_each( m_listModaless.begin(), m_listModaless.end(), std::mem_fun( &KUIWnd::ValidateWnd ) ); } /*void KUIWndManager::InvalidateWnd( KUIWnd* pWnd ) { if( m_bLockedToInvalidate || 0 == pWnd ) return; m_bLockedToInvalidate = true; m_pSmartInvalidator->SetDirtyRect( pWnd->GetRect() ); std::for_each( m_listWnd.begin(), m_listWnd.end(), *m_pSmartInvalidator ); std::for_each( m_listModal.begin(), m_listModal.end(), *m_pSmartInvalidator ); std::for_each( m_listModaless.begin(), m_listModaless.end(), *m_pSmartInvalidator ); //if( m_pSmartInvalidator->GetRectCount() ) // m_bValidation = false; m_bLockedToInvalidate = false; }*/ // } #endif KUIMsgControl* KUIWndManager::MessageBox( LPCSTR lpszID, LPCSTR lpszTitle, LPCSTR lpszMessage, const KMsgBoxBtnInfo& info, KObject* pCallback , DWORD dwTimer, bool bModal, LPCSTR lpszReqValue, int nX, int nY ) { KUIWND_CREATE_ARG arg; arg.lpszClassName = "msgwnd"; arg.lpszSprName = c_szDEF_SPR_NAME; arg.lpszID = lpszID; arg.dwStyle = KSTYLE_MSG_VERTICAL_REPEAT; arg.lpszCaption = lpszMessage; arg.lpszToolTip = lpszTitle; arg.pWndManager = this; if( 0 == ::strlen( lpszTitle ) ) arg.dwStyle |= KSTYLE_NOTITLE; KUIMsgControl* pWnd = reinterpret_cast( CreateControl( arg ) ); pWnd->SetReqValue( lpszReqValue ); pWnd->RegisterCallback( pCallback ); if( dwTimer ) pWnd->SetContinueTime( dwTimer ); pWnd->SetEndBtnIndex( info.GetDefaultItemIndex() ); for(int i = 0; i < info.GetBtnItemSize(); ++i) { const MSGBOX_BTN_INFO_ITEM& infoItem = info.GetBtnItemByIndex( i ); pWnd->AddButton(infoItem.sID.c_str(), infoItem.sCaption.c_str(), infoItem.bUseSprCaption, info.GetBtnItemSize() ); } pWnd->ChangeAlpha(0.f); int X( pWnd->GetRect().left ); int Y( pWnd->GetRect().top ); if( nX ) X = nX; if( nY ) Y = nY; pWnd->MovePos(X, Y); //pWnd->AddMsg( "static_msg", CStringUtil::StringFormat( "<#fbe7b4>%s", lpszMessage ).c_str() ); pWnd->AddMsg( "static_msg", CStringUtil::StringFormat( "<#ffffff>%s", lpszMessage ).c_str() ); KillFocus(); if( bModal ) m_listModal.push_back( pWnd ); else m_listModaless.push_back( pWnd ); return pWnd; } bool KUIWndManager::IsOpenModalWnd() { return m_listModal.empty() ? false : true; } bool IsFindMessageBox(std::list< KUIWnd* >& msgBoxlist, LPCSTR lpszboxID) { for( std::list::const_iterator it = msgBoxlist.begin(); it != msgBoxlist.end(); ++it ) { KUIWnd* pUIWnd = *it; if( strncmp( pUIWnd->GetClassName().c_str() , "msgwnd", 6) != 0) continue; // 같은놈 if( strcmp( pUIWnd->GetID(), lpszboxID) == 0) return true; } return false; } bool KUIWndManager::IsExistMessageBox(LPCSTR lpszboxID) { //Modal if( IsFindMessageBox( m_listModal, lpszboxID ) ) return true; //Modaless if( IsFindMessageBox( m_listModaless, lpszboxID ) ) return true; return false; } bool closeMsgBox( std::list< KUIWnd* >& msgBoxlist, KUIWnd* pWnd ) { for( std::list::iterator it = msgBoxlist.begin(); it != msgBoxlist.end(); ++it ) { KUIWnd* pUIWnd = *it; if( pUIWnd == pWnd ) { msgBoxlist.erase( it ); SAFE_DELETE( pUIWnd ); return true; } } return false; } bool KUIWndManager::CloseMessageBox(KUIWnd* pWnd) { if( closeMsgBox( m_listModal, pWnd ) ) return true; if( closeMsgBox( m_listModaless, pWnd ) ) return true; return false; } bool closeMsgBox( std::list< KUIWnd* >& msgBoxlist, LPCSTR lpszboxID ) { for( std::list::iterator it = msgBoxlist.begin(); it != msgBoxlist.end(); ++it ) { KUIWnd* pUIWnd = *it; if( strncmp( pUIWnd->GetClassName().c_str() , "msgwnd", 6) != 0) continue; // 같은놈 if( strcmp( pUIWnd->GetID(), lpszboxID) == 0) { KUIMsgControl* pMsgWnd = reinterpret_cast( pUIWnd ); msgBoxlist.erase( it ); SAFE_DELETE( pMsgWnd ); return true; } } return false; } bool KUIWndManager::CloseMessageBox(LPCSTR lpszboxID) { if( closeMsgBox( m_listModal, lpszboxID ) ) return true; if( closeMsgBox( m_listModaless, lpszboxID ) ) return true; // 못 찾았네? return false; } bool closeAllMessageBox( std::list< KUIWnd* >& msgBoxlist ) { std::list::iterator it = msgBoxlist.begin(); while( it != msgBoxlist.end() ) { KUIWnd* pWnd = (*it); if( ::strncmp(pWnd->GetClassName().c_str(), "msgwnd", 6) != 0 ) { it++; continue; } SAFE_DELETE(pWnd); it = msgBoxlist.erase(it); } return true; } bool KUIWndManager::CloseAllMessageBox() { CloseRebirthMessageBox(); CloseRebirth_PVP_MessageBox(); closeAllMessageBox( m_listModal ); closeAllMessageBox( m_listModaless ); return true; } bool KUIWndManager::CloseRebirthMessageBox() { std::list::iterator it = m_listModal.begin(); while( it != m_listModal.end() ) { KUIWnd* pWnd = (*it); if( ::strncmp(pWnd->GetClassName().c_str(), "genwnd", 6) == 0 && ::_stricmp( pWnd->GetID(), "window_system_resurrect" ) == 0 ) { pWnd->SetShow(false); it = m_listModal.erase(it); return true; } it++; } return false; } // kappamind. bool KUIWndManager::CloseRebirth_PVP_MessageBox() { std::list::iterator it = m_listModal.begin(); while( it != m_listModal.end() ) { KUIWnd* pWnd = (*it); if( ::strncmp(pWnd->GetClassName().c_str(), "genwnd", 6) == 0 && ::_stricmp( pWnd->GetID(), "window_player_pvp_rebirth" ) == 0 ) { pWnd->SetShow(false); it = m_listModal.erase(it); return true; } it++; } return false; } // void *KUIWndManager::Perform( KID _id, KArg& msg ) { _CID( WINDOWMSG ); if ( _id == id_WINDOWMSG ) { switch( msg.at(0)) { case WM_LBUTTONUP: case WM_RBUTTONUP: ::ReleaseCapture(); break; case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: ::SetCapture( m_sHWnd); break; } switch(msg.at(0)) { case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MOUSEMOVE: { short x = LOWORD(msg.at(2)); short y = HIWORD(msg.at(2)); if ( KMR_NORMAL & _SendMessage(msg.at(0), x,y) ) return (void*)1; break; } case WM_MOUSEWHEEL: { POINT pt; pt.x = (short)LOWORD(msg.at(2)); pt.y = (short)HIWORD(msg.at(2)); ScreenToClient( m_sHWnd, &pt ); short z = HIWORD(msg.at(1)); if(z > 0) { if ( KMR_NORMAL & _SendMessage(KWHEEL_UP,pt.x,pt.y) ) return (void*)1; } else { if ( KMR_NORMAL & _SendMessage(KWHEEL_DOWN,pt.x, pt.y) ) return (void*)1; } break; } //모달 윈도우 (ex.메세지 박스등) 키보드 처리 case WM_KEYUP: case WM_KEYDOWN: { DWORD dwKeyCode = msg.at(1); if ( KMR_NORMAL & _SendKeyModalMessage( msg.at(0), dwKeyCode ) ) return (void*)1; break; } // 이것을 넣으면 edit control로 키처리가 2번씩 가게되므로 절대로 해줘선 안된다 ... // 현재로써는 edit control 외에 키처리가 불필요하므로 그냥 이렇게 막아놨지만, 차후에 다른컨트롤에 // 키 처리가 필요하게 되어 이것을 풀게 될 경우 반드시 edit control로는 키메시지가 안가도록 처리해줘야 한다. //case WM_KEYUP: //case WM_KEYDOWN: // { // DWORD dwKeyCode = msg.at(1); // // if ( KMR_NORMAL & _SendMessage(msg.at(0), dwKeyCode, 0) ) // return (void*)1; // break; // } // edit control로 키처리가 2번씩 가게되므로 KUIControlEdit::IsNobodyHasFocus()로 // 현재 edit control에 포커스가 있는지 알아보고 edit control에 포커스가 없다면 키보드 메세지를 처리하게 한다. -N4- /*지금 다시 뺀것은 서버리스트윈도우 하나만 키보드 처리하기 때문에 필요 없는 메세지가 많이 처리되는거 방지위해서 -N4- case WM_KEYUP: case WM_KEYDOWN: { if( KUIControlEdit::IsNobodyHasFocus() ) { DWORD dwKeyCode = msg.at(1); if ( KMR_NORMAL & _SendMessage(msg.at(0), dwKeyCode, 0) ) return (void*)1; } } break; /**/ case WM_ACTIVATEAPP: if(msg.at(1) == TRUE) { // _oprint( "WM_ACTIVATEAPP true\n" ); ::SetFocus( m_sHWnd ); } else { // _oprint( "WM_ACTIVATEAPP false\n" ); KillFocus(); // Button Release를 위해서.. ::SendMessage( m_sHWnd, WM_LBUTTONUP, MAKELONG(-1, -1), 0 ); ::SendMessage( m_sHWnd, WM_RBUTTONUP, MAKELONG(-1, -1), 0 ); } break; } return NULL; } return NULL; } DWORD KUIWndManager::_SendMessage(DWORD dwMessage, DWORD dwWParam, DWORD dwLParam) { switch(dwMessage) { case KLBUTTON_DBLCLK: case KRBUTTON_DBLCLK: case KLBUTTON_DOWN: case KLBUTTON_UP: case KRBUTTON_DOWN: case KRBUTTON_UP: case KWHEEL_UP: case KWHEEL_DOWN: return _SendMouseMessage(dwMessage, static_cast(dwWParam), static_cast(dwLParam) ); break; case KMOUSE_MOVE: _SendMouseMessage(dwMessage, static_cast(dwWParam), static_cast(dwLParam) ); return KMR_NO_GET; break; case KKEY_UP: case KKEY_DOWN: return _SendKeyMessage(dwMessage, dwWParam); break; default: { assert(FALSE); } break; } return KMR_NO_GET; } void KUIWndManager::FocusWindowOff() { if( m_pMouseClickWnd ) { m_pMouseClickWnd->SetTooltipOff(); m_pMouseClickWnd->InitFocusWnd(); m_pMouseClickWnd = NULL; } } void KUIWndManager::_ProcMouseMessage( KUIWnd *pWnd, DWORD & dwMessage, KUIWnd * & pMouseWnd, bool & bFindFocusPanel, bool & bGetMouseMessage, DWORD &dwRet, int x, int y ) { if( pWnd == NULL ) return; if( !pWnd->IsShow() ) return; if( dwMessage == KLBUTTON_DOWN ) { int nDebug = 1; } if( pWnd->GetRect().IsInRect(x, y) ) { // 마우스 좌표위에 존재하는 가장 높은 Wnd if( pWnd->IsInRectWithChild(x,y) ) { // Drag And Drop이 있으면 마우스 메시지를 안받는다. if( bGetMouseMessage) { //막음 -N4- SetFocus(pWnd); // <임시적인 추가> 클릭 메세지가 Focus메세지 보다 늦게 전달되서 임시적으로 추가한 부분 -N4- dwRet = pWnd->OnMouseMessage(dwMessage, x,y); //예외 처리임. //캐릭터 이름 창 또는, 지역정보 표시는 선택 안됨. //아이템 드랍 툴팁, 게이지 윈도우 /// 2011.06.01 notice 추가, 이런식으로 해도 되나,,(다른 방법을 못 찾음) - prodongi if( _stricmp( pWnd->GetID(), "_character_wnd" ) != 0 && _stricmp( pWnd->GetID(), "window_area_title" ) != 0 && _stricmp( pWnd->GetID(), "_gauge_wnd" ) != 0 && _stricmp( pWnd->GetID(), "_dropitem_wnd" ) != 0 && strncmp( pWnd->GetClassName().c_str() , "msgwnd", 6) != 0 && _stricmp(pWnd->GetID(), "notice") != 0) { if( m_pMouseFocusWnd && _stricmp(pWnd->GetID(), m_pMouseFocusWnd->GetID()) != 0 ) { #ifdef _DEBUG const char * pName1 = m_pMouseFocusWnd->GetID(); const char * pName2 = pWnd->GetID(); #endif m_pMouseFocusWnd->SetTooltipOff();//툴팁 Off m_pMouseFocusWnd->InitFocusWnd(); //툴팁 초기화 } m_pMouseFocusWnd = pWnd; //툴팁을 끄기 위해 사용 // _oprint( "MouseFocusWnd : %s\n", m_pMouseFocusWnd->GetID() ); if( dwMessage == KLBUTTON_DOWN && m_pMouseFocusWnd ) { /* /// 2011.02.15 m_pMouseClickWnd가 잘 못된 포인터를 갖고 있는 것 같음, 그래서 위치 이동함 - prodongi if(m_pMouseClickWnd) { if(strcmp(m_pMouseClickWnd->GetID(), "window_number_input") == 0) //servantes 2011.01.03 { KUIControlEdit* pEdit = ( KUIControlEdit* )m_pMouseClickWnd->GetChild( "input_edit" ); if( pEdit ) pEdit->SetFocus(false); } } */ //윈도우 우선 순위 변경 m_pMouseClickWnd = m_pMouseFocusWnd; if( IsEnterChatMode() ) { KUIWnd* pCaptureWnd = m_pCaptureWnd; RemoveWnd( m_pMouseClickWnd ); AddWnd( m_pMouseClickWnd ); m_pMouseFocusWnd = m_pMouseClickWnd; //재 복구 if( pCaptureWnd ) SetCapture( pCaptureWnd ); } /// 2011.02.15 - prodongi if(m_pMouseClickWnd) { if(strcmp(m_pMouseClickWnd->GetID(), "window_number_input") == 0) //servantes 2011.01.03 { KUIControlEdit* pEdit = ( KUIControlEdit* )m_pMouseClickWnd->GetChild( "input_edit" ); if( pEdit ) pEdit->SetFocus(false); } } } } } pMouseWnd = pWnd; bFindFocusPanel = true; return; } } else { //남아 있는 툴팁 Off pWnd->OffToolTipWnd(); } ////////////////////////////////////////////////////////////////////////// // // MJ 2005/03/16 주석 달다 // 문제 발견 : 윈도우에 포커스가 없음에도 불구하고 모든 윈도우에 대해 마우스 무브를 호출한다. // 증상 : 각 윈도우의 컨트롤리스트 차례로 마우스 무브를 호출함으로써 프레임에 영향을 미친다 // 해결 : 아래 코드는 툴팁 표시용으로 예측, 확인하였음.. 100% 추측이 정확하지는 않음. // : 따라서 코드는 제거하고 툴팁은 재정의한다. // 좌표위에 들지 않았어도 보내줌 //else if( pWnd && false == pWnd->IsInRectWithChild(x,y) ) //{ // // Drag And Drop이 있으면 마우스 메시지를 안받는다. // if( bGetMouseMessage) // pWnd->OnMouseMessage(dwMessage, x,y); //} // ////////////////////////////////////////////////////////////////////////// } KUIWnd* KUIWndManager::_procWndList( std::list< KUIWnd* >& Origin_List, DWORD dwMessage, int x, int y, bool bFindFocusPanel, bool bGetMouseMessage, DWORD & dwRet ) { KUIWnd* pGenMouseWnd = NULL; std::list< KUIWnd* >::reverse_iterator it; std::list< KUIWnd* > wndList = Origin_List; //벡터 복사 해서 사용;; Origin_List가 중간에 삭제 된다.- -; for ( it = wndList.rbegin(); it != wndList.rend() ; ++it ) { KUIWnd *pWnd = (*it); if( !pWnd ) continue; if( pWnd->GetSortValue() ) continue; _ProcMouseMessage( pWnd, dwMessage, pGenMouseWnd, bFindFocusPanel, bGetMouseMessage, dwRet, x, y ); // KMR_GET_PASS의 본래 의미는 메시지를 처리하고 뒤에도 메시지를 보내자는 취지로 만들어진 것 같은데 // 기존처럼 KMR_GET_PASS 을 체크하지 않고 pMouseWnd에 쎄팅된 값만 보고서 를 쎄팅하면 다음 윈도우로 메시지가 가지 않는다 // 따라서 여기서 이것을 체크한다.... -N4- if( !(dwRet & KMR_GET_PASS) && pGenMouseWnd != NULL ) break; } wndList.clear(); return pGenMouseWnd; } DWORD KUIWndManager::_SendMouseMessage(DWORD dwMessage, int x, int y) { if(m_bInputDisable) return false; if ( m_pCaptureWnd ) return m_pCaptureWnd->OnMouseMessage(dwMessage, x,y); // If MsgBox is exist, doesn't send mousemsg. if(m_listModal.size() > 0) { m_listModal.front()->OnMouseMessage(dwMessage, x,y); return KMR_NORMAL; } DWORD dwRet = KMR_NO_GET; // Drag 관련 KUIDragAndDropMessage msg; msg.ptDropPos = KPoint( x, y); msg.pObject = m_pDragObject; // Focus 관련 KUIWnd *pMouseWnd = NULL; bool bFindFocusPanel = false; // Drag를 안하거나, 드래그를 한다면 Mouse Move는 그냥 씹어줘야 할 것이다. bool bGetMouseMessage = (m_pDragObject == NULL) || (dwMessage != KMOUSE_MOVE); //if( dwMessage == KLBUTTON_DOWN ) //{ // int nDebug = 0; //} //모달리스 KUIWnd* pGenModalessWnd = NULL; pGenModalessWnd = _procWndList( m_listModaless, dwMessage, x, y, bFindFocusPanel, bGetMouseMessage, dwRet ); if( pGenModalessWnd != NULL ) pMouseWnd = pGenModalessWnd; KUIWnd* pGenMouseWnd = NULL; /// 2011.06.14 mantis 13132 - prodongi pGenMouseWnd = _procWndList( m_listWebWnd, dwMessage, x, y, bFindFocusPanel, bGetMouseMessage, dwRet ); //일반 윈도우 if( !pGenModalessWnd && !pGenMouseWnd ) { pGenMouseWnd = _procWndList( m_listWnd, dwMessage, x, y, bFindFocusPanel, bGetMouseMessage, dwRet ); if( pGenMouseWnd != NULL ) pMouseWnd = pGenMouseWnd; if ( (dwRet & KMR_GET_PASS) || pMouseWnd == NULL ) { // 2008.5.29 floyd #2.3.1.20 // 퀵슬롯 밑에 있는 대상이 클릭되는 문제 수정 // 마우스 메시지가 정상적으로 처리되고 더 이상 다른 윈도우로 보낼 필요가 없는데도 보내어 // 리턴값(dwRet)이 정상적으로 메시지를 처리한 윈도우가 아닌 다른 윈도우의 리턴값이 전달되어 이상증상을 보이는 문제로 파악됨 //순서있는 윈도우(이름표) std::list< KUIWnd* > wndList = m_listSortedWnd; std::list< KUIWnd* >::reverse_iterator it; for (it = m_listSortedWnd.rbegin();it != m_listSortedWnd.rend() ; ++it ) { KUIWnd *pWnd = (*it); if( !pWnd ) continue; if( !pWnd->GetSortValue() ) continue; _ProcMouseMessage( pWnd, dwMessage, pMouseWnd, bFindFocusPanel, bGetMouseMessage, dwRet, x, y ); // KMR_GET_PASS의 본래 의미는 메시지를 처리하고 뒤에도 메시지를 보내자는 취지로 만들어진 것 같은데 // 기존처럼 KMR_GET_PASS 을 체크하지 않고 pMouseWnd에 쎄팅된 값만 보고서 를 쎄팅하면 다음 윈도우로 메시지가 가지 않는다 // 따라서 여기서 이것을 체크한다.... -N4- if( !(dwRet & KMR_GET_PASS) && pMouseWnd != NULL ) break; } wndList.clear(); } } if( pGenMouseWnd != NULL ) pMouseWnd = pGenMouseWnd; //다운되서 넣었음 - BERSERK if( bFindFocusPanel = false ) m_pMouseFocusWnd = NULL; //툴팁 끄기 if( m_pMouseFocusWnd && pMouseWnd == NULL ) { m_pMouseFocusWnd->SetTooltipOff(); m_pMouseFocusWnd->InitFocusWnd(); m_pMouseFocusWnd = NULL; } // Drag Object로 Drop 가능한 Object를 찾아놓자 ( 맨 위에 떠 있는 Focus 윈도우에 대해서만 한번 체크) if( NULL != pMouseWnd && NULL != m_pDragObject) { _CID( UI_CANDROP ); msg.pObject = m_pDragObject; pMouseWnd->Perform(id_UI_CANDROP, msg); } switch( dwMessage ) {//포커스를 받는것이 KLBUTTON_DOWN 말고도 많아서 더 추가 -N4- case KLBUTTON_DOWN: case KRBUTTON_DOWN: case KWHEEL_DOWN: case KLBUTTON_DBLCLK: // Focus Panel로 설정한다. if( NULL != pMouseWnd ) { if( !pMouseWnd->HasFocus() && !(pMouseWnd->GetFlag() & KFLAG_NO_GET_FOCUS) ) { if( !IsEnterChatMode() ) { SetFocus( pMouseWnd ); // _oprint( "Focus Window : %s\n", pMouseWnd->GetID() ); } } } break; case KLBUTTON_UP: // DragObject를 Drop if( NULL != m_pDragObject) { _CID( UI_SEND_DROP ); _CID( UI_RECV_DROP ); KUISendRecvDropMessage SendRecvMsg( msg ); // Receiver KUIWnd* pReceiver = FindWndWithChild( msg.sRecvDropParentID.c_str() ); if( NULL != pReceiver) { pReceiver->Perform( id_UI_RECV_DROP, SendRecvMsg); } // Sender KUIWnd* pSender = FindWndWithChild( msg.pObject->GetParentID() ); if( NULL != pSender) pSender->Perform( id_UI_SEND_DROP, SendRecvMsg); m_pDragObject = NULL; m_pDragIconRenderer = NULL; } break; default: break; } // Drag Icon Pos set if( NULL != m_pDragIconRenderer) { // Offset을 맞춰준다.( Icon이 처음 찍었을 당시의 위치에 존재하기 위해서) m_pDragIconRenderer->SetPosition(x - m_ptDragRendererOffset.x, y - m_ptDragRendererOffset.y); } return dwRet; } //메세지 박스 Key 처리 DWORD KUIWndManager::_SendKeyModalMessage(DWORD dwMessage, DWORD dwKeyCode) { if(m_bInputDisable) return false; // If Modal is exist, doesn't send key Msg if( m_listModal.size() > 0 ) { m_listModal.front()->OnKeyMessage( dwMessage,dwKeyCode ); return KMR_NORMAL; } return KMR_NO_GET; } DWORD KUIWndManager::_SendKeyMessage(DWORD dwMessage, DWORD dwKeyCode) { if(m_bInputDisable) return false; if ( m_pCaptureWnd ) { m_pCaptureWnd->OnKeyMessage( dwMessage,dwKeyCode ); return KMR_NORMAL; } // If Modal is exist, doesn't send key Msg if( m_listModal.size() > 0 ) { m_listModal.front()->OnKeyMessage( dwMessage,dwKeyCode ); return KMR_NORMAL; } if( m_listWnd.size() > 0 ) m_listWnd.back()->OnKeyMessage(dwMessage,dwKeyCode); return KMR_NO_GET; } bool IsLesserThen( KUIWnd *pLh, KUIWnd *pRh ) { return pLh->GetSortValue() > pRh->GetSortValue(); } void KUIWndManager::onChangeSortValue( KUIWnd* pWnd, int nOldValue ) { /* if( nOldValue && pWnd->GetSortValue() ) return; if( !nOldValue && !pWnd->GetSortValue() ) return; if( nOldValue && !pWnd->GetSortValue() ) { for ( std::list< KUIWnd* >::iterator it = m_listSortedWnd.begin();it != m_listSortedWnd.end() ; ++it ) { if( (*it) != pWnd ) continue; m_listSortedWnd.erase( it ); return; } } if( !nOldValue && pWnd->GetSortValue() ) { m_listSortedWnd.push_back( pWnd ); m_listSortedWnd.sort( IsLesserThen ); //std::sort( m_listSortedWnd.begin(), m_listSortedWnd.end(), IsLesserThen ); }*/ if( nOldValue != pWnd->GetSortValue() ) { for ( std::list< KUIWnd* >::iterator it = m_listSortedWnd.begin();it != m_listSortedWnd.end() ; ++it ) { if( (*it) != pWnd ) continue; m_listSortedWnd.erase( it ); break; } m_listSortedWnd.push_back( pWnd ); m_listSortedWnd.sort( IsLesserThen ); //std::sort( m_listSortedWnd.begin(), m_listSortedWnd.end(), IsLesserThen ); } } void KUIWndManager::Render( KViewportObject *viewport,bool isFront ) { std::list< KUIWnd* >::iterator it; if( m_bRenderFlag ) { for ( it = m_listSortedWnd.begin();it != m_listSortedWnd.end() ; ++it ) { if( (*it)->IsShow() && (*it)->GetSortValue() != 0 ) (*it)->Render( viewport,isFront ); } for( it = m_listWnd.begin();it != m_listWnd.end() ; ++it ) { KUIWnd* pWnd = *it; if( pWnd->IsShow() && pWnd->GetSortValue() == 0 ) { /// 2011.06.14 mantis 13132 - prodongi if (pWnd->getIsWeb()) continue; pWnd->Render( viewport,isFront ); } } } // 2010.06.11 renderPostWnd로 뺐습니다. - prodongi /* for( it = m_listModal.begin(); it != m_listModal.end() ; ++it ) { KUIWnd* pWnd = *it; if(pWnd->IsShow() ) pWnd->Render( viewport,isFront ); } for( it = m_listModaless.begin(); it != m_listModaless.end() ; ++it ) { KUIWnd* pWnd = *it; if(pWnd->IsShow() ) pWnd->Render( viewport,isFront ); } if( m_bRenderFlag ) { if (NULL != m_pDragIconRenderer) m_pDragIconRenderer->Render( viewport ); } */ } // 2010.06.11 - prodongi void KUIWndManager::renderPostWnd(KViewportObject *viewport,bool isFront) { std::list< KUIWnd* >::iterator it; /// 2011.06.14 mantis 13132 - prodongi for (it = m_listWebWnd.begin(); it != m_listWebWnd.end(); ++it) { KUIWnd* pWnd = *it; if(pWnd->IsShow() ) pWnd->Render( viewport,isFront ); } for( it = m_listModal.begin(); it != m_listModal.end() ; ++it ) { KUIWnd* pWnd = *it; if(pWnd->IsShow() ) pWnd->Render( viewport,isFront ); } for( it = m_listModaless.begin(); it != m_listModaless.end() ; ++it ) { KUIWnd* pWnd = *it; if(pWnd->IsShow() ) pWnd->Render( viewport,isFront ); } if( m_bRenderFlag ) { if (NULL != m_pDragIconRenderer) m_pDragIconRenderer->Render( viewport ); } } // 2010.06.11 - prodongi bool KUIWndManager::isExistPostWnd() const { if (!m_listModal.empty() || !m_listModaless.empty()) return true; return false; } void CheckDelete( std::list& msgBoxlist ) { // Reverse Iterator로 삭제하는 방법을 몰라서 우선은 루프를 한번 더 돔( r_it 로 삭제 가능하면 수정바람) std::list::iterator it = msgBoxlist.begin(); while( it != msgBoxlist.end() ) { KUIWnd* pWnd = (*it); if( pWnd->IsDestroy() ) { SAFE_DELETE(pWnd); it = msgBoxlist.erase(it); } else it++; } } void KUIWndManager::Process( DWORD dwTime ) { m_dwTime = dwTime; /// 2011.06.14 mantis 13132 - prodongi m_listWebWnd.clear(); for (std::list< KUIWnd* >::reverse_iterator r_it = m_listSortedWnd.rbegin(); r_it != m_listSortedWnd.rend() ; ++r_it ) { KUIWnd* pWnd = *r_it; if( pWnd->IsShow() ) pWnd->Process( dwTime ); else pWnd->ForcedProcess( dwTime ); // Handle things that must always be processed regardless of Show. By metarrgear } int k = m_listWnd.size()-1; for (std::list< KUIWnd* >::reverse_iterator r_it = m_listWnd.rbegin(); r_it != m_listWnd.rend() ; ++r_it, --k ) { KUIWnd* pWnd = *r_it; /// 2011.06.14 mantis 13132 - prodongi if (pWnd->getIsWeb()) { m_listWebWnd.push_back(pWnd); continue; } if(pWnd->IsShow() ) pWnd->Process( dwTime ); else pWnd->ForcedProcess( dwTime ); // Handle things that must always be processed regardless of Show. By metarrgear } /// 2011.06.14 mantis 13132 - prodongi for (std::list< KUIWnd* >::reverse_iterator r_it = m_listWebWnd.rbegin(); r_it != m_listWebWnd.rend() ; ++r_it ) { KUIWnd* pWnd = *r_it; if(pWnd->IsShow() ) pWnd->Process( dwTime ); else pWnd->ForcedProcess( dwTime ); // Handle things that must always be processed regardless of Show. By metarrgear } for (std::list< KUIWnd* >::reverse_iterator r_it = m_listModal.rbegin(); r_it != m_listModal.rend() ; ++r_it ) { KUIWnd* pWnd = *r_it; if(pWnd->IsDestroy() == false) pWnd->Process( dwTime ); } for (std::list< KUIWnd* >::reverse_iterator r_it = m_listModaless.rbegin(); r_it != m_listModaless.rend() ; ++r_it ) { KUIWnd* pWnd = *r_it; if(pWnd->IsDestroy() == false) pWnd->Process( dwTime ); } CheckDelete( m_listModal ); CheckDelete( m_listModaless ); } KUIWnd* KUIWndManager::FindWnd( const char *szWndID) { if (!szWndID) return NULL; std::list< KUIWnd* >::iterator it = m_listWnd.begin(); for ( ; it != m_listWnd.end() ; ++it ) { if ( _stricmp( (*it)->GetID(), szWndID ) == 0 ) return (*it); } return NULL; } KUIWnd *KUIWndManager::FindWnd( const char *szWndID, const char *szControlID ) { std::list< KUIWnd* >::iterator it = m_listWnd.begin(); for ( ; it != m_listWnd.end() ; ++it ) { if ( _stricmp( (*it)->GetID(), szWndID ) == 0 ) return (*it)->GetChild( szControlID ); } return NULL; } KUIWnd *KUIWndManager::FindWndWithChild( const char *szWndID) { for (std::list< KUIWnd* >::iterator it = m_listWnd.begin(); it != m_listWnd.end() ; ++it ) { if ( _stricmp( (*it)->GetID(), szWndID ) == 0 ) return (*it); } for(std::list< KUIWnd* >::iterator it = m_listWnd.begin();it != m_listWnd.end(); ++it) { KUIWnd* pWnd = (*it)->GetChild( szWndID ); if(pWnd) return pWnd; } return NULL; } void KUIWndManager::SetDragObject( KUIDragAndDropObject *pDragObject, const KPoint& ptOffset) { m_pDragObject = pDragObject; m_ptDragRendererOffset = ptOffset; if(NULL != m_pDragObject) { KUIWnd* pParentWnd = FindWndWithChild( pDragObject->GetParentID() ); // Parent(GenWnd) 에게 알림 if(NULL != pParentWnd ) { _CID( UI_BEGIN_DRAG ); KUIBeginDragMessage msg; msg.sDragControlID = m_pDragObject->GetControlID(); pParentWnd->Perform( id_UI_BEGIN_DRAG, msg); // Wnd에서 가져온 Renderer를 쓴다. m_pDragIconRenderer = msg.pDragAndDropRenderer; // Drop 안함. if( NULL == m_pDragIconRenderer) { m_pDragObject = NULL; } } } } KUIWnd *KUIWndManager::CreateControl( KUIWND_CREATE_ARG& CREATE_ARG) { CREATE_ARG.pWndManager = this; KUIWnd *pNewWnd = KUIFactory::GetInstance()->CreateObject( CREATE_ARG.lpszClassName.c_str() ); if( NULL == pNewWnd) return NULL; pNewWnd->Create( CREATE_ARG ); if( !CREATE_ARG.lpszSprName.empty() && !CREATE_ARG.lpszAniName.empty() ) KUITextureManager::GetManager()->GetSprAni( CREATE_ARG.lpszSprName.c_str(), CREATE_ARG.lpszAniName.c_str() ); if(NULL != CREATE_ARG.pParent && NULL != pNewWnd) CREATE_ARG.pParent->AddChild( pNewWnd); //Tool Tip은 사용 되고 있음. //assert( CREATE_ARG.pParent && "(KUIWndManager::CreateControl) Parent 가 없다!!!" ); return pNewWnd; } /// 2011.09.30 - prodongi bool KUIWndManager::isTop(char const* srcId, char const* destId) const { struct sFind { sFind() : m_isFindSrc(false), m_isFindDest(false) {} int find(char const* id, char const* srcId, char const* destId) { if (0 == ::_stricmp(id, srcId)) { if (m_isFindDest) { return 1; } m_isFindSrc = true; } else if (0 == ::_stricmp(id, destId)) { if (m_isFindSrc) { return 0; } m_isFindDest = true; } return -1; } bool m_isFindSrc; bool m_isFindDest; }; sFind f; std::list< KUIWnd* >::const_iterator it; for ( it = m_listSortedWnd.begin();it != m_listSortedWnd.end() ; ++it ) { int ret = f.find((*it)->GetID(), srcId, destId); if (-1 != ret) { return ret == 1 ? true : false; } } for( it = m_listWnd.begin();it != m_listWnd.end() ; ++it ) { int ret = f.find((*it)->GetID(), srcId, destId); if (-1 != ret) { return ret == 1 ? true : false; } } return false; }