Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Глюк при отрисовке 
V
    Опции темы
TGrey
Дата 22.1.2010, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 1.12.2007

Репутация: 1
Всего: 1



Здравствуйте, появился следующий прикол. Есть форма на ней рисуются Круги и Линии, а так же 4угольник.
Так вот если отрисовать КРУГ пока еще не нарисован 4угольник то круг выглядит нормально, но если это делать, когда 4угольник нарисован, то круг выглядит как-то странно
user posted image
С права нормальный вариант КРУГОВ. По сути это ГПИ(начинающий), поэтому эти элементы выделяются.
Так вот если создать 4кгольник и выделить круги то результат будет как на картинке с лева, а потом если выделить 4угольник, то круги приобретают нормальную форму, как с права.
Я думаю это возможно из-за того, что 4угольник может поворачиваться через XFORM и возможно координаты как-то меняются, что изменяет форму круга.
Есть идеи?
PM MAIL   Вверх
GremlinProg
Дата 23.1.2010, 08:54 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



кусочек кода был бы уместен


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
TGrey
Дата 23.1.2010, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 1.12.2007

Репутация: 1
Всего: 1



Так я даже не знаю, кусочек какой части кода будет уместен. Если бы я понимал причину этого эффекта, я бы возможно методом тыка, что-то надумал. А так я даже не знаю, от куда начинать.

Вот надыбал
Код

void IResistance::Draw(HDC *dc)
{
    HBRUSH lettuceBrush = CreateSolidBrush(RGB(0, 250, 0));

    if( !selected )
        SelectPen(*dc, RP);
    else
        SelectPen(*dc, SRP);

    //Rotate(dc);

    MoveToEx(*dc, GetSLX(), GetSLY(), NULL);
    LineTo(*dc, GetSRX(), GetSRY());
    LineTo(*dc, GetERX(), GetERY());
    LineTo(*dc, GetELX(), GetELY());
    LineTo(*dc, GetSLX(), GetSLY());

    if( selected )
    {
        SelectBrush(*dc, lettuceBrush);
        SelectPen(*dc, RP);
        int px = abs(GetSLX() - GetSRX()) / 2;
        int py = abs(GetELY() - GetERY()) / 2;
        Ellipse(*dc, (GetSLX()+px)-4, (GetSLY()+py)-4, (GetSLX()+px)+4, (GetSLY()+py)+4);
        Ellipse(*dc, (GetERX()-px)-4, (GetERY()-py)-4, (GetERX()-px)+4, (GetERY()-py)+4);
    }

    SetWorldTransform(*dc,&Desk->Normal);
}


Вот если убрать функцию Rotate(dc); то круг не изменяется.
Код

void IResistance::Rotate(HDC *dc)
{
    double ang = Angle * 3.14 / 180.;
    double s = sin(ang);
    double c = cos(ang);

    xform.eM11 = xform.eM22 = c;
    xform.eM12 = s;
    xform.eM21 = -s;
    xform.eDx =  Start.x -  Start.x * xform.eM11 -  Start.y * xform.eM21;
    xform.eDy =  Start.y -  Start.x * xform.eM12 -  Start.y * xform.eM22;

    SetGraphicsMode(*dc, GM_ADVANCED);
    SetWorldTransform(*dc, &xform);
}


Вот тут и есть проблема.

Это сообщение отредактировал(а) TGrey - 23.1.2010, 14:59
PM MAIL   Вверх
GremlinProg
Дата 23.1.2010, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(TGrey @  23.1.2010,  16:50 Найти цитируемый пост)
Если бы я понимал причину этого эффекта, я бы возможно методом тыка, что-то надумал. А так я даже не знаю, от куда начинать.

скрыть Rotate и есть метод тыка )

у меня пока 3 мысли:

1. почему SetGraphicsMode вызывается в Rotate, когда в конце вывода графики стоит SetWorldTransform (как понимаю - восстановление единичной матрицы преобразования)

SetWorldTransform работает только в GM_ADVANCED, так что лучше вынести смену режима из каких-либо дополнительных методов, а самый главный

GM_ADVANCED, помимо преобразований влияет еще на простые GDI-функции,
так что разногласия при таких условностях в принципе закономерны

2. не считал матрицу поворота, но она должна образовываться из умножения 3-х матриц: 
 - перенос фигуры из точки, вокруг которой нужно ее повернуть в ноль
 - сам поворот
 - перенос фигуры обратно в точку, вокруг которой нужно ее повернуть

все соответствует?

3. все функции возвращают результат, можно проверить что не выполняется


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
artsb
Дата 23.1.2010, 18:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 5
Всего: 64



GremlinProg, прав на счёт SetWorldTransform.
Тогда лучше так:
Код

