MFC 預設列印支援基於 MM_TEXT (像素座標),導致 GIS 向量圖形列印尺寸嚴重縮小。本文提出切換至 MM_LOMETRIC (0.01mm 邏輯單位) 配合座標縮放平移,實現所見即所得的 GIS 圖幅列印、分頁拼接與區域選擇列印。
MM_TEXT,像素座標,效能最佳MM_LOMETRIC,物理單位 (0.01mm),尺寸精確DrawVectorMap(CDC*),列印時傳入印表機 DC 觸發座標轉換將地理座標 (x, y) 轉為列印邏輯座標 (0.01mm):
x_print = (x - printStartX) * printScale + pageLeft * 100;
y_print = (y - printStartY) * printScale - mapHeight * 100 - pageUp * 100;
// 注意:MM_LOMETRIC Y 軸向上,故減去高度與上邊距
printScale = 100.0 * mapWidth / (xMax - xMin):地理單位 → 0.01mm 縮放比pageLeft, pageUp:圖幅相對紙張左上角邊距 (cm) → *100mapHeight = mapWidth * (yMax-yMin)/(xMax-xMin):依比例計算圖高void CBoundaryView::OnPrintMapSetup() {
CMapSetup dlg; // 屬性頁包含圖幅寬、上/左邊距
if (dlg.DoModal() == IDOK) {
mapWide = dlg.m_Page1.m_mapWide; // 圖幅寬 (cm)
pageUp = dlg.m_Page2.m_pageUp; // 上邊距 (cm)
pageLeft= dlg.m_Page2.m_pageLeft; // 左邊距 (cm)
}
}
BOOL CBoundaryView::OnPreparePrinting(CPrintInfo* pInfo) {
xWide = (int)(mapWide * 10); // mm → 0.1mm 單位
if (!printSelection) { // 全圖列印
mapHeight = mapWide * (yMax-ymin)/(xMax-xmin);
} else { // 選擇區域列印
mapHeight = mapWide * (printY1-printY2)/(printX2-printX1);
}
yHigh = (int)(mapHeight * 10);
return DoPreparePrinting(pInfo);
}
void CBoundaryView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo) {
// 取得可列印區域物理尺寸 (mm)
int pageW = pDC->GetDeviceCaps(HORZSIZE);
int pageH = pDC->GetDeviceCaps(VERTSIZE);
// 計算橫向/縱向頁數
nPageX = (xWide + pageW - 1) / pageW; // 無條件進位
nPageY = (yHigh + pageH - 1) / pageH;
nTotalPages = nPageX * nPageY;
pInfo->SetMinPage(1);
pInfo->SetMaxPage(nTotalPages);
}
void CBoundaryView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) {
if (!pInfo) return;
// 計算當前頁在網格中的行列 (1-based)
int nCol = (pInfo->m_nCurPage - 1) % nPageX + 1;
int nRow = (pInfo->m_nCurPage - 1) / nPageX + 1;
// 計算該頁對應的地理座標起始點
if (!printSelection) {
printStartX = xMin + (nCol-1) * (xMax-xMin) / nPageX;
printStartY = yMin - (nRow-1) * (yMax-yMin) / nPageY; // Y 向上
} else {
printStartX = printX1 + (nCol-1) * (printX2-printX1) / nPageX;
printStartY = printY2 - (nRow-1) * (printY1-printY2) / nPageY;
}
CView::OnPrepareDC(pDC, pInfo);
}
void CBoundaryView::OnPrintSelection() {
drawSelection = 1; // 顯示選取框
printSelection = 1; // 切換列印模式
// 滑鼠擷取選取矩形 → 轉換為 printX1,Y1,X2,Y2
// 列印時自動計算該區域分頁
}
void CBoundaryView::OnDraw(CDC* pDC) {
if (pDC->IsPrinting()) {
pDC->SetMapMode(MM_LOMETRIC);
printFlag = 1;
printScale = 100.0 * mapWide / (printSelection ? (printX2-printX1) : (xMax-xMin));
} else {
printScale = 1; printFlag = 0;
}
if (printFlag == 0) DrawVectorMap(mapFile); // 螢幕繪製
else DrawVectorMap(mapFile, pDC); // 列印繪製 (座標轉換版)
}
void CBoundaryView::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo) {
DrawVectorMap(mapFile); // 恢復螢幕顯示
InvalidateRect(NULL, TRUE);
printFlag = printSelection = 0;
}
OnDraw 依 IsPrinting() 動態切換,避免影響螢幕效能DrawVectorMapOnBeginPrinting 計算總頁數,OnPrepareDC 計算單頁原點,職責清晰此架構已在 VC6 + Win2000 大型 GIS 專案驗證,可輕鬆擴展支援多圖層、圖例、北向標、比例尺等製圖要素,是 MFC GIS 列印模組的經典實作範本。