Files
AveryDennisonUtil/PrintItem.cpp
T
yoshikazu 19d1c39370 Initial commit: OtozaiPrinter (AveryDennisonUtil) ラベル/レシート レイアウト設計・印刷 MFC アプリ
- 用紙設計キャンバス(1/100mm 基準)・テキスト/画像/矩形/直線アイテム
- コピー/複製/Zオーダー/整列/グリッドスナップ、原紙(下絵)読込と印刷可否
- GDI 直接印刷、.otz 保存/再読込(版数つき)
- MFC/CRT 静的リンクで VS2022 IDE から F5 デバッグ可
2026-06-05 17:27:29 +09:00

110 lines
3.5 KiB
C++

// 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;
}