Информация об изменениях

Сообщение MM_TEXT -> MM_HIMETRIC и обратно на Windows10 от 04.04.2017 7:09

Изменено 04.04.2017 7:16 sushko

Перевод из MM_TEXT в MM_HIMETRIC на Windows10
В своей программе я много рисую при помощи функций типа Rectangle(hDC, ...), LineTo(hDC, ...) и т.п., причем по характеру задачи мне выгодно почти все рисование мерять в пикселях, а одну конкретную фигуру — в сотых долях миллиметра: SetMapMode(MM_HIMETRIC), порисовал и потом опять SetMapMode(MM_TEXT).

У меня (win8) и на тестовом компьютере (XP) все работает, а на 2 компьютерах с win10 имею неожиданный артефакт: если нарисовать точку с координатами в пикселях, потом перевести эти же координаты в сотые миллиметра и снова нарисовать точку, то эти две точки не совпадут, и чем дальше от левого верхнего угла экрана мы рисуем, тем больше это расхождение. Причем, что характерно, именно в HIMETRIC оно рисует правильно: мерял линейкой прямо по экрану.

В результате получается дурацкая ситуация: выбираем нужную фигуру в палитре фигур, щелкаем мышью в середину экрана — а фигура рисуется не там, где мы щелкнули мышкой, а со сдвигом вправо-вниз на одной win10 и влево-вверх на другой win10.

Что именно я не учел при переводе из пикселей в HIMETRIC и обратно конкретно на win10?

#define MILLIMETERS_PER_INCH 25.4

int HimetricXToPixel(CDC *pDC, int iHimetricX)
{
    double fInches = (double)iHimetricX / (MILLIMETERS_PER_INCH * 100);
    double fPixel = fInches * (double)GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSX);
    return (int)fPixel;
}

int HimetricYToPixel(CDC *pDC, int iHimetricY)
{
    double fInches = (double)iHimetricY / (MILLIMETERS_PER_INCH * 100);
    double fPixel = fInches * (double)GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSY);
    return (int)fPixel;
}

int PixelToHimetricX(CDC *pDC, int iPixel)
{
    double fInches = (double)iPixel / (double)GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSX);
    int iHimetricX = (double)100 * MILLIMETERS_PER_INCH * fInches;
    return iHimetricX;
}

int PixelToHimetricY(CDC *pDC, int iPixel)
{
    double fInches = (double)iPixel / (double)GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSY);
    int iHimetricY = 100 * MILLIMETERS_PER_INCH * fInches;
    return iHimetricY;
}
MM_TEXT -> MM_HIMETRIC и обратно на Windows10
В своей программе я много рисую при помощи функций типа Rectangle(hDC, ...), LineTo(hDC, ...) и т.п., причем по характеру задачи мне выгодно почти все рисование мерять в пикселях, а одну конкретную фигуру — в сотых долях миллиметра: SetMapMode(MM_HIMETRIC), порисовал и потом опять SetMapMode(MM_TEXT).

У меня (win8) и на тестовом компьютере (XP) все работает, а на 2 компьютерах с win10 имею неожиданный артефакт: если нарисовать точку с координатами в пикселях, потом перевести эти же координаты в сотые миллиметра и снова нарисовать точку, то эти две точки не совпадут, и чем дальше от левого верхнего угла экрана мы рисуем, тем больше это расхождение. Причем, что характерно, именно в HIMETRIC оно рисует правильно: мерял линейкой прямо по экрану.

В результате получается дурацкая ситуация: выбираем нужную фигуру в палитре фигур, щелкаем мышью в середину экрана — а фигура рисуется не там, где мы щелкнули мышкой, а со сдвигом вправо-вниз на одной win10 и влево-вверх на другой win10.

Что именно я не учел при переводе из пикселей в HIMETRIC и обратно конкретно на win10?

#define MILLIMETERS_PER_INCH 25.4

int HimetricXToPixel(CDC *pDC, int iHimetricX)
{
    double fInches = (double)iHimetricX / (MILLIMETERS_PER_INCH * 100);
    double fPixel = fInches * (double)GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSX);
    return (int)fPixel;
}

int HimetricYToPixel(CDC *pDC, int iHimetricY)
{
    double fInches = (double)iHimetricY / (MILLIMETERS_PER_INCH * 100);
    double fPixel = fInches * (double)GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSY);
    return (int)fPixel;
}

int PixelToHimetricX(CDC *pDC, int iPixel)
{
    double fInches = (double)iPixel / (double)GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSX);
    int iHimetricX = (double)100 * MILLIMETERS_PER_INCH * fInches;
    return iHimetricX;
}

int PixelToHimetricY(CDC *pDC, int iPixel)
{
    double fInches = (double)iPixel / (double)GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSY);
    int iHimetricY = 100 * MILLIMETERS_PER_INCH * fInches;
    return iHimetricY;
}