мАСШТАБ в мИЛИМЕТРАХ
Как нарисовать линейку на Image в масштабе, т.е. деления должны рисовать через милиметр, а точнее как смаштабировать. Короче: сколько пикселей в одном милиметре. И как нарисовать линейку по вертикали и по горизонтали, и чтобы они одинаково выгледели. Если их нарисовать с одинаковыми параметрами, то деления у вертикальной будут короче. А если умножить на 1,333333 (1,33333 получается так: 800/600 или 640/480, делением количества пикселей по вертикали на пиксели по горизонтали), даже так не получается. Потому что (как я выяснил) пиксели имеют прямоугольную фому. Подскажите, пожалуста, как нарисовать это все. Если не понятен вопрос (а то я такого здесь нагородил), задайте вопрос.
Коротко говоря, Вы не должны полагаться на какие-либо допущения о возможном разрешении устройства отображения и его физической сущности. Для того, чтобы корректно работать с координатами, в Windows существуют так называемые режимы отображения. Ройте MSDN в сторону пар функций SetViewportExt/SetWindowExt и SetViewportOrg/SetWindowOrg, а также SetMapMode и всё, что с этим связано. Не забудьте о функциях, возвращающих системные метрики и системные уставки.
Спасибо за ответ.
У меня что-не выходит.
Я пишу в обработчике OnPaint формы: {
int i=SetMapMode(Canvas->Handle,MM_HIMETRIC);
i=GetMapMode(Canvas->Handle);/*проверяю постивился ли соответствующий режим*/
//рисую линию, а она не рисуется!!!
Canvas->Pen->Width=30;
Canvas->LineTo(100,100);
}
и вообще этот режим сбивается в MM_ANISOTROPIC (в режим по умолчанию) после выхода из обработчика.
Может я что-то не верно делаю. У меня нет опыта работы с этими функциями. Подскажите правильно ли я делаю. Кстати, я обладаю такой информацией, что в билдере эти функции не работают. Он ведь берет на себя графический интерфейс, и черт знает, что с ним делает. MSDN - это относится по больше части к VStudio.Net. А мне бы хотелось это сделать в билдере. Протестируйте, если можно, эту функцию в билдере.
А MSDN не только для NET хороший справочник, но и по Win32 тоже.
И ещё вот мысль появилась: от момента установки режима отображения до выхода из обработчика попробуйте использовать только функции GDI как такового. Т.е. забудьте про эти дегенеративные свойства, объекты и прочую VCL'овскую муру, используйте функции win32.
HWND hwnd;
HDC hdc;
long MapMode;
hwnd=GetDesktopWindow();
hdc=GetWindowDC(hwnd);
/*определим что устройство в природе существует и подключено*/
if(hdc>0)
{
MapMode=SetMapMode(hdc,MM_HIMETRIC);
/*выставляем нужный мод+запоминаем тот что был раньше*/
//
//мутим что-то что нам нужно
//
MapMode=SetMapMode(hdc,MapMode);
/*восстанавливаем мод+можно сделать проверку на то что когда мы закончили работу, мод был тот что нам нужен, а не подарок от VCL*/
}
/*а вообще все ф-ции завязанные на константах MM_ работают в bcb очень глючно, хотя это вполне возможно лечится прямыми руками*/
{
PAINTSTRUCT ps;
HDC hdc = ::GetDC(Handle);
::TextOut(hdc,20,20,"Тра-ля-ля",9);
int prevmm = ::SetMapMode(hdc,MM_LOMETRIC);
if(prevmm!=0)
{
POINT ovo;
::SetViewportOrgEx(hdc,0,600,&ovo);
HPEN hpen = ::CreatePen(PS_SOLID,4,0xff00ff);
HPEN prevpen = ::SelectObject(hdc,hpen);
if(::MoveToEx(hdc,0,0,NULL))
{
if(::LineTo(hdc,800,600))
{
::LineTo(hdc,600,800);
}
}
::SelectObject(hdc,prevpen);
::SetMapMode(hdc,prevmm);
}
::ReleaseDC(Handle,hdc);
}
RE:ух ты, какая загагулина)))
RE2:вообще очень темный пример, спасибо
тоже вариант, пойду побалуюсь, сам над похожей задачей работаю
RE:ух ты, какая загагулина)))
RE2:вообще очень темный пример, спасибо
;о) Да особо ничего тёмного нет. Многочисленные ифы только для проформы. Основное - это получение DC, установка MapMode, установка ViewportOrg. Константы - только для примера, в реальной проге все размеры должны браться в момент выполнения. И т.д. и т.п. Удачи ;о)
я то немножко в другую сторону работаю, меня интересует размер текста получить в мм, сначала обрадовался, прикрутил GetTextExtentPoint и хлопал в ладоши, всеравно большое расхождение, примерно миллиметра 2 на дюйм получается(((
Немудрено, ведь эта функция даёт результат в логических единицах (logical units). Их, я думаю, ещё надо к физическим преобразовывать (что-нибудь вроде LPtoDP).
Немудрено, ведь эта функция даёт результат в логических единицах (logical units). Их, я думаю, ещё надо к физическим преобразовывать (что-нибудь вроде LPtoDP).
в том то и дело
Побалуйтесь с этим:
{
PAINTSTRUCT ps;
HDC hdc = ::GetDC(Handle);
::TextOut(hdc,20,20,"Тра-ля-ля",9);
int prevmm = ::SetMapMode(hdc,MM_LOMETRIC);
if(prevmm!=0)
{
POINT ovo;
::SetViewportOrgEx(hdc,0,600,&ovo);
HPEN hpen = ::CreatePen(PS_SOLID,4,0xff00ff);
HPEN prevpen = ::SelectObject(hdc,hpen);
if(::MoveToEx(hdc,0,0,NULL))
{
if(::LineTo(hdc,800,600))
{
::LineTo(hdc,600,800);
}
}
::SelectObject(hdc,prevpen);
::SetMapMode(hdc,prevmm);
}
::ReleaseDC(Handle,hdc);
}
Спасибо, разобрался, одна проблема решена. Вторая: Как создать bmp - файл указав размер в милиметрах???
И еще, в вашем коде не зачем создавать перо и контекст устройства, в билдере это все автоматически делается. Следующий код демонстрирует это:
HDC hdc=Canvas->Handle;
Canvas->TextOut(20,20,"Тра-ля-ля");
int prevmm=SetMapMode(hdc,MM_LOMETRIC);
if(prevmm){
SetViewportOrgEx(hdc,0,600,NULL);
MoveToEx(hdc,400,400,NULL);
Canvas->LineTo(800,600);
Canvas->LineTo(600,800);
SetMapMode(hdc,prevmm);
}