/* $Header$ */

/*************** changes *******************
Date			Edit				Bug					Description
12-Nov-21	rmm11295								Changed GDIgetStockPen() to have two new arguments (GDI_STOCK_PEN_WINDOW and GDI_STOCK_PEN_WINDOWTEXT), replacing WHITE_PEN and BLACK_PEN respectively. Also tidied up some old menu code.
14-Apr-21	rmm10984								Removed compiler warnings on Windows platform.
14-Jan-21	rmm_ncs									Removed unnecessary ECM_GETCOMPSTORE... messages.
17-May-17	rmm9385			ST/EC/1457	$::min for slider was lost when re-opening window.
14-Jul-09	rmm6659			ST/WT/1323	Problem with slider face color
21-Aug-08 rjc0025			ST/EC/1153	Tooltip now displays on vista
19-Jun-08 AE6826			ST/WT/1323: Slider background now correct when in runtime pagepane
05-Jun-08	jc0004			ST/EC/1144	Fixed problem with enabled property
02-May-07	pkvista			            vista.
18-Oct-04	rmm5117			ST/EC/857		Problems with slider events.
30-Jun-04	rmm5006									Multiple select knobs were missing from quite a few components.
22-Jun-04	rmm4999									Finished rmm4993: remote form fields now show $xxx correctly.
22-May-03	AE6246			ST/WO/1415: XCOMP Slider & progress bar didn't support themes correctly.
23-Jan-03 MHn0206			ST/WT/682		Fixed single click events. 
30-Apr-02	AE6086									Changed rmm3980 so negative ranges are valid
16-Feb-01 MHCARBON								Fixed face colour mapping issue on OSX.
28-Dec-00	rmm3980			ST/WT/428		Problems with unusual ranges.
02-Feb-00 MHWEB										Web client changes
********************************************/

#include <extcomp.he>
#include <extfval.he>
#include <hwnd.he>
#include <gdi.he>
#include <string.h>

#include "slider.he"

#define COMPONENT_COUNT 	1				// Number of controls within library 

#define MAX_RANGE   32000					// AE6086

// MHWEB begins.
#ifdef isWEB
#define LIB_RES_NAME 			1001		/* Resource id of library name */
#define SLIDER_ID 			  2001		/* Resource id of control within library */
#else
#define LIB_RES_NAME 			1000		/* Resource id of library name */
#define SLIDER_ID 			  2000	  /* Resource id of control within library */
#endif
// MHWEB ends.

#define SLIDER_ICON 			1				// Resource bitmap id

const qshort
				cSliderMin 							= 1,
				cSliderMax    					= 2,
				cSliderValue						= 3,
				cSliderShowMarks				= 4,
				cSliderBlockSlider			= 5,
				cSliderVertical					= 6,
				cSliderBigRange					= 7,
				cSliderMarkFreq					= 8,
				cSliderSelStart					= 9,
				cSliderSelEnd						= 10,
				cSliderVertMargin				= 11,
				cSliderHorzMargin				= 12,
				cSliderMarkColor				= 13,
				cSliderBlockColor				= 14,
				cSliderFaceColor				= 15,
				cSliderRangeColor				= 16,
				cSliderSelRangeColor		= 17,
				// -----------------------
       	cHorizontalGap 					= 10,
       	cVerticalGap            = 10,
				// -----------------------
       	cSliderEvStartSlider		= 1,
       	cSliderEvEndSlider			= 2,
       	cSliderEvNewSliderPos		= 3;
       	

ECOproperty SLIDERproperties[] =
{ 
	cSliderMin,					4000,			fftInteger, 0, 0, 0, 0,												// min
	cSliderMax,					4001,			fftInteger, 0, 0, 0, 0,												// max
	cSliderValue,				4002,			fftInteger, 0, 0, 0, 0,												// val
	cSliderShowMarks,		4003,			fftBoolean, 0, 0, 0, 0,												// show marks
	cSliderBlockSlider,	4004,			fftBoolean, 0, 0, 0, 0,												// block slider
	cSliderVertical,		4005,			fftBoolean, 0, 0, 0, 0, 											// vertical
	cSliderBigRange,		4006,			fftBoolean, 0, 0, 0, 0, 											// big range
	cSliderMarkFreq,		4007,			fftInteger, 0, 0, 0, 0, 											// freq
	cSliderSelStart,		4008,			fftInteger, 0, 0, 0, 0, 											// sel start
	cSliderSelEnd,			4009,			fftInteger, 0, 0, 0, 0,												// sel end
	cSliderVertMargin,	4010,			fftInteger, 0, 0, 0, 0, 											// vertical margin
	cSliderHorzMargin,	4011,			fftInteger, 0, 0, 0, 0, 												// horizontal margin
	cSliderMarkColor,		4012,			fftInteger, EXTD_FLAG_PWINDCOL, 0, 0, 0, 			// mark color
	cSliderBlockColor,	4013,			fftInteger, EXTD_FLAG_PWINDCOL, 0, 0, 0, 			// block color
	cSliderFaceColor,		4014,			fftInteger, EXTD_FLAG_PWINDCOL, 0, 0, 0, 			// face color
	cSliderRangeColor,	4015,			fftInteger, EXTD_FLAG_PWINDCOL, 0, 0, 0, 			// range color 
	cSliderSelRangeColor,	4016,		fftInteger, EXTD_FLAG_PWINDCOL, 0, 0, 0, 			// sel range color 	
	anumBackgroundTheme,  0,			0,					0, 0, 0, 0,												// rmm6659
};
#define SLIDER_PROPERTY_COUNT (sizeof(SLIDERproperties)/sizeof(SLIDERproperties[0]))

