首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

VC++ 6.0 GIS 打印輸出控制:MM_TEXT 模式下的座標轉換與分頁列印實作

     編輯:關於VC++

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) → *100
  • mapHeight = mapWidth * (yMax-yMin)/(xMax-xMin):依比例計算圖高

三大功能模組實作

1. 圖幅尺寸與邊距設定

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

2. 分頁拼接控制 (左→右,上→下)

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

3. 螢幕選擇區域列印

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() 動態切換,避免影響螢幕效能
  • 座標系統統一:列印路徑全部使用地理座標,轉換邏輯集中在重載 DrawVectorMap
  • 分頁邏輯解耦:OnBeginPrinting 計算總頁數,OnPrepareDC 計算單頁原點,職責清晰
  • 區域選擇複用:同一套座標轉換支援全圖/區域兩種模式,僅改變輸入範圍參數

此架構已在 VC6 + Win2000 大型 GIS 專案驗證,可輕鬆擴展支援多圖層、圖例、北向標、比例尺等製圖要素,是 MFC GIS 列印模組的經典實作範本。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved