#include "stdafx.h"// Slider.cpp : Implementation of cSlider #include #include "DecalControls.h" #include "Slider.h" ///////////////////////////////////////////////////////////////////////////// // cSlider cSlider::cSlider() : m_nTextColor(RGB(0, 0, 0)), m_bMouseIn(VARIANT_FALSE), m_bGrappled(VARIANT_FALSE), m_nMinimum(0), m_nMaximum(100), m_nMinSliderColor( RGB(200,0,0) ), m_nMaxSliderColor( RGB(0,200,0) ), m_nSliderPos(0), m_strTextLeft(NULL), m_strTextRight(NULL), m_bVertical(VARIANT_FALSE) { } cSlider::~cSlider() { if (m_strTextLeft) free(m_strTextLeft); if (m_strTextRight) free(m_strTextRight); } STDMETHODIMP cSlider::get_Font(IFontCacheDisp **pVal) { _ASSERTE(pVal != NULL); if (m_pFont.p == NULL) *pVal = NULL; else m_pFont->QueryInterface(pVal); return S_OK; } STDMETHODIMP cSlider::putref_Font(IFontCacheDisp *newVal) { _ASSERTE(newVal != NULL); if (m_pFont.p) m_pFont.Release(); HRESULT hRes = newVal->QueryInterface(&m_pFont); _ASSERTE(SUCCEEDED(hRes)); m_pSite->Reformat(); return S_OK; } STDMETHODIMP cSlider::get_TextColor(long *pVal) { _ASSERTE(pVal != NULL); *pVal = m_nTextColor; return S_OK; } STDMETHODIMP cSlider::put_TextColor(long newVal) { _ASSERTE((newVal & 0xFF000000L) == 0); m_nTextColor = newVal; m_pSite->Invalidate(); Reformat(); return S_OK; } STDMETHODIMP cSlider::get_SliderPosition(long *pVal) { _ASSERTE(pVal != NULL); *pVal = m_nSliderPos; return S_OK; } STDMETHODIMP cSlider::put_SliderPosition(long newVal) { if (m_nSliderPos == newVal) return S_OK; if (newVal < m_nMinimum || newVal > m_nMaximum) return S_FALSE; m_nSliderPos = newVal; Reformat(); m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cSlider::get_Minimum(long *pVal) { _ASSERTE(pVal != NULL); *pVal = m_nMinimum; return S_OK; } STDMETHODIMP cSlider::put_Minimum(long newVal) { if (m_nMinimum == newVal) return S_OK; m_nMinimum = newVal; Reformat(); m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cSlider::get_Maximum(long *pVal) { _ASSERTE(pVal != NULL); *pVal = m_nMaximum; return S_OK; } STDMETHODIMP cSlider::put_Maximum(long newVal) { if (m_nMaximum == newVal) return S_OK; m_nMaximum = newVal; Reformat(); m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cSlider::SchemaLoad(IView *pView, IUnknown *pSchema) { // First attempt to load the font CComPtr< IPluginSite > pPlugin; m_pSite->get_PluginSite( &pPlugin ); pPlugin->CreateFontSchema(14, 0, pSchema, &m_pFont); MSXML::IXMLDOMElementPtr pElement = pSchema; _variant_t vTextColor = pElement->getAttribute(_T("textcolor")), vMinSliderColor = pElement->getAttribute(_T("mincolor")), vMaxSliderColor = pElement->getAttribute(_T("maxcolor")), vVertical = pElement->getAttribute(_T("vertical")), vDefault = pElement->getAttribute(_T("default")), vMaximum = pElement->getAttribute(_T("maximum")), vMinimum = pElement->getAttribute(_T("minimum")), vName = pElement->getAttribute(_T("name")); // Maximum must exist _ASSERTE(vMaximum.vt == VT_INT); if (vTextColor.vt != VT_NULL) { try { m_nTextColor = static_cast(vTextColor); } catch(...) { // Type conversion error _ASSERTE(FALSE); } } if (vMinSliderColor.vt != VT_NULL) { try { _bstr_t szWhat = vMinSliderColor.bstrVal; m_nMinSliderColor = wcstoul( szWhat, 0, 16 ); } catch( ... ) { // Type conversion error _ASSERTE(FALSE); } } if (vMaxSliderColor.vt != VT_NULL) { try { _bstr_t szWhat = vMaxSliderColor.bstrVal; m_nMaxSliderColor = wcstoul( szWhat, 0, 16 ); } catch( ... ) { // Type conversion error _ASSERTE(FALSE); } } if (vVertical.vt != VT_NULL) { try { m_bVertical = (static_cast(vVertical)) ? VARIANT_TRUE : VARIANT_FALSE; } catch( ... ) { // Type conversion error _ASSERTE(FALSE); } } if (vMaximum.vt != VT_NULL) { try { m_nMaximum = static_cast(vMaximum); } catch( ... ) { // Type conversion error _ASSERTE(FALSE); } } if (vMinimum.vt != VT_NULL) { try { m_nMinimum = static_cast(vMinimum); } catch( ... ) { // Type conversion error _ASSERTE(FALSE); } } if (vDefault.vt != VT_NULL) { try { m_nSliderPos = static_cast(vDefault); } catch( ... ) { m_nSliderPos = m_nMinimum; } } /* fprintf( f, "name - %s\n", OLE2A(vName.bstrVal) ); fprintf( f, "textcolor - %08X\n", m_nTextColor ); fprintf( f, "mincolor - %08X\n", m_nMinSliderColor ); fprintf( f, "maxcolor - %08X\n", m_nMaxSliderColor ); fprintf( f, "vertical - %X\n", m_bVertical ); fprintf( f, "maximum - %08X\n", m_nMaximum ); fprintf( f, "minimum - %08X\n\n", m_nMinimum ); */ /* // it's a pain in the ass that we need set the min and max for them to work, aye? let's fix it RECT rc; m_pSite->get_Position(&rc); long siteHHalf = (rc.bottom - rc.top) / 2; // The background bar m_rcBackground.left = 0; m_rcBackground.top = siteHHalf - 4; m_rcBackground.bottom = siteHHalf + 6; m_rcBackground.right = rc.right - rc.left; // The middle bar m_rcBar.top = siteHHalf; m_rcBar.left = 0; m_rcBar.bottom = siteHHalf + 3; m_rcBar.right = rc.right - rc.left; // Ensure sane slider position if (m_nSliderPos < m_nMinimum) m_nSliderPos = m_nMinimum; if (m_nSliderPos > m_nMaximum) m_nSliderPos = m_nMaximum; long siteDiff = abs(m_rcBar.right - m_rcBar.left); long extentDiff = abs(m_nMaximum - m_nMinimum); long valDiff = m_nSliderPos - m_nMinimum; if (valDiff == 0) { m_ptSlider.x = m_rcBar.left; } else { long diff = (long)(((float)valDiff / (float)extentDiff) * (float)siteDiff); m_ptSlider.x = m_rcBar.left + diff; if (m_ptSlider.x >= m_rcBar.right - 6) m_ptSlider.x = m_rcBar.right - 6; } m_ptSlider.y = siteHHalf - 5; */ // fclose( f ); return S_OK; } STDMETHODIMP cSlider::Reformat() { USES_CONVERSION; char strTemp[16]; if (m_strTextLeft) free(m_strTextLeft); if (m_strTextRight) free(m_strTextRight); _snprintf(strTemp, 15, "%i", m_nMinimum); m_strTextLeft = strdup(strTemp); _snprintf(strTemp, 15, "%i", m_nMaximum); m_strTextRight = strdup(strTemp); if (m_pFont.p == NULL) { // No font was specified, create the default font CComPtr pPlugin; m_pSite->get_PluginSite(&pPlugin); BSTR bstrFontName; pPlugin->get_FontName(&bstrFontName); pPlugin->CreateFont(bstrFontName /*_bstr_t(_T("Times New Roman"))*/, 14, 0, &m_pFont); } RECT rc; m_pSite->get_Position(&rc); SIZE textRight; m_pFont->MeasureText(_bstr_t(m_strTextRight), &textRight); long siteHHalf = (rc.bottom - rc.top) / 2; // The background bar m_rcBackground.left = 0; m_rcBackground.top = siteHHalf - 4; m_rcBackground.bottom = siteHHalf + 6; m_rcBackground.right = rc.right - rc.left; // The middle bar m_rcBar.top = siteHHalf; m_rcBar.left = 0; m_rcBar.bottom = siteHHalf + 3; m_rcBar.right = rc.right - rc.left; m_ptLeftText.x = m_rcBackground.left + 1; m_ptLeftText.y = m_rcBackground.bottom + 1; m_ptRightText.x = m_rcBackground.right - (textRight.cx + 1); m_ptRightText.y = m_rcBackground.bottom + 1; // Ensure sane slider position if (m_nSliderPos < m_nMinimum) m_nSliderPos = m_nMinimum; if (m_nSliderPos > m_nMaximum) m_nSliderPos = m_nMaximum; long siteDiff = abs(m_rcBar.right - m_rcBar.left); long extentDiff = abs(m_nMaximum - m_nMinimum); long valDiff = m_nSliderPos - m_nMinimum; if (valDiff == 0) { m_ptSlider.x = m_rcBar.left; } else { long diff = (long)(((float)valDiff / (float)extentDiff) * (float)siteDiff); m_ptSlider.x = m_rcBar.left + diff; if (m_ptSlider.x >= m_rcBar.right - 6) m_ptSlider.x = m_rcBar.right - 6; } m_ptSlider.y = siteHHalf - 5; return S_OK; } STDMETHODIMP cSlider::Render(ICanvas *pCanvas) { // intensity to lose or gain for 3d effect #define COLOR_BAND 20 USES_CONVERSION; CComPtr pPlugin; m_pSite->get_PluginSite(&pPlugin); CComPtr pIcon; SIZE szIcon = {7, 12}; pPlugin->GetIconCache(&szIcon, &pIcon); // we're averaging color differences w/bias... float fractional = m_nSliderPos / m_nMaximum; float lFraction = (1 - fractional) * 2; float rFraction = fractional * 2; long lMinSliderRed = lFraction * (BYTE) m_nMinSliderColor; long lMinSliderGreen = lFraction * (BYTE) (m_nMinSliderColor >> 8); long lMinSliderBlue = lFraction * (BYTE) (m_nMinSliderColor >> 16); long lMaxSliderRed = rFraction * (BYTE) m_nMaxSliderColor; long lMaxSliderGreen = rFraction * (BYTE) (m_nMaxSliderColor >> 8); long lMaxSliderBlue = rFraction * (BYTE) (m_nMaxSliderColor >> 16); long lFillColorTop, lFillColorMiddle, lFillColorBottom; long lFillColorRed = (lMinSliderRed + lMaxSliderRed) / 2, lFillColorGreen = (lMinSliderGreen + lMaxSliderGreen) / 2, lFillColorBlue = (lMinSliderBlue + lMaxSliderBlue) / 2; if( m_nMinSliderColor && m_nMaxSliderColor ) // not black .. who would choose all black for both bars anyway? grr. { // find the most intense color channel to maul for our evil purposes (we're using std::max here) long lMax = max( max( lFillColorRed, lFillColorGreen ), lFillColorBlue ); // if we're dark, don't overflow long lOffset = lMax > (COLOR_BAND - 1) ? COLOR_BAND : 0; long lOffset2 = lMax > (COLOR_BAND - 1) ? 0 : COLOR_BAND; // red if( lMax == lFillColorRed ) { lFillColorTop = RGB( lFillColorRed - lOffset, lFillColorGreen, lFillColorBlue ); lFillColorMiddle = RGB( lFillColorRed + lOffset2, lFillColorGreen, lFillColorBlue ); lFillColorBottom = RGB( lFillColorRed - lOffset, lFillColorGreen, lFillColorBlue ); } // green else if( lMax == lFillColorGreen ) { lFillColorTop = RGB( lFillColorRed, lFillColorGreen - lOffset, lFillColorBlue ); lFillColorMiddle = RGB( lFillColorRed, lFillColorGreen + lOffset2, lFillColorBlue ); lFillColorBottom = RGB( lFillColorRed, lFillColorGreen - lOffset, lFillColorBlue ); } // has to be blue else { lFillColorTop = RGB( lFillColorRed, lFillColorGreen, lFillColorBlue - lOffset ); lFillColorMiddle = RGB( lFillColorRed, lFillColorGreen, lFillColorBlue + lOffset2 ); lFillColorBottom = RGB( lFillColorRed, lFillColorGreen, lFillColorBlue - lOffset ); } } // someone's a GOTH else { lFillColorTop = 0; lFillColorMiddle = 0x00161616; lFillColorBottom = 0; } pCanvas->Fill( &m_rcBar, lFillColorMiddle ); RECT topBar = {m_rcBar.left, m_rcBar.top, m_rcBar.right, m_rcBar.top + 1}; pCanvas->Fill( &topBar, lFillColorTop ); RECT bottomBar = {m_rcBar.left, m_rcBar.bottom - 1, m_rcBar.right, m_rcBar.bottom}; pCanvas->Fill( &bottomBar, lFillColorBottom ); pIcon->DrawIcon(&m_ptSlider, 0x06001286, 0, pCanvas); m_pFont->DrawText(&m_ptLeftText, _bstr_t(m_strTextLeft), RGB(0, 0, 0), pCanvas); m_pFont->DrawText(&m_ptRightText, _bstr_t(m_strTextRight), RGB(0, 0, 0), pCanvas); return S_OK; } STDMETHODIMP cSlider::MouseDown(struct MouseState *mouseState) { _ASSERTE(m_pSite != NULL); POINT pt = mouseState->client; if (pt.x >= (m_ptSlider.x) && (pt.x <= m_ptSlider.x + 6) && pt.y >= (m_ptSlider.y) && (pt.y <= m_ptSlider.y + 12)) { // They hit the grapple point! m_ptLastMouse = mouseState->client; m_bGrappled = VARIANT_TRUE; } else { // The hit the bar - see if that's within the bar rect if (pt.x > m_rcBar.left && pt.x < m_rcBar.right && pt.y > (m_rcBar.top - 3) && pt.y < (m_rcBar.bottom + 3)) { // Calcuate the new slider position float pixelValue = (float)((float)(m_nMaximum - m_nMinimum) / (float)(m_rcBar.right - m_rcBar.left)); m_nSliderPos = (pt.x - m_rcBar.left) * pixelValue; Reformat(); m_pSite->Invalidate(); long nID; m_pSite->get_ID(&nID); _ASSERTE(m_pSite.p != NULL); Fire_Change(nID, m_nSliderPos); } } return S_OK; } STDMETHODIMP cSlider::MouseUp(struct MouseState *mouseState) { m_bGrappled = VARIANT_FALSE; return S_OK; } STDMETHODIMP cSlider::MouseMove(struct MouseState *mouseState) { if (m_bGrappled) { long dx; POINT pt = mouseState->client; dx = m_ptLastMouse.x - pt.x; m_ptLastMouse = pt; float pixelValue = (float)((float)(m_nMaximum - m_nMinimum) / (float)(m_rcBar.right - m_rcBar.left)); m_nSliderPos -= ((float)dx * pixelValue); // I personally like being able to drag the slider // PAST THE EDGE OF THE SLIDE BAR without needing pixel accuracy... if( pt.x >= m_rcBar.right ) m_nSliderPos = m_nMaximum; Reformat(); m_pSite->Invalidate(); long nID; m_pSite->get_ID(&nID); _ASSERTE(m_pSite.p != NULL); Fire_Change(nID, m_nSliderPos); } return S_OK; }