ECOparam SLIDERnewPos[1] =
{
	6000, fftInteger, 0, 0
};

ECOmethodEvent SLIDERevents[3] = 
{
// MHWEB begins.
#ifdef isWEB
	cSliderEvStartSlider,  	5000, 0, 1, &SLIDERnewPos[0], 0, 0,
	cSliderEvEndSlider,  		5001, 0, 1, &SLIDERnewPos[0], 0, 0,
	cSliderEvNewSliderPos,  5002, 0, 1, &SLIDERnewPos[0], 0, 0
#else
	cSliderEvStartSlider,  	5000, 0, 0, 0, 0, 0,
	cSliderEvEndSlider,  		5001, 0, 0, 0, 0, 0,
	cSliderEvNewSliderPos,  5002, 0, 1, &SLIDERnewPos[0], 0, 0
#endif
// MHWEB ends.
};
               
// ---------------------------------------------------------------------------------------------------------

tqfSlider::tqfSlider( HWND pFieldHWnd )
{
	mInitialized = qfalse;	// rmm9385
	mIsVista = 0;
	mHWnd = pFieldHWnd;
	mSetLastNewPosVal = qfalse; // MHn0206 // rmm5117
	mLastNewPosVal = 0;	// rmm5117
	
	qlong style = WNDgetWindowLong( mHWnd, GWL_EXSTYLE );
	style |= WND_REDRAWONSIZE;
	WNDsetWindowLong( mHWnd, GWL_EXSTYLE, style );
	
	mShowMarks = mBlockSlider = mVertical = qtrue;
	mBigRange = qfalse;
	mMin = 1; mMax = 10; mVal = 5; 
	mMarkFreq = 1;
	mSelStart = mSelEnd = 0;
	mMouseDown = 0; mHot = 0;

	mSelRangeColor = GDI_COLOR_3DSHADOW;
	mMarkColor = GDI_COLOR_3DSHADOW;
	mRangeColor = GDI_COLOR_3DHIGHLIGHT;
	mFaceColor = GDI_COLOR_3DFACE;
	mBlockColor= GDI_COLOR_3DFACE;

	mVertMargin = cVerticalGap;
	mHorzMargin = cHorizontalGap;
	
	#ifndef isWEB
		WNDsendMessage(mHWnd,WM_CONTROL,DRAW_SETPARENTERASE,1);	// AE6246

		#if defined(iswin32)
			// pkvista13
			DWORD verinfo = WNDwinGetVersion(); // rmm10984
			mIsVista = ((verinfo & 0xff) >= 6);
		#endif
	#endif
}

tqfSlider::~tqfSlider()
{
}

