// PrintItem.cpp #include "pch.h" #include "PrintItem.h" IMPLEMENT_DYNAMIC(CPrintItem, CObject) // 選択ハンドルの一辺(デバイスピクセル) static const int kHandleSize = 7; // コンストラクタ。矩形を空(0,0,0,0)で初期化。 CPrintItem::CPrintItem() : m_rect(0, 0, 0, 0) { } CPrintItem::~CPrintItem() { } // 当たり判定。指定座標(1/100mm)がこのアイテムの矩形内なら TRUE。 // 既定は矩形の内側判定。直線など特殊な形状は派生側で上書きできる。 BOOL CPrintItem::HitTest(const CPoint& huPt) const { return m_rect.PtInRect(huPt); } // 共通の永続化処理。矩形(left/top/right/bottom)だけを保存/復元する。 // 派生クラスは自分の Serialize で本関数を呼んでから固有データを読み書きする。 void CPrintItem::Serialize(CArchive& ar) { CObject::Serialize(ar); if (ar.IsStoring()) { ar << (int)m_rect.left << (int)m_rect.top << (int)m_rect.right << (int)m_rect.bottom; } else { int l, t, r, b; ar >> l >> t >> r >> b; m_rect.SetRect(l, t, r, b); } } // 8 個のハンドル(四隅 + 各辺中央)の中心座標 static CPoint HandleCenter(const CRect& dr, int i) { int mx = (dr.left + dr.right) / 2; int my = (dr.top + dr.bottom) / 2; switch (i) { case 0: return CPoint(dr.left, dr.top); // 左上 case 1: return CPoint(mx, dr.top); // 上中央 case 2: return CPoint(dr.right, dr.top); // 右上 case 3: return CPoint(dr.right, my); // 右中央 case 4: return CPoint(dr.right, dr.bottom); // 右下 case 5: return CPoint(mx, dr.bottom); // 下中央 case 6: return CPoint(dr.left, dr.bottom); // 左下 case 7: return CPoint(dr.left, my); // 左中央 } return CPoint(0, 0); } // index 番目(0..7)のハンドルが占める小矩形(デバイス座標)を返す。 CRect CPrintItem::HandleRectAt(const CRect& devRect, int index) { CPoint c = HandleCenter(devRect, index); int h = kHandleSize / 2; return CRect(c.x - h, c.y - h, c.x + h + 1, c.y + h + 1); } // 選択中アイテムの装飾(破線枠 + 8個のサイズ変更ハンドル)を描画する。 // devRect はアイテム矩形をデバイス座標へ変換したもの。 void CPrintItem::DrawSelection(CDC& dc, const CRect& devRect) { // 破線の選択枠 CPen pen(PS_DOT, 1, RGB(0, 0, 255)); CPen* pOld = dc.SelectObject(&pen); int oldBk = dc.SetBkMode(TRANSPARENT); CBrush* pOldBrush = (CBrush*)dc.SelectStockObject(NULL_BRUSH); dc.Rectangle(devRect); dc.SelectObject(pOldBrush); dc.SetBkMode(oldBk); dc.SelectObject(pOld); // ハンドル(白塗り+黒枠) CBrush white(RGB(255, 255, 255)); CPen black(PS_SOLID, 1, RGB(0, 0, 0)); CPen* pOld2 = dc.SelectObject(&black); CBrush* pOld3 = dc.SelectObject(&white); for (int i = 0; i < 8; ++i) dc.Rectangle(HandleRectAt(devRect, i)); dc.SelectObject(pOld3); dc.SelectObject(pOld2); } // devPt(デバイス座標)がどのハンドル上にあるかを返す。0..7、無ければ -1。 // 判定矩形を少し広げて掴みやすくしている。 int CPrintItem::HitHandle(const CRect& devRect, const CPoint& devPt) { for (int i = 0; i < 8; ++i) { CRect hr = HandleRectAt(devRect, i); hr.InflateRect(2, 2); // 掴みやすく if (hr.PtInRect(devPt)) return i; } return -1; }