Как сделать многооконное приложение

Обновлено: 07.07.2024

Приложение с однооконным интерфейсом не всегда может полностью удовлетворять потребностям пользователя. Если нужно одновременно работать с несколькими документами, вы, конечно, можете одновременно запустить несколько копий одного приложения, но гораздо удобнее использовать приложения с многооконным интерфейсом.

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

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

Далее мы усовершенствуем наше приложение так, что оно сможет работать с документами двух типов – графическими и текстовыми.

В ходе своих объяснений мы иногда будем ссылаться на однооконное приложение Single, также созданное с использованием средств MFC AppWizard. Приложение Single мы рассматривали в 24 томе “Библиотеки системного программиста”. Если у вас нет под рукой 24 тома, вы можете быстро создать приложение Single, воспользовавшись MFC AppWizard.

Создайте новое приложение с многооконным интерфейсом и назовите его Multi. При определении свойств приложения оставьте все предложения по умолчанию. Приложение Multi не будет использовать технологию OLE и сетевые технологии, не будет работать с базами данных. Процедура создания приложений с использованием MFC AppWizard описана в разделе “Приложение с оконным интерфейсом” 24 тома серии “Библиотека системного программиста”, поэтому мы будем считать, что вы уже создали проект.

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

Сразу после запуска приложения Multi, открывается дочернее окно, предназначенное для просмотра документа, которое получает название Multi1. Вы можете создать новые дочерние окна, выбрав из меню File строку New – открыть новый документ или строку Open – открыть файл (рис. 1.1). Для просмотра уже открытого документа можно открыть еще одно окно (рис. 1.11). В названии такого окна указывается дополнительный числовой индекс.

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


Рис. 1.1. Приложение Multi


Рис. 1.2. Окно Project Workspace, файлы проекта

В следующей таблице кратко описаны основные файлы проекта Multi. Ниже мы подробно рассмотрим ресурсы приложения Multi, а также опишем составляющие его классы и их методы.

Имя файла Описание
ChildFrm.cpp Файл содержит определение методов класса CChildFrame
ChildFrm.h В файле находится определение класса дочернего окна MDI – CChildFrame
MainFrm.cpp Файл содержит определения методов класса CMainFrame
MainFrm.h Содержит описание класса главного окна приложения, который называется CMainFrame. Класс CMainFrame наследуется от базового класса CFrameWnd, определенного в библиотеке классов MFC
Multi.cpp Основной файл приложения. В нем определены методы основного класса приложения CMultiApp
Multi.h В этом файле перечислены другие включаемые файлы и описан главный класс приложения CMultiApp
Multi.pch Файл создается во время первой трансляции программы, если вы используете предварительную компиляцию включаемых файлов
Multi.rc Файл ресурсов. В этом файле описаны все ресурсы приложения. Сами ресурсы могут быть записаны в каталоге RES, расположенном в главном каталоге проекта
MultiDoc.cpp Включает определение методов класса CMultiDoc
MultiDoc.h Содержит определение класса документов приложения – CMultiDoc
MultiView.cpp Включает определение методов класса CMultiView
MultiView.h Содержит описание класса окна просмотра приложения – CMultiView
ReadMe.txt Текстовый файл, содержащий описание проекта. В нем кратко рассмотрен каждый файл, входящий в проект, перечислены классы приложения, а также представлена некоторая другая дополнительная информация
res\Multi.ico Пиктограмма приложения
res\Multi.rc2 В этом файле определены ресурсы, которые нельзя редактировать с помощью редактора ресурсов среды Visual C++
res\MultiDoc.ico Пиктограмма для документов приложения
res\Toolbar.bmp Файл содержит растровое изображение кнопок панели управления
Resource.h Файл содержит определения идентификаторов ресурсов приложения, например, идентификаторы строк меню
StdAfx.h, StdAfx.cpp Использование этих файлов позволяет ускорить процесс повторного построения проекта. Более подробное описание файлов представлено ниже