qlong tqfSlider::attributeSupport( LPARAM pMessage, WPARAM wParam, LPARAM lParam, EXTCompInfo* eci )
{
	switch( pMessage )
	{ 
		case ECM_PROPERTYCANASSIGN: return 1L;
		case ECM_SETPROPERTY: 
		{       
			EXTParamInfo* param = ECOfindParamNum( eci, 1 );
			if ( param )
			{
				EXTfldval fval( (qfldval)param->mData );
				switch( ECOgetId(eci) )
				{
					case anumBackgroundTheme:	// rmm6659: allow the default processing for this to occur
						return 0L;
					case cSliderMin:
						mMin = fval.getLong(); 
						if (mInitialized && (mMax-mMin) > MAX_RANGE) // AE6086 // rmm9385
							mMin = mMax - MAX_RANGE;
						break; 			
					case cSliderMax: 					
						mMax = fval.getLong(); 
						if (mInitialized && (mMax-mMin) > MAX_RANGE ) // AE6086 // rmm9385
							mMax = mMin + MAX_RANGE;
						break; 			
					case cSliderValue: 				mVal = fval.getLong(); break; 
					case cSliderShowMarks: 		mShowMarks = (qbool)fval.getLong(); break; 			
					case cSliderBlockSlider: 	mBlockSlider = (qbool)fval.getLong(); break; 
					case cSliderVertical: 		mVertical = (qbool)fval.getLong(); break; 			
					case cSliderBigRange:			mBigRange = (qbool)fval.getLong(); break; 			
					case cSliderMarkFreq:			mMarkFreq = fval.getLong(); break; 			
					case cSliderSelStart:			mSelStart = fval.getLong(); break; 			
					case cSliderSelEnd:				mSelEnd = fval.getLong(); break; 			
					case cSliderVertMargin:		mVertMargin = fval.getLong(); break; 			
					case cSliderHorzMargin:		mHorzMargin = fval.getLong(); break; 			
					case cSliderMarkColor:		mMarkColor = (qcol)fval.getLong(); break; 	
					case cSliderBlockColor:		mBlockColor = (qcol)fval.getLong(); break; 	
					case cSliderFaceColor:		mFaceColor = (qcol)fval.getLong(); break; 	
					case cSliderRangeColor:		mRangeColor = (qcol)fval.getLong(); break; 	
					case cSliderSelRangeColor:		mSelRangeColor = (qcol)fval.getLong(); break; 	
				} 
				if (mInitialized) // rmm9385
				{
					// Start rmm9385: Simplified
					if (param->mId == cSliderMin && mMin > mMax) { mMin = mMax; }
					if (param->mId == cSliderMax && mMax < mMin) { mMax = mMin; }

					if (mVal < mMin) { mVal = mMin; ECOupdatePropInsp(mHWnd, cSliderValue); }
					else if (mVal > mMax) { mVal = mMax; ECOupdatePropInsp(mHWnd, cSliderValue); }
					// End rmm9385
					if (ECOisSetup(mHWnd))
					{
						WNDinvalidateRect(mHWnd, NULL);
						WNDupdateWindow(mHWnd);
					}
				}
				return 1L;
			}
			break;
		}
		case ECM_GETPROPERTY: 
		{
			EXTfldval fval;
			switch( ECOgetId(eci) )
			{
				case anumBackgroundTheme:	// rmm6659: allow the default processing for this to occur
					return 0L;
				case cSliderMin: 					fval.setLong( mMin ); break; 			
				case cSliderMax: 					fval.setLong( mMax ); break; 			
				case cSliderValue: 				fval.setLong( mVal ); break; 
				case cSliderShowMarks: 		fval.setLong( (qlong)mShowMarks ); break; 			
				case cSliderBlockSlider: 	fval.setLong( (qlong)mBlockSlider ); break; 
				case cSliderVertical: 		fval.setLong( (qlong)mVertical ); break; 	
				case cSliderBigRange:			fval.setLong( (qlong)mBigRange ); break; 			
				case cSliderMarkFreq:			fval.setLong( mMarkFreq ); break;
				case cSliderSelStart:			fval.setLong( mSelStart ); break;
				case cSliderSelEnd:				fval.setLong( mSelEnd ); break;
				case cSliderVertMargin:		fval.setLong( mVertMargin ); break; 			
				case cSliderHorzMargin:		fval.setLong( mHorzMargin ); break; 			
				case cSliderMarkColor:		fval.setLong( (qlong)mMarkColor ); break; 	
				case cSliderBlockColor:		fval.setLong( (qlong)mBlockColor ); break; 	
				case cSliderFaceColor:		fval.setLong( (qlong)mFaceColor ); break; 	
				case cSliderRangeColor:		fval.setLong( (qlong)mRangeColor ); break; 	
				case cSliderSelRangeColor:	fval.setLong( (qlong)mSelRangeColor ); break; 	
			}         
			ECOaddParam(eci,&fval);
			return 1L;
		}
	}
	return 0;
}