void IResistance::Rotate(HDC *dc)
{
    int OldMode;
    OldMode = SetGraphicsMode(*dc, GM_ADVANCED);
    SetWorldTransform(*dc, &xform);

    double ang = Angle * 3.14 / 180.;
    double s = sin(ang);
    double c = cos(ang);
    xform.eM11 = xform.eM22 = c;
    xform.eM12 = s;
    xform.eM21 = -s;
    xform.eDx =  Start.x -  Start.x * xform.eM11 -  Start.y * xform.eM21;
    xform.eDy =  Start.y -  Start.x * xform.eM12 -  Start.y * xform.eM22;

    SetGraphicsMode(*dc, OldMode);
}




--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
TGrey
Дата 23.1.2010, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 1.12.2007

Репутация: 1
Всего: 1



Та все вроде работает, поворачивает на все 360 градусов нормально. Я думал возможно после Фнкции поворота очистить экран, чтобы оно могла отрисовать уже с нормальными координатами. Но плохо то, что сстановка норм. коорд происходит после отрисовки 4угольника. Поэтому если потом вызывать Invalidate, то стирается и сам рисунок.
PM MAIL   Вверх
TGrey
Дата 23.1.2010, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 1.12.2007

Репутация: 1
Всего: 1



Не не помогло возвращать ГрафикМод. Все равно круг выглядит странно, до тех пор пока, не выделить 4угольник.
А функция выделения устанавливает только флаг, что оно выделено. После чего обновляется окно. Но такой же эффект происходит и с выделением круга, почему оно его не возвращает в нормальное состояние smile 
PM MAIL   Вверх
artsb
Дата 23.1.2010, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 5
Всего: 64



Цитата(TGrey @  23.1.2010,  19:06 Найти цитируемый пост)
Не не помогло возвращать ГрафикМод.

Конечно не видя кода, тяжело что-то сказать... Попробуйте например и координаты в исходное состояние вернуть:
Код

void IResistance::Rotate(HDC *dc)
{
    int OldMode;
    OldMode = SetGraphicsMode(*dc, GM_ADVANCED);
    double ang = Angle * 3.14 / 180.;
    double s = sin(ang);
    double c = cos(ang);
    xform.eM11 = xform.eM22 = c;
    xform.eM12 = s;
    xform.eM21 = -s;
    xform.eDx =  Start.x -  Start.x * xform.eM11 -  Start.y * xform.eM21;
    xform.eDy =  Start.y -  Start.x * xform.eM12 -  Start.y * xform.eM22;
    SetWorldTransform(*dc, &xform);
   // рисуем наклонённую фигуру
   // восстанавливаем координаты и режим 
    xform.eM11 = 1.0;
    xform.eM12 = 0.0;
    xform.eM21 = 0.0;
    xform.eM22 = 1.0;
    xform.eDx =  0.0;
    xform.eDy =  0.0;
    SetWorldTransform(*dc, &xform);
    SetGraphicsMode(*dc, OldMode);
}

Может для вас в этой же функции не удобно рисовать и восстанавливать координаты (я же не знаю smile). Но думаю суть понятна: после отрисовки наклонённой фигуры, восстановить координаты.


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
TGrey
Дата 23.1.2010, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 1.12.2007

Репутация: 1
Всего: 1



Так они и так восстанавливаются.
Код

void IResistance::Draw(HDC *dc)
{
    HBRUSH lettuceBrush = CreateSolidBrush(RGB(0, 250, 0));
    if( !selected )
        SelectPen(*dc, RP);
    else
        SelectPen(*dc, SRP);
    //Rotate(dc);
    MoveToEx(*dc, GetSLX(), GetSLY(), NULL);
    LineTo(*dc, GetSRX(), GetSRY());
    LineTo(*dc, GetERX(), GetERY());
    LineTo(*dc, GetELX(), GetELY());
    LineTo(*dc, GetSLX(), GetSLY());
    if( selected )
    {
        SelectBrush(*dc, lettuceBrush);
        SelectPen(*dc, RP);
        int px = abs(GetSLX() - GetSRX()) / 2;
        int py = abs(GetELY() - GetERY()) / 2;
        Ellipse(*dc, (GetSLX()+px)-4, (GetSLY()+py)-4, (GetSLX()+px)+4, (GetSLY()+py)+4);
        Ellipse(*dc, (GetERX()-px)-4, (GetERY()-py)-4, (GetERX()-px)+4, (GetERY()-py)+4);
    }
    SetWorldTransform(*dc,&Desk->Normal);
}


В самом низу установка норм. коорд. + я дописал еще ГрафМод останавливать, но тоже ничего.
PM MAIL   Вверх
artsb
Дата 23.1.2010, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 5
Всего: 64



Цитата(TGrey @  23.1.2010,  23:30 Найти цитируемый пост)
Так они и так восстанавливаются.

Сори. Не посмотрел smile

Цитата(TGrey @  23.1.2010,  23:30 Найти цитируемый пост)
В самом низу установка норм. коорд. + я дописал еще ГрафМод останавливать, но тоже ничего. 

Странно. Надо бы всю прогу глянуть. Что и как устроено. Может вы в логике где-то ошиблись...


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
TGrey
Дата 24.1.2010, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 1.12.2007

