日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ChartCtrl源码剖析之——CChartAxis类

發布時間:2023/12/9 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ChartCtrl源码剖析之——CChartAxis类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CChartAxis類用來繪制波形控件的坐標軸,這個源碼相對較復雜,當初閱讀的時候耗費了不少精力來理解源碼中的一些實現細節。?

CChartAxis類的頭文件。

#if !defined(AFX_CHARTAXIS_H__063D695C_43CF_4A46_8AA0_C7E00268E0D3__INCLUDED_) #define AFX_CHARTAXIS_H__063D695C_43CF_4A46_8AA0_C7E00268E0D3__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "ChartObject.h" #include "ChartScrollBar.h" #include "ChartString.h" #include <afx.h> #include <list> class CChartGrid; class CChartSerie; class CChartAxisLabel;class CChartAxis : public CChartObject {friend CChartCtrl;friend CChartGrid;friend CChartSerie;friend CChartScrollBar; public:enum AxisType{atStandard = 0,atLogarithmic,atDateTime};void SetAxisType(AxisType Type);AxisType GetAxisType() const { return m_AxisType; }enum TimeInterval{tiSecond,tiMinute,tiHour,tiDay,tiMonth,tiYear};void SetDateTimeIncrement(bool bAuto, TimeInterval Interval, int Multiplier);void SetTickIncrement(bool bAuto, double Increment);double GetTickIncrement() const { return m_TickIncrement; }void SetDateTimeFormat(bool bAutomatic, const TChartString& strFormat);int GetPosition();void SetInverted(bool bNewValue);bool IsInverted() const { return m_bIsInverted; }void SetLogarithmic(bool bNewValue){if (bNewValue)m_AxisType = atLogarithmic;elsem_AxisType = atStandard;RefreshAutoAxis();}bool IsLogarithmic() const { return (m_AxisType == atLogarithmic); }void SetAutomatic(bool bNewValue); bool IsAutomatic() const { return m_bIsAutomatic; }void SetMinMax(double Minimum, double Maximum);void GetMinMax(double& Minimum, double& Maximum) const{Minimum = m_MinValue;Maximum = m_MaxValue;}long ValueToScreen(double Value) const;double ScreenToValue(long ScreenVal) const;void SetTextColor(COLORREF NewColor);COLORREF GetTextColor() const { return m_TextColor; }void SetFont(int nPointSize, const TChartString& strFaceName);CChartAxisLabel* GetLabel() const { return m_pAxisLabel; }CChartGrid* GetGrid() const { return m_pAxisGrid; }CChartAxis(CChartCtrl* pParent,bool bHoriz);virtual ~CChartAxis();void SetMarginSize(bool bAuto, int iNewSize);void SetPanZoomEnabled(bool bEnabled) { m_bZoomEnabled = bEnabled; }void SetZoomLimit(double dLimit) { m_dZoomLimit = dLimit; }void EnableScrollBar(bool bEnabled);bool ScrollBarEnabled() const {if (m_pScrollBar)return (m_pScrollBar->GetEnabled());elsereturn false;}void SetAutoHideScrollBar(bool bAutoHide);bool GetAutoHideScrollBar() const; private:void CalculateTickIncrement();void CalculateFirstTick();double GetNextTickValue(double Previous);CString GetTickLabel(double Tick);CSize GetLargestTick(CDC* pDC);void Recalculate();COleDateTime AddMonthToDate(const COleDateTime& Date, int iMonthsToAdd);void DrawLabel(CDC* pDC);void RefreshDTTickFormat();void PanAxis(long PanStart, long PanEnd);void SetZoomMinMax(double Minimum, double Maximum);void UndoZoom();void SetDecimals(int NewValue) { m_DecCount = NewValue; }bool IsHorizontal() const { return m_bIsHorizontal; }int GetAxisLenght() const;void SetSecondary(bool bNewVal) { m_bIsSecondary = bNewVal; }bool GetSecondary() const { return m_bIsSecondary; }bool RefreshAutoAxis();void GetSeriesMinMax(double& Minimum, double& Maximum);void SetAxisSize(CRect ControlRect,CRect MarginRect);int ClipMargin(CRect ControlRect,CRect& MarginRect,CDC* pDC); // Allows to calculate the margin required to displayys ticks and textvoid Draw(CDC* pDC);// To register/Unregister series related to this axisvoid RegisterSeries(CChartSerie* pSeries);void UnregisterSeries(CChartSerie* pSeries);void CreateScrollBar();void UpdateScrollBarPos();void RefreshScrollBar();AxisType m_AxisType; // Type of the axis (standard, log or date/time)bool m_bIsHorizontal; // Indicates if this is an horizontal or vertical axisbool m_bIsInverted; // Indicates if the axis is invertedbool m_bIsAutomatic; // Indicates if the axis is automaticbool m_bIsSecondary; // If the axis is secondary, it will be positioned to// the right (vertical) or to the top (horizontal)double m_MaxValue; // Maximum value on the axisdouble m_MinValue; double m_UnzoomMin; // Min and max values of the axis before it has been zoomeddouble m_UnzoomMax; // (used when we unzoom the chart -> go back to previous state)bool m_bAutoTicks; // Specify if the tick increment is manual or automaticdouble m_TickIncrement; // Indicates the space between ticks (in axis value) or for log axis the mult base between two ticksdouble m_FirstTickVal;unsigned int m_DecCount; // Number of decimals to displayint m_StartPos; // Start position of the axisint m_EndPos;int m_nFontSize; TChartString m_strFontName;CChartGrid* m_pAxisGrid;CChartAxisLabel* m_pAxisLabel;typedef std::list<CChartSerie*> SeriesList;SeriesList m_pRelatedSeries; // List containing pointers to series related to this axis// The user can specify the size of the margin, instead of// having it calculated automaticallybool m_bAutoMargin;int m_iMarginSize;COLORREF m_TextColor;// Data for the date/time axis type.TChartString m_strDTTickFormat; // Format of the date/time tick labelsbool m_bAutoTickFormat;TimeInterval m_BaseInterval;int m_iDTTickIntervalMult;bool m_bZoomEnabled;double m_dZoomLimit;CChartScrollBar* m_pScrollBar; }; #endif // !defined(AFX_CHARTAXIS_H__063D695C_43CF_4A46_8AA0_C7E00268E0D3__INCLUDED_)

CChartAxis類的源文件。