void tqfSlider::drawMarks( HDC pHdc )
{
	qreal range = (qreal)( mMax - mMin );
	if ( !range ) return;
	
	qreal dist = (qreal)( mVertical ? mLastSlide.height() : mLastSlide.width() );
	qreal perpos = dist / range;
	
	qpen pen = qpen( 1, mMarkColor );
	HPEN pen1 = GDIcreatePen(&pen);
	HPEN oldpen = GDIselectObject( pHdc, pen1 );

	qrect slider = mLastSlide;
	qreal markPos = (qreal)(mVertical ? mLastSlide.top : mLastSlide.left);

	if ( mVertical )
	{
	  slider.right = slider.left - 2;
	  slider.left = slider.right - 5;
	}
	else
	{
	  slider.top = slider.bottom + 3;
	  slider.bottom = slider.top + 5;
 	}

	qshort freqcnt = (qshort)mMarkFreq;
	for ( qlong pos = mMin; pos<=mMax; pos++ )
	{  
		if ( mMarkFreq==1 || freqcnt==mMarkFreq )
		{ 
	  	if ( mVertical )
			{
				GDImoveTo( pHdc, slider.left, (qshort)markPos );				
				GDIlineTo( pHdc, slider.right, (qshort)markPos );
			}
			else
			{
				GDImoveTo( pHdc, (qshort)markPos, slider.bottom );			
				GDIlineTo( pHdc, (qshort)markPos, slider.top );
			} 	
			freqcnt = 0;
		}
		markPos+=perpos;
		if ( mMarkFreq!=1 )
			freqcnt++;
	}
	// final mark
	if ( mMarkFreq!=1 )
	{
		qreal markPos = (qreal)(mVertical ? mLastSlide.bottom+1 : mLastSlide.right+1);
		if ( mVertical )
		{
			GDImoveTo( pHdc, slider.left, (qshort)markPos );				
			GDIlineTo( pHdc, slider.right, (qshort)markPos );
		}
		else
		{
			GDImoveTo( pHdc, (qshort)markPos, slider.bottom );			
			GDIlineTo( pHdc, (qshort)markPos, slider.top );
		} 	
	}
	GDIselectObject( pHdc, oldpen );
	GDIdeleteObject( pen1 );
}

void tqfSlider::setSlideArea()
{ 
	qrect client;
	WNDgetClientRect( mHWnd, &client );
	mLastSlide = client;
	if ( mVertical )
	{     
		qshort width = client.width()/2;
		mLastSlide.top += mVertMargin;
		mLastSlide.bottom -= mVertMargin;
		mLastSlide.left = width - ( mBigRange ? 6 : 2 ); 
		mLastSlide.right = width + ( mBigRange ? 6 : 2 );
	}
	else
	{     
		qshort height = client.height()/2;
		mLastSlide.left += mHorzMargin;
		mLastSlide.right -= mHorzMargin;
		mLastSlide.top = height - ( mBigRange ? 6 : 2 ); 
		mLastSlide.bottom = height + ( mBigRange ? 6 : 2 );
	} 
}

void tqfSlider::drawSlide( HDC pHdc )
{ 
	WNDborderStruct borderSpec = WNDborderStruct( WND_BORD_INSET );
	WNDpaintBorder(	NULL, pHdc, &mLastSlide, &borderSpec );
	GDIinsetRect( &mLastSlide, 2, 2 );
	if ( mBigRange )
	{
		GDIsetTextColor( pHdc, mRangeColor );
		GDIsetBkColor( pHdc, mRangeColor );
		GDIfillRect( pHdc, &mLastSlide, GDIgetStockBrush( BLACK_BRUSH ) ); 
		if ( mBigRange && mSelStart<mSelEnd )
		{
			qrect fillr = mLastSlide;
			GDIinsetRect( &fillr, 1,1 );			
			GDIsetTextColor( pHdc, mSelRangeColor );
			GDIsetBkColor( pHdc, mSelRangeColor );

			qreal range = (qreal)( mMax - mMin );
			if ( !range ) return;
			qreal dist = (qreal)( mVertical ? fillr.height() : fillr.width() );
			qreal perpos = dist / range;
			if ( mVertical )
			{ 
				fillr.top += (qshort)( ( mSelStart - mMin ) * perpos );
				fillr.bottom = fillr.top + (qshort)( ( mSelEnd - mSelStart ) * perpos );
			}
			else
			{
				fillr.left += (qshort)( ( mSelStart - mMin ) * perpos );
				fillr.right = fillr.left + (qshort)( ( mSelEnd - mSelStart ) * perpos );
			}
			GDIfillRect( pHdc, &fillr, GDIgetStockBrush( BLACK_BRUSH ) ); 
		}
	}
}

qshort tqfSlider::getValueFromPt( qpoint* pt )
{
	qreal range = (qreal)( mMax - mMin );
	if ( !range ) return (qshort)mMin;
	qreal dist = (qreal)( mVertical ? mLastSlide.height() : mLastSlide.width() );
	qreal perpos = dist / range;
	if ( mVertical )
	{
		qreal top = (qreal)mLastSlide.top + ( perpos / 2 );
		qshort val = (qshort)mMin;
		while( (qshort)top<pt->v && val<=mMax )
		{         
			top+=perpos;
			val++;
		}
		if ( val>mMax ) val = (qshort)mMax;
		if ( val<mMin ) val = (qshort)mMin;  // AE6086
		return val;
	} 	
	else
	{
		qreal left = mLastSlide.left + ( perpos / 2 );
		qshort val = (qshort)mMin;
		while( (qshort)left<pt->h && val<=mMax )
		{         
			left+=perpos;
			val++;
		}       
		if ( val>mMax ) val = (qshort)mMax;
		if ( val<mMin ) val = (qshort)mMin;  // AE6086
		return val;
	} 	          
	return (qshort)mMin;
}

