Читайте также:
|
|
Модальные диалоги.
При выводе на экран модальной диалоговой панели работа приложения приостанавливается. Функции главного окна приложения и всех его дочерних окон перестают получать сообщения от мыши и клавиатуры. Все сообщения попадают в окно диалоговой панели. Когда работа с диалоговой панелью будет завершена, главное окно приложения и его дочерние окна будут разблокированы.
Немодальные диалоги.
Создание немодалъной диалоговой панели не останавливает выполнение приложения. Более того, немодальные диалоговые окна всегда остаются поверх окна-владельца, даже если окно-владелец получает фокус ввода. Немодальные окна используются значительно реже модальных диалогов в случаях, когда пользователю необходимо одновременно работать как с окном диалога, так и с основным окном приложения.
Главным отличием этих диалогов является то, что при создании модального диалога работа приложения приостанавливается, и все окна кроме диалога перестают получать сообщения. Немодальные диалоги не блокируют работу приложения. Более того, все сообщения для диалога в этом случае будут передаваться в очередь сообщений приложения, поэтому цикл обработки сообщений модифицируется при использовании данного типа диалогов.
Ещё одним отличием немодальных диалогов можно назвать тот факт, что приложение должно самостоятельно отслеживать существование немодального диалога при работе с ними, т.к. после создания, такой диалог работает параллельно.
Модальные диалоги блокируют приложение при создании их с помощью функции DialogBox (возврата из этой функции не происходит, пока диалог находится на экране), при возврате из этой функции модальный диалог больше не существует.
83. Отличия модального диалога от системного модального диалога.
Каждый диалог определяется некоторым шаблоном и диалоговой функцией. Отличие системного модального диалога состоит в том, что диалоговая функция в этом случае находится внутри ОС, для диалога созданного приложением эта функция находится в приложении.
Модальные диалоги, созданные приложением, блокируют только его работу, системные же диалоги блокируют все окна (т.к. родительским окном для них является desktop, для которого все остальные окна являются дочерними для него).
84. Диалоговая процедура, сходства и отличия от обычной оконной процедуры.
Диалоговая процедура, или функция диалога, обрабатывает сообщения, получаемые окном диалога. Она напоминает обычную оконную процедуру, но таковой процедурой не является. Настоящая оконная процедура панели диалога находится в ядре Windows и вызывает диалоговую процедуру приложения, передавая ей большинство сообщений, которые получает сама.
У функции диалога и у обычной оконной процедуры имеется много общего, однако видны и отличия.
Сходства:
1. Обе процедуры являются функциями обратного вызова (CALLBACK);
2. Параметры для диалоговой функции и обычной оконной процедуры одинаковы;
Различия:
1. Оконная процедура возвращает значение LRESULT, а диалоговая процедура – значение типа BOOL;
2. Если оконная процедура не обрабатывает сообщение, то она вызывает обработчик по умолчанию DefWindowProc. Если процедура диалога не обрабатывает сообщение, то она возвращает FALSE или, в противном случае, TRUE;
3. Процедура диалога никогда не получает сообщения WM_CREATE, вместо этого вся инициализация выполняется при обработке специального сообщения WM_INITDIALOG. Это сообщение является первым, которое получает процедура диалога.
4. Процедура диалога, как правило, не обрабатывает сообщения WM_PAINT и WM_DESTROY.
85. Диалоговая процедура и сообщения WM_PAINT, WM_CREATE, WM_DESTROY, особенности обработки этих сообщений.
Сообщение WM_CREATE никогда не посылается функции диалога, вместо этого вся инициализация выполняется при обработке специального сообщения WM_INITDIALOG. Это сообщение является первым, которое получает процедура диалога.
Сообщение WM_PAINT обычно не обрабатывается для диалогов, потому что все функции диалогового окна реализуются элементами управления. Тем не менее, при необходимости разработчик, может обрабатывать его.
Сообщение WM_DESTROY для диалоговых панелей обрабатывается также как и для обычных окон. При закрытии диалога ему посылается данное сообщение. В обработчик данного сообщения может быть помещён код, сохраняющий данные введённые пользователем в элементы управления.
86. При каких условиях в диалоговую процедуру поступает сообщение WM_COMMAND с идентификатором IDCANCEL.
Все диалоги снабжаются кнопкой «Cancel», для того чтобы пользователь смог отменить внесённые изменения. Так при нажатии на кнопку «Cancel» генерируется сообщение WM_COMMAND с идентификатором IDCANCEL, которое и поступает в функцию диалога. Эта же ситуация возникает тогда, когда пользователь нажимает клавишу «Esc».
87. При каких условиях в диалоговую процедуру поступает сообщение WM_COMMAND с идентификатором IDOK.
Все диалоги снабжаются также кнопкой «OK», для того чтобы пользователь смог принять сделанные изменения. При нажатии на эту кнопку генерируется сообщение WM_COMMAND с идентификатором IDOK, которое поступает в функцию диалога. Кроме того, сообщение WM_COMMAND с идентификатором IDOK поступает и в том случае, если пользователь нажимает клавишу <Enter>, в тот момент, когда выполняются одновременно два условия: 1) ни одна из кнопок, расположенных в диалоговой панели, не имеет фокус ввода; 2) ни одна из кнопок не имеет стиля WS_DEFPUSHBUTTON.
88. Функции для создания модальной диалоговой панели, их особенности.
Для создания модального диалога, в основном используется функция DialogBox, имеющая прототип:
int DialogBox(HINSTANCE hlnst.LPCTSTR pTemplate, HWND hWndParent.DLGPROC pDlgFunc).
Эта функция создает диалоговое окно, используя ресурс шаблона pTemplate, и отображает эту панель как модальное диалоговое окно. Функция DialogBox() не возвращает управления до тех пор, пока диалоговое окно не будет закрыто пользователем. В точке вызова DialogBox() происходит блокировка окна, владеющего диалогом. Дескриптор этого окна передается через параметр hWndParent.
Также для создания модального диалога можно использовать функции: DialogBoxParam, DialogBoxIndirect, DialogBoxIndirectParam. Функции DialogBoxIndirect и DialogBoxIndirectParam предназначены для создания диалога из шаблона находящегося в памяти. DialogBoxParam и DialogBoxIndirectParam также создают диалог из шаблона, находящегося в ресурсах, и позволяют передать 4-байтовый параметр, который будет передан в параметре lParam сообщения WM_INITDIALOG.
89. Действия диалоговой функции для закрытия модальной диалоговой панели, возвращаемое значение из диалоговой функции.
Поскольку окно-владелец заблокировано во время работы модального диалога, единственно корректным способом уничтожения диалогового окна является саморазрушение в диалоговой процедуре, что достигается вызовом функции EndDialog():
if (nID = IDCANCEL) {
EndDialog(hDlg,nlD);
return TRUE;
Эта функция не только закрывает диалоговую панель, но и разблокирует вызывающую функцию DialogBox, которая передает в приложение в качестве возвращаемого значения параметр nID функции EndDialog(). Как правило, диалог завершает работу при нажатии кнопки.
90. Сообщения для модальных диалоговых окон и очередь сообщений приложения.
При выводе на экран модальной диалоговой панели работа приложения приостанавливается. Функции главного окна приложения и всех его дочерних окон перестают получать сообщения от мыши и клавиатуры. Все сообщения попадают в окно диалоговой панели. Когда работа с диалоговой панелью будет завершена, главное окно приложения и его дочерние окна будут разблокированы.
91. Окна сообщений, характеристика, способ создания.
Окна сообщений являются специальным видом модального диалога. Они предназначены только для отображения коротких информационных сообщений, поэтому могут иметь только заголовок, текст сообщения, одну из предопределенных пиктограмм и одну или несколько кнопок. Например, окно сообщения можно использовать для уведомления пользователя о возникновении какой-либо ошибки или запроса на подтверждение необратимого действия.
Окно сообщения с заголовком szCaption и выводимым текстом szText создается с помощью функции MessageBox:
int MessageBox(HWND hWnd.LPCTSTR szText, LPCTSTR szCaption, UINT uType);
Как правило, параметр hWnd является дескриптором того окна (обычного или диалогового), которое создает окно сообщения. Если окно сообщения закрывается, то фокус ввода передается окну hWnd. Если дескриптор окна недоступен или если приложению не нужно, чтобы фокус ввода получило одно из окон приложения, вместо этого дескриптора можно использовать значение NULL
Параметр uType функции MessageBoxQ представляет собой набор битовых флагов. Первая группа флагов указывает, какие кнопки будут отображены в окне сообщения, например МВ_ОК, MB_OKCANCEL, MB_YESNO. Заметим, что окно сообщения может использовать максимум четыре кнопки. Вторая группа флагов задает номер кнопки, получающей по умолчанию фокус ввода, например MB_DEFBUTTONx, где х = 1.....4. Третья группа задает пиктограмму, которая появится в окне сообщения, например: MBJCONINFIRMATION — информационный значок, MBJCONWARNING — значок напоминания, MBJCONSTOP — значок критической ошибки, MBJCONQUESTION — значок запроса. Пиктограмма по умолчанию не задается.
В зависимости от нажатой кнопки, приводящей к удалению панели, окно сообщений возвращает один из следующих идентификаторов: IDOK, IDCANCEL, IDYES, IDNO, 1DRETRY, IDIGNORE, IDABORT.
92. Стандартные диалоговые панели, схема использования.
В Windows реализован ряд часто употребляемых диалоговых окон, что освобождает разработчика от необходимости их повторной реализации для каждого своего приложения. К этим окнам относятся следующие диалоги:
1. Диалог открытия файла (GetOpenFileName)
2. Диалог сохранения файла (GetSaveFileName)
3. выбора цвета (ChooseColor)
4. Выбор шрифта (ChooseFont)
5. Диалог печати (PrintDlg)
6. Диалог настройки параметров страницы при печати (PageSetupDlg)
7. Диалог поиска текста по странице (FindText)
8. Диалог поиска и замены текста на странице (ReplaceText)
Приложение создаёт эти диалоги, посредством вызова соответствующих функций, передавая им указатель на специальную структуру (эти структуры описаны в заголовочных файлах windows для каждого типа диалога). Все эти функции заполняют структуру, указатель на которую им передаётся при вызове. Анализируя поля заполненной структуры, приложение может выполнить необходимые действия.
Стоит отметить, что стандартные диалоги всего лишь получают информацию от пользователя, и не выполняют никаких других действий. Например, стандартный диалог открытия файла возвращает только имя файла выбранного пользователем в нём, но не открывает файл. Вся работа по открытия файла ложится на разработчика.
Другими словами, стандартные диалоги созданы для того, чтобы получить информацию от пользователя, а выполнение конкретных действий (открытие/сохранения и т.д. файла в приложении) задаётся алгоритмом в приложении (т.к. Windows не может знать и учитывать особенностей каждого приложения).
93. Способы создания немодальной диалоговой панели, возвращаемое значение.
Создание немодального диалога производится вызовом одной из следующих функций: CreateDialog, CreateDialogParam, CreateDialogIndirect, CreateDialogIndirectParam.
CreateDialogIndirect и CreateDialogIndirectParam создают немодальный диалог из шаблона находящегося в памяти (при динамическом создании диалогов).
CreateDialog и CreateDialogParam создают диалог, используя шаблон, который находится в ресурсах.
Все эти функции после создания диалога сразу возвращают управление вызывающему потоку. В случае успешного выполнения функции возвращают дескриптор диалогового окна, либо NULL в случае ошибки.
Узнать дополнительную информацию о произошедшей ошибке можно воспользовавшись функцией GetLastError.
94. Действия для закрытия немодальной диалоговой панели.
Для закрытия немодального диалога используется иной подход, нежели для модальных диалогов. Чтобы закрыть немодальный диалог, необходимо вызвать функцию DestroyWindow, указав дескриптор диалоговой панели, полученный при её создании. Разрушить диалог можно и из главного окна. Если дескриптор панели был объявлен как глобальная переменная, его лучше сбросить в NULL. Это позволит приложению определить, существует ли диалог в данный момент.
95. Сообщения для немодальных диалоговых окон и очередь сообщений приложения, изменения в цикле обработки сообщений.
Создание немодалъной диалоговой панели не останавливает выполнение приложения. Все сообщения для немодального диалога будут передаваться в очередь сообщений приложения, поэтому цикл обработки сообщений модифицируется для корректной обработки сообщений.
while (GetMessage(&msg,0,0,0)){
if (!IsDialogMessage (hDlgModeless, &msg)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Смысл изменений заключается в следующем: если не изменить цикл, то все сообщения для диалога будут направляться оконной процедуре главного окна. Цикл обработки сообщений должен проверить, является ли сообщение, выбранное из очереди сообщением для диалога. В случае если сообщение адресовано не диалогу, его нужно передать функцию окна приложения для обработки, в противном случае это сообщение должно быть предано для обработки в диалоговую функцию.
Функция IsDialogMessage – проверяет предназначено ли сообщение для данного, немодального диалога. Если сообщение является таковым, она отправляет его оконной процедуре окна диалога и возвращает TRUE, в противном случае просто возвращает FALSE.
96. Меню приложения, типы, общая характеристика.
Меню приложения является достаточно важной частью интерфейса практического любого приложения.
Выделяют 4 типа меню.
1. Главное меню окна, или меню верхнего уровня. Представляет собой горизонтальную строку, которая расположена под заголовком окна и состоит из нескольких элементов.
2. Подменю (submenu). Появляется под главным меню при выборе одного из его элементов.
3. Плавающее меню (floating menu). Не связано с главным меню и может быть создано в любом месте экрана как независимое всплывающее меню.
4. Системное меню (system menu). У подавляющего большинства главных окон приложений в левой части заголовка находится пиктограмма. Щелчок мыши по ней приводит к появлению системного меню, которое похоже на подменю главного меню приложения. Обычно системное меню всех приложений одинаково, с его помощью можно минимизировать или максимизировать окно приложения, перемещать его и пр. Однако приложение имеет возможность изменить системное меню, дополняя его новыми элементами, и удаляя существующие.
97. Способы создания меню, меню по умолчанию, меню приложения.
Для создания меню применяются три метода.
1. Шаблон меню создается в файле ресурсов приложения, а затем загружается при создании главного окна приложения. (Для статических меню)
2. Меню из шаблона создается динамически только при помощи функций Win32 API. (для приложений, меняющих свой внешний вид, где нельзя заранее разработать подходящий шаблон)
3. Шаблон меню подготавливается непосредственно в оперативной памяти и с помощью специальных функций подключается к приложению.
Меню по умолчанию, это главное меню, дескриптор которого был указан при регистрации класса окна. В этом случае, для всех окон регистрируемого класса по умолчанию будет добавлено меню указанное в классе.
Меню приложения – это меню главного окна приложения.
Прикрепить меню к окну можно тремя способами.
1. Указав дескриптор соответствующего меню при регистрации окна.
2. Указать дескриптор при создании окна функцией CreateWindow.
3. Во время выполнения приложения с помощью функции SetMenu.
98. Для чего необходимы идентификаторы пунктов меню.
При выборе пунктов меню Windows генерирует сообщение WM_COMMAND. Его можно назвать сообщением пользовательского интерфейса, поскольку оно посылается каждый раз, когда пользователь что-то выбирает, меняет и т.д.
Идентификаторы для каждого пункта меню нужны для того, чтобы при обработке сообщения WM_COMMAND знать, от какого именно элемента меню было прислано сообщение.
99. Отличия сообщения WM_COMMAND, поступающего от пункта меню и от элемента управления.
Сообщение WM_COMMAND, сгенерированное пунктом меню отличается от сообщения WM_COMMAND сгенерированного другими типами элементов управления. В частности, для меню нотификационный код, содержащийся в старшем слове wParam (HIWORD(wParam)), и дескриптор окна элемента управления находящийся в параметре lParam, всегда равны 0.
100. Способы модификации меню окна.
Приложение может модифицировать меню окна: заменять само меню, изменять его содержимое.
Замена меню производится с помощью функции SetMenu. Изменение содержимого может осуществляться посредством функций SetMenuItemInfo (есть обратная ей функция GetMenuItemInfo, получающая информацию о пункте меню), которая в качестве параметра принимает адрес структуры MENUITEMINFO. Изменяя поля этой структуры перед передачей её в функцию SetMenuItemInfo, можно изменять различные свойства пункта меню. Также существуют и другие функции для работы с меню: CheckMenuItem, InsertMenuItem, GetMenuItemCount, и т.д.
101. Обработка сообщения WM_SYSCOMMAND.
Сообщение WM_SYSCOMMAND посылается, когда пользователь выбрал пункт системного меню, а также когда пользователь нажимает кнопки минимизации и максимизации окна.
Параметр wParam определяет команду выбранную пользователем (идентификатор пункта системного меню). Параметр lParam – содержит координаты (в системе координат экрана) курсора.
102. Создание и использование плавающего меню.
Всплывающее меню создаётся с помощью функции CreateMenu. Эта функция создаёт пустое меню, и возвращает его дескриптор. Для того чтобы заполнить созданное меню можно воспользоваться функциями: InsertMenuItem, AppendMenu, InsertMenu. Чтобы показать меню нужно вызвать функцию TrackPopupMenu, возврат из которой не произойдёт, пока пользователь не выберет пункт.
Уничтожение плавающего меню производится функцией DestroyMenu, которой нужно передать дескриптор созданного меню.
103. Особенности организации памяти в ОС Windows.
Для каждого запущенного процесса Win32 создаёт виртуальное адресное пространство размером в 4 ГБ. Для того чтобы расширить объём выделяемой памяти до таких размеров, Windows использует файлы подкачки (свопинг).
Приложения не могут напрямую получить доступ к адресному пространству других приложения. Приложения могут взаимодействовать, записывая и считывая данные из блока разделяемой памяти.
104. Функции ядра Windows и CRT для управления памятью, схема их применения.
Для работы с динамической памятью, в Windows используются два подхода.
1. С использованием CRT-heap (C RunTime). Реализация старых методов захвата памяти (malloc, calloc, realloc, free, и т.д.).
2. С использованием Windows-heap.
Первый способ используется функциями malloc, calloc, realloc для захвата памяти в CRT-heap, или в программном heap’е. Данный подход используется в основном для захвата малых блоков памяти (<64 КБ) для недлительного хранения. По умолчанию процессу выделяется CRT-heap размером 1 МБ. Минимальный объём выделяемой памяти 4 КБ. Захват производится в виртуальном адресном пространстве процесса.
Второй способ подразумевает использование Windows-heap’а. Такой подход используется для захвата больших объёмов памяти более 1 МБ. Минимальным размером, выделяемым в этой куче 64 КБ. Данная куча не терпит фрагментации, т.е. следует захватывать память один раз при старте приложения, и освобождать при завершении.
Захват памяти в CRT heap’е осуществляется функциями malloc, calloc, realloc. Эти функции возвращают указатель на захваченный участок памяти. Освобождение производится функцией free.
Для того чтобы использовать Windows heap, применяется иная схема захвата.
1. Создать кучу с помощью функции HeapCreate.
2. Произвести захват памяти функцией HeapAlloc.
3. Использование захваченной памяти.
4. Освободить память HeapFree.
5. Разрушить кучу HeapDestroy.
105. Функции ядра Windows и CRT для работы с файлами, особенности применения.
Для работы с файлами в Windows можно использовать два подхода.
1. Использование функций потового ввода вывода. При этом используются функции языка Си для работы с файлами, такие как: fopen, fread, fwrite, fclose и др. Данный способ накладывает ограничения на максимальный размер файла, с которым можно работать в 2ГБ. Также он использует только монопольный доступ к файлу. Преимуществом данного способа является переносимость кода.
2. Функции ядра, предоставляют быстрый и эффективный доступ к файлам очень большого размера (до 264 байт). Они позволяют работать с файлами в разделяемом режиме. Достоинством данного метода является быстрый доступ к файлам и наличие разделяемого режима работы. К недостаткам относится непереносимость кода использующего такие функции. Для доступа к файлам используются следующие функции: CreateFile (для открытия файла), ReadFile (для чтения из файла), WriteFile (для записи в файл) и др.
Функция CreateFile может открывать не только файлы, но и другие системные объекты.
1. Именованные каналы (Pipe) – объекты, использующиеся для коммуникации в локальных сетях с установлением логического канала связи (TCP).
2. Mail-слоты – объекты для коммуникации в локальных сетях без установления логического канала связи (UDP).
3. Com-порты – для работы с устройствами подключенными через com-порт.
Такой подход предоставляет единый интерфейс для работы с различными объектами.
106. Общая схема печати документа в ОС Windows.
Печать документов в прежние времена, была очень сложной задачей. Разработчикам приходилось учитывать особенности работы с различными принтерами. В настоящее время Windows берёт на себя вопросы, связанные с особенностями конкретных принтеров, предоставляя разработчикам единый интерфейс для организации печати. Другими словами, разработчик может не заботиться о том, с каким принтером будет работать приложение и т.д.
Печать производится в след.последовательности:
1. Получить или создать контекст устройства принтера;
2. Создать немодальный диалог для отмены печати;
3. Активизировать процесс спулинга печати (спулинг - способ работы с выделенными устройствами в мультипрограммной системе);
4. «нарисовать» каждую страницу документа, отправляя её на печать по мере готовности;
5. Завершить процесс спулинга печати;
6. Закрыть модальный диалог и освободить контекст устройства принтера.
107. Функции для обеспечения печати документа, последовательность использования.
Для обеспечения печати документа используется следующая схема вызова функций.
1. CreateDC – создаёт контекст отображения, или можно использовать стандартный диалог PageSetup, для получения контекста принтера.
2. StartDoc – активирует процесс спулинга печати.
3. Формирование страницы с использованием интерфейса GDI.
4. EndDoc – печать сформированной страницы.
Алгоритм должен предусмотреть возможность отмены печати используя функцию AbortDoc.
108. Работа приложений в многозадачной операционной среде.
В операционных системах на базе Win32 организована вытесняющая многозадачность – способность операционной системы выполнять несколько программ одновременно. В основе этого принципа лежит использование операционной системой аппаратного таймера для выделения квантов времени каждому из одновременно выполняемых процессов. Если эти отрезки времени достаточно малы и машина не перегружена слишком большим количеством программ, то пользователю кажется, что все эти программы выполняются параллельно.
109. Основные понятия процесса и потока в Win 32.
Процесс – исполняемый модуль, которому Windows выделяет память и другие системные ресурсы. Поток – это последовательность исполняемых команд. Процесс может состоять из одного потока, а может содержать несколько потоков.
110. Реализация вытесняющей многозадачности в Win 32.
В операционных системах на базе Win32 организована вытесняющая многозадачность – способность операционной системы выполнять несколько программ одновременно. В основе этого принципа лежит использование операционной системой аппаратного таймера для выделения квантов времени каждому из одновременно выполняемых процессов.
Так же Win32 поддерживает многопоточность (multithreading). Программа может быть разделена на отдельные потоки, выполняемые параллельно. Истинная Win32-программа – это совокупность одного процесса и нескольких потоков. Реализован сложный механизм диспетчеризации, обеспечивающий принудительное прерывание (вытеснение активного потока).
111. Схема создания рабочего потока.
Для создания потока для начала нужно написать функцию потока, имеющую следующий прототип.
DWORD WINAPI ThreadProc(LPVOID);
Имя функции не имеет значения (Windows использует её адрес, а не имя). Особенностью данной функции является то, что при выходе из неё поток завершается. Именно это способ нужно использовать для завершения потока.
Непосредственно создание потока происходит посредством вызова функции CreateThread.
HANDLE CreateThread(
SECURITY_ATTRIBUTES* pThreadAttr,
DWORD dwStackSize,
THREAD_START_ROUTINE* pThreadFunc,
LPVOID pData,
DWORD dwFlags,
LPDWORD pldThread);
Эта функция возвращает дескриптор потока, который позволяет проводить с ним некоторые манипуляции. Поток с процессом разделяют все ресурсы кроме стека.После завершения потоком своей работы нужно вызывать CloseHandle() для освобождения ресурсов.
112. Синхронизация потоков, события, критические секции.
Когда в приложении несколько потоков работают с одним набором данных, возникает задача синхронизации – т.е. организации работы потоков таким образом, чтобы они не влияли на работу друг друга.
Для синхронизации потоков используются специальные системные объекты: события и критические секции.
События – объекты синхронизации, предназначенные для координации потоков. Эти объекты могут находиться в двух состояниях «установлено» и «сброшено». Сам по себе объект «событие» не представляет интереса, он используется в комбинации со специальными функциями ожидания. Дескриптор на объект «событие» возвращает функция CreateEvent.
Критические секции – объект синхронизации позволяющий организовать совместное использование набора данных несколькими потоками. Они представляют собой разделы кода, во время выполнения которого текущий поток не может быть прерван, а все остальные переводятся в состояние ожидания. Для начала критической секции используется функция EnterCriticalSection, а для завершения LeaveCriticalSection.
Дата добавления: 2015-11-16; просмотров: 39 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Environmental noise is the summary of noise from transport, industrial and recreational activities. | | | Определение и главные особенности ГИС |