#include "stdafx.h" #include "ChartAxis.h" #include "ChartAxisLabel.h" #include "ChartGrid.h" #include "ChartCtrl.h" #include "Math.h" #include <sstream> using namespace std; #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif // // Construction/Destruction // CChartAxis::CChartAxis(CChartCtrl* pParent,bool bHoriz):CChartObject(pParent) {m_AxisType = atStandard;m_bIsHorizontal = bHoriz;m_bIsInverted = false;m_bIsAutomatic = false;m_bIsSecondary = false;m_MaxValue = m_UnzoomMax = 10;m_MinValue = m_UnzoomMin = 0;m_bAutoTicks = true;m_TickIncrement = 1;m_FirstTickVal = 0;m_DecCount = 0;m_StartPos = m_EndPos = 0;m_nFontSize = 80;m_strFontName = _T("Microsoft Sans Serif");m_pAxisGrid = new CChartGrid(pParent,bHoriz);m_pAxisLabel = new CChartAxisLabel(pParent,bHoriz);m_bAutoMargin = true;m_iMarginSize = 0;m_TextColor = m_ObjectColor;m_strDTTickFormat = _T("%d %b");m_bAutoTickFormat = true;m_BaseInterval = tiDay;m_iDTTickIntervalMult = 1;m_bZoomEnabled = true;m_dZoomLimit = 0.001;m_pScrollBar = NULL; } CChartAxis::~CChartAxis() {if (m_pAxisGrid){delete m_pAxisGrid;m_pAxisGrid = NULL;}if (m_pAxisLabel){delete m_pAxisLabel;m_pAxisLabel = NULL;}if (m_pScrollBar){delete m_pScrollBar;m_pScrollBar = NULL;} } void CChartAxis::SetAxisType(AxisType Type) {m_AxisType = Type;m_pParent->RefreshCtrl(); } int CChartAxis::ClipMargin(CRect ControlRect,CRect& MarginRect,CDC* pDC) {if (!m_bIsVisible)return 0;int Size = 0; CSize TickSize = GetLargestTick(pDC);CSize LabelSize = m_pAxisLabel->GetSize(pDC);if (m_bIsHorizontal){if (!m_bAutoMargin)Size = m_iMarginSize;else{Size += 4 + 2; //Space above and under the textSize += TickSize.cy;Size += LabelSize.cy;m_iMarginSize = Size;}if (!m_bIsSecondary){ControlRect.bottom -= Size;ControlRect.right -= TickSize.cx/2+3;if (ControlRect.bottom < MarginRect.bottom)MarginRect.bottom = ControlRect.bottom;if (ControlRect.right < MarginRect.right)MarginRect.right = ControlRect.right;}else{ControlRect.top += Size;ControlRect.right -= TickSize.cx/2+3;if (ControlRect.top > MarginRect.top)MarginRect.top = ControlRect.top;if (ControlRect.right < MarginRect.right)MarginRect.right = ControlRect.right;}}else{if (!m_bAutoMargin)Size = m_iMarginSize;else{Size += 7 + 1; //Space before and after the text + TickSize += TickSize.cx;Size += LabelSize.cx + 2;m_iMarginSize = Size;}if (!m_bIsSecondary){ControlRect.left += Size;ControlRect.top += TickSize.cy/2+3;if (ControlRect.top > MarginRect.top)MarginRect.top = ControlRect.top;if (ControlRect.left > MarginRect.left)MarginRect.left = ControlRect.left;}else{ControlRect.right -= Size;ControlRect.top += TickSize.cy/2+3;if (ControlRect.top > MarginRect.top)MarginRect.top = ControlRect.top;if (ControlRect.right < MarginRect.right)MarginRect.right = ControlRect.right;}}return Size; } int CChartAxis::GetPosition() {if (m_bIsHorizontal){if (m_bIsSecondary)return 0;elsereturn 100;}else{if (m_bIsSecondary)return 100;elsereturn 0;} } void CChartAxis::SetAutomatic(bool bNewValue) {m_bIsAutomatic = bNewValue;if (m_bIsAutomatic)m_MinValue = m_MaxValue = 0;if (RefreshAutoAxis())m_pParent->RefreshCtrl(); } void CChartAxis::SetTickIncrement(bool bAuto, double Increment) {if (m_AxisType == atDateTime)return;m_bAutoTicks = bAuto;if (!m_bAutoTicks)m_TickIncrement = Increment;elseCalculateTickIncrement();CalculateFirstTick();m_pParent->RefreshCtrl(); } void CChartAxis::SetDateTimeIncrement(bool bAuto, TimeInterval Interval, int Multiplier) {if (m_AxisType != atDateTime)return;m_bAutoTicks = bAuto;if (!m_bAutoTicks){m_BaseInterval = Interval;m_iDTTickIntervalMult = Multiplier;} } void CChartAxis::SetDateTimeFormat(bool bAutomatic, const TChartString& strFormat) {m_bAutoTickFormat = bAutomatic;m_strDTTickFormat = strFormat;m_pParent->RefreshCtrl(); } void CChartAxis::SetAxisSize(CRect ControlRect,CRect MarginRect) {if (m_bIsHorizontal){m_StartPos = MarginRect.left; m_EndPos = MarginRect.right;if (!m_bIsSecondary){CRect AxisSize = ControlRect;AxisSize.top = MarginRect.bottom;SetRect(AxisSize); }else{CRect AxisSize = ControlRect;AxisSize.bottom = MarginRect.top;SetRect(AxisSize); }}else{m_StartPos = MarginRect.bottom;m_EndPos = MarginRect.top;if (!m_bIsSecondary){CRect AxisSize = ControlRect;AxisSize.right = MarginRect.left;SetRect(AxisSize);}else{CRect AxisSize = ControlRect;AxisSize.left = MarginRect.right;SetRect(AxisSize);}} } void CChartAxis::Recalculate() {CalculateTickIncrement();CalculateFirstTick(); } void CChartAxis::Draw(CDC *pDC) {if (!m_bIsVisible)return;if (pDC->GetSafeHdc() == NULL)return;CPen SolidPen(PS_SOLID,0,m_ObjectColor);CPen* pOldPen;CFont NewFont;CFont* pOldFont;COLORREF OldTextColor;NewFont.CreatePointFont(m_nFontSize,m_strFontName.c_str(),pDC) ;pOldPen = pDC->SelectObject(&SolidPen);pOldFont = pDC->SelectObject(&NewFont);OldTextColor = pDC->SetTextColor(m_TextColor);int iPrevMode = pDC->SetBkMode(TRANSPARENT);CSize LabelSize = m_pAxisLabel->GetSize(pDC);// Draw the axis lineint Pos = 0;if (m_bIsHorizontal){if (!m_bIsSecondary)Pos = m_ObjectRect.top+1;elsePos = m_ObjectRect.bottom-1;pDC->MoveTo(m_StartPos,Pos);pDC->LineTo(m_EndPos,Pos);}else{if (!m_bIsSecondary)Pos = m_ObjectRect.right-1;elsePos = m_ObjectRect.left+1;pDC->MoveTo(Pos,m_StartPos);pDC->LineTo(Pos,m_EndPos);}// Draw the label DrawLabel(pDC);m_pAxisGrid->ClearTicks();//char szBuffer[255]; CString strBuffer;int TickPos = 0;double TickValue = m_FirstTickVal;do{strBuffer = GetTickLabel(TickValue);CSize TextSize = pDC->GetTextExtent(strBuffer);TickPos = ValueToScreen(TickValue);if (m_bIsHorizontal){if (!m_bIsSecondary){pDC->MoveTo(TickPos,m_ObjectRect.top+1);pDC->LineTo(TickPos,m_ObjectRect.top+4);pDC->ExtTextOut(TickPos-TextSize.cx/2,m_ObjectRect.top+5,ETO_CLIPPED|ETO_OPAQUE,NULL,strBuffer,NULL);}else{pDC->MoveTo(TickPos,m_ObjectRect.bottom-1);pDC->LineTo(TickPos,m_ObjectRect.bottom-4);pDC->ExtTextOut(TickPos-TextSize.cx/2,m_ObjectRect.bottom-5-TextSize.cy,ETO_CLIPPED|ETO_OPAQUE,NULL,strBuffer,NULL);}}else{if (!m_bIsSecondary){pDC->MoveTo(m_ObjectRect.right-1,TickPos);pDC->LineTo(m_ObjectRect.right-4,TickPos);pDC->ExtTextOut(m_ObjectRect.left+LabelSize.cx+4,TickPos-TextSize.cy/2,ETO_CLIPPED|ETO_OPAQUE,NULL,strBuffer,NULL);}else{pDC->MoveTo(m_ObjectRect.left+1,TickPos);pDC->LineTo(m_ObjectRect.left+4,TickPos);pDC->ExtTextOut(m_ObjectRect.left+6,TickPos-TextSize.cy/2,ETO_CLIPPED|ETO_OPAQUE,NULL,strBuffer,NULL);}}m_pAxisGrid->AddTick(TickPos);TickValue = GetNextTickValue(TickValue);} while ((TickValue < m_MaxValue+0.0000001) && (m_TickIncrement || m_iDTTickIntervalMult) );CRect Size = m_pParent->GetPlottingRect();m_pAxisGrid->SetRect(Size);m_pAxisGrid->Draw(pDC);pDC->SelectObject(pOldPen);DeleteObject(SolidPen);pDC->SelectObject(pOldFont);DeleteObject(NewFont);pDC->SetTextColor(OldTextColor);pDC->SetBkMode(iPrevMode); } void CChartAxis::DrawLabel(CDC* pDC) {// Draw the axis label.CSize LabelSize = m_pAxisLabel->GetSize(pDC);int HalfAxisPos = (int)fabs((m_EndPos + m_StartPos)/2.0);int XPos = 0;int YPos = 0;if (m_bIsHorizontal){if (!m_bIsSecondary){CString Buffer;Buffer.Format(_T("%.*f"),m_DecCount,m_MaxValue);CSize TextSize = pDC->GetTextExtent(Buffer);YPos = m_ObjectRect.top + TextSize.cy + 2;XPos = HalfAxisPos - LabelSize.cx/2;}else{YPos = m_ObjectRect.top + 0;XPos = HalfAxisPos - LabelSize.cx/2;}}else{if (!m_bIsSecondary){YPos = HalfAxisPos + LabelSize.cy/2;XPos = m_ObjectRect.left + 0;}else{YPos = HalfAxisPos + LabelSize.cy/2;XPos = m_ObjectRect.right - LabelSize.cx - 2;}}m_pAxisLabel->SetPosition(XPos,YPos,pDC);m_pAxisLabel->Draw(pDC); } void CChartAxis::SetMinMax(double Minimum, double Maximum) {if (Minimum > Maximum){TRACE("Maximum axis value must be > minimum axis value");return;}m_MinValue = m_UnzoomMin = Minimum;m_MaxValue = m_UnzoomMax = Maximum;RefreshScrollBar();m_pParent->RefreshCtrl(); } void CChartAxis::SetInverted(bool bNewValue) {m_bIsInverted = bNewValue;RefreshScrollBar();m_pParent->RefreshCtrl(); } int CChartAxis::GetAxisLenght() const {int Length = (int)fabs( (m_EndPos-m_StartPos) * 1.0);return Length; } long CChartAxis::ValueToScreen(double Value) const {long Offset = 0;if (m_MaxValue==m_MinValue){Offset = (int)fabs((m_EndPos-m_StartPos)/2.0);if (m_bIsHorizontal)return m_StartPos + Offset;elsereturn m_StartPos - Offset;}if (m_AxisType != atLogarithmic)Offset = (int)floor( (Value - m_MinValue) * GetAxisLenght()/(m_MaxValue-m_MinValue) );elseOffset = (int)floor((log10(Value)-log10(m_MinValue)) * GetAxisLenght()/(log10(m_MaxValue)-log10(m_MinValue)) );if (m_bIsHorizontal){if (!m_bIsInverted)return (m_StartPos + Offset);elsereturn (m_EndPos - Offset);}else{if (!m_bIsInverted)return (m_StartPos - Offset);elsereturn (m_EndPos + Offset);} } double CChartAxis::ScreenToValue(long ScreenVal) const {if (m_MaxValue==m_MinValue)return 0;int AxisOffset = 0;if (!m_bIsHorizontal){if (m_bIsInverted)AxisOffset = ScreenVal - m_EndPos; elseAxisOffset = m_StartPos - ScreenVal;}else{if (!m_bIsInverted)AxisOffset = ScreenVal - m_StartPos;elseAxisOffset = m_EndPos - ScreenVal;}if (m_AxisType != atLogarithmic)return ( (AxisOffset * 1.0 / GetAxisLenght()*(m_MaxValue-m_MinValue)) + m_MinValue);elsereturn (pow(10.0,(AxisOffset *1.0 / GetAxisLenght()*(log10(m_MaxValue)-log10(m_MinValue)) ) + log10(m_MinValue)) ); }void CChartAxis::SetTextColor(COLORREF NewColor) {m_TextColor = NewColor;m_pParent->RefreshCtrl(); } void CChartAxis::SetFont(int nPointSize, const TChartString& strFaceName) {m_nFontSize = nPointSize;m_strFontName = strFaceName;m_pParent->RefreshCtrl(); } void CChartAxis::SetMarginSize(bool bAuto, int iNewSize) {m_bAutoMargin = bAuto;m_iMarginSize = iNewSize;m_pParent->RefreshCtrl(); } void CChartAxis::PanAxis(long PanStart, long PanEnd) {double StartVal = ScreenToValue(PanStart);double EndVal = ScreenToValue(PanEnd);if (m_AxisType != atLogarithmic){double Shift = StartVal - EndVal;SetZoomMinMax(m_MinValue+Shift,m_MaxValue+Shift);}else{double Factor = StartVal/EndVal;SetZoomMinMax(m_MinValue*Factor,m_MaxValue*Factor);} } void CChartAxis::SetZoomMinMax(double Minimum, double Maximum) {if (!m_bZoomEnabled)return;if (Minimum > Maximum){TRACE("Maximum axis value must be > minimum axis value");return;}m_MinValue = Minimum;if ( (Maximum - Minimum) < m_dZoomLimit && m_AxisType!=atLogarithmic)m_MaxValue = m_MinValue + m_dZoomLimit;elsem_MaxValue = Maximum;RefreshScrollBar(); } void CChartAxis::UndoZoom() {SetMinMax(m_UnzoomMin,m_UnzoomMax); } void CChartAxis::RegisterSeries(CChartSerie* pSeries) {// First check if the series is already present in the listSeriesList::iterator iter = m_pRelatedSeries.begin();for (iter; iter!=m_pRelatedSeries.end(); iter++){if ( (*iter) == pSeries)return;}m_pRelatedSeries.push_back(pSeries); } void CChartAxis::UnregisterSeries(CChartSerie* pSeries) {SeriesList::iterator iter = m_pRelatedSeries.begin();for (iter; iter!=m_pRelatedSeries.end(); iter++){if ( (*iter) == pSeries){m_pRelatedSeries.erase(iter);return;}} } COleDateTime CChartAxis::AddMonthToDate(const COleDateTime& Date, int iMonthsToAdd) {COleDateTime newDate;int nMonths = Date.GetMonth()-1 + iMonthsToAdd;int nYear = Date.GetYear() + nMonths/12;newDate.SetDateTime(nYear,nMonths%12+1,Date.GetDay(),Date.GetHour(),Date.GetMinute(),Date.GetSecond());return newDate; } bool CChartAxis::RefreshAutoAxis() {RefreshScrollBar();bool bNeedRefresh = false;if (!m_bIsAutomatic)return bNeedRefresh;double SeriesMin = 0;double SeriesMax = 0;GetSeriesMinMax(SeriesMin, SeriesMax);if ( (SeriesMax!=m_MaxValue) || (SeriesMin!=m_MinValue) )SetMinMax(SeriesMin,SeriesMax);return bNeedRefresh; } void CChartAxis::GetSeriesMinMax(double& Minimum, double& Maximum) {Minimum = 0;Maximum = 0;double TempMin = 0;double TempMax = 0;SeriesList::iterator iter = m_pRelatedSeries.begin();if (iter != m_pRelatedSeries.end()){if (m_bIsHorizontal)(*iter)->GetSerieXMinMax(Minimum,Maximum);else(*iter)->GetSerieYMinMax(Minimum,Maximum);}for (iter; iter!=m_pRelatedSeries.end(); iter++){if (m_bIsHorizontal)(*iter)->GetSerieXMinMax(TempMin,TempMax);else(*iter)->GetSerieYMinMax(TempMin,TempMax);if (TempMin < Minimum)Minimum = TempMin;if (TempMax > Maximum)Maximum = TempMax;} } void CChartAxis::CalculateTickIncrement() {if (!m_bAutoTicks)return;if (m_MaxValue == m_MinValue){m_iDTTickIntervalMult = 0;m_TickIncrement = 0;return;}int PixelSpace;if (m_bIsHorizontal){if (m_AxisType == atDateTime)PixelSpace = 60;elsePixelSpace = 30;}elsePixelSpace = 20;int MaxTickNumber = (int)fabs((m_EndPos-m_StartPos)/PixelSpace * 1.0);//Calculate the appropriate TickSpace (1 tick every 30 pixel +/-)switch (m_AxisType){case atLogarithmic:m_TickIncrement = 10;break;case atStandard:{//Temporary tick incrementdouble TickIncrement = (m_MaxValue-m_MinValue)/MaxTickNumber;// Calculate appropriate tickSpace (not rounded on 'strange values' but// on something like 1, 2 or 5*10^X where X is optimalized for showing the most// significant digits)int Zeros = (int)floor(log10(TickIncrement));double MinTickIncrement = pow(10.0,Zeros);int Digits = 0;if (Zeros<0) {//We must set decimal places. In the other cases, Digits will be 0.Digits = (int)fabs(Zeros*1.0);}if (MinTickIncrement>=TickIncrement){m_TickIncrement = MinTickIncrement;SetDecimals(Digits);}else if (MinTickIncrement*2>=TickIncrement){m_TickIncrement = MinTickIncrement*2;SetDecimals(Digits);}else if (MinTickIncrement*5>=TickIncrement){m_TickIncrement = MinTickIncrement*5;SetDecimals(Digits);}else if (MinTickIncrement*10>=TickIncrement){m_TickIncrement = MinTickIncrement*10;if (Digits)SetDecimals(Digits-1);elseSetDecimals(Digits);}}break;case atDateTime:{COleDateTime StartDate(m_MinValue);COleDateTime EndDate(m_MaxValue);COleDateTimeSpan minTickInterval = (EndDate - StartDate)/MaxTickNumber;double Seconds = minTickInterval.GetTotalSeconds();double Minutes = minTickInterval.GetTotalMinutes();double Hours = minTickInterval.GetTotalHours();double Days = minTickInterval.GetTotalDays();if (Seconds < 60){m_BaseInterval = tiSecond;if (Seconds > 30){m_BaseInterval = tiMinute;m_iDTTickIntervalMult = 1;}else if (Seconds > 10)m_iDTTickIntervalMult = 30;else if (Seconds > 5)m_iDTTickIntervalMult = 10;else if (Seconds > 2)m_iDTTickIntervalMult = 5;elsem_iDTTickIntervalMult = 1;}else if (Minutes < 60){m_BaseInterval = tiMinute;if (Minutes > 30){m_BaseInterval = tiHour;m_iDTTickIntervalMult = 1;}else if (Minutes > 10)m_iDTTickIntervalMult = 30;else if (Minutes > 5)m_iDTTickIntervalMult = 10;else if (Minutes > 2)m_iDTTickIntervalMult = 5;elsem_iDTTickIntervalMult = 2;}else if (Hours < 24){m_BaseInterval = tiHour;if (Hours > 12){m_BaseInterval = tiDay;m_iDTTickIntervalMult = 1;}else if (Hours > 6)m_iDTTickIntervalMult = 12;else if (Hours > 2)m_iDTTickIntervalMult = 6;elsem_iDTTickIntervalMult = 2;}else if (Days < 31){m_BaseInterval = tiDay;if (Days > 7){m_BaseInterval = tiMonth;m_iDTTickIntervalMult = 1;}else if (Days > 2){m_BaseInterval = tiDay;m_iDTTickIntervalMult = 7;}elsem_iDTTickIntervalMult = 2;}else if (Days < 365){m_BaseInterval = tiMonth;if (Days > 186) // Approx 6 months {m_BaseInterval = tiYear;m_iDTTickIntervalMult = 1;}else if (Days > 124)m_iDTTickIntervalMult = 6;else if (Days > 62)m_iDTTickIntervalMult = 4;elsem_iDTTickIntervalMult = 2;}else{m_BaseInterval = tiYear;m_iDTTickIntervalMult = (int)Days/365 + 1;}if (m_bAutoTickFormat)RefreshDTTickFormat();}break;} } void CChartAxis::CalculateFirstTick() {switch (m_AxisType){case atStandard:{m_FirstTickVal = 0;if (m_TickIncrement!=0){if (m_MinValue == 0)m_FirstTickVal = 0;else if (m_MinValue>0){m_FirstTickVal = (int)(m_MinValue/m_TickIncrement) * m_TickIncrement;while (m_FirstTickVal<m_MinValue)m_FirstTickVal += m_TickIncrement;}else{m_FirstTickVal = (int)(m_MinValue/m_TickIncrement) * m_TickIncrement;while (m_FirstTickVal>m_MinValue)m_FirstTickVal -= m_TickIncrement;if (!(m_FirstTickVal == m_MinValue))m_FirstTickVal += m_TickIncrement;}}else // m_TickIncrement!=0 {m_FirstTickVal = m_MinValue;}}break;case atLogarithmic:{int LogBase = (int)log10(m_MinValue);m_FirstTickVal = pow(10.0,LogBase);}break;case atDateTime:{COleDateTime dtMin((DATE)m_MinValue);COleDateTime dtFirstTick(dtMin);switch (m_BaseInterval){case tiSecond:dtFirstTick.SetDateTime(dtMin.GetYear(),dtMin.GetMonth(),dtMin.GetDay(),dtMin.GetHour(),dtMin.GetMinute(),dtMin.GetSecond()+1);break;case tiMinute:dtFirstTick.SetDateTime(dtMin.GetYear(),dtMin.GetMonth(),dtMin.GetDay(),dtMin.GetHour(),dtMin.GetMinute(),0);if (dtMin.GetSecond() != 0)dtFirstTick += COleDateTimeSpan(0,0,1,0); break;case tiHour:dtFirstTick.SetDateTime(dtMin.GetYear(),dtMin.GetMonth(),dtMin.GetDay(),dtMin.GetHour(),0,0);if ( (dtMin.GetMinute()!=0) || (dtMin.GetSecond()!=0) )dtFirstTick += COleDateTimeSpan(0,1,0,0); break;case tiDay:dtFirstTick.SetDate(dtMin.GetYear(),dtMin.GetMonth(),dtMin.GetDay());if ( (dtMin.GetHour()!=0) || (dtMin.GetMinute()!=0) ||(dtMin.GetSecond()!=0) ){dtFirstTick += COleDateTimeSpan(1,0,0,0);}break;case tiMonth:{dtFirstTick.SetDate(dtMin.GetYear(),dtMin.GetMonth(),1);if ((dtMin.GetDay()!=1) || (dtMin.GetHour()!=0) ||(dtMin.GetMinute()!=0) || (dtMin.GetSecond()!=0) ){dtFirstTick = AddMonthToDate(dtFirstTick,1);}}break;case tiYear:break;}m_FirstTickVal = (DATE)dtFirstTick;}break;} } double CChartAxis::GetNextTickValue(double Previous) {double NewTick = 0;switch (m_AxisType){case atStandard:NewTick = Previous + m_TickIncrement;break;case atLogarithmic:NewTick = Previous * m_TickIncrement;break;case atDateTime:{COleDateTime dtTick((DATE)Previous);COleDateTimeSpan dtSpan;switch (m_BaseInterval){case tiSecond:dtSpan.SetDateTimeSpan(0,0,0,m_iDTTickIntervalMult);dtTick += dtSpan;break;case tiMinute:dtSpan.SetDateTimeSpan(0,0,m_iDTTickIntervalMult,0);dtTick += dtSpan;break;case tiHour:dtSpan.SetDateTimeSpan(0,m_iDTTickIntervalMult,0,0);dtTick += dtSpan;break;case tiDay:dtSpan.SetDateTimeSpan(m_iDTTickIntervalMult,0,0,0);dtTick += dtSpan;break;case tiMonth:{dtTick = AddMonthToDate(dtTick,m_iDTTickIntervalMult);}break;case tiYear:break;}NewTick = (DATE)dtTick;}break;}return NewTick; } CString CChartAxis::GetTickLabel(double TickValue) {CString strLabel;switch (m_AxisType){case atStandard:strLabel.Format(_T("%.*f"),m_DecCount,TickValue);// ssLabel << setprecision(m_DecCount) << TickValue;// sprintf(szBuffer,"%.*f",m_DecCount,TickValue);break;case atLogarithmic:{double fLogDecCount;int nLogDecCount;fLogDecCount = log10(TickValue);if (fLogDecCount < 0.0)nLogDecCount = (int)(fabs(fLogDecCount) + 0.1);elsenLogDecCount = 0;strLabel.Format(_T("%.*f"), nLogDecCount, TickValue);}break;case atDateTime:{COleDateTime tickTime((DATE)TickValue);strLabel = tickTime.Format(m_strDTTickFormat.c_str());// ssLabel << tickTime.Format(m_strDTTickFormat.c_str());// strcpy(szBuffer,strLabel); }break;}return strLabel; } void CChartAxis::RefreshDTTickFormat() {switch (m_BaseInterval){case tiSecond:m_strDTTickFormat = _T("%H:%M:%S");break;case tiMinute:m_strDTTickFormat = _T("%H:%M");break;case tiHour:m_strDTTickFormat = _T("%H:00");break;case tiDay:m_strDTTickFormat = _T("%d %b");break;case tiMonth:m_strDTTickFormat = _T("%b %Y");break;case tiYear:m_strDTTickFormat = _T("%Y");break;} } CSize CChartAxis::GetLargestTick(CDC* pDC) {CSize TickSize;CFont* pOldFont;CFont NewFont;NewFont.CreatePointFont(m_nFontSize,m_strFontName.c_str(),pDC);pOldFont = pDC->SelectObject(&NewFont);CString strBuffer;strBuffer.Format(_T("%.*f"),m_DecCount,m_MaxValue);if (m_bIsHorizontal)TickSize = pDC->GetTextExtent(strBuffer);else{switch (m_AxisType){case atStandard:{int MaxChars = abs( (int)log10(fabs(m_MaxValue) )) + 1;int MinChars = abs( (int)log10(fabs(m_MinValue) )) + 1;if (m_MinValue<0)MinChars++;if (m_MaxValue<0)MaxChars++;if (MaxChars>MinChars)strBuffer.Format(_T("%.*f"),m_DecCount,m_MaxValue);elsestrBuffer.Format(_T("%.*f"),m_DecCount,m_MinValue);}break;case atLogarithmic:{CString strBuffMax;CString strBuffMin;int MaxDecCount = (int)log10(m_MaxValue);if (MaxDecCount < 0)MaxDecCount = -MaxDecCount;elseMaxDecCount = 0;strBuffMax.Format(_T("%.*f"),MaxDecCount,m_MaxValue);int MinDecCount = (int)log10(m_MinValue);if (MinDecCount < 0)MinDecCount = -MinDecCount;elseMinDecCount = 0;strBuffMin.Format(_T("%.*f"),MinDecCount,m_MinValue);if (strBuffMin.GetLength() > strBuffMax.GetLength() )strBuffer = strBuffMin;elsestrBuffer = strBuffMax;} break;case atDateTime:{double TickValue = m_FirstTickVal;CString strTemp;do{strTemp = GetTickLabel(TickValue);if (strTemp.GetLength() > strBuffer.GetLength() )strBuffer = strTemp;TickValue = GetNextTickValue(TickValue);} while ((TickValue < m_MaxValue+0.0000001) && (m_TickIncrement|| m_iDTTickIntervalMult) );}break;}TickSize = pDC->GetTextExtent(strBuffer);}pDC->SelectObject(pOldFont);DeleteObject(NewFont);return TickSize; } void CChartAxis::EnableScrollBar(bool bEnabled) {if (m_pScrollBar){m_pScrollBar->SetEnabled(bEnabled);if (bEnabled)m_pScrollBar->ShowWindow(SW_SHOW);elsem_pScrollBar->ShowWindow(SW_HIDE);} } void CChartAxis::SetAutoHideScrollBar(bool bAutoHide) {if (m_pScrollBar)m_pScrollBar->SetAutoHide(bAutoHide); } bool CChartAxis::GetAutoHideScrollBar() const {if (m_pScrollBar)return (m_pScrollBar->GetAutoHide());elsereturn false; } void CChartAxis::CreateScrollBar() {m_pScrollBar = new CChartScrollBar(this);m_pScrollBar->CreateScrollBar(m_pParent->GetPlottingRect()); } void CChartAxis::UpdateScrollBarPos() {CRect PlottingRect = m_pParent->GetPlottingRect();PlottingRect.top++; PlottingRect.left++;CRect Temp;m_pScrollBar->GetWindowRect(&Temp);if (m_bIsHorizontal && !m_bIsSecondary)PlottingRect.top = PlottingRect.bottom - Temp.Height();if (!m_bIsHorizontal && !m_bIsSecondary)PlottingRect.right = PlottingRect.left + Temp.Width();if (m_bIsHorizontal && m_bIsSecondary)PlottingRect.bottom = PlottingRect.top + Temp.Height();if (!m_bIsHorizontal && m_bIsSecondary)PlottingRect.left = PlottingRect.right - Temp.Width();m_pScrollBar->MoveWindow(&PlottingRect); } void CChartAxis::RefreshScrollBar() {if (m_pScrollBar)m_pScrollBar->Refresh(); }