void tqfSlider::drawSlider( HDC pHdc )
{
	qreal range = (qreal)( mMax - mMin );
	if ( !range ) return;
	qreal dist = (qreal)( mVertical ? mLastSlide.height() : mLastSlide.width() );
	qreal perpix = dist / range;
	qshort realpos = (qshort)( perpix * ( mVal - mMin ) );

	qrect slider = mLastSlide;
	GDIinsetRect( &slider, 2, 2 );
	if ( mVertical )
	{
		mBlockRect.top = mLastSlide.top + realpos - 5;
		mBlockRect.bottom = mBlockRect.top + 10;
		mBlockRect.left = slider.left - 10;
		mBlockRect.right = slider.right + 10;
	}
	else
	{
		mBlockRect.left = mLastSlide.left + realpos - 5;
		mBlockRect.right = mBlockRect.left + 10;
		mBlockRect.top = slider.top - 10;
		mBlockRect.bottom = slider.bottom + 10;
	}
	if ( mBlockSlider )
	{
		qrect borderRect = mBlockRect;
		WNDborderStruct borderSpec = WNDborderStruct( WND_BORD_EMBOSSED );
		GDIsetTextColor( pHdc, mBlockColor );
		GDIsetBkColor( pHdc, mBlockColor );
		GDIfillRect( pHdc, &borderRect, GDIgetStockBrush( BLACK_BRUSH ) );
		WNDpaintBorder(	NULL, pHdc, &borderRect, &borderSpec );
	}
	else
	{
		// pkvista13
#ifndef isWEB
		if ( mIsVista )
		{					
			int code = mVertical ? 0 : THEME_CONTROL_VERTICAL;
			if ( mMouseDown ) code |= THEME_CONTROL_CHECKED;
			else if ( mHot ) code |= THEME_CONTROL_HOT;
			else code |= THEME_CONTROL_DISABLED;
			WNDdrawThemeControl(mHWnd, pHdc, THEME_TRACKBAR, code, &mBlockRect);
		}
		else
#endif
		{
			qpoint p[6]; 
			
			if ( mVertical )
			{
				p[0].h = mBlockRect.right; p[0].v = mBlockRect.top;
				p[1].h = mBlockRect.right; p[1].v = mBlockRect.bottom;
				p[2].h = mBlockRect.left+5; p[2].v = mBlockRect.bottom;
				p[3].h = mBlockRect.left; p[3].v = mBlockRect.top+5;
				p[4].h = mBlockRect.left+5; p[4].v = mBlockRect.top;
				p[5].h = mBlockRect.right; p[5].v = mBlockRect.top;
				HBRUSH oldbrush = GDIselectObject( pHdc, GDIgetStockBrush( BLACK_BRUSH ) );
				GDIsetTextColor( pHdc, mBlockColor );
				GDIsetBkColor( pHdc, mBlockColor );
				GDIfillPoly( pHdc, &p[0], 6 );
				GDIselectObject( pHdc, oldbrush );
		
				HPEN pen2 = GDIgetStockPen( GDI_STOCK_PEN_WINDOW ); // rmm11295
				HPEN oldpen = GDIselectObject( pHdc, pen2 );
				GDImoveTo( pHdc, p[3].h, p[3].v );  GDIlineTo( pHdc, p[4].h, p[4].v ); 
				GDIlineTo( pHdc, p[0].h, p[0].v );
				qpen pen = qpen( 1, mBlockColor==GDI_COLOR_3DFACE ? GDI_COLOR_3DSHADOW : GDIgetDarkerShade(mBlockColor) );
				HPEN pen1 = GDIcreatePen(&pen); GDIselectObject( pHdc, pen1 );
				GDIlineTo( pHdc, p[1].h, p[1].v ); GDIlineTo( pHdc, p[2].h, p[2].v ); GDIlineTo( pHdc, p[3].h, p[3].v );
				GDIselectObject( pHdc, oldpen );
				GDIdeleteObject( pen1 );
			}
			else
			{
				p[0].h = mBlockRect.left; p[0].v = mBlockRect.top;
				p[1].h = mBlockRect.right; p[1].v = mBlockRect.top;
				p[2].h = mBlockRect.right; p[2].v = mBlockRect.bottom-5;
				p[3].h = mBlockRect.left+5; p[3].v = mBlockRect.bottom;
				p[4].h = mBlockRect.left; p[4].v = mBlockRect.bottom-5;
				p[5].h = mBlockRect.left; p[5].v = mBlockRect.top;
				HBRUSH oldbrush = GDIselectObject( pHdc, GDIgetStockBrush( BLACK_BRUSH ) );
				GDIsetTextColor( pHdc, mBlockColor );
				GDIsetBkColor( pHdc, mBlockColor );
				GDIfillPoly( pHdc, &p[0], 6 );
				GDIselectObject( pHdc, oldbrush );

				HPEN pen2 = GDIgetStockPen( GDI_STOCK_PEN_WINDOW ); // rmm11295
				HPEN oldpen = GDIselectObject( pHdc, pen2 );
				GDImoveTo( pHdc, p[3].h, p[3].v );  GDIlineTo( pHdc, p[4].h, p[4].v ); 
				GDIlineTo( pHdc, p[0].h, p[0].v );  GDIlineTo( pHdc, p[1].h, p[1].v );
				qpen pen = qpen( 1, mBlockColor==GDI_COLOR_3DFACE ? GDI_COLOR_3DSHADOW : GDIgetDarkerShade(mBlockColor) );
				HPEN pen1 = GDIcreatePen(&pen); 	GDIselectObject( pHdc, pen1 );
				GDIlineTo( pHdc, p[2].h, p[2].v ); GDIlineTo( pHdc, p[3].h, p[3].v );
				GDIselectObject( pHdc, oldpen );
				GDIdeleteObject( pen1 );
			}
		}
	} 
}