Рассмотрим ресурсы, которые MFC AppWizard создал для нашего приложения. Откройте страницу RecourceView в окне проекта Project Workspace. В нем отображается полный список всех ресурсов приложения (рис. 1.3).


Рис. 1.3. Окно Project Workspace, ресурсы приложения

Сравните эти ресурсы с ресурсами приложения с однооконным интерфейсом (том 24 серии “Библиотека системного программиста”). Вы заметите, что в состав приложения с многооконным интерфейсом входит больше ресурсов. Так, например, для многооконного приложения определены два меню, две пиктограммы, больше размер таблицы текстовых строк.

Национальные ресурсы

Обратите внимание, что все ресурсы, представленные на странице RecourceView в окне проекта Project Workspace, английские. К сожалению, MFC AppWizard из доступных нам версий Microsoft Visual C++ не позволяет выбрать для создаваемого приложения русские ресурсы (язык для ресурсов выбирается в первой панели MFC AppWizard – Step 1, во время определения свойств приложения). Поэтому для приложения Multi и всех других приложений, созданных с помощью MFC AppWizard, мы выбрали английский язык.

Если вы в Control Panel с помощью приложения Regional Settings выбрали русский язык, то в некоторых случаях ClassWizard может работать неправильно. Например, если вы добавите к английской диалоговой панели новые органы управления, то ClassWizard не позволит автоматически привязать к ним переменные. Возникнут также сложности при использовании русского текста в строковых ресурсах, помеченных как английские. Чтобы избежать этих проблем, измените язык, используемый для ресурсов. Для этого достаточно в окне Project Workspace щелкнуть по идентификатору ресурса правой кнопкой мыши и выбрать из открывшегося контекстного меню строку Properties. На экране появится диалоговая панель со свойствами выбранного ресурса. Измените в ней язык ресурса, выбрав из списка Language строку Russian.

Шаблон меню

Для многооконного приложения в ресурсах проекта определены два меню с идентификаторами IDR_MAINFRAME и IDR_MULTITYPE. Приложение использует одно из этих меню, в зависимости от того, открыт документ или нет.

Меню с идентификатором IDR_MAINFRAME используется, если в приложении не открыт ни один документ. Как видите, идентификатор меню совпадает с идентификатором меню приложения с однооконным интерфейсом, однако строки этих меню различаются:

Метки:Android NMulti-окноВ прошломAndroidВ системе все действия выполняются в полноэкранном режиме. Если вы не установите эффект прозрачности, вы можете одновременно видеть только один интерфейс действий.

Но начиная с версии Android N (7.0), система поддерживает многооконный режим. Благодаря поддержке нескольких окон пользователи могут одновременно открывать и видеть интерфейс нескольких приложений. И система также поддерживает перетаскивание между несколькими приложениями. Эта функция очень полезна на устройствах с большим экраном.

В этой статье подробно объясняется реализация многооконной функции в системе Android.

Введение в многооконные функции

очертание

В Android появилась многооконная функция от Android N (7.0).

Для новых функций Android N, пожалуйста, смотрите здесь:Android 7.0 for Developers
Подробные инструкции по работе с несколькими окнами см. здесь:Multi-Window Support

Многооконный режим на Android N имеет три режима:

splitscreen

Режим разделенного экрана
Этот режим можно использовать на мобильных телефонах. Этот режим разделяет экран на две части и отображает интерфейс двух приложений одновременно. Как показано ниже:

pip-active


2. Режим PIP
Этот режим в основном используется на телевизоре. В этом режиме окно воспроизведения видео всегда может отображаться на верхнем слое. Как показано ниже:

freeform_mode


3. Режим свободной формы
Этот режим похож на наш обычный рабочий столОперационная системаОкно интерфейса приложения можно свободно перетаскивать и изменять его размер. Как показано ниже:

Жизненный цикл