Репутация: 1
Всего: 1



Так а логика тут при чем? Тут работают 3 функции.
Клик, Поворот, Отрисовка.
Код

bool IResistance::OnClick(int x, int y)
{
    if ( GetSide(x, y) == 0 && selected )
    {
        MessageBox(NULL,  "Ïîïàë 1", "OnClick", 0);
    }
    if ( GetSide(x, y) == 1 && selected )
    {
        MessageBox(NULL, "Ïîïàë 2", "OnClick", 0);
    }

    if ( (CheckSel(x, y, GetSLX(), GetSLY(), GetSRX(), GetSRY()) >= 0) 
        && (CheckSel(x, y, GetERX(), GetERY(), GetELX(), GetELY()) >= 0) 
        && (CheckSel(x, y, GetELX(), GetELY(), GetSLX(), GetSLY()) >= 0) 
        && (CheckSel(x, y, GetSRX(), GetSRY(), GetERX(), GetERY()) >= 0) )
    {
        selected = Moving = true;
        //offsetx = x;
        //offsety = y;
        Desk->SetSelected(this);
        UpdateZOrder();
        return true;
    }
    return false;
}

Вот функция клика, все что она делает это устанавливает флаг ВЫДЕЛЕНО. Больше она ни на что не влияет.
Поэтому выполняется все так
Click->InvalidateRect->Draw->Rotate

------------------------------
Посидев, потыкав нашел вот что. При клике по объекту вызывается функция UpdateZOrder(); которая выводит на верхний план выделенный объект, а все объекты записаны в векторе и во время отрисовки рисуются тоже по вектору. Поэтому и выходит, что если выделить 4угольник, то круг становится меньше Зордером и рисуется ДО 4угольника и значит ДО изменения координат. Потом же если выбрать круг, то 4угольк падает ниже и рисуется раньше круга, поэтому круг уже идет со смещением.
Это выходит, что преобразование к нормальным координатам, устанавливает не совсем нормальные координаты как хотелось бы.
А за нормальные мой друг взял
Код

    Normal.eM11 = Normal.eM22 = 1;
    Normal.eM12 = Normal.eM21 = Normal.eDx = Normal.eDy = 0;

PM MAIL   Вверх
GremlinProg
Дата 24.1.2010, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(GremlinProg @  23.1.2010,  19:30 Найти цитируемый пост)
GM_ADVANCED, помимо преобразований влияет еще на простые GDI-функции,так что разногласия при таких условностях в принципе закономерны


чтобы не быть голословным, выполни следующий код в любом месте WM_PAINT
Код

PAINTSTRUCT ps;
INT gMode = NULL;
...
hBrush    = ::GetStockObject( BLACK_BRUSH );
hBrush    = ::SelectObject( ps.hdc, hBrush );
//gMode = ::SetGraphicsMode( ps.hdc, GM_ADVANCED );
::Ellipse( ps.hdc, 0, 0, 12, 12 );
::SelectObject( ps.hdc, hBrush );
//::SetGraphicsMode( ps.hdc, gMode );
...

запусти программу, сделай скриншот,
а теперь раскомментируй строки, запусти программу и снова сделай скриншот,
сравни результаты

Цитата(GremlinProg @  23.1.2010,  19:30 Найти цитируемый пост)
лучше вынести смену режима из каких-либо дополнительных методов, а самый главный




--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
TGrey
Дата 24.1.2010, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 1.12.2007

Репутация: 1
Всего: 1



Хорошо, сейчас попробую, но у меня возникла такая идея, что раз после преобразования коорд. в норм состояние они становятся не совсем нормальными, то можно сразу в OnPaint к примеру до отрисовки чего-либо изменить их на те НЕ совсем нормальные коорды. После чего когда нарисуется повернутый четырехугольник и оно вернет коорды. в норм состояние, круги и т.п. уже будут рисоваться тоже по нем.
Тогда конечно немного странная форма останется, но по крайней мере не будет изменятся после кликов.
PM MAIL   Вверх
artsb
Дата 24.1.2010, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 5
Всего: 64



Цитата(TGrey @  24.1.2010,  11:30 Найти цитируемый пост)
можно сразу в OnPaint к примеру до отрисовки чего-либо изменить их на те НЕ совсем нормальные коорды. После чего когда нарисуется повернутый четырехугольник и оно вернет коорды. в норм состояние, круги и т.п. уже будут рисоваться тоже по нем.

Я про это и толковал ;)

Цитата(TGrey @  24.1.2010,  11:30 Найти цитируемый пост)
Тогда конечно немного странная форма останется, но по крайней мере не будет изменятся после кликов. 

А может сейчас странная форма... smile


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
TGrey
Дата 24.1.2010, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 1.12.2007

Репутация: 1
Всего: 1



Та не) После преобразования круги не совсем круглые какие-то.
artsb я видимо не допонял суть.
Ну я попробовал, в общем нормально, придется привыкать к таким кружкам)
По видимому вопрос решен. Будут предложения - пишите.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0826 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.