// rmm6659:
void tqfSlider::doErase(HDC pHdc, qrect &pRect)
{
	qbool done = qfalse;
	#ifndef isWEB
		if (WNDgetWindowLong(mHWnd, GWL_BKTHEME) == WND_BK_PARENT)
			done = (qbool) (WNDsendMessage(mHWnd, WM_CONTROL, DRAW_THEMETABPANE, (LPARAM)pHdc) != 0);
	#endif
	if (!done) 
	{
		if (!WNDdrawThemeBackground(mHWnd,pHdc,&pRect,WND_BK_DEFAULT))
		{
			GDIsetTextColor( pHdc, mFaceColor );
			GDIfillRect( pHdc, &pRect, GDIgetStockBrush( BLACK_BRUSH ) );
		}
	}			
}

qbool tqfSlider::paint()
{	
	WNDpaintStruct paintStruct;
	WNDbeginPaint( mHWnd, &paintStruct );
	
	qrect r; WNDgetClientRect( mHWnd, &r );
	HBITMAP hbmp = GDIcreateBitmap( r.width(), r.height(), 0 );
	HDC hdc = GDIgetTempDC();
	HBITMAP old = GDIselectBitmap( hdc, hbmp );

	doErase(hdc, r); // rmm6659
	setSlideArea();
	drawSlide( hdc );
	if ( mShowMarks ) drawMarks( hdc );
	drawSlider( hdc ); 
	
	GDIcopyBits( hdc, paintStruct.hdc, &r, &r, qfalse );
	GDIselectBitmap( hdc, old );
	GDIdeleteBitmap( hbmp );

	// Start rmm4999
	if (ECOisShowNumber(mHWnd))
		ECOdrawNumberEx(mHWnd, paintStruct.hdc, qtrue);
	// End rmm4999
	ECOdrawMultiKnobs(mHWnd, paintStruct.hdc);	// rmm5006
	WNDendPaint( mHWnd, &paintStruct );	
	return qtrue;
}


