(C / CLI) Проверка положения мыши в прямоугольнике, соответствующем родительскому

#c -cli #contains

#c -cli #содержит

Вопрос:

Я возился с классом Graphics, чтобы нарисовать некоторые вещи на панели. До сих пор для рисования я просто использовал прямоугольную структуру. На панели, нажав кнопку, она создает прямоугольник в случайном месте и добавляет его к массиву других прямоугольников (на самом деле это класс с именем 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 для выполнения фактического рисования, поскольку я использовал графику.Метод FillRectangle. Когда я изменил его, я заметил, что DrawReversibleFrame нарисован в другом месте, чем FillRectangle . Я полагаю, это связано с тем, что DrawReversibleFrame рисует со своими позициями относительно окна, в то время как FillRectangle делает это относительно любого события рисования, в котором оно находится (шахты в методе рисования панели.) Итак, позвольте мне просто показать код:

 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() прямоугольника ищет прямоугольник, относящийся к окну, а не к панели. Это то, что мне нужно исправить 🙂

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

Обновить:

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

Ответ №1:

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

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

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

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

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

Комментарии:

1. Спасибо, я думаю, мне придется немного посчитать, чтобы исправить это.

2. Круто, это делает его еще проще 🙂