這份源碼大概讀了有至少四遍,總算把這份源碼吃透。回過頭來看當初覺得不理解的地方,感覺一開始的心態不正確,沒下定決心把它搞定,只走馬觀花的讀肯定行不通。經過反復的閱讀,之前一些不理解的地方都慢慢的消化了。一開始不理解的函數有ClipMargin、CalculateTickIncrement、CalculateFirstTick、ValueToScreen、ScreenToValue函數看不懂,ClipMargin函數用來設置軸與控件邊緣的間距,CalculateTickIncremen函數用來計算標記間的增量,CalculateFirstTick函數用來計算第一個標記的值,ValueToScreen函數用來將值轉化為屏幕中的值,ScreenToValue函數用來將屏幕中的值轉化為具體的數值。在讀自繪控件相關的源碼時,一定要先建立所繪制模塊在屏幕中的具體位置這樣一個體系,這樣在讀源碼的時候才會有的放矢。

?

假如想給橫軸、縱軸加箭頭和單位,需要在CChartAxis::Draw函數里面進行。調整后代碼如下:

CString strXAxisBuffer("ms"), strYAxisBuffer("Y");// Draw the axis lineint Pos = 0;if (m_bIsHorizontal){if (!m_bIsSecondary)Pos = m_ObjectRect.top+1;elsePos = m_ObjectRect.bottom-1;pDC->MoveTo(m_StartPos,Pos);pDC->LineTo(m_EndPos + 25, Pos);pDC->MoveTo(m_EndPos + 15, Pos - 5);pDC->LineTo(m_EndPos + 25, Pos);pDC->LineTo(m_EndPos + 15, Pos + 5);pDC->ExtTextOut(m_EndPos + 15, m_ObjectRect.top + 5, ETO_CLIPPED|ETO_OPAQUE, NULL, strXAxisBuffer, NULL);}else{if (!m_bIsSecondary)Pos = m_ObjectRect.right-1;elsePos = m_ObjectRect.left+1;pDC->MoveTo(Pos,m_StartPos);pDC->LineTo(Pos, m_EndPos - 25);pDC->MoveTo(Pos - 5, m_EndPos - 15);pDC->LineTo(Pos, m_EndPos - 25);pDC->LineTo(Pos - 5, m_EndPos - 15);pDC->ExtTextOut(Pos + 15, m_EndPos - 20, ETO_CLIPPED|ETO_OPAQUE, NULL, strYAxisBuffer, NULL);}