Многооконный режим не влияет и не меняет жизненный цикл исходного действия.

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

  • Когда пользователь запускает приложение в многооконном режиме
  • Когда пользователь меняет размер окна действия
  • Когда пользователь меняет окно приложения из многооконного режима в полноэкранный режим

Как приложение обрабатывает изменения состояния, смотрите здесь:Handling Runtime ChangesЯ не буду повторять их здесь.

Связанный с разработчиком

Начиная с API уровня 24, Android предоставляет следующие механизмы для поддержки использования многооконных функций.

  • Манифест нового атрибута
    • android:resizeableActivity=["true" | "false"]
    • android:defaultWidth,android:defaultHeight Ширина и высота по умолчанию в режиме произвольной формы
    • android:gravity Начальная гравитация в режиме произвольной формы
    • android:minWidth, android:minHeight Минимальная высота и ширина в разделенном экране и режиме произвольной формы

    Вот пример кода:

    Перед перетаскиванием Android N система позволяет перетаскивать только в пределах действия. Но начиная с Android N, система поддерживает перетаскивание между несколькими действиями. Вот некоторые связанные API. Смотрите официальную документацию для конкретных инструкций.

    • DragAndDropPermissions
    • View.startDragAndDrop()
    • View.cancelDragAndDrop()
    • View.updateDragShadow()
    • Activity.requestDragAndDropPermissions()

    Связанные модули и основные классы

    В этой статье мы в основном сосредоточены на реализации многооконных функций. Основные классы и модули для реализации многооконных функций перечислены здесь.

    Путь к коду здесь относится к исходному пути AOSP. Чтобы узнать, как получить исходный код AOSP, смотрите здесь:Downloading the Source。

    Путь к коду: / frameworks / base / services / core /Java/com/android/server/am

    Путь к коду: / frameworks / base / services / core / java / com / android / server / wm

    Путь к коду: frameworks / base / core / java /

    Путь к коду: / frameworks / base / packages / SystemUI /

    Как следует из названия: Системный интерфейс, сюда входят: NavigationBar, StatusBar, Keyguard и т. Д.

    Для объяснения, классы, упомянутые здесь, будут использоваться непосредственно ниже. Если вы хотите увидеть исходный код для этих классов, посмотрите путь здесь.

    Реализация многооконной функции

    Реализация многооконной функции в основном зависит от двух системных служб ActivityManagerService и WindowManagerService, которые расположены в процессе system_server. Этот процесс является очень важным системным процессом в системе Android. Многие сервисы в рамках находятся в этом процессе.

    Весь AndroidархитектураЯвляется ли модель CS, приложением является Клиент, а процессом system_server является соответствующий Сервер.

    Многие API, вызываемые приложением, будут отправлены для обработки соответствующей системной службе в процессе system_server. Например, API-интерфейс startActivity в конечном итоге обрабатывается ActivityManagerService.

    Поскольку прикладная программа и system_server выполняются в отдельных процессах, запросы на системные службы должны выполнять межпроцессное взаимодействие (IPC) через Binder для завершения вызова и возврата результата вызова.

    Введение в два системных сервиса

    ActivityManagerService отвечает за управление деятельностью.

    Для каждого действия, созданного в приложении, в ActivityManagerService будет соответствующая ему ActivityRecord, этот ActivityRecord записывает состояние действия в приложении. ActivityManagerService будет использовать этот ActivityRecord в качестве идентификатора для планирования процессов Activity в приложении, таких как управление жизненным циклом.

    На самом деле ответственность ActivityManagerService выходит далеко за рамки его названия: ActivityManagerService отвечает за управление всеми четырьмя основными компонентами (Activity, Service, BroadcastReceiver, ContentProvider) и управление процессами приложения.

    WindowManagerService отвечает за управление окнами. В том числе:

    Подождите. Каждое действие будет иметь свое собственное окно, и в WindowManagerService будет соответствующий WindowState. WindowManagerService использует это для идентификации окон в приложении и использует это WindowState для хранения, запроса и управления состоянием окна.

    ActivityManagerService и WindowManagerService должны работать в тесном сотрудничестве, поскольку создание или уничтожение Activity включает создание и уничтожение объектов Actiivty и объектов окна. Эти два независимы и тесно связаны.

    Процесс запуска деятельности

    Процесс запуска действия в основном включает в себя следующие этапы:

    Данная статья не предназначена для подробного объяснения процесса запуска Activity, читателям, интересующимся этой частью контента, обращайтесь к другим материалам.

    Задача и стек

    Каждое действие в системе Android находится в задании. Задача может содержать несколько действий, и может быть несколько экземпляров одного и того же действия. В AndroidManifest.xml мы можем передатьandroid:launchModeДля управления экземпляром Activity в Task.

    Кроме того, в startActivity мы также можем передатьsetFlagДля управления экземпляром запущенного Действия в Задаче.

    Важность управления задачами также заключается в недавнем списке задач и заднем стеке. Когда вы вызываете многозадачность с помощью клавиши многозадачности (нажмите и удерживайте клавишу Home на некоторых устройствах и клавишу многозадачности на некоторых устройствах), вы фактически получаете список недавно запущенных задач из ActivityManagerService.

    Стек Back управляет логикой, к которой должен переходить Activity, когда вы нажимаете кнопку Back в Activity. Стеки заданий и задних уровней см. Здесь:Tasks and Back Stack。

    Фактически, во внутреннем управлении ActivityManagerService и WindowManagerService в дополнение к Task есть слой контейнера, который разработчик и пользователь приложения контейнера может не почувствовать или использовать, но это очень важно, то есть Stack. Далее мы увидим, что многооконное управление в системе Android построено на стеке.Структура данныхНа. Стек содержит несколько задач, а задача содержит несколько действий (окно). На следующем рисунке показано их отношение:


    Следует также отметить, что структуры Task и Stack в ActivityManagerService и WindowManagerService имеют взаимно-однозначное соответствие, и соответствующее отношение выглядит следующим образом:

    То есть каждый ActivityStack или TaskRecord в ActivityManagerService имеет соответствующий TaskStack и Task в WindowManagerService. Оба типа объектов имеют уникальные идентификаторы (id имеет тип int), и они связаны по id.

    Многооконный и Стек

    Люди, которые использовали macOS или Ubuntu, должны были использовать функцию виртуального рабочего стола, как показано на следующем рисунке:


    Чтобы поддерживать несколько окон, Android создает несколько стеков во время выполнения, и здесь стек похож на роль виртуального рабочего стола.

    Каждый стек будет иметь уникальный идентификатор. Эти идентификаторы стека определены в ActivityManager.java:

    /** First static stack ID. */

    public static final int FIRST_STATIC_STACK_ID = 0;

    /** Home activity stack ID. */

    public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;

    /** ID of stack where fullscreen activities are normally launched into. */

    public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;

    /** ID of stack where freeform/resized activities are normally launched into. */

    public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;

    /** ID of stack that occupies a dedicated region of the screen. */

    public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;

    /** ID of stack that always on top (always visible) when it exist. */

    public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;

    Из этого мы можем знать, что система может содержать так много стеков:

    Следует отметить, что не все эти стеки создаются сразу после запуска системы. Он создается при необходимости. Как уже упоминалось выше, ActivityStackSupervisor отвечает за управление ActivityStack.

    С учетом вышеизложенных базовых знаний давайте подробнее рассмотрим три многооконных режима в системе Android.

    Режим разделенного экрана

    На телефонах Nexus 6P запуск и выход из режима разделенного экрана - длительное нажатие многозадачной виртуальной кнопки. На следующем рисунке показано, как запустить режим разделенного экрана на Nexus 6P:


    После активации режима разделенного экрана экран разделяется на две части. Открытое в данный момент приложение перемещается в верхнюю часть экрана (в левую сторону, если оно находится в горизонтальной ориентации), а все остальные открытые приложения перечислены ниже (если оно в горизонтальной ориентации, оно находится справа) в многозадачной форме.

    После этого, когда пользователь работает, нижняя половина экрана сохраняет исходный режим использования: вы можете запускать или выходить из приложения, вы можете переключаться после многозадачности, а приложение в верхней части остается неизменным. Как мы упоминали ранее, на самом деле приложение, которое зафиксировано в первой половине экрана, находится в Docked Stack (Id - 3), а нижняя половина экрана - предыдущий полноэкранный Stack, размер которого был изменен (Id - 1).

    Далее, давайте проследим за долгим нажатием кнопки многозадачности в качестве подсказки, чтобы выяснить, как активируется режим разделенного экрана: на самом деле, и NavigationBar (три виртуальные кнопки внизу экрана), и StatusBar (строка состояния вверху экрана) оба Это в SystemUI. Мы можем использовать это как вход для расследования.

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

    Создаем новый проект в Andoid Studio, все названия традиционно оставляем по умолчанию. Итак, сейчас мы имеем всего одно Activity - MainActivity, 1 файл разметки интерфейса activity_ main .xml, описывающий наше MainActivity . Создадим еще одно Activity . Слева, в окне, отображающем структуру приложения, выделяем папку приложения app --- New --- Java Class:

    Новый класс

    Выбираем где именно поместить новый созданный класс: app\src\main\java:

    Папка назначения

    В следующем окне вводим имя создаваемой активности: SecondActivity и жмем ОК. Слева в панели сразу откроется папка, где создано новое Activity, проследите, чтобы обе активности были в одной папке. Если у вас вышло вот так:

    Перенос активности

    то просто перетащите файл SecondActivity в папку с MainActivity.

    Теперь нужно создать файл разметки для SecondActivity. Делаем это аналогично созданию активности: в окне слева раскрываем папку res и нажимаем правой кнопкой мыши на подпапку layout: жмем New --- Layout resourse file. В открывшемся окне вводим имя: second и жмем ОК. Все, все необходимые файлы созданы.

    Теперь нужно привязать созданный файл разметки интерфейса second.xml к SecondActivity. Открываем SecondActivity и выполняем эту привязку:

    Как видите, здесь ничего сложного. Устанавливаем наследование нашим новым классом extends Activity, создаем метод onCreate. Чтобы не писать его вручную, делаем так: на верхней панели ищем кнопку Code --- Override Methods, начинаем вводить название OnCreate, подсказка нам его быстренько выдаст, и жмем ОК. Настраиваем вид контента окна с нашего файла second.xml: setContentView(R.layout.second).

    Теперь начнем реализацию нашей мечты: при нажатии на кнопку на одном экране - происходит переход на другой экран с другим содержимым.

    Открываем файл activity_main.xml и создаем там кнопку, при нажатии на которую будет происходить переход:

    Теперь нужно описать процесс нажатия, кликнем на надпись "Click" в последней строчке и нажмем комбинацию клавиш Alt + Enter:

    Описываем нажатие

    и жмем еще раз Enter по строчке "Create "Click(View)" in "MainActirvity"". Таким образом мы автоматически добавили метод обработки щелчка в MainActivity.

    Теперь в созданном методе " Click " нужно написать код, который будет производить переход при нажатии:

    Перед тем, как приступить к тестированию нашего творения вспомним, что еще нужно зарегистрировать наш новый класс SecondActivity в файле манифеста приложения. Открываем файл AndroidManifest.xml и между тегами впихиваем это:

    В принципе все. Давайте только заполним хоть каким то содержимым наш SecondActivity, чтобы переход был более очевидным.

    Откроем созданный нами файл second.xml. Ну а тут свобода! Добавьте то, что сами желаете увидеть при переходе на эту активность. Например я добавлю туда элемент

    с надписью "Приехали!" и размещу ее в центре:

    Переход

    Все, поздравляю, можем запускать и тестировать наше чудо (если у вас что то не вышло, пересмотрите все шаги внимательней, там все работает).

    После освоения этого урока сразу советую вам заглянуть сюда, а также сюда . Удачи!

    Целью данной части главы будет закрепление навыков работы с оконными приложениями. Мы рассмотрим на примере, как создаются элементы меню, панели инструментов, увидим, как создаются и вызываются дополнительные диалоговые окна, как работать с окнами выбора файлов. Также мы познакомимся еще с несколькими элементами управления и научимся динамически загружать изображения в форму.


    Первоначально, создайте новый проект, указав в качестве шаблона Windows Form Application и назовите second_application. Затем нажмите OK.

    Перед нами откроется код функции обработчика:


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

    Новый код функции с комментариями:

    Теперь можно откомпилировать приложение и проверить работоспособность кнопки.

    Часто панель управления (Toolbar) дублирует элементы меню для быстрого к ним доступа.

    Нам снова нужно перейти к окну Toolbox (Панель инструментов) и развороту Menus & Toolbars. В этот раз мы выберем элемент ToolStrip (рис. 5).
    Рисунок 5. Окно Toolbox.
    Перетащите элемент управления на окно и вы увидите, как вдоль его верхней границы разместиться панель ToolBar (рис. 6).
    Рисунок 6. Добавленный элемент Toolbar.
    Мы изменим положение привязки нашего ToolBar’a. Для этого щелкнем по нему правой кнопкой и в открывшемся контекстном меню выберем пункт Свойства. Откроется окно свойств: здесь мы изменим привязку на левую часть окна, внеся изменения в параметр Dock, как показано на рисунке 7.
    Рисунок 7. Привязка панели инструментов к левой стороне.
    Теперь увеличим размеры кнопок на Toolbar'e. Для этого сначала необходимо в его свойствах установить параметр AutoSize равным false. Теперь мы можем изменить размеры самих кнопок: установим параметры Size - Width равным 44. Поле станет шире (рис. 8).
    Рисунок 8. Установка размеров изображений, размещаемых на кнопках создаваемого Toolbar.
    Теперь добавим 3 кнопки на наш ToolBar. Для этого щелкните по нему и в раскрывающемся списке элементов, которые мы можем добавить, выберите элемент button (рис. 9).
    Рисунок 9. Добавление кнопок на панель элементов (Toolbar).
    Повторите операцию, чтобы кнопок на панели стало две. Теперь поочередно выберите каждую кнопку и в ее свойствах установите AutoSize равный false. После это перейдите к полю Size и установите высоту равную 42. Теперь кнопки примут квадратный вид.

    Мы будем использовать 3 следующих изображения:


    Изображение для кнопки 1: будет назначено кнопке, отвечающей за открытие дополнительного диалогового окна.

    Два следующих изображения будут назначены кнопкам, которые будут отвечать за загрузку файлов jpg и png.


    Изображение для кнопки 2.


    Изображение для кнопки 3.

    (. ) Обратите внимание, что у данных изображений прозрачный фон.

    2 кнопки будут дублировать меню с функциями загрузки изображений, 1-я кнопка будет предназначена для вызова окна, с отображением картинки, которую мы загрузили.

    Теперь для установки изображений необходимо перейти в свойства картинки, после чего мы установим значение параметра ImageScaling равным none, чтобы изображение не масштабировалось. Теперь в параметре Image мы можем выбрать изображение для загрузки, как показано на рисунке 11.
    Рисунок 11. Установка изображений на кнопки.
    В процессе выбора откроется окно, показанное на рисунке 12.
    Рисунок 12. Импорт рисунка для установки на кнопке.
    Теперь щелкните на кнопке Import и выберите необходимый рисунок. Аналогично повторите с другими рисунками. В результате вы получите 3 красивые кнопки, как показано на рисунке 13.
    Рисунок 13. Пример созданной панели инструментов.
    Для того чтобы создать обработчики нажатий на кнопки этого ToolBox'а, достаточно совершить двойной щелчок мыши на каждом из них – MS Visual Studio автоматически сгенерирует код обработчик события и заготовки функций.

    В будущем мы добавим вызов необходимых нам функций из этого обработчика.

    Чтобы пользователь мог выбирать файл для загрузки через стандартное в Windows окно загрузки файлов, мы выполним следующие действия.
    Перейдите к окну ToolBox (Панель элементов).
    Теперь перетащите элемент управления OpenFileDialog (рис. 15) на форму.
    Рисунок 15. Добавление элемента OpenFileDialog.
    Местоположение, куда вы перетащите элемент, неважно: он добавится в поле под окном, к другим специфическим объектам (рис. 16).
    Рисунок 16. Элемент OpenFileDialog, расположенный под редактируемой формой.
    Как видно из рисунка 16, к дополнительным элементам, уже установленным на наше окно (меню и ToolBox), добавился еще и элемент OpenFileDialog1.
    Теперь мы реализуем код открытия окна выбора файла, с необходимыми нам параметрами.

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


    Теперь напишем следующую функцию LoadImage.

    Далее функции обработчики нажатий пунктов меню и кнопок на панели управления реализуют вызов функции загрузки с необходимым флагом.

    Добавление и вызов дополнительного диалогового окна

    Для этого перейдите к окну Solution Explorer (Обозреватель решений), после чего щелкните на названии проекта правой кнопкой мыши и в открывшемся контекстном меню выберите Add->Form, как показано на рисунке 18.
    Рисунок 18. Добавление в проект нового диалогового окна.
    В открывшемся окне введите названия класса, который будет отвечать за генерацию нашего вспомогательного окна – Preview.cs (рис. 19).
    Рисунок 19. Установка названия создаваемой формы для нового диалогового окна.
    Теперь измените размер окна так, как показано на рисунке 20. Затем на форме разместите элемент panel. Внутри элемента panel разместите элемент pictureBox, как показано на рисунке 20.
    Рисунок 20. Размещение элементов panel и picturebox на созданном диалоговом окне.
    Данное окно будет получать при загрузке в качестве параметра ссылку на наше загруженное изображение. Затем оно будет устанавливать границы элемента pictureBox равными размерам полученного изображения, после чего устанавливать его в элемент pictureBox.

    Перейдите к свойствам элемента panel и установите значение параметра AutoScroll равное true. Теперь, в том случае, если размер изображения будет превышать размер элемента panel1, будут появляться вертикальная и горизонтальная полоса прокрутки, с помощью которых можно будет просмотреть изображение.

    Теперь рассмотрим исходный код, необходимый для реализации данных возможностей.

    Первым делом назначим обработчик кнопки с изображением стрелки направленной вправо на нашем главном окне. Щелкните по ней дважды, после чего вы перейдете к редактированию кода функции, которая будет вызвана при щелчке по данной кнопке.

    Он будет выглядеть следующим образом:


    Как видно из исходного кода, класс Preview получает в качестве параметра наше загруженное изображение. Для правильной работы программы мы должны изменить конструктор класса Preview, а также реализовать остальную функциональность программы.

    Перейдите к окну Preview, после чего сделайте двойной щелчок левой клавшей мыши на нем (НЕ на размещенных на нем объектах).

    Откроется для редактирования функция:


    Но мы сначала изменим код конструктора класса, теперь он будет выглядеть следующим образом:


    Теперь отредактируем код функции Preview_Load. Он будет выглядеть следующим образом:


    В заключении, самостоятельно добавьте обработчик нажатия кнопки закрыть. Функция закрытия будет выглядеть следующим образом:

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

    Читайте также: