Примечание: Данная статья публикуется
с небольшими сокращениями,
дополнениями и исправлениями.
Оригинал статьи находится на сайте http://www.rsdn.ru/article/dotnet/winforms2.xml
В новой версии Visual Studio .NET 2005 ожидается несколько коренных изменений. Чтобы узнать, чем же в новой версии можно будет «скрасить» свои будни, я исследовал библиотеку System.Windows.Forms.dll (в предварительной версии Community Technical Preview). Изменений в WinForms нашлось немало — наберётся где-то на небольшой праздник.
Здесь, например, стоит упомянуть развитие понятия Layout, усовершенствование связывания (DataBinding), расширенную поддержку тем XP и другие изменения.
В этом разделе — как крупные, так и небольшие, но полезные доработки существующих контролов. Практически во всех контролах так или иначе детализированы свойства, добавлены новые функции. Например, большинство контролов в новой версии поддерживают режим OwnerDraw.
Два действительно новых контрола, WebBrowser и ActiveDocumentHost, относятся к взаимодействию с умирающим миром ActiveX. В новой версии вы сможете расположить на форме HTML-страницу или OLE-документ одним-двумя щелчками мыши.
Здесь достойны упоминания добавление новых методов в классе Application, двойная буферизация и многое другое.
Есть две новости — плохая и хорошая. Плохая: в новой версии придётся выбросить на помойку все полюбившиеся приёмы, при помощи которых вы приучали контролы к темам Windows XP.
Вы привыкли устанавливать FlatStyle в значение System? Теперь это бесполезное занятие.
А вот хорошая новость: теперь все контролы автоматически — врождённо — поддерживают темы Windows XP. Вам не понадобятся ваши устаревшие приёмчики, потому что темы работают и без этой самодеятельности!
Обидно, да? Нет, это ещё рано делать выводы. Подумайте вот над какой функцией.
Включить/выключить поддержку тем теперь можно прямо на ходу, во время работы приложения. Не верится? Ничего, это еще не все.
Любители спецэффектов могут включать-выключать темы отдельно для клиентской и неклиентской части окна. Грубо говоря, клиентская часть окна — это кнопочки и всякие чек-боксики. А неклиентская часть — скроллбар и заголовок формы. А вот как это выглядит:
Рисунок 1
Рисунок 2
Рисунок 3
Рисунок 4
Переключение тем производится установкой свойства VisualStylesState в объекте Application. На рисунках можно увидеть особенности каждого режима: каждая кнопка устанавливает своё значение VisualStylesState.
Внутренний механизм отрисовки контролов немного переделан для использования тем. Для каждого стандартного контрола, например, Button введён специальный класс-рендерер, ответственный за отрисовку этого контрола. Для Button это ButtonRenderer. Пока по документации не очень ясно, как можно ещё использовать такой Renderer, и даёт ли этот механизм какие-то дополнительные бонусы, кроме собственно поддержки тем.
Плюс к тому, добавлено новое пространство имён, System.Windows.Forms.VisualStyles. Здесь можно найти порядка сотни перечислений (enum), которые, по-видимому, используются внутри логики рисования. Эти перечисления указывают такие особенности, как вдавленное/приподнятое отображение, всяческие градиенты, эффекты размытых теней и пр. Прямого применения для этой информации я не вижу. Возможно, в окончательной версии .NET Framework все перечисления из VisualStyles будут скрыты (internal).
В новой версии .NET Framework контролы WinForms приобретут некоторые свойства HTML-контролов – например, Padding, Margin и AutoSize.
В классе Control (а значит во всех контролах) введены два новых свойства. Те, кто знаком со стилями HTML/CSS уже поняли, для чего это используется. Это отступы — внутри и снаружи контрола.
Padding задаёт внутренний «отступ», как бы «поля». Примерно вот так:
Рисунок 5.
Margin должен задавать такие же расстояние между контролом и его соседями. К сожалению, пока это свойство работает только в Design-Time, например, при перетаскивании контрола на форме.
Свойства Padding и Margin, как видно из рисунка, будут работать не только для плоских контролов-контейнеров вроде Panel, но и для любых контролов, содержащих «контент». В том числе для Button, Label и др.
Два новых контрола-контейнера предназначены для автоматического расположения контролов. FlowLayoutPanel располагает контролы один за другим: слева направо и сверху вниз. TableLayoutPanel располагает контролы в колонки, образуя ячейки некой виртуальной таблицы.
Таким образом, если вы начнёте помещать какие-нибудь кнопки и надписи в FlowLayoutPanel, они автоматически выстроятся в рядочек.
Вещь явно полезная, но сценарий использования в реальной жизни привести не могу. Придумайте сами, зачем это нужно.
Этот, безусловно, полезный контрол — один из примеров того, как в новой версии Visual Studio поставлена работа над повышением производительности труда. SplitContainer представляет собой две панели и сплиттер-разделитель «в одном флаконе».
Казалось бы, сделать такую комбинацию из Panel и Splitter можно за пару минут. Но почему не сберечь эти пару минут и не избавить людей от рутины?
Сам контрол устроен несложно. При изменении размеров окна положение сплиттера может измениться пропорционально, или одна из панелей будет «зафиксирована», а вторая начнёт «растягиваться». Можно также скрыть одну из панелей.
А контролы-панели доступны через свойства Panel1 и Panel2. Почему не PanelLeft и PanelRight? Да потому, что SplitContainer может быть разделен как по вертикали, так и по горизонтали.
Изменения в DataBinding пока не приняли законченных очертаний, их функциональность ещё недостаточно документирована. Опишу только направления разработок.
Очевидно, с появлением generic-интерфейсов и generic-коллекций, DataBinding должен быть доработан для их поддержки. И здесь есть один головоломный момент.
Обычное «старое» связывание работает с помощью интерфейса IList. Например, какой-нибудь ListBox может отобразить элементы любого списка IList как строки. Это возможно потому, что все объекты, реализующие IList, можно привести к одному общему интерфейсу.
Но объекты, реализующие IList<T> невозможно привести к общему интерфейсу. У одного класса это может быть IList<DataRow>, у другого – IList<string>, и эти интерфейсы несовместимы! Мало того, один и тот же класс может реализовать и IList<DataRow>, и IList<string>, и IList<double>. Какой же интерфейс тогда нужно использовать для отображения в контроле?
Очевидно, ребята из Микрософта как-то справятся с этой ситуацией, но документация пока этого не проясняет.
Одним из основных «направлений удара» в новом .NET Framework 2.0 будет работа с XML, долгожданный System.XML v2.0. Скорость работы с XML-данными возрастёт значительно, добавится поддержка последних стандартов, новых методов обработки — и многое другое. Со стороны WinForms эту инициативу обещает поддержать возможность прямого DataBinding'а между XML-данными и контролами.
В новом ADO.NET в придачу к DataTable появится класс DbTable. Это и другие смежные изменения позволят (по крайней мере, это анонсировалось) автоматизировать получение и отправку данных между клиентом и сервером. Там, где сейчас нужно создавать DataAdapter, вручную вызывать метод Fill, — теперь можно будет просто настроить некоторые связи в дизайнере, и данные будут доставляться автоматически.
Для этого должна быть доработана как ADO.NET, так и WinForms-составляющая.
В первой версии .NET Framework компания Микрософт предлагала только один контрол для отображения табличных данных, DataGrid. Почему один? Меньше — не имело смысла. Видимо, аналитики сочли этот контрол подходящим решением на все случаи жизни.
Итак, потребность в новом табличном контроле, решающем проблемы DataGrid, будет удовлетворена с выходом новой версии .NET Framework.
Впрочем, в Visual Studio Codename Widbey (PDC build) был похожий контрол с названием Table. Так сказать, бедный родственник нашего перспективного вундеркинда GridView. Он был помечен атрибутом Obsolete и объявлен устаревшим ещё в альфа-версии.
В теперешней предварительной версии Visual Studio 2005 CTP тоже есть свой «бедный родственник». Некий DataGridView — то ли это действительно возможное действующее лицо, то ли такой же мимолётный фантом, как и почивший Table.
Складывается впечатление, что поветрие повального гридостроительства не обошло стороной даже разработчиков из Микрософта. Ну что ж, пока побеждает команда GridView. Интерестно, какой приз у них назначен победителю?
Этот контрол легко может вызвать приступ дежа-вю у знатоков Дельфи. Функция DataNavigator — управлять позицией и состоянием «курсора» коллекций и таблиц. Сейчас точные свойства и внешний вид этого контрола ещё не устоялся, поэтому я не буду его детально описывать. Предполагается, что контрол будет представлять собой набор кнопок типа «Вперёд», «Назад», «Добавить», «Удалить».
Рассказать об этом контроле проще всего на простом примере.
Я пишу программы для торговли, и в таких программах почти всегда требуется отображать форму-карточку товара: название, цена, и другие свойства. Это обычный подход. Если вы пишете учёт кадров, у вас будет карточка сотрудника. Автоматизация производства — карточка узла или детали.
Как мы обычно делаем такие формы-карточки? Очень просто: берём контролы — Label, TextBox, ComboBox — и кладём их на форму в каком-то порядке по вкусу. Но на самом деле это работа интересна только первые два часа.
DataContainer создан, чтобы выполнить эту скучную работу за вас. Вы указываете источник данных, назначаете стиль, после чего DataContainer создаёт набор полей и располагает его в более-менее прилизанном порядке.
Что каждый программист-новичок начинает делать после создания объёмных Label с эффектом тени? Конечно, тулбары в стиле Office XP и Office 2003. Теперь новичкам придётся мастерить другие велосипеды, потому что в .NET Framework 2.0 будут входить готовые классы ToolStrip, MenuStrip и StatusStrip. Впрочем, точные названия могут ещё поменяться: в предыдущей версии тот же ToolStrip назывался WinBar.
Внешний вид панелек один в один похож на Office 2003. Впрочем, можно переключить его на более унылый и стандартный, если ваш клиент страстно привержен Windows 98.
Я не буду описывать детально свойства и особенности этих классов, скорее всего это ещё большой «subject to change». Приведу только картинки, думаю, это даст достаточное представление:
Рисунок 6
Рисунок 7
Рисунок 8
Классам SoundPlayer, SystemSound, SystemSounds просто на роду написано производить звуки. Этим они и занимаются по воле породившего их Микрософта. SoundPlayer может проигрывать любые WAV-файлы, но не подерживает остальные форматы — MIDI, MP3, WMA.
SystemSounds содержит набор системных звуков (SystemSound), примерно так же, как класс Brushes содержит набор кистей Brush.
Каждый отдельный системный звук — экземпляр класса SystemSound, который можно проиграть при помощи метода Play. Одновременно может играть только один системный звук И только один SoundPlayer.
Для проигрывания классу SoundPlayer задаётся или путь к файлу, или бинарный поток, Stream. Что это даёт? Поясняю на пальцах: мы сможем встроить звук в своё приложение как ресурс, и в нужный момент проиграть этот звук в SoundPlayer. Причём это может быть звук, сжатый кодеком MP3 или ему подобным.
Несколько общих усовершенствований, связанных с изображениями, они касаются большинства контролов.
В .NET Framework v1.0 и v1.1 фоновое изображение BackgroundImage всегда отображалось в режиме «Tile», то есть заполняло весь фон с повторением. Теперь можно выбрать способ заполнения для фона: Tile, Center, Stretch и Zoom. Чтобы не путаться: Zoom производит пропорциональное масштабирование по обеим координатам, а Stretch растягивает изображение по размерам контрола.
Для получения иконки из ImageList в .NET Framework использовались индексы. В этом есть своё неудобство: когда прописываешь индекс нужной иконки в коде, легко спутать число 18 и 19. А если в ImageList потом добавится иконка? А если, не дай бог, придётся удалить иконку? Индексы «поедут» и будут отображаться не те иконки, которые задуманы.
Поэтому в новой версии введены строковые ключи для доступа к иконкам. То есть, иконку можно получить не только по индексу в списке, но и по ключу-имени. Ключ задаётся произвольно при заполнении ImageList.
Соответственно, в тех объектах, которые раньше ссылались на индекс иконки в ImageList, появились свойства ImageKey, ссылающиеся на строковый ключ иконки. Например, свойство ListViewItem.ImageKey — аналог ListViewItem.ImageIndex.
Улучшился дизайнер ImageList-а, теперь он позволяет добавлять за один прием любое количество картинок, а не одну, как раньше.
Иногда в контроле требуется отобразить одновременно надпись и небольшую иконку. Это может быть, например, кнопка с картинкой — Button. Или ссылка — LinkLabel. Для отображения иконки над, под или справа-слева от текста, заведено новое свойство. В принципе, похожего вида можно было добиться и раньше, но теперь стало куда аккуратнее.
Рисунок 9
Дополнения в PictureBox позволяют загружать и отображать изображение асинхронно. В свойстве ImageLocation указывается адрес картинки, и она начинает загружаться (с локального диска, по сети или с указанного URL) в фоновом режиме.
Пока картинка загружается, отображается иконка-заместитель, как в InternetExplorer. После окончания загрузки эта иконка сменяется самой картинкой. Если загрузка не завершилась успешно, отображается соответствующая иконка.
Иконки-заметстители задаются свойствами InitialImage и ErrorImage, а по умолчанию выбраны такие же иконки, как в IE.
Можно запретить этот механизм асинхронной загрузки изображения — тогда после установки ImageLocation контрол будет загружать картинку синхронно, блокируя пользовательский интерфейс.
Если не использовать свойство ImageLocation, PictureBox работает, как и раньше — отображает картинку из свойства Image.
Эти события дополнительно показывают причину закрытия формы: нажатие «крестика», закрытие по Alt+F4, закрытие через Task Manager.
Мигание заголовка формы — в панели задач и самого заголовка окна.
Когда форма свёрнута (минимизирована), её предыдущие, до минимизации, размеры теперь будут доступны в свойстве RestoreBounds.
Классы EditBox и ComboBox в новой версии поддерживают функцию AutoComplete. При этом можно выбрать «источник» вариантов для AutoComplete — каталоги/файлы, просмотренные адреса из кеша веб-страниц или созданный вручную набор значений.
Добавлены специфические свойства, отвечающие за Flat-режим отображения. Это BorderColor, BorderSize и MouseOverBackColor. Впрочем, Flat-режим теряет свою привлекательность с приходом автоматической поддержки тем Windows XP.
В режиме OwnerDraw контрол отрисовывает все элементы путём вызова специального события. При этом программист должен больше потрудиться, но за это он получает большие визуальные возможности. Например, это позволяет в табличном виде ListView рисовать значение какого-нибудь показателя в отдельной ячейке в виде «градусника». Или выделять текущий элемент не цветом Highlight, а красивым переливающимся градиентом. Режим OwnerDraw в .NET v2.0 поддерживают и ListView, и TreeView.
В первой версии .NET Framework всплывающие подсказки можно было указать только для всего контрола ListView или TreeView в целом. Теперь каждый элемент имеет свою отдельную всплывающую подсказку, что совершенно логично.
Для отображения элементов в контроле ListView нужно заполнить коллекцию Items объектами ListViewItem. Иногда список отображаемых элементов может заполняться из базы данных, при этом элементов в таблице может быть много. С увеличением количества до сотен, тысяч и более, механизм заполнения через ListViewItem становится действительно очень медленным.
В новой версии .NET Framework у контрола ListView появился новый альтернативный способ отображения элементов, так называемый виртуальный режим. При переходе в виртуальный режим контрол перестаёт хранить в себе набор элементов. Теперь контрол только обращается к своим событиям за получением данных строк.
Для компонента-всплывающей подсказки добавлена возможность произвольной отрисовки, то есть OwnerDraw. Вы можете отображать в подсказке к любому контролу специфическую картинку, или график, или что вообще придёт в голову — используя все средства System.Drawing.
Кроме того, теперь ToolTip поддерживает вид «баллона».
Изменения в классах MainMenu, ContextMenu и MenuItem затрагивают одну функцию — отображение иконок в пунктах меню. Впрочем, с выпуском новой версии Микрософт настоятельно советует переходить к новому классу MenuStrip вместо MainMenu. Внешний вид и возможности MenuStrip действительно лучше старого MainMenu.
Одно небольшое изменение — возможность настройки отступов позиций табуляции. Если вы не используете ListBox для создания таблиц, это вас не очень заинтересует. Хотя на самом деле тут есть один интересный момент.
Для хранения отступов табуляции (то есть чисел) используется внутренний класс ListBox.IntegerCollection. Это коллекция элементов типа int, другими словами — коллекция ValueType. Как известно, самым нашумевшим изменением в .NET Framework 2.0 стали generic-и, и одним из их преимуществ считается способность создавать типизированные коллекции классов ValueType. Логично было бы предположить, что для хранения IntegerCollection будет использоваться какой-нибудь generic-класс, например, List<int>,.
На самом деле никаких generic-ов в этом случае разработчики не применили. Ну что ж, им виднее.
Как и SplitContainer, этот контрол наверняка окажется полезным каждому разработчику. В то же время он совершенно не претендует на революционность.
Уже из названия понятно, что это доработанный EditBox для ввода и контроля форматированных данных (это могут быть даты, телефоны, идентификационные коды и т.п). Контрол сделан на совесть, разработчики продумали кучу тонких деталей. Например, есть такие свойства:
Основным же свойством является Mask — формат заполнения. Для упрощения заполнения маски в дизайнере предлагаются некоторые часто используемые форматы. Правда, тут Микрософт отошёл от своего стремления к глобализации — среди форматов предлагаются в основном разнообразные афроамериканские ZIP-коды и подобная незатейливая политкорректность. Хитом продаж станет, конечно, формат «Time: European/Military». Как видно, «на той стороне Земли» Европа считается главным милитаристом.
В новой версии свойство Tag есть не только у компонентов. Оно добавлено и во множество других объектов.
Этот контрол позволит расположить на форме любой OLE-документ. До появления .NET Framework такая функциональность считалась сама собой разумеющейся. Visual Basic и Delphi поддерживали подобные контролы чуть ли не с первой версии. Хотя нет, всё-таки со второй. Ну что ж, .NET Framework тоже будет иметь такой контрол во второй версии.
Поддерживается стандартный букет функций: редактирование in-place, загрузка из файла и т.п. Мода на OLE-объекты уже давно прошла, но для некоторых специфических задач контрол действительно будет полезен.
Этот контрол тоже скорее восполнение старых недоделок, чем что-то революционно новое. В первой версии .NET Framework путём несложных манипуляций можно было положить на форму элемент AxWebBrowser. При этом в раздел References проекта автоматически добавлялись две ссылки. Иногда это сопровождалось забавными сбоями.
Теперь потребность в самодельных велосипедных WebBrowser-контролах отпала, Микрософт даёт нам готовый, так сказать, авторизированный WebBrowser. Этот контрол, конечно же, является обёрткой над MSHTML.dll, то есть предоставляет доступ к стандартному ядру рендеринга Internet Explorer. Ни о каком managed HTML browser речь не идёт.
Интересной и удобной особенностью WebBrowser является доступ к содержимому загруженных страниц. Чтобы не создавать зависимости от библиотеки Microsoft.mshtml.dll, был сделан небольшой набор классов-оберток, таких как HtmlDocument, HtmlWindow и т.п. Они предоставляют урезанную и упрощённую функциональность обычного DHTML DOM. Кроме того, для каждого такого объекта можно получить и его полный вариант, соответствующий RCW-объект из библиотеки Microsoft.mshtml.
В форумах часто спрашивают, как перебрать все открытые на экране формы. Видимо, эти вопросы дошли до нужных ушей и в новой версии на этот вопрос появится ответ. Application.OpenForms.
Этот метод запускает новый процесс с теми же аргументами, что и текущий (System.Diagnostics.Process) и закрывает текущее приложение (Application.Exit). Вопрос — зачем это нужно?
Я думаю, этот метод нужен для новой технологии установки распространения приложений ClickOnce. Как известно, ClickOnce позволит приложениям автоматически обновляться через интернет или локальную сеть. Когда обновления будут скачаны, очевидно, приложение должно быть перезагружено для запуска новой версии. Здесь и пригодится Application.Restart.
И ещё одна поучительная особенность реализации этого метода. Программист из Микрософт, который написал код этого метода, был непростой малый. Чтобы собрать строки-аргументы нового процесса в одну целую строку, как того требует класс Process, он использовал StringBuilder.
Такой подход рекомендуют лучшие собаководы, но парень на этом не остановился. Хотя, возможно, это была девушка. Тогда я снимаю шляпу перед женской логикой. Итак, кто бы это ни был, он при инициализации StringBuilder рассчитал примерный требуемый размер — из расчёта 16 байт на один аргумент.
Когда программа затевает длительную операцию, хорошим тоном считается отображение курсора-песочных часов. Свойство Application.UseWaitCursor позволяет глобально установить для всех контролов такой курсор.
В новой версии .NET Framework появится ряд свойств и событий, позволяющих как отслеживать, так и вызывать состояния компьютера Suspend и Hibernate. Кроме того, при работе с мобильной техникой можно будет реагировать на степень разрядки батарей.
Right To Left — это способ, которым выражают свои мысли два народа-антагониста. Арабы и евреи пишут «в другую сторону». В новой версии WinForms можно будет учитывать эту особенность и соответственно изменять положение внешний вид каких-нибудь контролов.
Можно в целом описать эти новые свойства так. В операционных системах Windows XP и Windows 2003 Server есть настройка внешнего вида. Можно включить/выключить анимацию меню, тени, прозрачность иконок и т.п. И вот эти и другие похожие настройки и отражаются в новых свойствах класса SystemInformation:
Во времена Windows NT функциональность терминального доступа поставлялась за отдельную плату. Очень и очень отдельную плату. Но со временем эта возможность появилась даже в базовых версиях серверных ОС. А начиная с Windows XP терминальные функции окончательно ассимилировались во всю линейку операционных систем Windows.
Неудивительно, что новая версия .NET Framework даёт возможность определить факт работы «под терминалом». Кстати, Микрософт советует в этом случае отключать в программе «красивости» и «рюшечки» — для улучшения производительности.
Вполне вероятно, в .NET Framework 2.0 появятся и другие, более глубокие функции управления терминальными сессиями.
В классе Clipboard появились функции, упрощающие копирование и вставку текста, изображений, аудио-потоков. Это всего лишь упрощение, не более — то же самое можно было сделать и раньше, всего на одну строчку сложнее.
Сначала я подумал, что эта функция позволит определить состояние нажатия любой клавиши. Но эксперименты показали, что IsKeyLocked работает только с клавишами-модификаторами типа CapsLock, NumLock и т.п. Вообще-то для этого есть свойство ModifierKeys. По крайней мере вас теперь этот двусмысленный метод не обманет.
Добавились клавиши Oem1-Oem7, Oem102. Странно, что в первой версии была только клавиша Oem8.
Кроме Click и DoubleClick появились события MouseClick и MouseDoubleClick (события Click и DoubleClick не позволяют получить координаты мыши в момент щелчка).
Метод Invoke для асинхронного вызова теперь понимает переменный список аргументов. Добавился только модификатор params.
Двойная буферизация реализована в .NET Framework первой версии. Для этого используется метод SetStyle и флажок DoubleBuffer. В новой версии, кажется, этот механизм дополнительно оптимизирован.
Фактически, флаг DoubleBuffer помечен как нежелательный, Obsolete, и заменён OptimizeDoubleBuffer. Также добавлено свойство DoubleBuffered (оно всего лишь устанавливает/снимает тот же самый флажок OptimizeDoubleBuffered).
В чём заключается эта оптимизация, мне неизвестно. Наверняка мы увидим эту информацию в документации к финальной версии Visual Studio 2005.
Также следует знать, что в библиотеке System.Drawing.dll появился новый класс BufferedGraphics. Как следует из названия, он участвует в буферизации отрисовки контролов. Вообще, новшества System.Drawing не ограничиваются только BufferedGraphics. Например, теперь эта библиотека содержит возможность рисования не только при помощи GDI+, но и при помощи GDI — более старого, но (теоретически) более быстрого API. Если же вернуться к BufferedGraphics, то этот класс использует оба API.
Метод WndProc всех контролов теперь помечен атрибутом безопасности, требующим специальных привилегий для перегрузки. Ранее такой атрибут был только у базового класса Control. Видимо, это сочли не совсем правильным с точки зрения безопасности.
Очень похоже на то, что утилиту FxCop теперь масштабно применяют в Микрософте при разработке на всех уровнях, в том числе и в FCL.
При изменении размера вызываются два дополнительных метода: ResizeBegin и ResizeEnd. Это позволяет провести дополнительные проверки и пересчёты. Эти методы упрощают работу контролам FlowLayoutPanel и TableLayoutPanel. Кроме них, появился метод SizeFromClientSize, тоже управляющий размерами. Думаю, его назначение очевидно из названия – он рассчитывает необходимый размер контрола или формы так, чтобы размер клиентской области соответствовал размерам, переданным в этот метод. Следующий пример выставляет размер формы, клиентская область которой точно соответствует размеру кнопки (кнопка при этом сдвигается в левый верхний угол).
this.AutoSize = false;this.MinimumSize = new Size(0, 0);this.button1.Left = 0;this.button1.Top = 0; this.Size = this.SizeFromClientSize(this.button1.ClientRectangle.Size); |
Добавлен метод ScrollWindow, вызывающий прокрутку окна на указанное количество пикселей. Ещё два свойства, AutoRelocate и AutoScrollOffset, не документированы.
Моя статья представляет собой небольшую «разведку» будущего плацдарма WinForms 2.0. Конечно, много ещё может измениться. Цель такой разведки — не абсолютно достоверные данные о новой версии .NET Framework, а проявление ключевых направлений. Я надеюсь, эти изыскания помогут и вам заранее освоиться с новыми функциями.