void tqfSlider::trackMouse( LPARAM Msg, WPARAM wParam, LPARAM lParam )
{
	qpoint pt;      
	qbool canSendMessage = ECOisOMNISinTrueRuntime( mHWnd );
	if ( Msg==WM_MOUSEMOVE || Msg==WM_LBUTTONDOWN )
	{
		// Start rmm5117
		if (WM_LBUTTONDOWN == Msg)
		{
			mSetLastNewPosVal = qfalse;
		}
		// End rmm5117
		// rmm5117: The following block is unnecessary, since we have the mouse capture.
		// rmm5117: It was preventing evEndSlider if the mouse was released quickly

		// rmm5117: if ( Msg==WM_MOUSEMOVE && !WNDmouseLeftButtonDown() )
		// rmm5117: {
		// rmm5117: 	WNDreleaseCapture( WND_CAPTURE_MOUSE );
		// rmm5117: 	return;
		// rmm5117: }

		WNDmakePoint( lParam, &pt );
		qshort newPos = getValueFromPt( &pt );
		// pkvista13
		if ( Msg==WM_LBUTTONDOWN ) 
			mMouseDown = qtrue;

		if ( mIsVista && canSendMessage && Msg==WM_MOUSEMOVE && !mMouseDown )
		{
			qbool redrawNow = 0; qbool hotState = GDIptInRect( &mBlockRect, &pt );			
			if ( hotState!=mHot ) redrawNow = qtrue; 
			mHot = hotState;
			if (!mHot && WNDhasCapture( mHWnd, WND_CAPTURE_MOUSE ) ) 
				WNDreleaseCapture( WND_CAPTURE_MOUSE );
			else if ( mHot && !WNDhasCapture( mHWnd, WND_CAPTURE_MOUSE ) ) 
				WNDsetCapture( mHWnd, WND_CAPTURE_MOUSE );
			if ( redrawNow ) 
			{ 
				WNDinvalidateRect( mHWnd, NULL ); 
				WNDupdateWindow( mHWnd ); 
			}
			return;
		}

		if ( newPos!=mVal )
		{
			mVal = newPos;
			WNDinvalidateRect( mHWnd, NULL );
			WNDupdateWindow( mHWnd );
		}
		// pkvista13
		else if ( mIsVista && mMouseDown )
		{
			WNDinvalidateRect( mHWnd, NULL );
			WNDupdateWindow( mHWnd );
		}
		if ( canSendMessage )
		{
// MHWEB begins.
#ifndef isWEB
			if ( Msg==WM_LBUTTONDOWN ) 
				ECOsendEvent( mHWnd, cSliderEvStartSlider, 0, 0 );
	
			if (!mSetLastNewPosVal || mLastNewPosVal != mVal)	// rmm5117
			{
				EXTfldval newposparam; newposparam.setLong(mVal);
				ECOsendEvent( mHWnd, cSliderEvNewSliderPos, &newposparam, 1 );

				mSetLastNewPosVal = qtrue;		// rmm5117
				mLastNewPosVal = mVal;				// rmm5117
			}
#else
			EXTfldval newposparam; newposparam.setLong(mVal);
			// MHn0206 begins
			if ( Msg==WM_LBUTTONDOWN ) 
			{
				ECOsendEvent( mHWnd, cSliderEvStartSlider, &newposparam, 1 );
			}
			else
			{
				if (!mSetLastNewPosVal || mLastNewPosVal != mVal)	// rmm5117
				{
					ECOsendEvent( mHWnd, cSliderEvNewSliderPos, &newposparam, 1, qfalse ); // rmm5117: queue this event, otherwise it can be lost
					mSetLastNewPosVal = qtrue;		// rmm5117
					mLastNewPosVal = mVal;				// rmm5117
				}
			}
			// MHn0206 ends
#endif
// MHWEB ends.
		}
	}
  else
  {
		// pkvista13
		if ( mMouseDown)
		{
			mMouseDown = qfalse;	
			WNDinvalidateRect( mHWnd, NULL );
			WNDupdateWindow( mHWnd );
		}

// MHWEB begins.
#ifndef isWEB
  	WNDreleaseCapture( WND_CAPTURE_MOUSE );          
  	if ( canSendMessage ) ECOsendEvent( mHWnd, cSliderEvEndSlider, 0, 0 );
#else
		EXTfldval newposparam; newposparam.setLong(mVal);
  	WNDreleaseCapture( WND_CAPTURE_MOUSE );          
		// MHn0206 begins
  	if ( canSendMessage ) 
		{
			if (!mSetLastNewPosVal || mLastNewPosVal != mVal)	// rmm5117
			{
				ECOsendEvent( mHWnd, cSliderEvNewSliderPos, &newposparam, 1, qfalse ); // rmm5117: queue this event, otherwise it can be lost
			}
			ECOsendEvent( mHWnd, cSliderEvEndSlider, &newposparam, 1, qfalse ); // rmm5117: queue this event, otherwise it can be lost
		}
		// MHn0206 ends
#endif
// MHWEB ends.
  }
}

// jc0004 begins
qbool tqfSlider::isenabled()
{
	return qbool(0 != WNDsendMessage(mHWnd, WM_CONTROL, IS_FLD_EDITABLE, 0));
}
// jc0004 ends

// rmm6659:
void tqfSlider::getBackgroundTheme()
{
	qlong theme;
	EXTfldval fval;
	theme = WNDgetWindowLong(mHWnd, GWL_BKTHEME);
	ECOgetProperty(mHWnd, anumBackgroundTheme, fval);	
	if (theme != fval.getLong()) WNDsetWindowLong(mHWnd, GWL_BKTHEME, fval.getLong());
}

