Здравствуйте!
Спасибо за обратную связь!
На данный момент в ГИС Конструктор версии 11 реализовано то поведение полей, которое Вы описываете.
Для того, чтобы при печати добавлялись поля, мы можем предложить Вам одно из следующих решений:
- использовать функции из состава ГИС Констуктор 12 (для этого потребуется выполнить обновление);
- включить сборку обновленных функций печати в состав Вашего проекта (прилагаю необходимые файлы и обновленный тестовый пример печати в pdf).
Исходный файл с функциями печати:
[CODE]#include <cmath>
#include <qimage.h>
#include <qprinter.h>
#include <qprintdialog.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <QTextCodec>
#include "mapview.rh"
#include "struct.h"
struct BORDER
{
DOUBLEPOINT UpLeft;
DOUBLEPOINT UpRight;
DOUBLEPOINT DownRight;
DOUBLEPOINT DownLeft;
DOUBLEPOINT UpLeftLast;
};
extern "C"
{
void SetupParam(HMAP hmap, SCRIPTPARAM *ScriptParam, DFRAME *FrameTrap);
void msInitPrintParam(MAPPRINTPARMEX *printParam, BORDER border, double frameAngle, bool isClockWise);
long int msPrintMap(HMAP hMap, SCRIPTPARAM *scriptparam, MAPPRINTPARMEX *printparam, QPrinter *printer);
}
// Максимальный характерный размер "элементарной"
// страницы для печати
const int MAXPAGEWIDTH = 4000;
const int MAXPAGEHEIGHT = 4000;
long int msPrintOneSimplePage(HMAP hMap, QPainter *p, int px, int py, int cx, int cy, int cw, int ch,
double printprecisionX, double printprecisionY);
long int msPrintOnePage(HMAP hMap, QPainter *p, int cx, int cy, int cw, int ch,
double printprecisionX, double printprecisionY);
// Инициализировать параметры печати
// printparam - структура параметров печати
// border - структура координат рамки выделения
// frameAngle - угол поворота рамки выделения
// isClockWise - признак того, что точки рамки выделения выбраны по часовой стрелке
void msInitPrintParam(MAPPRINTPARMEX *printParam, BORDER border, double frameAngle, bool isClockWise) // 24/08/15 Савелов
{
// Определить координаты рамки печати
DFRAME *planeFrame = &printParam->PlaneFrame;
// В режиме выбора прямоугольной рамки поменять местами
// координаты точек прямоугольника
if (printParam->TurnFrame == 0)
{
DFRAME tempFrame = *planeFrame;
planeFrame->X1 = tempFrame.X2;
planeFrame->Y1 = tempFrame.Y1;
planeFrame->X2 = tempFrame.X1;
planeFrame->Y2 = tempFrame.Y2;
return;
}
if (frameAngle < 0)
{
if (isClockWise == true)
{
planeFrame->X1 = border.DownRight.x;
planeFrame->Y1 = border.DownRight.y;
planeFrame->X2 = border.UpLeft.x;
planeFrame->Y2 = border.UpLeft.y;
}
else
{
planeFrame->X1 = border.UpRight.x;
planeFrame->Y1 = border.UpRight.y;
planeFrame->X2 = border.DownLeft.x;
planeFrame->Y2 = border.DownLeft.y;
}
}
// Определить угол поворота карты
double *printAngle = &printParam->Angle;
if (frameAngle < -M_PI/2 && frameAngle > -M_PI)
*printAngle = fabs(frameAngle) - M_PI/2;
else if (frameAngle < 0 && frameAngle > -M_PI/2)
*printAngle = fabs(frameAngle) - M_PI/2;
else
*printAngle = -(fabs(frameAngle) - M_PI/2);
}
//-----------------------------------------------------------------
// Печать выбранного фрагмента карты
//-----------------------------------------------------------------
long int msPrintMap(HMAP hMap, SCRIPTPARAM *scriptparam, MAPPRINTPARMEX *printparam, QPrinter *printer)
{
if (hMap == 0)
return 0;
QPainter p;
QTextCodec *MainCodec = QTextCodec::codecForName("KOI8-R");
// Установить параметры принтера
if (strlen(scriptparam->NamePrinter) > 0)
{
printer->setPrinterName(MainCodec->toUnicode(scriptparam->NamePrinter));
}
else if (strlen(scriptparam->NameInputPost) > 0)
{
printer->setOutputFormat(QPrinter::PdfFormat);
printer->setOutputFileName(MainCodec->toUnicode(scriptparam->NameInputPost));
}
else
return 0;
if ( !p.begin(printer) )
return 0;
// Повернуть карту
if (printparam->TurnFrame != 0)
mapSetupTurn(hMap, printparam->Angle, 0);
// Запросить точный масштаб отображения карты
double oldscale = mapGetRealShowScale(hMap);
// Установить точный масштаб отображения карты
mapSetRealShowScale(hMap, scriptparam->Scale);
// Функции настройки ядра согласно данным принтера
double oldhor = mapGetHorizontalScreenPrecision();
double oldver = mapGetVerticalScreenPrecision();
double printprecisionX = printer->physicalDpiX() * 1000 / 25.4;
double printprecisionY = printer->physicalDpiY() * 1000 / 25.4;
mapSetScreenPrecisionEx(printprecisionX, printprecisionY);
long int x = 0, y = 0;
mapChangeViewScale(hMap, &x, &y, 1.0);
// Печать нескольких копий
int copyCount = printer->copyCount();
for (int copyId = 0; copyId < copyCount; copyId++)
{
if(copyId != 0)
printer->newPage();
int cw = 800, ch = 600, cx = 0, cy = 0;
// Переведем в пикселы габариты печати
double x1 = printparam->PlaneFrame.X1;
double y1 = printparam->PlaneFrame.Y1;
double x2 = printparam->PlaneFrame.X2;
double y2 = printparam->PlaneFrame.Y2;
mapPlaneToPicture(hMap, &x1, &y1);
mapPlaneToPicture(hMap, &x2, &y2);
int xbegin = x1;
// Запомним левую и нижнюю границу в пикселах
cx = x2;
cy = y2;
// Габариты области печати в пикселах
cw = x2 - x1;
ch = y2 - y1;
// Габариты страницы формата принтера в пикселах
QRectF rectf = printer->pageRect(QPrinter::DevicePixel);
int wpage = rectf.width();
int hpage = rectf.height();
// Количество страниц по высоте
int ss = (ch + hpage - 1) / hpage;
// Количество страниц по ширине
int cc = (cw + wpage - 1) / wpage;
for (int s = 0; s < ss; s++)
{
y2 = y1 + hpage;
if (y2 > cy) y2 = cy;
x1 = xbegin;
for (int c = 0; c < cc; c++)
{
if (s + c > 0) printer->newPage();
x2 = x1 + wpage;
if (x2 > cx) x2 = cx;
cw = x2 - x1;
ch = y2 - y1;
// Печать одной страницы
msPrintOnePage(hMap, &p, x1, y1, cw, ch, printprecisionX, printprecisionY);
x1 = x2;
}
y1 = y2;
}
}
p.end();
mapSetScreenPrecisionEx(oldhor, oldver);
mapChangeViewScale(hMap, &x, &y, 1.0);
// Установить точный масштаб отображения карты
mapSetRealShowScale(hMap, oldscale);
// Инвертировать поворот карты
if (printparam->TurnFrame != 0)
mapSetupTurn(hMap, 0, 0);
}
//-----------------------------------------------------------------
// Печать одной страницы
// hMap - указатель на карту
// p - указатель на текущий класс отрисовки Qt
// cx - начало области отрисовки на карте в пикселах по x
// cy - начало области отрисовки на карте в пикселах по y
// cw - ширина области отрисовки на карте в пикселах
// ch - высота области отрисовки на карте в пикселах
// printprecisionX - текущее разрешение карты для принтера по X
// printprecisionY - текущее разрешение принтера карты для по Y
//-----------------------------------------------------------------
long int msPrintOnePage(HMAP hMap, QPainter *p, int cx, int cy, int cw, int ch, double printprecisionX, double printprecisionY)
{
// Запомнить координаты правого нижнего угла
int cx2 = cx + cw;
int cy2 = cy + ch;
// Получить число "элементарных" страниц для печати
int horSimplePagesNum = ceil((double)cw / MAXPAGEWIDTH);
int verSimplePagesNum = ceil((double)ch / MAXPAGEHEIGHT);
// Если размер "комплексной" страницы укладывается в одну элементарную -
// распечатать "как есть"
if(horSimplePagesNum == 1 && verSimplePagesNum == 1)
{
msPrintOneSimplePage(hMap, p, 0, 0, cx, cy, cw, ch,
printprecisionX, printprecisionY);
return 0;
}
// Распечатать набор "элементарных" страниц
int pageY = cy;
// Положение на одном листе
int pagePY = 0;
for(int verId = 0; verId < verSimplePagesNum; verId++)
{
int pageX = cx;
int pagePX = 0;
for(int horId = 0; horId < horSimplePagesNum; horId++)
{
// Вычислить размер печатаемой страницы
int printWidth = MAXPAGEWIDTH, printHeight = MAXPAGEHEIGHT;
if(pageX + MAXPAGEWIDTH > cx2)
printWidth = cx2 - pageX;
if(pageY + MAXPAGEHEIGHT > cy2)
printHeight = cy2 - pageY;
// Напечатать "элементарную" страницу
int res = msPrintOneSimplePage(hMap, p, pagePX, pagePY, pageX, pageY, printWidth, printHeight,
printprecisionX, printprecisionY);
if(res == -1) {
fprintf(stderr, "cannot print simple page\n");
return -1;
}
// Сместиться на лист вправо
pageX += MAXPAGEWIDTH;
pagePX += MAXPAGEWIDTH;
}
// Сместиться на лист вниз
pageY += MAXPAGEHEIGHT;
pagePY += MAXPAGEHEIGHT;
}
return 0;
}
//-----------------------------------------------------------------
// Печать одной страницы
// hMap - указатель на карту
// p - указатель на текущий класс отриовки Qt
// px - начало области отрисовки на листе в пикселах по x
// py - начало области отрисовки на листе в пикселах по y
// cx - начало области отрисовки на карте в пикселах по x
// cy - начало области отрисовки на карте в пикселах по y
// cw - ширина области отрисовки на карте в пикселах
// ch - высота области отрисовки на карте в пикселах
// printprecisionX - текущее разрешение карты для принтера по X
// printprecisionY - текущее разрешение принтера карты для по Y
//-----------------------------------------------------------------
long int msPrintOneSimplePage(HMAP hMap, QPainter *p, int px, int py, int cx, int cy, int cw, int ch, double printprecisionX, double printprecisionY)
{
// Размер строки в байтах
int allignwidth = cw * CELLSIZE;
// Размер DIB в памяти
int size = allignwidth * ch;
// Указатель на DIB в памяти
char *bits = AllocateTheMemory(size);
if(bits == NULL) // 09/02/15
return -1;
memset(bits, 0, size);
// Формирование структуры отрисовки карты
XIMAGEDESC Ximagedesc;
Ximagedesc.Point = bits; // Адрес начала области пикселов
Ximagedesc.Width = cw; // Ширина строки в пикселах
Ximagedesc.Height = ch; // Число строк
Ximagedesc.Depth = CELLSIZE * 8; // Размер элемента в битах (8,15,16,24,32)
Ximagedesc.CellSize = CELLSIZE; // Размер элемента(пиксела) в байтах
Ximagedesc.RowSize = allignwidth;// Ширина строки в байтах
RECT RectDraw;
RectDraw.left = cx ;
RectDraw.top = cy ;
RectDraw.right = cx + cw;
RectDraw.bottom = cy + ch;
long oldViewType = mapSetViewType(hMap, VT_PRINTRST);
// Установим белый цвет фона
COLORREF oldback = mapGetBackColor(hMap);
mapSetBackColor(hMap, 0x0FFFFFF);
// Отобразим фрагмент карты в памяти
mapPaintToXImage(hMap, &Ximagedesc, 0, 0, &RectDraw);
mapSetBackColor(hMap, oldback);
mapSetViewType(hMap, oldViewType);
// Создать QImage по XImage
QImage image((const uchar *)bits, cw, ch, allignwidth, QImage::Format_RGB32);
// Отобразить карту на принтер средствами Qt
p->drawImage(px, py, image, 0, 0, cw, ch);
FreeTheMemory(bits);
return 0;
}[/CODE]
Заголовочный файл (обновленная версия struct.h с необходимыми структурами):
[CODE]#if !defined(STRUCT_H)
#define STRUCT_H
#include "mapapi.h"
class TMapAccess;
class TMapWindow;
typedef struct
{
double ResolutionGor; // метр.эл гориз
double ResolutionVer; // метр.эл вертик
double Scale; // масштаб
long int Length; // размер структуры
char NameInputPost[MAX_PATH]; // имя выходного файла
char NamePrinter[MAX_PATH]; // имя принтера
char PrintPage[MAX_PATH]; // номера страниц
long int CutListFlag; // 1-5 - однолистовая печать
// 1 - A0;...; 5 - A4
// -1-(-5) печать по листам
// -1 - A0;...;-5 - A4
long int Resolution; // точки на дюйм
long int FormatPage; // Формат страницы:
// 0 - A0; 1 - A1; 2 - A2; 3 - A3; 4 - A4
TMapWindow *MapWindow; // окно обрабатываемой карты
} SCRIPTPARAM;
typedef struct MAPPRINTPARMEX
{
int Length; // Длина структуры MAPPRINTPARM
#ifdef _M_X64
int MapPrintZero; // Выравнивание
#endif
HWND Handle; // Идентификатор окна карты
// 0x008
int Scale; // Масштаб печати (знаменатель)
int ScaleSave; // Масштаб печати (сохраняется при FitToPage = 1)
// 0x010 (16)
RECT RectMetr; // Прямоугольник печати в районе в метрах
// (Если обнулен - расчитывается по габаритам района).
// При заданных габаритах выбранной области
// (PlaneFrame) игнорируется
// 0x020 (32)
int ShiftLTmm; // Смещение (в миллиметрах)
int ShiftUPmm; //
// 0x028 (40)
int FieldLTmm; // Поля страницы (в миллиметрах)
int FieldUPmm; //
int FieldRTmm; //
int FieldDNmm; //
// 0x038 (56)
int Intensity; // Интенсивность заливки площадных (0-100)
int Copies; // Количество копий
// 0x040 (64)
char Regime; // Режим работы задачи (см. MAPPRINT_REGIME)
char Preview; // Режим работы окна (см. MAPPRINT_PREVIEW)
char TypePrint; // Тип печати (см. MAPPRINT_TYPE)
char TypeOutput; // Тип вывода (см. MAPPRINT_OUTPUT)
// 0x044 (68)
char Orientation; // Ориентация (см. MAPPRINT_ORIENT)
char File; // Флаг устройства вывода (1 - файл, 0 - принтер)
char Border; // Флаг вывода рамки (1 - есть, 0 - нет)
char FitToPage; // Согласование с размером страницы
// (см. MAPPRINT_FITTING)
char Black; // Флаг черно-белой печати (1 - есть, 0 - нет)
char Calibration; // Флаг учета коэффициентов калибровки
// (1 - учитывать, 0 - нет)
char Mirror; // Флаг зеркального вывода (1 - есть, 0 - нет)
char CutLine; // Флаг вывода линий обрезки (1 - есть, 0 - нет)
// (при OverlapLT, OverlapUP,
// OverlapRT или OverlapDN > 0) // 0x04C (76)
char FileName[260]; // Имя файла печати
// 0x150 (336)
int OverlapLTmm; // Поля перекрытия изображения соседних
int OverlapUPmm; // страниц (в миллиметрах)
int OverlapRTmm; //
int OverlapDNmm; //
// 0x160 (352)
double PageWidth; // Размеры печатаемой области страницы за вычетом
double PageHeight; // полей перекрытия (в миллиметрах)
// 0x170 (368)
double Angle; // Угол поворота карты (в радианах)
// 0x178 (376)
DFRAME PlaneFrame; // Габариты выбранной области в метрах
// (Если обнулен - расчитывается по габаритам района).
// X1,Y1 - 1 точка прямоугольной области
// X2,Y2 - 3 точка прямоугольной области
// При TurnFrame = 1, считать 1 и 3 точки вершинами
// наклонного прямоугольника, на неповернутой карте
// 0x198 (408)
HSITE SiteDecor; // Зарамочное оформление (должен быть обнулен)
// 0x19C (412)
int FrameKey; // Номер объекта карты, по которому устанавливается
// габариты области печати PlaneFrame
// (Если равен 0 или объект отсутствует,
// то параметр игнорируется)
// 0x1A0 (416)
#ifdef _M_X64
int MapPrintAddZero; // Выравнивание
#endif
char FrameList[32]; // Имя листа (номенклатура) объекта FrameKey
// 0x1C0 (448)
int PaperWidth; // Размер листа (в миллиметрах)
int PaperHeight; //
// 0x1C8 (456)
char ReserveEx[48]; // Резерв (должен быть обнулен)
unsigned char PageCountHor; // Число страниц по горизонтали
// (используется при FitToPage = MPF_FITBYHOR)
unsigned char PageCountVer; // Число страниц по вертикали
// (используется при FitToPage = MPF_FITBYVER)
char FileCount; // Число формируемых файлов (используется при PostScript = 1)
// (1 - файл содержит все составляющие цвета C,M,Y,K или R,G,B
// 4 - каждый из четырех файлов содержит одну из
// составляющих цвета C,M,Y,K)
// 0x1FB (507)
char ColorModel; // Цветовая модель вывода в PostScript
// (0 - RGB, 1 - CMYK)
char PostScript; // Флаг PostScript-вывода
char Restore; // Флаг необходимости восстановления параметров
// из INI-файла карты (1 - есть, 0 - нет)
char TurnFrame; // Флаг поворота области выбора (1 - есть, 0 - нет)
char Decoration; // Флаг зарамочного оформления (должен быть обнулен)
} // 0x200 (512)
MAPPRINTPARMEX;
typedef struct FRAMEPRINTPARAM
{
int DeleteSite; // Признак удаления Site после печати
int TurnFrame; // Тип рамки (0 - прямая, 1 - наклонная)
DFRAME PlaneFrame; // Габариты рамки повернутые
DFRAME ExpandFrame; // Расширенные повернутые габариты рамки
double Angle; // Угол наклона рамки
HSITE SiteDecor; // Зарамочное оформление
int EnableSite; // Запрет/разрешение редактирования Sit
#ifdef _M_X64
int FramePrintZero; // Выравнивание
#endif
} FRAMEPRINTPARAM;
#endif[/CODE]
Обновленный файл примера печати в pdf:
[CODE]#include <QApplication>
#include <QPrinter>
#include "qdmcmp.h"
#include "mapapi.h"
#include "struct.h"
struct BORDER
{
DOUBLEPOINT UpLeft;
DOUBLEPOINT UpRight;
DOUBLEPOINT DownRight;
DOUBLEPOINT DownLeft;
DOUBLEPOINT UpLeftLast;
};
extern "C" {
void WINAPI SetupParam(HMAP hmap, SCRIPTPARAM *ScriptParam, DFRAME *FrameTrap);
void msInitPrintParam(MAPPRINTPARMEX *printParam, BORDER border, double frameAngle, bool isClockWise);
long int msPrintMap(HMAP hMap, SCRIPTPARAM *scriptparam, MAPPRINTPARMEX *printparam, QPrinter *printer);
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QDMapView mapView;
HMAP mapHandle = mapOpenData("/tmp/Noginsk/Noginsk.sit");
struct BORDER border;
memset(&border, 0, sizeof(border));
DFRAME FrameTrap;
mapGetTotalBorder(mapHandle, &FrameTrap, PP_PLANE);
SCRIPTPARAM ScriptParam;
memset(&ScriptParam, 0, sizeof(ScriptParam));
strncpy(ScriptParam.NameInputPost, "/tmp/mapprint.pdf", sizeof(ScriptParam.NameInputPost));
ScriptParam.Scale = mapGetShowScale(mapHandle);
ScriptParam.Resolution = 300;
ScriptParam.CutListFlag = 1; // Одностраничная печать формат - A0
MAPPRINTPARMEX printParm;
memset(&printParm, 0, sizeof(printParm));
printParm.PlaneFrame = FrameTrap;
printParm.Scale = mapGetShowScale(mapHandle);
FRAMEPRINTPARAM frameprnpar;
memset(&frameprnpar, 0, sizeof(frameprnpar));
frameprnpar.PlaneFrame = FrameTrap;
frameprnpar.ExpandFrame = FrameTrap;
QPrinter *printer = new QPrinter(QPrinter::HighResolution);
printer->setColorMode(QPrinter::Color);
// Подготовить параметры к печати
msInitPrintParam(&printParm, border, 0, true);
// Отправить на печать на выбранный принтер
msPrintMap(mapHandle, &ScriptParam, &printParm, printer);
mapCloseData(mapHandle);
return 0;
}
[/CODE]