#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:
Оранжевая рамка — это то место, где я щелкнул, черная — это место ее отображения. Это показывает мне, что метод Contains() прямоугольника ищет прямоугольник, относящийся к окну, а не к панели. Это то, что мне нужно исправить 🙂
Мне интересно, происходит ли это из-за того, что столкновение проверяется вне метода рисования панелей. Но я не вижу, как я мог бы реализовать это тестирование на столкновение внутри метода Paint.
Обновить:
Хорошо, итак, я только что обнаружил, что, похоже, то, что рисуют DrawReversibleFrame и FillRectangle, всегда находится на определенном расстоянии друг от друга. Я не совсем понимаю это, но кто-то другой может.
Ответ №1:
Оба параметра Cursor::Position и DrawReversableFrame работают в экранных координатах. Это касается всего экрана, всего на вашем мониторе, а не только вашего окна. С другой стороны, FillRectangle работает с координатами окна, то есть с положением в вашем окне.
Если вы возьмете свой пример, в котором вы рисовали обоими, и два поля всегда находятся на одинаковом расстоянии друг от друга, и переместите свое окно на экран, а затем щелкните еще раз, вы увидите, что разница между двумя полями меняется. Это будет разница между верхним левым углом вашего окна и верхним левым углом экрана.
Именно поэтому, когда вы проверяете, какой прямоугольник вы щелкнули, он ничего не попадает. Вы проверяете положение курсора в координатах экрана относительно координат прямоугольника в пространстве окна. Возможно, что он попадет в один из прямоугольников, но, вероятно, это будет не тот, на который вы на самом деле нажали.
Вы всегда должны знать, в каких системах координат находятся ваши переменные. Это связано с первоначальным намерением венгерской нотации, о которой Джоэл Спольский говорит в своей записи, заставляя неправильный код выглядеть неправильно.
Обновить:
Для преобразования координат между координатами экрана и окна следует использовать PointToScreen и PointToClient.
Комментарии:
1. Спасибо, я думаю, мне придется немного посчитать, чтобы исправить это.
2. Круто, это делает его еще проще 🙂