Моя проблема:
System.ComponentModel.Win32Exception: «Ошибка создания дескриптора окна».
Действительно. Вы создаете слишком много элементов управления для Winforms
приложения.
И избавление от них на самом деле не помогает, потому что вы больше не можете использовать уничтоженный объект ..
Чтобы иметь такую большую головоломку ( 10k штук), вам нужно перейти от использования PictureBoxes
(или любой другой Controls
), чтобы отобразить кусочки головоломки для другого подхода. Это было предложено в оригинальном вопросе , но тогда вы хотели иметь только 100 штук, помните?
Наиболее распространенный подход заключается в следующем: ведите список изображений (если они <= 256x256 пикселей, поместите их в <code>ImageList!) И рисуйте их в событии Paint
на доске. Это избавит от всех накладных расходов, связанных с PictureBoxes
.
(Помимо: можно подумать, что это не будет работать со всеми вызовами DrawImage
. Но все эти PictureBoxes
также должны нарисовать все пиксели на всех своих поверхностях, так что это не проблема. Но они также имеют чтобы нести накладные расходы на то, чтобы быть (под капотом) полностью функциональным windows
(см. сообщение об ошибке!), поэтому в системе их может быть только ограниченное количество, всегда старайтесь сохранять количество элементов управления < 1k !)
Вам нужно будет переместить логику размещения на событие доски Paint
, а также изменить модель события ..:
Вместо того, чтобы каждый PictureBox
отвечал на свои собственные события, вам нужно будет найти способ выполнить всю работу в событиях на доске. Это должно быть различным, в зависимости от события.
Поскольку мы не знаем, какое у вас мероприятие и что они делают, и какие данные им нужны для их работы, сложно дать все необходимые подробности, поэтому я просто укажу несколько вещей ...:
Не будет никакого события Enter
или Leave
, которое вы можете использовать. Вместо этого вам нужно обнаружить вход в область фигуры, проверив ее в событии MouseMove. Если у вас есть List<Rectangle>
, вы можете использовать Rectangle.Contains(e.Location)
для этого теста.
Вы можете обнаружить MouseClick, но затем вам нужно будет определить, какая область была нажата. Если ваша логика ввода и вывода из MouseMove работает, вы можете использовать ее результат, чтобы узнать, куда щелкнул щелчок.
Подобные идеи могут быть использованы для всех других событий; некоторые из них простые, некоторые требуют небольшого расчета, но все они будут быстрыми и довольно простыми в реализации.
Чтобы оптимизировать производительность, попробуйте сделать изображение n нужного размера и используйте Format32bppPArgb в качестве формата пикселей, потому что оно быстрее отображается.
Другой вариант - извлечь данные пикселей прямо из исходного изображения в событии Paint
, используя те же вычисления, которые вы используете сейчас для их создания. (Существует оверлей DrawImage
, который использует два Rectangles
, один для определения цели и один для исходной области ...) Это сохраняет GDI
маркеры, по крайней мере, если вы не можете использовать ImageList
.
Всегда планируйте рост! Для лучшей реализации создайте класс Piece
. Он должен содержать Rectangle
и целочисленный индекс в коллекции ImageList
Images
. Он также может иметь метод Switch(Piece otherPiece)
, который будет либо переключать Rectangles
, либо индексы.
Удачи: -)