在添加軸單位這塊還有另外一種做法,直接使用CChartAxisLabel::SetText函數也可以實現同樣的效果,但需要將CChartAxis::DrawLabel函數調整如下:??

void CChartAxis::DrawLabel(CDC* pDC) {CSize LabelSize = m_pAxisLabel->GetSize(pDC);int XPos = 0;int YPos = 0;if(m_bIsHorizontal){if(!m_bIsSecondary){YPos = m_AxisRect.top + 0;}else{YPos = m_AxisRect.bottom + 0;}if(!m_bIsInverted){XPos = m_AxisRect.right - LabelSize.cx/2 + 10;}else{XPos = m_AxisRect.left - 2 - LabelSize.cx/2;}}else{CSize TextSize = GetLargestTick(pDC);if(!m_bIsSecondary){XPos = m_AxisRect.right - 5 - LabelSize.cx;}else{XPos = m_AxisRect.left + 5;}YPos = m_AxisRect.top - 2 - LabelSize.cy/2 - 10;}m_pAxisLabel->SetPosition(XPos, YPos, pDC);m_pAxisLabel->Draw(pDC); }

?

轉載于:https://www.cnblogs.com/wolfmvp/p/7212093.html

總結

以上是生活随笔為你收集整理的ChartCtrl源码剖析之——CChartAxis类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

