У меня есть код для печати, который рисует сетку на бумаге.
Сетка состоит из 4 столбцов одинаковой длины по горизонтали. Высота ячейки составляет десятые доли размера бумаги. Общее количество строк неизвестно, но я точно знаю, что будет хотя бы одна строка.
Каждая ячейка имеет одинаковый физический размер -> ширина составляет четверть ширины бумаги, а высота составляет одну десятую высоты бумаги. Максимальное количество символов, которое может уместиться в ячейке, - 50.
Проблема, с которой я сталкиваюсь, заключается в выборе правильного размера шрифта, чтобы текст максимальной длины мог поместиться в ячейку.
Просматривая документацию MSDN и WinAPI
примеры, я увидел, что они используют GetTextExtPoint32
для аналогичных целей, но это работает, только если шрифт уже существует и выбран в контексте устройства, что не дело здесь.
Единственное, что пришло мне в голову, это создать «фиктивный шрифт», посмотреть, поместится ли текст примера в ячейку, а затем отрегулировать его размер, если тест не пройден. Я также нашел этот блог, который рекомендует интересный подход к этому проблема, но из-за неопытности я не могу решить, «правильный ли это путь».
Вы можете порекомендовать правильное решение моей проблемы?
ИЗМЕНЕНО 30 июня 2014 г .:
Ниже приведен пример функции, которая рисует сетку и окрашивает верхнюю левую ячейку в светло-серый цвет, поскольку эта ячейка будет содержать образец текста. Таким образом мы можем визуально проверить успешность нашего кода рисования:
// hWnd is the window that owns the property sheet.
HRESULT GDI_PRINT(HWND hWnd)
{
HRESULT hResult;
PRINTDLGEX pdx = {0};
LPPRINTPAGERANGE pPageRanges = NULL;
// Allocate an array of PRINTPAGERANGE structures.
pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
if (!pPageRanges)
return E_OUTOFMEMORY;
// Initialize the PRINTDLGEX structure.
pdx.lStructSize = sizeof(PRINTDLGEX);
pdx.hwndOwner = hWnd;
pdx.hDevMode = NULL;
pdx.hDevNames = NULL;
pdx.hDC = NULL;
pdx.Flags = PD_RETURNDC;
pdx.Flags2 = 0;
pdx.ExclusionFlags = 0;
pdx.nPageRanges = 0;
pdx.nMaxPageRanges = 10;
pdx.lpPageRanges = pPageRanges;
pdx.nMinPage = 1;
pdx.nMaxPage = 1000;
pdx.nCopies = 1;
pdx.hInstance = 0;
pdx.lpPrintTemplateName = NULL;
pdx.lpCallback = NULL;
pdx.nPropertyPages = 0;
pdx.lphPropertyPages = NULL;
pdx.nStartPage = START_PAGE_GENERAL;
pdx.dwResultAction = 0;
// Invoke the Print property sheet.
hResult = PrintDlgEx(&pdx);
if ( ( hResult == S_OK ) && ( pdx.dwResultAction == PD_RESULT_PRINT ) )
{
// User clicked the Print button,
// so use the DC and other information returned in the
// PRINTDLGEX structure to print the document.
//======= Various initializations ==========//
DOCINFO diDocInfo = {0};
diDocInfo.cbSize = sizeof( DOCINFO );
diDocInfo.lpszDocName = L"Testing printing...";
int pageWidth = GetDeviceCaps( pdx.hDC, HORZRES ),
pageHeight = GetDeviceCaps( pdx.hDC, VERTRES );
//===================== IMPORTANT !!! ==========================//
// Must test this on real printer !!! //
// For now testing is done in XPS and MS OneNote2007 //
//==============================================================//
//================== end of initialization =====================//
if( StartDoc( pdx.hDC, &diDocInfo ) > 0 )
{
if( StartPage( pdx.hDC ) > 0 )
{
//===== creating red pen that will draw grid =====//
LOGBRUSH lb;
lb.lbColor = RGB( 255, 0, 0 );
lb.lbHatch = 0;
lb.lbStyle = BS_SOLID;
HPEN hPen = ExtCreatePen( PS_COSMETIC | PS_SOLID, 1, &lb, 0, NULL);
HGDIOBJ oldPen = SelectObject( pdx.hDC, hPen );
// create test font
HFONT font, oldFont;
long lfHeight = -MulDiv( 14,
GetDeviceCaps( pdx.hDC, LOGPIXELSY ),
72 );
font = CreateFont( lfHeight, 0, 0, 0,
FW_BOLD, TRUE, FALSE, FALSE,
0, 0, 0,
0, 0, L"Microsoft Sans Serif" );
oldFont = SelectFont( pdx.hDC, font );
SetBkMode( pdx.hDC, TRANSPARENT );
SetTextColor( pdx.hDC, RGB( 255, 0, 0 ) );
// testing rectangle -> top left cell of the grid
RECT rcText;
rcText.left = 0;
rcText.top = 0;
rcText.right = pageWidth / 4;
rcText.bottom = pageHeight / 10;
// fill destination rectangle with gray brush
// so we can visually validate rectangle coordinates
FillRect( pdx.hDC, &rcText, (HBRUSH)GetStockObject(LTGRAY_BRUSH) );
// implement solution mentioned in the comment to this question
SIZE s;
::GetTextExtentPoint32( pdx.hDC,
L"Хидрогеотермална енергија Хидрогеотермална енерги",
wcslen( L"Хидрогеотермална енергија Хидрогеотермална енерги" ),
&s );
// select old font back and dispose test font
SelectObject( pdx.hDC, oldFont );
DeleteObject( font );
// adjust font height
lfHeight *= s.cy / ( rcText.bottom - rcText.top );
// now we can create proper font
font = CreateFont( lfHeight, 0, 0, 0,
FW_BOLD, TRUE, FALSE, FALSE,
0, 0, 0,
0, 0, L"Microsoft Sans Serif" );
oldFont = SelectFont( pdx.hDC, font );
// draw text in test rectangle
DrawTextEx( pdx.hDC,
L"Хидрогеотермална енергија Хидрогеотермална енерги",
wcslen( L"Хидрогеотермална енергија Хидрогеотермална енерги" ),
&rcText, DT_CENTER | DT_WORDBREAK | DT_NOCLIP, NULL );
//============== draw a testing grid ===============//
// draw vertical lines of the grid
for( int i = 0; i <= pageWidth; i += pageWidth / 4 )
{
MoveToEx( pdx.hDC, i, 0, NULL );
LineTo( pdx.hDC, i, pageHeight );
}
// draw horizontal lines of the grid
for( int j = 0; j <= pageHeight; j += pageHeight / 10 )
{
MoveToEx( pdx.hDC, 0, j, NULL );
LineTo( pdx.hDC, pageWidth, j );
}
// no need for pen anymore so delete it
SelectObject( pdx.hDC, oldPen );
DeleteObject( hPen );
// no need for font, delete it
SelectFont( pdx.hDC, oldFont );
DeleteFont( font );
if( EndPage( pdx.hDC ) < 0 )
// for now pop a message box saying something went wrong
MessageBox( hWnd, L"EndDoc failed!", L"Error", MB_OK );
}
EndDoc( pdx.hDC );
}
}
if (pdx.hDevMode != NULL)
GlobalFree(pdx.hDevMode);
if (pdx.hDevNames != NULL)
GlobalFree(pdx.hDevNames);
if (pdx.lpPageRanges != NULL)
GlobalFree(pPageRanges);
if (pdx.hDC != NULL)
DeleteDC(pdx.hDC);
return hResult;
}
Чтобы использовать эту функцию, просто запустите ее нажатием кнопки / выбором меню или чем-то еще.
Результаты в XPS кажутся согласованными, но я получаю странные результаты в MS OneNote 2007, которые иллюстрируют следующие изображения:
Размер шрифта 14:
Размер шрифта 20:
Размер шрифта 20, но было применено масштабирование из вышеуказанной функции:
КОНЕЦ РЕДАКТИРОВАНИЯ
ИЗМЕНЕНО 6 июля 2014 г .:
Третье изображение сверху было результатом GDI
использования значения высоты по умолчанию, потому что результат моей математической корректировки высоты шрифта был 0
. Как только передается в CreateFont указанное поведение ожидается.
После правильного преобразования с double
в int
я получил почти идеальный результат -> последняя буква в строке едва превышает предел. Я буду продолжать попытки улучшить эту формулу, поскольку считаю ее многообещающей. Если у кого-то есть другое математическое решение, не стесняйтесь публиковать его.
КОНЕЦ РЕДАКТИРОВАНИЯ
Если требуется дополнительная информация / редактирование, оставьте комментарий, и я отвечу как можно скорее.
DrawTextExt
для рисования тестовой строки, а тестовая строка состоит из нескольких слов. Текст должен быть выровнен по центру. Несмотря на то, что вся тестовая строка помещается в ячейку, центрирование по вертикали некорректно. При необходимости я дополню свой пост небольшим демонстрационным фрагментом. Возможно, я неправильно вас понял или неправильно применил ваш совет. С уважением. - person AlwaysLearningNewStuff   schedule 30.06.2014