(C ++ / CLI) Проверка положения мыши в прямоугольнике, передаваемом родителю - PullRequest
0 голосов
/ 23 октября 2011

Я возился с Графическим классом , чтобы рисовать некоторые элементы на панели. Что касается рисования, я только что использовал Прямоугольную структуру . На панели, нажав кнопку, он создает прямоугольник в произвольном месте и добавляет его в массив других прямоугольников (на самом деле это класс с именем UIElement, который содержит член Rectangle). При нажатии на эту панель она запускает тест со всеми элементами, чтобы определить, находится ли мышь внутри какого-либо из них, например:

void GUIDisplay::checkCollision()
{
    Point cursorLoc = Cursor::Position;
    for(int a = 0; a < MAX_CONTROLS; a++)
    {
        if(elementList[a] != nullptr)
        {
            if(elementList[a]->bounds.Contains(cursorLoc))
            {
                elementList[a]->Select();
                //MessageBox::Show("Click!", "Event");
                continue;
            }
            elementList[a]->Deselect();
        }
    }
    m_pDisplay->Refresh();
}

Проблема в том, что когда я щелкаю прямоугольник, ничего не происходит.

Класс UIElement рисует свои прямоугольники в следующем фрагменте кода. Тем не менее, я немного изменил его, потому что в этом примере он использует метод DrawReversibleFrame для фактического рисования, как я использовал Graphics.FillRectangle метод. Когда я изменил его, я заметил, что DrawReversibleFrame рисовал в другом месте, чем FillRectangle. Я полагаю, что это потому, что DrawReversibleFrame рисует с его позициями относительно окна, в то время как FillRectangle делает это относительно любого события Paint, в котором он присутствует (Mines в методе Paint панели). Итак, позвольте мне просто показать код:

void UIElement::render(Graphics^ g)
{
    if(selected)
    {
        Pen^ line = gcnew Pen(Color::Black, 3);
        //g->FillRectangle(gcnew SolidBrush(Color::Red), bounds);
        ControlPaint::DrawReversibleFrame(bounds, SystemColors::Highlight, FrameStyle::Thick);
        g->FillRectangle(gcnew SolidBrush(Color::Black), bounds);
        //g->DrawLine(line, bounds.X, bounds.Y, bounds.Size.Width, bounds.Size.Height);
    }
    else
    {
        ControlPaint::DrawReversibleFrame(bounds, SystemColors::ControlDarkDark, FrameStyle::Thick);
        //g->FillRectangle(gcnew SolidBrush(SystemColors::ControlDarkDark), bounds);
    }
}

Я добавляю и DrawReverisbleFrame, и FillRectangle, чтобы я мог видеть разницу. Вот как это выглядело, когда я щелкнул рамку, нарисованную DrawReversibleFrame:

http://i.imgur.com/asStd.png

Оранжевая рамка - там, где я щелкнул, черная - там, где ее рендеринг. Это показывает, что метод Contains () Rectangle ищет прямоугольник, соответствующий окну, а не панели. Это то, что мне нужно исправить:)

Мне интересно, происходит ли это, потому что столкновение проверяется вне метода рисования панелей. Но я не понимаю, как можно реализовать это тестирование столкновений в методе Paint.

UPDATE:

Хорошо, поэтому я только что обнаружил, что кажется, что то, что рисуют DrawReversibleFrame и FillRectangle, всегда на некотором расстоянии друг от друга. Я не совсем понимаю это, но кто-то другой мог бы.

1 Ответ

2 голосов
/ 23 октября 2011

Оба Cursor :: Position и DrawReversableFrame работают в экранных координатах.Это касается всего экрана, всего на вашем мониторе, а не только вашего окна. FillRectangle , с другой стороны, работает с координатами окна, то есть позицией в вашем окне.

Если вы берете свой пример, где вы рисуете с обоими, и эти два поля всегда находятся на одинаковом расстоянииРаздвиньте окно и переместите его на экран, затем нажмите еще раз, и вы увидите, что разница между двумя полями меняется.Это будет разница между верхним левым углом вашего окна и верхним левым углом экрана.

По этой же причине, когда вы проверяете, какой прямоугольник вы щелкнули, ничего не попало.Вы проверяете положение курсора в координатах экрана относительно координат прямоугольника в пространстве окна.Возможно, он попадет в один из прямоугольников, но, вероятно, это будет не тот, на который вы на самом деле нажали.

Вы должны всегда знать, в каких системах координат находятся ваши переменные. Это связано спервоначальное намерение Венгерская нотация , о котором Джоэл Спольски говорит в своей записи Создание неправильного кода, выглядит неправильно .

Обновление:
PointToScreen и PointToClient следует использовать для преобразования координат между координатами экрана и окна.

...