久久久片 | 瑞典xxxx性hd极品 | 日韩高清黄色 | 黄色毛片大全 | 国产精品美女久久久久久久久久久 | 国际精品久久久 | 国产区精品视频 | 国产日韩欧美在线播放 | 国产精品一区免费在线观看 | 日韩在线播放欧美字幕 | 免费h精品视频在线播放 | 免费亚洲一区二区 | 黄色.com| 久久少妇免费视频 | 91av在线免费观看 | 一区二区三区电影在线播 | 久9在线 | 在线观看黄网站 | 免费在线观看中文字幕 | 国产成人一级 | 97国产 | 国产成人精品在线观看 | 国产精品久久久久久久久久久久午 | 久久精品这里精品 | 中文一区在线 | 国产精品二区在线观看 | 在线看黄网站 | 色婷在线| 国产精品乱码久久久 | 国产福利av| 精品视频久久久久久 | 亚洲尺码电影av久久 | 精品国产一区二区三区久久久蜜臀 | 狠狠插天天干 | 男女拍拍免费视频 | 国产美女搞久久 | 成人av影视在线 | 69亚洲视频 | av片子在线观看 | 亚洲国产网站 | 午夜视频欧美 | 91av视频在线免费观看 | 最新国产精品视频 | 亚洲精品www久久久 www国产精品com | 欧美精品一级视频 | 中文字幕888 | 国产麻豆视频网站 | 搡bbbb搡bbb视频 | 99精品在线观看 | 91爱在线| 国产 日韩 欧美 在线 | 久久精品8 | 人人讲| 中文字幕在线有码 | 久久久精品免费看 | 中文字字幕在线 | 成人久久久精品国产乱码一区二区 | 91精品视频在线免费观看 | 欧美狠狠操 | 成人在线观看av | 毛片1000部免费看 | 亚洲激情在线播放 | 丁香激情婷婷 | 成人看片| 在线观看日韩国产 | 一区二区三区免费在线观看视频 | 国产精品免费麻豆入口 | a在线视频v视频 | 最新超碰 | 午夜视频在线观看网站 | 欧美a性 | 久久综合偷偷噜噜噜色 | 欧美一区二区在线刺激视频 | 日韩网站在线观看 | 国产裸体视频网站 | 91成人观看| 伊色综合久久之综合久久 | 91少妇精拍在线播放 | 99视频99| 亚洲免费永久精品国产 | 91精品国产欧美一区二区成人 | 草久久av | 国产999在线 | 国产精品原创视频 | 色小说av | 在线观看va | 96av视频| 丁香电影小说免费视频观看 | 日韩在线观看你懂得 | 人人爽人人爽人人片av | 在线看一区 | 久久精品久久精品久久39 | 中文在线免费一区三区 | 国内精品久久久久久久97牛牛 | 97天天综合网 | 日韩精品五月天 | 日日干天天插 | 毛片一区二区 | 日韩av一区二区在线播放 | 精品字幕在线 | 韩日三级av | 色综合久久久久久中文网 | 人人揉人人揉人人揉人人揉97 | 久草9视频 | 中日韩在线视频 | 午夜精品视频一区 | 五月婷婷激情 | 欧美日韩视频免费看 | 亚洲国产成人高清精品 | 婷婷色中文网 | 亚洲视频 一区 | 午夜精品久久久久久久久久久久久久 | 日韩黄色免费 | 9在线观看免费高清完整版在线观看明 | 97在线免费 | 国产视频在线看 | 国产大陆亚洲精品国产 | 91在线看黄 | 欧美日韩国产色综合一二三四 | 91视频久久| 一区二区三区在线播放 | 国产精品一区二区精品视频免费看 | 天天鲁一鲁摸一摸爽一爽 | 麻豆影视网站 | 狠狠干天天色 | 亚洲黄色免费在线看 | 五月婷网站| 久草在线视频资源 | 久久精品网站视频 | 黄色在线看网站 | 高清不卡免费视频 | 成人午夜电影在线 | 97超碰超碰 | 国产久视频 | 亚洲狠狠婷婷 | 五月天色丁香 | av黄色在线 | 黄色1级大片 | 久久久视屏| 午夜免费视频网站 | 国产精品麻豆视频 | 久久99精品久久久久婷婷 | 久久九九精品久久 | 久久少妇 | 日韩三级一区 | 成人av高清在线观看 | 久久99精品国产91久久来源 | 99热这里只有精品免费 | 黄污视频大全 | 国产黄色av网站 | 99精品免费久久久久久日本 | 久久在线视频在线 | 一区二区不卡视频在线观看 | 综合网中文字幕 | 激情小说网站亚洲综合网 | 999男人的天堂 | 亚洲精品女人 | 黄在线免费看 | 日韩动漫免费观看高清完整版在线观看 | 日韩资源在线播放 | av大全在线播放 | 在线亚洲日本 | 久久另类小说 | 色爱成人网 | 国产理论一区二区三区 | 狠狠撸电影 | 97在线超碰 | 欧美一级视频免费看 | 美女免费黄视频网站 | 天天爽天天爽天天爽 | 中文字幕观看视频 | 国产精品剧情在线亚洲 | 欧美日韩在线看 | 中文字幕一区二区三区四区久久 | 日韩欧美一区二区三区视频 | av在线网站免费观看 | 亚洲传媒在线 | 亚洲精品视频大全 | 亚洲天天摸日日摸天天欢 | 在线观看aaa| 欧美色噜噜噜 | 日韩在线国产精品 | 久久这里 | 亚洲精品系列 | 亚洲午夜精品在线观看 | 天天色天天操综合 | 成年人免费观看在线视频 | 99热国产在线 | 91在线九色 | 91人人爱| aaa毛片视频 | 丝袜+亚洲+另类+欧美+变态 | 国产91九色视频 | 午夜美女网站 | 97超碰总站 | 99看视频在线观看 | 五月天狠狠操 | 午夜av在线免费 | 国产精品久久久久久爽爽爽 | 精品亚洲免费视频 | 亚洲黄色精品 | 五月婷香蕉久色在线看 | 在线视频日韩一区 | 九九综合久久 | 成人亚洲综合 | 久久久精品国产一区二区 | 九九亚洲视频 | 91视频午夜| 狠狠色免费 | 国产成人精品久久二区二区 | 成人av观看 | 公开超碰在线 | 在线免费观看国产精品 | 国产 日韩 在线 亚洲 字幕 中文 | 贫乳av女优大全 | 久久99日韩 | 伊人色**天天综合婷婷 | 午夜精品一二区 | 激情久久综合网 | 欧美激情一区不卡 | 一区二区三区四区五区六区 | 在线成人免费电影 | 亚洲视频免费在线 | 欧美精品一区二区三区四区在线 | 97精品超碰一区二区三区 | 天天干天天做 | 欧美精品久久久久久久久久丰满 | 国产精品乱码一区二区视频 | www.久久爱.cn| 在线观看日韩免费视频 | 成人羞羞视频在线观看免费 | 久久精品一二三区 | 久久久久免费精品视频 | 国产一级特黄电影 | 国产亚洲高清视频 | avlulu久久精品 | 美女视频黄频大全免费 | 国产成人一区二区三区在线观看 | 少妇精品久久久一区二区免费 | 青青草国产免费 | 成av在线 | 综合久久2023 | 欧美孕交vivoestv另类 | 四虎影视国产精品免费久久 | 国产婷婷vvvv激情久 | 99re亚洲国产精品 | 国产一级片观看 | 天天色官网 | 九九亚洲精品 | 黄色视屏免费在线观看 | 美女网站色免费 | 国产精品久久久久久久毛片 | 国产精品网站一区二区三区 | 日韩毛片在线免费观看 | 国产日本在线 | 欧美久草网| 91精品国产乱码 | 精品一区二区在线看 | 91精品人成在线观看 | 日韩精品一区二区三区第95 | 人人干在线 | 91免费高清观看 | www免费在线观看 | 美女精品| 日韩精品一区二区三区高清免费 | 在线不卡a | 深爱激情综合网 | 中文字幕av全部资源www中文字幕在线观看 | 狠狠色狠狠色综合日日92 | 97色国产 | 国产69精品久久app免费版 | www最近高清中文国语在线观看 | 精品99久久久久久 | 免费看的黄色 | 天天操天天操天天操天天操天天操天天操 | 69热国产视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 天天色天天干天天 | 嫩草91影院 | 天天摸天天弄 | 亚洲精品综合在线 | 亚洲最新在线视频 | 99热精品视 | 亚洲乱码精品久久久 | 免费av网址在线观看 | 欧美国产91| 97超碰色偷偷 | 成年人电影免费看 | 99久久日韩精品视频免费在线观看 | 精品在线你懂的 | 91精品久久久久久 | 天天综合视频在线观看 | 久热色超碰 | 在线国产日本 | 国产精品免费不卡 | 久久免费视频一区 | 久久免费看毛片 | 婷婷日韩 | 欧美在线aa | 三级黄色免费片 | 国产福利一区在线观看 | 黄色软件视频大全免费下载 | 天天天天色射综合 | 91成人看片| 在线黄色观看 | 91黄色视屏| av大全在线观看 | 国产视频 亚洲视频 | 天天综合五月天 | 特级西西www44高清大胆图片 | 久草在线资源观看 | 精品福利国产 | 精品不卡av | 午夜影院一级片 | 久久久久日本精品一区二区三区 | 在线日韩一区 | 综合久久五月天 | 婷婷色在线资源 | 国产一级视频在线 | 美女国内精品自产拍在线播放 | 日韩一二三在线 | 夜夜躁日日躁 | 99精品国产福利在线观看免费 | 国产精品福利在线 | 亚洲一区二区三区91 | 欧美日韩在线视频一区二区 | 精品国产精品一区二区夜夜嗨 | 免费在线色 | 欧美精品被| 亚洲综合欧美激情 | 色综合久久综合网 | 伊人黄 | 国产精品久久久久久久久软件 | 天天玩天天操天天射 | www.狠狠干 | 久久人人爽 | 精品一区二区电影 | www日韩在线观看 | 国产视频精品免费播放 | 亚洲精品一区二区三区新线路 | 亚洲砖区区免费 | 久久久免费| 日本中文字幕在线电影 | 丁香六月在线观看 | 国产 日韩 欧美 自拍 | 欧美成人中文字幕 | av国产网站 | 婷婷av资源| 丁香婷婷激情五月 | 高清不卡毛片 | 我爱av激情网 | 婷婷国产一区二区三区 | 黄色在线免费观看网址 | 天天干天天色2020 | 国产在线观看你懂得 | 精品久久影院 | 日韩av片无码一区二区不卡电影 | 欧美精品三级在线观看 | 日韩在线视频免费观看 | 91看片在线 | 国产一级91 | 日韩在线观| 黄色毛片视频 | 日韩在线观看视频中文字幕 | 香蕉视频在线观看免费 | 成人av免费播放 | 精品影院一区二区久久久 | 韩国一区二区三区在线观看 | 午夜在线国产 | avove黑丝 | 国产精品普通话 | 97超级碰碰碰碰久久久久 | 视频在线亚洲 | 人人爱爱 | 9999国产精品 | 草久中文字幕 | 91在线视频免费观看 | 日韩精品大片 | 中文字幕亚洲精品日韩 | 在线久久 | 射射射av| 中文字幕一区二区三区四区 | 一区二区三区精品在线视频 | 黄色美女免费网站 | 玖玖爱国产在线 | 91日韩国产| 2019天天干天天色 | 国产欧美精品xxxx另类 | 天天草天天色 | 精品一区中文字幕 | 午夜电影久久久 | 69精品人人人人 | 国产涩涩在线观看 | 在线视频 区 | 久久久久久欧美二区电影网 | 九九视频这里只有精品 | 成人免费在线播放 | 日韩av成人在线 | 国产一级免费片 | 久久国产精品电影 | 国产精品视频在线观看 | 精品久久国产精品 | 美女免费网视频 | av一级片网站 | 色狠狠操 | 9免费视频 | 国产精品久久久久久久久久久久午夜片 | 欧美亚洲国产精品久久高清浪潮 | 99精品视频观看 | 久久黄色小说视频 | 91毛片视频| 999精品视频 | www视频在线播放 | 日日干干夜夜 | 欧美性色xo影院 | 日韩精品你懂的 | 婷婷激情综合五月天 | 欧美日韩91 | 成人av高清 | 96视频免费在线观看 | 天天综合天天综合 | 日韩欧美xxxx | 在线91观看| 国产精品一区二区精品视频免费看 | 中文字幕乱码电影 | 国产精品k频道 | 亚洲视频中文 | 成人在线观看免费视频 | 成人 亚洲 欧美 | 日本爱爱片 | 亚洲国产精品人久久电影 | 中文字幕一区二区三区久久蜜桃 | 国产精品a成v人在线播放 | 亚洲一区二区视频 | 国产中年夫妇高潮精品视频 | 国产麻豆精品免费视频 | 日韩中文在线电影 | 免费人成在线观看 | 亚洲国产三级 | 欧美性大胆 | 国产精品福利视频 | 免费观看视频黄 | 国内外成人在线视频 | 狠狠狠狠干 | 在线观看日本高清mv视频 | 亚洲精品乱码久久久久久蜜桃欧美 | 人人搞人人干 | 亚洲视频在线播放 | 精品国产一区二区三区久久久蜜月 | 91视频久久久久久 | 久久在线影院 | av在线在线| 国产最新视频在线观看 | 天天操天天色天天 | 91免费高清视频 | 国产精品久久久777 成人手机在线视频 | 91在线你懂的 | 一区二区三区在线免费观看 | 亚洲综合网 | 久久婷婷国产 | 青青久草在线视频 | 亚洲国产精品久久久 | 一本到视频在线观看 | 国产区精品区 | 国产在线传媒 | 天天操天天干天天 | 成人免费视频观看 | 在线观看中文 | 日韩在线视频二区 | 亚洲免费婷婷 | 三级av在线免费观看 | 久久国产精品久久精品国产演员表 | 日韩精品中文字幕一区二区 | 欧美在线free | 久久久999精品视频 国产美女免费观看 | 国产成人久久精品亚洲 | 久久免费高清 | 在线免费黄网站 | 综合久久2023 | 日韩精品一区二区久久 | 国产精品嫩草影院123 | 人人插人人干 | 高清久久久久久 | 91成人精品一区在线播放69 | 黄色小网站免费看 | 国外调教视频网站 | 69久久99精品久久久久婷婷 | 国产精品一区二区在线 | 色婷婷狠狠五月综合天色拍 | 欧美精品一区二区在线观看 | 91视频在线免费 | 精品一区二三区 | 精品国产自在精品国产精野外直播 | 美女网站视频免费都是黄 | 国内视频1区 | 亚洲专区在线播放 | 国产18精品乱码免费看 | 成人av片在线观看 | 97国产大学生情侣酒店的特点 | 久草在线免费看视频 | 一区二区三区四区五区在线视频 | 444av| 国产打女人屁股调教97 | 国外调教视频网站 | 日韩免费高清 | 成人av资源 | 久久福利精品 | 视频一区二区国产 | www五月天com | 久久久久9999亚洲精品 | 国产精品日韩欧美一区二区 | 日本久久不卡视频 | 午夜久久久影院 | 91av片| 视频在线国产 | 日韩欧美视频免费观看 | 国产区av在线 | 日本激情视频中文字幕 | 粉嫩av一区二区三区入口 | 中文字幕免费高清在线观看 | 国产永久免费高清在线观看视频 | 欧美日韩免费一区 | 亚洲三级黄色 | 久久资源在线 | 狠狠色丁婷婷日日 | 日韩精品久久久久久中文字幕8 | 国产福利免费在线观看 | 在线免费观看黄色av | www.国产高清| 午夜国产影院 | 色操插| 国产精品久久久影视 | 丁香色婷 | 国产免费中文字幕 | 91视频91色| av在线超碰 | 91在线播放视频 | 日韩av一区二区三区四区 | 欧美黑人性猛交 | 国内精品久久久久久久久久清纯 | 亚洲老妇xxxxxx | 91看片看淫黄大片 | 91最新在线| 亚洲在线精品视频 | 日本久久成人中文字幕电影 | 蜜桃视频成人在线观看 | 91精品国产自产91精品 | av三级av | 天天干天天操人体 | 99国产精品久久久久久久久久 | 日本性久久 | 久久婷婷精品视频 | 草久在线播放 | 最近中文字幕高清字幕在线视频 | 国产在线精品观看 | 中文字幕韩在线第一页 | 久久精品亚洲精品国产欧美 | 综合激情伊人 | 亚洲自拍自偷 | 久久亚洲影视 | 高清av在线免费观看 | 中文字幕在线播放日韩 | 午夜精品久久久 | 欧美一区二区伦理片 | 久久久18 | 国产视频1 | 免费视频资源 | 在线免费观看视频一区 | 伊人六月 | 黄色一区二区在线观看 | 精品一区二区日韩 | 青青河边草免费视频 | 99色免费 | 免费成人av| 碰超在线 | 免费观看成人 | 久久婷综合 | 2023年中文无字幕文字 | 亚洲精品tv久久久久久久久久 | 国产精品区免费视频 | 久久久久免费网站 | 深爱五月激情五月 | 欧美视屏一区二区 | 亚洲精品在线观看中文字幕 | 99久久精品国 | 久久久久9999亚洲精品 | 久久久久久免费毛片精品 | 国产精品久久9 | 狠狠的操| 国产精品区免费视频 | 92精品国产成人观看免费 | 久久99国产精品久久99 | 成人av网站在线观看 | 久久精久久精 | 9i看片成人免费看片 | 国产99一区视频免费 | 草在线视频 | 精品欧美一区二区三区久久久 | 久久人人射 | 欧美一二在线 | 最新日韩电影 | 成人免费一区二区三区在线观看 | 在线观看你懂的网站 | 成年人在线观看 | 青青河边草观看完整版高清 | 欧美精品久久久久久 | 一区二区高清在线 | 99久久99久久 | 在线 欧美 日韩 | 久久精品成人热国产成 | 亚洲精选视频在线 | 在线直播av | 久久久久久久久久久精 | 精品在线观看视频 | 日韩激情av在线 | 99免在线观看免费视频高清 | 天天看天天干天天操 | 午夜久久福利影院 | 久久久亚洲影院 | 久久精品人人做人人综合老师 | 99热这里只有精品在线观看 | 狠狠插狠狠操 | 最近更新好看的中文字幕 | 日日干精品 | 成人h在线观看 | 成在线播放 | 久草视频免费播放 | 欧美日韩免费网站 | 美女视频免费精品 | 免费视频成人 | 天天做日日做天天爽视频免费 | 亚洲天天在线 | 亚洲精品动漫成人3d无尽在线 | 91天堂素人约啪 | 黄色福利视频网站 | 色综合久久中文综合久久牛 | 97色在线视频 | 激情欧美网 | 99热精品在线 | 欧美一区免费观看 | 91精品国产三级a在线观看 | 91在线播放视频 | 久久人人精品 | 天天操天天操天天爽 | 99久免费精品视频在线观看 | 中文字幕你懂的 | 久久午夜羞羞影院 | 99综合电影在线视频 | 久久伊人八月婷婷综合激情 | 日韩一区二区三区在线看 | 久久久久久久久久久成人 | 超碰公开在线 | 国产经典三级 | 国产在线观看中文字幕 | 6080yy精品一区二区三区 | 日韩欧美综合精品 | 成人18视频 | 婷婷在线视频观看 | 欧美性色综合网站 | 激情偷乱人伦小说视频在线观看 | 日韩视频免费 | 日韩区欠美精品av视频 | 日韩影视在线 | 亚洲影院天堂 | 久久免费视频网站 | 亚洲精品视频中文字幕 | 亚洲一区二区视频 | 国产v视频| 国产对白av | 国产成人精品一二三区 | 999热视频| 九九热免费在线视频 | 国产精品午夜久久久久久99热 | av超碰免费在线 | jizz18欧美18 | 奇米网777 | www.亚洲激情.com | 夜夜操天天干 | 国产高清视频免费观看 | 欧美日韩亚洲在线 | 香蕉视频4aa| 欧美色婷婷 | 91精品毛片| 一级片免费视频 | 国产精品久久久久久久久久免费 | 99爱视频| 久久情爱 | 中文字幕在线视频第一页 | 玖玖视频免费在线 | 精品国内自产拍在线观看视频 | 成人在线超碰 | 在线观看中文av | 国产亚洲91 | 在线观看中文字幕 | 麻豆视频免费在线播放 | 免费看日韩 | 国产精品久久一区二区三区, | 又黄又爽又色无遮挡免费 | 天天艹天天干天天 | 二区三区在线视频 | 国产91亚洲 | 久久久综合 | 久久不射网站 | 日韩精品一区二区三区免费观看 | 国产成人久久精品77777综合 | 亚洲精品国产成人 | 久久国内精品视频 | 亚洲综合在线五月天 | 在线观看国产一区二区 | 99热最新地址 | 久久精品视频免费播放 | 免费在线观看日韩视频 | 国产免费观看久久黄 | 久热超碰 | 成人一级电影在线观看 | www视频在线播放 | 91九色蝌蚪国产 | 国产精品久久久久久久久久久久久久 | 国产精品国内免费一区二区三区 | 黄色影院在线免费观看 | 国产 日韩 欧美 自拍 | 91麻豆产精品久久久久久 | 免费三级骚 | 色欧美88888久久久久久影院 | 日韩欧美专区 | 91人人爽人人爽人人精88v | 黄色电影在线免费观看 | 国产精品2019 | 成人免费观看网站 | 久久久久成 | 最新午夜电影 | 亚洲综合五月 | 精品亚洲国产视频 | 日日爱999| 深夜男人影院 | 久日精品 | 九九热在线播放 | 欧美激情视频一区 | 亚洲国产精品99久久久久久久久 | 国产中文字幕在线视频 | 一区二区视频电影在线观看 | 色网站在线观看 | 久章草在线 | 爱爱av在线| 中文字幕在线观看免费观看 | 六月丁香激情综合色啪小说 | 亚洲综合网 | 亚洲少妇xxxx | 97视频一区 | 超薄丝袜一二三区 | 操操操av | 亚洲精品久久激情国产片 | 亚洲精品短视频 | 久久免费公开视频 | 2019中文字幕网站 | 日韩黄色软件 | 久久久精品 | 日韩免费在线观看视频 | 亚洲激情国产精品 | 国产精品美女视频网站 | 亚洲91av| 三级黄色欧美 | 国内免费久久久久久久久久久 | 色一级片 | 日韩在线理论 | 国产在线一卡 | 91精品国产综合久久婷婷香蕉 | 久久伊人精品一区二区三区 | 久久精品女人毛片国产 | 免费在线观看一级片 | 日韩精品在线看 | 色视频一区 | 国内精品久久久久久久久久久久 | 国产91av视频在线观看 | 亚洲国产片色 | 久久五月天综合 | av福利网址导航 | 国产精彩视频一区 | h视频在线看 | 国产亚洲资源 | 激情电影在线观看 | 三级黄免费看 | 精品v亚洲v欧美v高清v | 狠狠色狠狠色综合日日小说 | 最近免费中文字幕大全高清10 | 国产视频资源在线观看 | 欧美精品久久久久久久久久白贞 | 国产精品一区二区在线免费观看 | 成人久久18免费 | 日韩性色 | 久久久久欧美精品999 | 国产一级电影网 | 美女视频久久 | 一级片视频在线 | 一区二区三区日韩视频在线观看 | 精品欧美乱码久久久久久 | 黄色片视频在线观看 | 9在线观看免费高清完整 | 亚洲国产小视频在线观看 | 在线观看91精品视频 | 日韩一区二区免费播放 | 国产一级高清 | 日韩视频免费观看高清完整版在线 | 精品福利在线观看 | 午夜视频色 | 日本色小说视频 | 国产精品扒开做爽爽的视频 | 在线免费观看亚洲视频 | 日韩免费网址 | 成年美女黄网站色大片免费看 | 久久欧美综合 | 国产区 在线 | 九色精品免费永久在线 | 成人影片在线播放 | 一级黄色在线免费观看 | 99久热在线精品视频成人一区 | 色综合五月天 | 久久久av电影 | 人人操日日干 | 欧美xxxxx在线视频 | 91免费在线 | 欧美夫妻性生活电影 | 色偷偷88欧美精品久久久 | 激情综合啪 | 怡红院av久久久久久久 | 日韩免费小视频 | 国产精品一区二区三区电影 | 国产黄在线免费观看 | 久久精品5 | 六月丁香在线观看 | 五月天最新网址 | 久久精品免费播放 | 亚洲国产欧美在线人成大黄瓜 | 日韩欧美成人网 | 欧美精品在线观看一区 | 国产一区二区三区高清播放 | 国产日韩欧美视频在线观看 | 激情综合婷婷 | 久久毛片高清国产 | 日韩网页| 国产露脸91国语对白 | 婷婷伊人五月天 | 91精品啪| 黄网站色视频 | 久久高清片| 91亚洲精品乱码久久久久久蜜桃 | 8x8x在线观看视频 | 国产视频 亚洲精品 | 亚洲丁香久久久 | 在线激情av电影 | av大全在线免费观看 | 欧美日韩精 | 人人干网站 | 片黄色毛片黄色毛片 | 久久影视精品 | free. 性欧美.com | 99视频精品全部免费 在线 | 四虎8848免费高清在线观看 | 久久99这里只有精品 | 一级黄色电影网站 | 色婷婷国产精品一区在线观看 | 一区二区三区www | 亚洲免费av网站 | 日日夜夜噜噜噜 | av电影不卡在线 | 久久国内精品视频 | 精品国偷自产在线 | 欧美日韩视频在线 | 精品国产精品国产偷麻豆 | 国产午夜三级一区二区三桃花影视 | h视频日本 | 91av视频观看| 国产精品久久久久aaaa九色 | 婷婷中文字幕在线观看 | 久久久久久久久久免费视频 | 97精品国产 | 99久久久| 福利电影久久 | 久久精品国产久精国产 | 久久久影视| 99夜色 | 四虎影视8848aamm | 成人午夜电影免费在线观看 | 视频一区二区三区视频 | 色五丁香 | 久草在线视频首页 | 四虎影视成人永久免费观看亚洲欧美 | 亚洲最大av网 | 中文在线字幕免 | 国产成人精品av在线观 | 国产高清久久久 | 久久天天躁夜夜躁狠狠躁2022 | 操夜夜操 | 黄a网| 国产精品专区一 | 在线观看亚洲电影 | 在线播放视频一区 | 国产精品久久久久久久久婷婷 | 国产精品久久久久久av | 久久国产精品二国产精品中国洋人 | 俺要去色综合狠狠 | 狠狠干天天射 | 午夜资源站 | 国产黑丝袜在线 | 久久在线观看视频 | 久热这里有精品 | 99免费视频 | 98精品国产自产在线观看 | 超碰在线公开免费 | 黄色小说网站在线 | 91少妇精拍在线播放 | 在线观看黄色 | 久草在线观 | 伊人色综合久久天天 | 国产一区成人在线 | 欧美日韩不卡一区 | 亚洲三级在线播放 | 中文字幕av影院 | 天天操夜夜想 | 麻豆久久久久久久 | 亚洲人人射| 国内精品99| 99精品在线免费 | 一区三区视频 | 欧美日韩一区二区免费在线观看 | 国产香蕉97碰碰碰视频在线观看 | 日韩精品第一区 | 亚洲国产三级在线观看 | 日本中文字幕在线 | 最近免费观看的电影完整版 | 久久综合五月天婷婷伊人 | 欧美午夜视频在线 | 免费av片在线 | 激情深爱 | 国产资源免费 | 久久精品久久99 | 狠狠色噜噜狠狠 | 国产91精品一区二区 | 久久人视频| 日韩中文字幕国产精品 | 精久久久久 | 美女视频黄免费 | 成人av一二三区 | 欧美美女一级片 | 中文字幕在线观看网站 | 中文字幕亚洲精品在线观看 | 日本中文字幕网 | 日日夜夜狠狠操 | 国产一级片久久 | 国产成人在线看 | 国产一线二线三线性视频 | 国产免费一区二区三区网站免费 | 亚洲一级黄色大片 | 在线观看免费成人av | 亚洲精品午夜久久久久久久 | 九九九热精品免费视频观看网站 | 五月激情在线 | 99热免费在线 | 久久国产精品影片 | www五月| 成年人电影免费在线观看 | 久久一视频 | 免费男女羞羞的视频网站中文字幕 | 免费看片成年人 | 国产一级视频免费看 | 伊人激情综合 | 911国产在线观看 | 欧美成人aa| 欧美日韩免费看 | 波多野结衣在线视频免费观看 | 久久精品国产亚洲 | 亚洲国产成人精品在线观看 | 国产玖玖精品视频 | www.久久久 | 国产视频2区 | 国产精品美女久久久久久2018 | 久久视频这里有精品 | 欧美极度另类性三渗透 | 中文字幕视频免费观看 | 91精品视频导航 | 成人免费视频视频在线观看 免费 | 久草视频免费在线观看 | 亚洲精品九九 | 亚洲天堂网视频在线观看 | 国产精品一区二区久久精品爱微奶 | 国产精品中文字幕在线 | 九九九热 | 国产成人1区| 最近中文字幕大全中文字幕免费 | 91福利国产在线观看 | 亚洲精品久久久久久久蜜桃 | 五月综合婷 | 国产精品白浆视频 | 国产爽妇网 | 这里只有精品视频在线观看 | 日韩免费在线视频 | 天天干,天天操,天天射 | 国产精在线 |