extern "C" LRESULT OMNISWNDPROC GenericWndProc( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, EXTCompInfo* eci )
{
   ECOsetupCallbacks(hwnd,eci);
	 switch (Msg)
	 {
			case WM_ERASEBKGND:
			{
				// no need to erase as paint paints all
				return 1L;
			}
			case WM_MOUSEMOVE:
			case WM_LBUTTONUP:
			{
				if ( !ECOisDesign( hwnd ) )
				{           
					// pkvista13
					tqfSlider* object = (tqfSlider*)ECOfindObject( eci, hwnd );   
					//if ( (object && !WNDhasCapture( hwnd, WND_CAPTURE_MOUSE ) && object->mIsVista ) || WNDhasCapture( hwnd, WND_CAPTURE_MOUSE ) )
					if ( (object && WNDhasCapture( hwnd, WND_CAPTURE_MOUSE ) && object->mIsVista ) || WNDhasCapture( hwnd, WND_CAPTURE_MOUSE ) )	// rjc0025
					{           
						object->trackMouse( Msg, wParam,lParam );
						return 1L;
					}
				}
				break;
			}
			case WM_LBUTTONDOWN:
			{
				if ( !ECOisDesign( hwnd ) )
				{
			 		tqfSlider* object = (tqfSlider*)ECOfindObject( eci, hwnd );   
					if (object->isenabled())	// jc0004
					{
						ECOhideTooltip( hwnd );
						object->trackMouse( Msg, wParam, lParam );
						WNDsetCapture( hwnd, WND_CAPTURE_MOUSE );
					}
					return 1L;
				}
				break;
			}
			case WM_PAINT:							
			{
				tqfSlider* object = (tqfSlider*)ECOfindObject( eci, hwnd );
				if ( object && object->paint() )
					return qtrue;
				break;
			}
	    case WM_FLD_FILLCHANGED:	// rmm6659
	    {
				tqfSlider* object = (tqfSlider*)ECOfindObject( eci, hwnd );
				if ( object )
				{
 					object->getBackgroundTheme();
 				}
				break;
	    }
			case ECM_OBJCONSTRUCT:				/* Construct an object */
			{
				tqfSlider* object = new tqfSlider( hwnd );
				ECOinsertObject( eci, hwnd, (void*)object );
				return qtrue;
			}
			case ECM_OBJDESTRUCT:					/* Destruct the object */
			{
				tqfSlider* object = (tqfSlider*)ECOremoveObject( eci, hwnd );
				if ( object ) delete object;              
				return qtrue;
			}
	    case ECM_OBJINITIALIZE:	// rmm6659
	    {
 				if ( wParam )
 				{
 					tqfSlider* object = (tqfSlider*)ECOfindObject( eci, hwnd );
 					if ( object )
 					{
						object->mInitialized = qtrue;	// rmm9385: Initial property setting has completed, so properties can now be validated if necessary when set
 						object->getBackgroundTheme();	
 					}
 				}
 				return qtrue;
		  }
			case ECM_PROPERTYCANASSIGN:  	/* Object: Is the property assignable (ie readonly?) */
			case ECM_SETPROPERTY: 				/* Object: Assignment to a property */
			case ECM_GETPROPERTY:					/* Object: Retrieve value from property */
			{
				tqfSlider* object = (tqfSlider*)ECOfindObject( eci, hwnd );
				if ( object )
					return object->attributeSupport( Msg, wParam, lParam, eci );
				return 0L;
			}
      case ECM_GETCOMPLIBINFO:
      {
      	return ECOreturnCompInfo( gInstLib, eci, LIB_RES_NAME, COMPONENT_COUNT );
      }
			case ECM_GETCOMPICON:
			{ 	
				if ( eci->mCompId==SLIDER_ID ) return ECOreturnIcon( gInstLib, eci, SLIDER_ICON );
				return qfalse;
			}
			case ECM_GETCOMPID:
			{
				if ( wParam==1 )
					return ECOreturnCompID( gInstLib, eci, SLIDER_ID, cObjType_Basic );
				return 0L;
			}
			case ECM_GETEVENTNAME:
			{
				return ECOreturnEvents(gInstLib,eci,&SLIDERevents[0],3);
			}
			case ECM_GETPROPNAME:
			{
				return ECOreturnProperties( gInstLib, eci, &SLIDERproperties[0], SLIDER_PROPERTY_COUNT );
			}
// MHWEB begins.
			case ECM_GETVERSION:	
			{
				return ECOreturnVersion(gInstLib);
			}                                                                 
#ifdef isRCCDESIGN
	 		case ECM_CONNECT:
      {
		    return EXT_FLAG_LOADED|EXT_FLAG_ALWAYS_USABLE|EXT_FLAG_REMAINLOADED; // Return external flags	// rmm_thindl
      } 			
#endif
// MHWEB ends.
			case ECM_ISUNICODE:	// rmmuni
			{
				return qtrue;
			}
	 }
	 return WNDdefWindowProc(hwnd,Msg,wParam,lParam,eci);
}
// End of file
