// ******************************** //@name 操作 // ******************************** bool CaDcdGrid_PageSelector::DcDraw() { bool bRv = 0 ; int iXColumnNumberTail = m_pCDcdGrid->getXColumnCount() - 1 ; if ( m_iXPage < (int)m_contiXFixafterColumnNumber.size() - 1 ){ iXColumnNumberTail = m_contiXFixafterColumnNumber[ m_iXPage + 1 ] - 1 ; } int iYColumnNumberTail = m_pCDcdGrid->getYColumnCount() - 1 ; if ( m_iYPage < (int)m_contiYFixafterColumnNumber.size() - 1 ){ iYColumnNumberTail = m_contiYFixafterColumnNumber[ m_iYPage + 1 ] - 1 ; } //iXColumnNumberTail = // 完全に表示できている最も右の列番号 //iYColumnNUmberTail = // 完全に表示できている最も下の列番号 CdDcdZone zoneXColumnNumberTail ; CdDcdZone zoneYColumnNumberTail ; zoneXColumnNumberTail = m_pCDcdGrid->getXColumnBorderZone( m_pIfDcdTarget , iXColumnNumberTail ) ; zoneYColumnNumberTail = m_pCDcdGrid->getYColumnBorderZone( m_pIfDcdTarget , iYColumnNumberTail ) ; //zoneXColumnNumberTail = 完全に表示できている最も右の列の罫線位置 //zoneYColumnNumberTail = 完全に表示できている最も下の列の罫線位置 CdDcdZoneXy zonexyClip = m_pIfDcdTarget->getZone() ; { CdDcdZone zoneClip = zonexyClip.getX() ; zoneClip.setSize( zoneXColumnNumberTail.getEndPos() - zoneClip.getPos() ) ; zonexyClip.setX( zoneClip ) ; } { CdDcdZone zoneClip = zonexyClip.getY() ; zoneClip.setSize( zoneYColumnNumberTail.getEndPos() - zoneClip.getPos() ) ; zonexyClip.setY( zoneClip ) ; } //zonexyClip = クリッピング領域とします。 CaDcdTargetClip aCaDcdTargetClip( m_pIfDcdTarget , zonexyClip ) ; aCaDcdTargetClip.validate() ; bRv = m_pCDcdGrid->DcDraw( &aCaDcdTargetClip ) ; return ( bRv ) ; };
// ******************************** ///@name IfDcDraw // ******************************** bool CDcdFreeLine::DcDraw( IfDcdTarget* pIfDcdTarget ) { bool bRv = 0 ; CConverter_WinGdi aConverter ; // -------------------------------- // m_iLogicalunitWidth が // 0 なら、何も描画しません。 // -------------------------------- if ( m_CdLineProp.getLogicalunitWidth() <= 0 ){ return ( false ) ; } // -------------------------------- // 描画のための論理ペンを生成 // (サイズは、物理座標とします) // -------------------------------- Ou<CGdiHPenHolder> pHPenHolder ; int iDeviceunitPenWidth = CDcDeviceUnitSizeX( pIfDcdTarget->getHdc() ). setLogicalUnitSize( m_CdLineProp.getLogicalunitWidth() ). getDeviceUnitSize() ; if ( iDeviceunitPenWidth <= 0 ){ iDeviceunitPenWidth = 1 ; } { CdPenProp aCdPenProp ; aCdPenProp.setLogicalunitWidth( iDeviceunitPenWidth ) ; aCdPenProp.setColor( m_CdLineProp.getColor() ) ; aCdPenProp.setStyle( CdPenProp::SOLID ) ; pHPenHolder = pIfDcdTarget->createGdiHPenHolder( aCdPenProp ) ; } //iDeviceunitPenWidth = デバイス座標系での // ペンの太さ // -------------------------------- CdDcdPosXy posOrg = m_posOrg ; CdDcdPosXy posDst = m_posDst ; //posOrg,posDst = 起点と終点の座標(論理座標) // -------------------------------- // DcdTargetの範囲に、起点と終点を補正 // -------------------------------- if ( m_bAdjustForDcdTarget ){ //X方向をDcdTargetの範囲に収める { CdDcdZone zoneX( posOrg.getX() , posDst.getX() - posOrg.getX() ); CdDcdZone zoneXTarget = pIfDcdTarget->getZone().getX() ; CdDcdZone zoneXCrossed = zoneX.CrossZone( zoneXTarget ) ; //X座標を、デバイス領域内に正規化しました。 if ( zoneXCrossed.getSize() != 0 ){ CLineFunc aCLineFunc( m_posOrg , m_posDst ) ; // zoneXCrossed が描画領域にあり、 // しかも斜線である場合は、 // 起点・終点それぞれにおいて、 // デバイス領域内に正規化した // X座標からY座標を求めます。 // // (zoneXCrossed.Sizeが0の場合(垂線の場合)は、 // 対応する特定のY座標を求めることができませんので、 // calcLineYofX() を呼び出してはいけません) if ( zoneX.getPos() != zoneXCrossed.getPos() ){ posOrg.setX( zoneXCrossed.getPos() ) ; posOrg.setY( aCLineFunc.calcYofX( zoneXCrossed.getPos() ) ); } if ( zoneX.getEndPos() != zoneXCrossed.getEndPos() ){ posDst.setX( zoneXCrossed.getEndPos() ) ; posDst.setY( aCLineFunc.calcYofX( zoneXCrossed.getEndPos() ) ) ; } } if ( zoneXCrossed.getSize() == 0 && !zoneXTarget.IsInner( zoneXCrossed.getPos() ) ){ // zoneXCrossed が描画領域外である場合は、 // 直線の描画はできませんので、偽でリターンします。 return ( false ) ; } } //Y方向をDcdTargetの範囲に収める { CdDcdZone zoneY( posOrg.getY() , posDst.getY() - posOrg.getY() ); CdDcdZone zoneYTarget = pIfDcdTarget->getZone().getY() ; CdDcdZone zoneYCrossed = zoneY.CrossZone( zoneYTarget ) ; //Y座標を、デバイス領域内に正規化しました。 if ( zoneYCrossed.getSize() != 0 ){ CLineFunc aCLineFunc( m_posOrg , m_posDst ) ; // zoneYCrossed が描画領域にあり、 // しかも斜線である場合は、 // 起点・終点それぞれにおいて、 // デバイス領域内に正規化した // Y座標からX座標を求めます。 // // (zoneYCrossed.Sizeが0の場合(水平線の場合)は、 // 対応する特定のX座標を求めることができませんので、 // calcLineXofY() を呼び出してはいけません) if ( zoneY.getPos() != zoneYCrossed.getPos() ){ posOrg.setX( aCLineFunc.calcXofY( zoneYCrossed.getPos() ) ) ; posOrg.setY( zoneYCrossed.getPos() ) ; } if ( zoneY.getEndPos() != zoneYCrossed.getEndPos() ){ posDst.setX( aCLineFunc.calcXofY( zoneYCrossed.getEndPos() ) ) ; posDst.setY( zoneYCrossed.getEndPos() ) ; } } if ( zoneYCrossed.getSize() == 0 && !zoneYTarget.IsInner( zoneYCrossed.getPos() ) ){ // zoneYCrossed が描画領域外である場合は、 // 直線の描画はできませんので、偽でリターンします。 return ( false ) ; } } //posOrg,posDst = // DcdTargetの範囲に、起点と終点を補正しました。 } // -------------------------------- // デバイス座標系での // 線の座標を求める // -------------------------------- { POINT aPoint = aConverter.POINTOf( posOrg ) ; ::LPtoDP( pIfDcdTarget->getHdc() , &aPoint , 1 ) ; posOrg = aConverter.CdDcdPosXyOf( aPoint ) ; } { POINT aPoint = aConverter.POINTOf( posDst ) ; ::LPtoDP( pIfDcdTarget->getHdc() , &aPoint ,1 ) ; posDst = aConverter.CdDcdPosXyOf( aPoint ) ; } //posOrg,posDst = デバイス座標に変換しました。 // -------------------------------- // DCの属性を変更 // -------------------------------- int idSave = SaveDC( pIfDcdTarget->getHdc() ) ; int iMapModePrev = SetMapMode( pIfDcdTarget->getHdc() , MM_TEXT ) ; // SetMapMode() で MM_TEXT モードに移行すると、 // 論理単位とデバイス単位の比は1:1に変更されますが、 // 座標の原点値は変更されません。 // // LPtoDP() で変換されたデバイス座標は、デバイスコンテキストの // 左上隅を原点とした座標を返します。 // この座標を使って描画を行うためには、デバイスコンテキストの // 論理座標の原点も、デバイス座標 0,0 (左上隅)に設定しなくては // なりません。 //※ 原点の設定は、マッピングモードが MM_TEXT であっても可能です。 // ここが、SetViewportExtEx() , SetWindowExtEx() との違いです。 SetViewportOrgEx( pIfDcdTarget->getHdc() , 0 , 0 , NULL ) ; HPEN hPenSid = (HPEN)SelectObject( pIfDcdTarget->getHdc() , pHPenHolder->getHPen() ) ; // -------------------------------- // 線の描画 // -------------------------------- int iLongWidth = 0 ; bool bYIsLong = false ; { int iXWidth = abs( posDst.getX() - posOrg.getX() ) ; int iYWidth = abs( posDst.getY() - posOrg.getY() ) ; //iXWidth, iYWidth = X,Yの両座標の差。 // 起点・終点が同一座標の場合は0 if ( iXWidth > iYWidth ){ iLongWidth = iXWidth ; bYIsLong = false ; } else { iLongWidth = iYWidth ; bYIsLong = true ; } } //iLongWidth = X,Y の座標の差のうち、長いほう //iShortWidth = X,Y の座標の差のうち、短いほう // 起点・終点が同一座標の場合は0 //bYIsLong = false iLongWidthがX,iShortWidthがY // true iLongWidthがY,iShortWidthがX if ( m_CdLineProp.isSolidLineStyle() ){ // ******************************** // 実線 // ******************************** MoveToEx( pIfDcdTarget->getHdc() , posOrg.getX() , posOrg.getY() , NULL ) ; LineTo(pIfDcdTarget->getHdc() , posDst.getX() , posDst.getY() ) ; } else { // ******************************** // 破線 // ******************************** wstring aLINESTYLE = m_CdLineProp.getLinestyle() ; int idxStyle = 0 ; int iLongCurr ; for ( iLongCurr = 0 ; iLongCurr < iLongWidth ; ){ CLineFunc aCLineFunc( posOrg , posDst ) ; // -------------------------------- // 破線部分 // -------------------------------- { int iLongDst = iLongCurr + ( aLINESTYLE[idxStyle] - '0' ) * iDeviceunitPenWidth ; iLongDst -= ( iDeviceunitPenWidth - 1 ) ; idxStyle ++ ; if ( idxStyle >= (int)aLINESTYLE.size() ){ iLongDst += ( aLINESTYLE[0] - '0' ) ; idxStyle = 1 ; } if ( iLongDst > iLongWidth ){ iLongDst = iLongWidth ; } //iLongDst = // 今回描画を行う線は、iLongCurr ~ iLongDst の範囲です。 int iXSrc = 0 ; int iYSrc = 0 ; int iXDst = 0 ; int iYDst = 0 ; if ( bYIsLong ){ iYSrc = posOrg.getY() + iLongCurr * sign( posDst.getY() - posOrg.getY() ) ; iYDst = posOrg.getY() + iLongDst * sign( posDst.getY() - posOrg.getY() ) ; iXSrc = aCLineFunc.calcXofY( iYSrc ) ; iXDst = aCLineFunc.calcXofY( iYDst ) ; } else { iXSrc = posOrg.getX() + iLongCurr * sign( posDst.getX() - posOrg.getX() ) ; iXDst = posOrg.getX() + iLongDst * sign( posDst.getX() - posOrg.getX() ) ; iYSrc = aCLineFunc.calcYofX( iXSrc ) ; iYDst = aCLineFunc.calcYofX( iXDst ) ; } MoveToEx( pIfDcdTarget->getHdc() , iXSrc , iYSrc , NULL ) ; LineTo(pIfDcdTarget->getHdc() , iXDst, iYDst) ; iLongCurr = iLongDst ; } // -------------------------------- // 空白部分 // -------------------------------- { int iLongDst = iLongCurr + ( aLINESTYLE[idxStyle] - '0' ) * iDeviceunitPenWidth ; iLongDst += ( iDeviceunitPenWidth - 1 ) ; idxStyle ++ ; if ( idxStyle >= (int)aLINESTYLE.size() ){ idxStyle = 0 ; } if ( iLongDst > iLongWidth ){ iLongDst = iLongWidth ; } iLongCurr = iLongDst ; } } } // -------------------------------- // DCの属性を復帰 // -------------------------------- SelectObject( pIfDcdTarget->getHdc() , hPenSid ) ; hPenSid = NULL ; if ( idSave != 0 ){ RestoreDC( pIfDcdTarget->getHdc() , idSave ) ; idSave = 0 ; } return ( true ) ; }
// ******************************** //@name IfDcDraw // ******************************** bool CDcdDiagram::DcDraw( IfDcdTarget* pIfDcdTarget ) { bool bRv = false ; CdDcdFreeLineProp linepropDot( 1 , m_colorDiaJikuColor , LINESTYLE_DOT2 ) ; CdDcdFreeLineProp linepropNormal( 1 , m_colorDiaJikuColor ) ; CdDcdFreeLineProp linepropBold( 2 , m_colorDiaJikuColor ) ; // -------------------------------- // DcdTargetの領域に // クリッピングを行います。 // -------------------------------- CaDcdTargetClip* pTargetClip = NULL ; { CdDcdZoneXy zonexyCentDedDgrDia = getCentDedDgrDia()->getZone() ; //zonexyCentDedDgrDia = ダイヤグラムの範囲を、 // 『ダイヤグラムエンティティ座標系』で保持します。 // X座標は24時間分、Y座標は起点から終点までを表します。 CdDcdZoneXy zonexyDcd_CentDedDgrDia = DgrToDcd( pIfDcdTarget , zonexyCentDedDgrDia ) ; //zonexyDcd_CentDedDgrDia = // ダイヤグラムの範囲を、『DcDraw座標系』で保持します。 // 但し、この値をクリップ領域にすると、 // EndPosはクリップ領域に含まれません。 zonexyDcd_CentDedDgrDia.setX( CdDcdZone( zonexyDcd_CentDedDgrDia.getX().getPos() , zonexyDcd_CentDedDgrDia.getX().getSize() + DIAGRAM_SIZE_MARGIN_DCD ) ) ; zonexyDcd_CentDedDgrDia.setY( CdDcdZone( zonexyDcd_CentDedDgrDia.getY().getPos() , zonexyDcd_CentDedDgrDia.getY().getSize() + DIAGRAM_SIZE_MARGIN_DCD ) ) ; //zonexyDcd_CentDedDgrDia = ダイヤグラムの範囲を // 『DcDraw座標系』で保持します。 //クリップ領域は、 // IfDcdTargetの領域と // ダイヤグラムの範囲の交差領域です。 CdDcdZoneXy zonexyClip = pIfDcdTarget->getZone().CrossZone( zonexyDcd_CentDedDgrDia ) ; pTargetClip = new CaDcdTargetClip( pIfDcdTarget , zonexyClip ) ; pTargetClip->validate() ; } // -------------------------------- // 描画を行う領域の計算 // -------------------------------- CdDcdZoneXy zonexyCentDedDgrDia = m_pCentDedDgrDia->getZone() ; //zonexyCentDedDgrDia = ダイヤグラムの範囲を、 // 『ダイヤグラムエンティティ座標系』で保持します。 // X座標は24時間分、Y座標は起点から終点までを表します。 // -------------------------------- // 縦罫線を描画します。 // -------------------------------- { // 縦罫線は、ダイヤグラム起点時刻の次の、縦罫線描画時刻から開始 // (4:01で2分目なら4:02、1分目なら4:01、10分目なら4:10) DcdPos posDgrXVlineOrg = zonexyCentDedDgrDia.getX().getPos() ; { int iMod = zonexyCentDedDgrDia.getX().getPos() % getVlinePitch() ; if ( iMod > 0 ) { posDgrXVlineOrg += getVlinePitch() - iMod ; } } //posDgrXVlineOrg = 時刻表示の開始位置 // ダイヤグラム起点時刻の次の正時から開始(4:59なら5:00、5:00なら5:00) for ( DcdPos posDgrX = posDgrXVlineOrg ; posDgrX <= zonexyCentDedDgrDia.getX().getEndPos() ; posDgrX += getVlinePitch() ) { //posDgrX = ダイヤグラムエンティティ座標での、 // 縦罫線の位置 CDcdFreeLine aCDcdFreeLine ; if ( posDgrX % getVlineBoldPitch() == 0 ) { aCDcdFreeLine.setCdLineProp( linepropBold ) ; } else if ( posDgrX % getVlineMiddlePitch() == 0 ) { aCDcdFreeLine.setCdLineProp( linepropNormal ) ; } else { aCDcdFreeLine.setCdLineProp( linepropDot ) ; } // 座標を、Dgr→Dcdに変換 DcdPos posDcdX = XDgrToDcd( pTargetClip , posDgrX ) ; CdDcdZone zoneDcdY = YDgrToDcd( pTargetClip , zonexyCentDedDgrDia.getY() ) ; if ( pTargetClip->getZone().getX().getPos() - 1 <= posDcdX && posDcdX < pTargetClip->getZone().getX().getEndPos() + 1 ) { aCDcdFreeLine.setOrg( CdDcdPosXy( posDcdX , zoneDcdY.getPos() ) ) ; aCDcdFreeLine.setDst( CdDcdPosXy( posDcdX , zoneDcdY.getEndPos() ) ) ; aCDcdFreeLine.DcDraw( pTargetClip ) ; bRv = true ; } } } // -------------------------------- // 横罫線を描画します。 // -------------------------------- { const Mu<CentDedDgrEki>* pCentDedDgrEkiCont = m_pCentDedDgrDia->getCentDedDgrEkiCont() ; for ( int iEkiIndex = 0 ; iEkiIndex < pCentDedDgrEkiCont->size() ; iEkiIndex ++ ) { CentDedDgrEki aCentDedDgrEki = pCentDedDgrEkiCont->get( iEkiIndex ) ; DcdPos posDgrY = m_pCentDedDgrDia->getDgrYPosOfEki( iEkiIndex ) ; CDcdFreeLine aCDcdFreeLine ; if ( aCentDedDgrEki.getIsSyuyoueki() ) { aCDcdFreeLine.setCdLineProp( linepropBold ) ; } else { aCDcdFreeLine.setCdLineProp( linepropNormal ) ; } // 座標を、Dgr→Dcdに変換 DcdPos posDcdY = YDgrToDcd( pTargetClip , posDgrY ) ; CdDcdZone zoneDcdX = XDgrToDcd( pTargetClip , zonexyCentDedDgrDia.getX() ) ; if ( pTargetClip->getZone().getY().getPos() - 1 <= posDcdY && posDcdY < pTargetClip->getZone().getY().getEndPos() + 1 ) { aCDcdFreeLine.setOrg( CdDcdPosXy( zoneDcdX.getPos() , posDcdY ) ) ; aCDcdFreeLine.setDst( CdDcdPosXy( zoneDcdX.getEndPos() , posDcdY ) ) ; aCDcdFreeLine.DcDraw( pTargetClip ) ; } } } // -------------------------------- // 列車線を描画します。 // -------------------------------- { CRessyasenDraw aCRessyasenDraw( this , pTargetClip , m_bDisplayRessyasenKudari , m_bDisplayRessyasenNobori ) ; aCRessyasenDraw.execute() ; } // -------------------------------- // 列車情報を描画します。 // -------------------------------- { CRessyajouhouDraw aCRessyajouhouDraw( this , pTargetClip , m_bDisplayRessyasenKudari , m_bDisplayRessyasenNobori ) ; aCRessyajouhouDraw.execute() ; } // -------------------------------- // 停車記号を描画します。 // -------------------------------- { CDcdDiagram_CStopMarkDraw aCDcdDiagram_CStopMarkDraw( this , pTargetClip , m_bDisplayRessyasenKudari , m_bDisplayRessyasenNobori ) ; aCDcdDiagram_CStopMarkDraw.execute() ; } // -------------------------------- if ( pTargetClip != NULL ) { delete pTargetClip ; pTargetClip = NULL ; } return ( bRv ) ; }