Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Лабораторная работа 1.
- Создание окон.
- Программы для Windows называют приложениями. Пользователь с приложением взаимодействует через окна следующих видов:
- 1. Окно приложения. Оно организует работу, появляется первым при запуске и закрывается вместе с прекращением работы приложения.
- 2. MDI-окиа. Они служат для одновременной обработки нескольких документов.
- 3. Окно помощи. Оно в большей степени работает под управлением операционной системы, чем под управлением приложения.
- 4. Диалоговое окно. Оно обеспечивает оперативный обмен данными между пользователем и приложением (рис. 1.1).
- Рис. 1.1. Окно со множеством элементов: 1 - кнопка системного меню; 2 - кнопка сворачивания окна в пиктограмму; 3- кнопка максимализации или восстановления размеров окна; 4- кнопка закрытия окна; 5 - рамки изменения размеров окна
- С точки зрения языка программирования, окна - это объекты (пере¬менные), над которыми выполняют действия.
- Класс окон.
- Набор используемых ресурсов класса задают в структуре типа WNDCLASS. Эта структура описана следующим образом: typedef struct
- {
- UINT style;
- WNDPROC IpfnWndProc;
- Int cbClsExtra;
- Int cbWndExtra;
- HANDLE hlnstance;
- HICON hlcon;
- HCURSOR hCursor;
- HBRUSH hbrBackground;
- LPCTSTR IpszMenuName
- LPCTSTR IpszClassName;
- } WNDCLASS;
- Назначение полей структуры:
- 1. style – описывает стиль клааса окна.
- Например: wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
- 2. IpfnWndProc – указывает на функцию окна.
- 3. cbClsExtra – равно количеству дополнительных байт класса.
- 4. cbWndExtra – равно количеству дополнительных байт окна этого класса.
- 5. hlnstance – указывает на дескриптор текущего приложения.
- 6. hlcon – указывает на имя пиктограммы (иконки), в которую превраща¬ется окно при минимизации. Ресурс иконки загружают функцией LoadIcon.
- 7. hCursor – задает вид курсора мыши при его прохождении над окном. Ресурс курсора агружают функцией LoadCursor.
- 8. hbrBackground – задает дескриптор кисти закрашивания фона окна.
- 9. IpszMenuName – указывает на имя ресурса главного меню окон этого класса. Если задать NULL, окна этого класса не имеют заданного по умолчанию меню.
- 10. IpszClassName – указывает на текстовую строку, содержащую имя ре¬гистрируемого класса окон.
- Для регистрации класса окон удобно использовать функцию следу¬ющего вида:
- int RegClass( WNDPROC Proc, LPCTSTR szName)
- {
- WNDCLASS wc;
- wcstyle = CS.HREDRAW | CS.VREDRAW;
- wc.cbClsExtra = wccbWndExtra = 0;
- wclpfnWndProc = Proc; wc.hlnstance = hlnstance;
- wchlcon = Loadlcon(NULL, IDLAPPLICATION);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wchbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wc.lpszMenuName = (LPCTSTR)NULL;
- wc.lpszClassName = szName;
- return RegisterClass(&wc);
- }
- Формальными параметрами этой функции являются указатели на функцию окна и строку с именем класса. Имя, список формальных пара¬метров и тип возврата функции могут быть любыми другими. Главное, чтобы приложению после регистрации были доступны имя зарегистри¬рованного класса, а операционной системе - функция окна этого класса.
- Функция окна описывает реакцию окна на поступающие сообщения. Она от обычных функций отличается следующим;
- • имеет стандартные тип возврата и список формальных парамет¬ров;
- • вызывается только операционной системой при поступлении сообще¬ния окну;
- • сообщения, которые не обрабатываются функцией окна, возвра¬щаются операционной системе.
- Есть еще одно отличие. В объектно-ориентированном программиро¬вании методы изменения параметров состояния объекта обычно описывают отдельно. Функция окна реализует единствен¬ный метод для изменения всех параметров состояния окна.
- Имя функции окна - это обычное имя, определяемое разработчиком. При регистрации класса операционная система запоминает указатель на эту функцию.
- Рассмотрим пример описания функции окна.
- LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM IParam)
- {
- static short ex, cy, left, top; //Описание локальных переменных
- switch (msg) //Обработка сообщения
- { caseWM_CREATE: { ...; return 0;}
- case WM.MOVE:
- { left=LOWORD(IParam); top=HIWORD(IParam); return 0;
- }
- case WM_SIZE:
- {
- cx= LOWORD(IParam); cy=HIWORD(IParam);
- return 0;
- }
- case WM_COMMAND: //Обрабатываем команды
- {
- switch (LOWORD(wParam))
- {
- case CM_FILE_EXIT:
- { DestroyWindow(hwnd); return 0; }
- //Далее могут быть ветви других команд
- } return 0;
- }
- case WM_DESTROY:
- { ...; PostQuitMessage(O); return 0;}
- }
- return DefWindowProc(hwnd, msg, wParam, IParam);
- }
- Заголовок функции окна определен соглашениями Windows и имеет вид:
- LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM IParam)
- Тип возврата LRESULT равноценен типу signed long. Модификатор CALLBACK указывает на соглашения о том, что эта функция вызывает¬ся операционной системой (такие функции называют функциями об¬ратного вызова).
- Имена типов UINT, WPARAM, LPARAM описаны следующим образом:
- typedef unsigned int UINT;
- typedef UINT WPARAM;
- typedef LONG LPARAM;
- Параметр hwnd - дескриптор окна-адресата, a msg, wParam и IParam описывают полученное сообщение. Например, параметр msg принимает код сообщения.
- Рассмотрим, каким сообщениям соответствуют используемые в при¬мере имена констант. В Windows описаны несколько сот кодов сообще¬ний с префиксом WM_.
- Код WM_CREATE поступает от функции CreateWindow перед созданием окна. Если после обработки этого сообщения функции CreateWindow возвращается значение -1, то окно не создается.
- Код WM_SIZE функция окна получает после изменения размеров окна, a WM_MOVE - после перемещения левого верхнего угла рабочей области окна. Если при изменении размеров окна изменились координа¬ты левого верхнего угла рабочей области, то функция окна сначала по¬лучает код WM_MOVE, а затем - WM_SIZE.
- Код WM_COMMAND функция окна получает при поступлении ко¬манды. Тогда младшее слово параметра wParam содержит код команды.
- Код WM_DESTROY функции окна посылают перед разрушением окна. В примере функция окна, вызывая функцию DestroyWindow, сама себе отправляет сообщение WMDESTROY.
- Рассмотрим сообщения от мыши. Пусть курсор мыши находится над рабочей областью окна. После нажатия левой клавиши мыши функция окна получит код WM_LBUTTONDOWN а правой клавиши - WM_RBUTTON DOWN. После отжатия левой (правой) клавиши функция окна получит код WMJLBUTTONUP (WM_RBUTTONUP). После перемещении кур¬сора мыши функция окна получает код WM_MOUSEMOVE.
- Можно получать сообщения от мыши, даже если курсор мыши не на¬ходится над рабочей областью окна. Для передачи мыши в монопольное использование окну hwnd вызывают функцию: HWND SetCapture(HWND hwnd);
- Эта функция возвращает дескриптор окна, у которого в монопольном пользовании была мышь, или NULL.
- Вызов функции void ReleaseCapture(void); отменяет режим монопольного использования.
- Значение параметра IParam зависит от кода сообщения.
- При поступлении кода WMMOVE параметр IParam содержит экранные координаты левого верхнего угла рабочей области. Например:
- left=LOWORD(IParam); //Координата левого края рабочей области
- top=HIWORD(IParam); //Координата верхнего края рабочей области
- Для кода WM_SIZE параметр IParam несет информацию о ширине сх и высоте су рабочей области:
- cx=LOWORD(IParam); //Ширина рабочей области
- cy=HIWORD(IParam); //Высота рабочей области
- При поступлении любых сообщений от мыши расстояние курсора мыши от левого края рабочей области равно LOWORD(lParam), а от верхнего края - HIWORD(lParam).
- Вызов функции DefWindowProc означает, что. необработанное сооб¬щение возвращают операционной системе.
- Для создания окна вызывают функцию CreateWindow. Она создает перекрывающееся, временное или дочернее окно и устанавливает на¬чальные значения некоторых его параметров. Эта функция объявлена следующим образом:
- HWND CreateWindow{
- LPCSTR IpClassName,
- LPCSTR IpWindowName,
- DWORD dwStyle,
- int x,
- int y,
- int nWidth,
- int Height,
- HWND hWndParent,
- HMENU hMenu,
- HANDLE hInstanse,
- LPVOID IpParam
- };
- Назначение параметров вызова этой функции:
- 1. IpClassName указывает на имя зарегистрированного функцией RegisterClass или определенного операционной системой класса.
- 2. dwStyie задает стиль окна..
- 3. х - координата левого края окна в пикселях. Для перекрывающихся или временных окон х отсчитывают от левого края экрана, дочерних окон - от левого края рабочей области родительского окна. Если для перекрывающегося окна со стилем WSVISIBLE в качестве х задать константу CWJJSEDEFAULT, Windows устанавливает не обязатель¬но нулевую позицию по умолчанию для левого верхнего угла окна и игнорирует координату у верхнего края окна. Для временного и дочернего окна такая позиция по умолчанию равна (0,0).
- 4. у - координата верхнего края окна в пикселях. Для перекрывающихся и временных окон ее отсчитывают от верхнего края экрана, дочерних окон - от верхнего края рабочей области родительского окна.
- 5. nWidth - ширина окна в пикселях. Для перекрывающихся окон мож¬но задать равной WJJSEDEFAULT. В этом случае система уста¬навливает ненулевые значения ширины и высоты по умолчанию и игнорирует заданную высоту nHeight окна. Ширина и высота вре¬менного и дочернего окна по умолчанию равны нулю.
- 6. hWndParent может указывать только на инициированное окно. Де¬скриптор окна-родителя обязательно указывают при создании до¬чернего окна. Дескриптор окна-владельца для временного окна ука¬зывать необязательно.
- 7. hMenu - дескриптор меню или идентификатор создаваемого дочер¬него окна.
- еню перекрывающегося или временного окна можно задать тремя способами:
- 1) в классе окон указывают имя меню, и все окна этого класса мо¬
- гут пользоваться этим меню;
- 2) имя меню указывают как аргумент функции CreateWindow, и создаваемое окно будет пользоваться этим меню, игнорируя меню класса;
- 3) меню создают в процессе или после создания окна.
- Стиль окна задает внешнее поведение окна.
- Для описания стиля окна используют символические константы с префиксом WS_.
- По совокупности свойств различают перекрывающиеся (overlapped), временные (pop-up) и дочерние (child) окна.
- Перекрывающиеся окна чаще используют в качестве окон при¬ложения. Они всегда имеют заголовок (title bar), рамку и рабочую об¬ласть окна (client region), могут иметь системное меню, кнопки восста¬новления размеров, закрытия и сворачивания окна в пиктограмму, го¬ризонтальную и вертикальную полосы просмотра (scroll bar), меню, панель инструментов (tool bar) и строку состояния (status bar) (см. рис. 1.1). Базовый стиль таких окон описан константой WS_OVERLAPPED. Чаще используемый стиль окон WS_OVERLAPPED WINDOW вдобавок к базовому указывает, что окно имеет системное меню, кнопки восста¬новления размеров, закрытия и сворачивания окна.
- Перекрывающееся окно может принадлежать другому окну (владельцу). Если окно-владелец сворачивается в пиктограмму, то подчиненные ему окна становятся невидимыми. При уничтожении окна автоматически унич¬тожаются подчиненные ему окна. Подчиненные окна всегда располагаются над поверхностью окна-владельца, загораживая его.
- Временные окна обычно используют для вывода сообщений пользо¬вателю и остаются на экране непродолжительное время. Базовый стиль временного окна описан константой WS_POPUP. Такое окно по умолча¬нию не имеет заголовка. Чаще временное окно описывают константой WS_POPUPWINDOW. Для добавления к временному окну системного меню и заголовка стиль WS_POPUPWINDOW комбинируют со стилем WS_CAPTION. Во всем остальном временные окна - это специальный вид перекрывающихся окон.
- Дочерние окна используют для создания органов управления. Опре¬деляемые системой классы органов управления (кнопки, полосы про¬смотра и т. п.) представляют собой дочерние окна. Базовый стиль дочер¬них окон описан константой WS_CHILD. Этот стиль полностью совпа¬дает со стилем WS_ CHILDWINDOW. Дочерние окна не имеют кнопок минимизации и максимального увеличения размера, но всегда имеют ок¬но-родителя. Они "прилипают" к поверхности родителя, перемещаются с ним и не могут выйти за пределы родительского окна.
- Приложения всегда описывают функцию с именем WinMain. Она получает управление при запуске приложения, выполняет присущие обычным функциям действия, регистрирует классы окон, создает окна, опрашивает очередь сообщений и распределяет свои сообщения.
- Пример описания функции WinMain:
- int WINAPI WinMain( HINSTANCE hlnstance,
- HINSTANCE hPrevlnstance, LPSTR IpszCmdLine, int nCmdShow)
- {
- MSG msg; HWND hwnd;
- if (!RegClass(WndPrtic, szClassName)) return FALSE;
- hwnd = CreateWindow(szCiassName, “Пример 1”, WS_OVERLAPPEDWINDOW, CWJJSEDEFAULT, CWJJSEDEFAULT,CWJJSEDEFAULT, CWJJSEDEFAULT,
- 0,0, hlnstance.NULL);
- if (!hwnd) return FALSE;
- ShowWindow( hwnd, SW_SHOWMAXIMIZED);
- UpdateWindow(hwnd); while (GetMessage(&msg, 0,0,0))
- { TransiateMessage(&msg); DispatchMessage(&msg); }
- return msg.wParam;
- }
- В теле функции WinMain описаны переменные msg и hwnd. Пере¬менная msg предназначена для временного хранения сообщений при их получении и распределении. Переменная hwnd хранит дескриптор созданного окна.
- Структура текста приложения определяется двумя требованиями:
- 1. Текст содержит описание функции с именем WinMain.
- 2. Если регистрируются новые классы, то текст содержит описание структуры типа WNDCLASS и функций окон этих классов.
- Windows API содержит множество функций, связанных с созданием окон. Это функции поиска, определения состояния, перемещения окон, а также обмена сообщениями с пользователем.
- Функции поиска и определения состояния окон.
- Часто требуется определить, существует ли окно для некоторого де¬скриптора. На этот вопрос отвечает функция IsWindow: BOOL lsWindow( HWND hwnd);
- Если нужно определить, имеет ли заданное окно фокус ввода, вызы¬вают функцию IsWindowEnabled:
- BOOL lsWindowEnabled( HWND hwnd);
- Для передачи или отнятия фокуса ввода у окна вызывают функцию EnableWindow:
- BOOL EnableWindow( HWND hwnd, BOOL bEnable);
- Фокус ввода окну hwnd передают с помощью функции SetFocus:
- SetFocus(hwnd);
- Следующая функция возвращает ненулевое значение, если окно hwnd свернуто в пиктограмму: BOOL lslconic(HWND hwnd);
- Функция FindWindow у операционной системы запрашивает деск¬риптор окна класса lpClassName с заголовком lpWindowName. Эта функция объявлена следующим образом:
- HWND FindWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName);
- Функции перемещения окон
- Для перемещения и изменения размеров окна hwnd вызывают функ¬цию MoveWindow. Ей передают новые координаты окна.
- Функция SetWindowPos изменяет координаты окна hwnd на экране и его расположение по отношению к другим окнам.
- При одновременной работе нескольких приложений одно из них можно вывести на передний план и передать его окну фокус ввода. Для этих целей используют функцию SetForegroundWindow. Она по¬мещает поток, который создал заданное окно, на передний план и акти¬визирует это окно. Синтаксис этой функции:
- BOOL SetForegroundWindow (HWND hwnd );
- Для перемещения окна важно знать системные метрики экрана и ок¬на. Их получают с помощью функции GetSystemMetrics. Она возвращает метрики и текущие установки конфигурации системы. Метрики систе¬мы - это габариты (ширина и высота) отображаемых элементов Windows. Все габариты возвращаются в пикселях..
- Функция GetSystemMetrics объявлена следующим образом:
- int GetSystemMetrics (int nlndex);
- Параметр nlndex указывает на возвращаемую метрику системы или установку конфигурации.
- Например, следующий оператор определяет ширину экрана:
- Int w=GetSystemMetrics(SM_GXSCREEN);
- Следующая функция позволяет получить координаты обрамляющего окно liwnd прямоугольника:
- BOOL GetWindowRect( HWND hwnd, LPRECT IpRect);
- Параметр IpRect указывает на структуру типа RECT.
- Функция GetClientRect возвращает координаты прямоугольника, об¬рамляющего рабочую область окна:
- BOOL GetClientRect( HWND hwnd, LPRECT IpRect);
- Сообщения приложения для пользователя
- Для вывода текстовых сообщений и получения ответа пользователя применяют окно сообщения. Функция MessageBox создает, отображает, обеспечивает работу и закрывает окно сообщения.
- Приложение может обработать ответ пользователя на сообщение, анализируя возвращаемое функцией MessageBox значение.
- Windows предусматривает возможность выдачи и звуковых "сообще¬ний". Например, при вызове функции MessageBeep компьютер проигры¬вает "звук" из множества зарегистрированных в системе "звуков". Син¬таксис этой функции:
- BOOL MessageBeep( UINT uType);
- Параметр uType этой функции определяет звуковой тип и принимает одно из следующих значений:
- Если требуется обратить внимание пользователя на определенное ок¬но, то можно несколько раз изменить подсветку окна или его пикто¬граммы.
- Для этой цели используют функцию FlashWindow, которая за один вызов один раз изменяет подсветку указанного окна:
- BOOL FlashWindow(
- HWND hwnd, //Дескриптор подсвечиваемого окна
- BOOL blnvert //Параметр подсветки
- );
- Пример. После нажатия левой клавиши мыши над окном hwnd 5 раз изменить подсветку неактивного окна OwnedHwnd.
- Следующий фрагмент описывает версию решения этой задачи:
- case WM_LBUTTONDOWN:
- { FlashWindow(OwnedHwnd, TRUE);
- for (int i=0; i<9; i++)
- { for (long j=0;j<1e7;j++);
- FlashWindow(OwnedHwnd, TRUE);
- } .
- return 0;
- }
- Задания.
- 1. После нажатия на левую (правую) клавишу мыши над рабочей об¬ластью окна в левом верхнем (правом нижнем) углу области отобразить временное окно размером в четверть области. Временное окно скрыть после отжатия клавиши в любом месте экрана.
- 2. В левом верхнем (в правом нижнем) углу рабочей области окна! создать временное (дочернее) окно. После нажатия левой клавиши мыши 4 раза "мигает" временное окно, а после нажатия правой - 3 раза "мига¬ет" дочернее окно. При этом окна выдают различные звуковые сигналы.
- 3. Создать окно приложения размером в одну шестнадцатую площади эрана с заголовком "Форматирование диска" без кнопок изменения размеров, закрытия и сворачивания в пиктограмму и без кнопки систем¬ного меню. При перемещении курсора мыши над рабочей областью окно должно "убегать" от курсора мыши в случайным образом выбранном на¬правлении, оставаясь в пределах экрана.
- 4. В левом верхнем углу рабочей области окна создать временное ок¬но площадью в одну шестнадцатую площади этой области. При нажатии па левую (правую) клавишу мыши временное окно переместить в сосед¬ний по ходу (против хода) часовой стрелки угол рабочей области.
- 5. При запуске i-го экземпляра (i>2) приложения спросить пользова¬теля, нужно ли его запустить. Если пользователь ответит "Да", то запус¬тить его. Иначе на передний план переместить 2-й экземпляр приложе¬ния и завершить работу i-го экземпляра.
- 6. Углы рабочей области окна приложения полностью занимают 4 временных окна одного класса. Если нажать левую клавишу мыши над временным окном, то это окно выдает сообщение о своем заголовке.
- 7. Окно приложения без заголовка занимает весь экран фоном рабо¬чего стола.
- 8. В центре рабочей области окна располагается невидимое окно без заголовка размером в четверть площади рабочей области. После нажатия пеной клавиши мыши над рабочей областью любого из окон окно без заголовка должно стать видимым, а после нажатия правой - невидимым.
- 9. В центре рабочей области окна отображено дочернее окно с фоном циста трехмерных элементов с вертикальной и горизонтальной полосами просмотра размером в четверть этой области. Дочернее окно перемещается и тот угол рабочей области, где нажали левую клавишу мыши.
- 10. В центре рабочей области окна расположено окно без заголовка V вертикальной и горизонтальной полосами просмотра размером в чет¬верть рабочей области. При нажатии разных клавиш мыши временное нк но выдает разный звуковой сигнал.
- 11. Создать окно размером в четверть площади экрана. После двой¬ною щелчка мыши окно перемещается так, что его центр совпадает с координатами курсора мыши в момент щелчка.
- 12. Дочернее окно размером 100*100 пикселей при перемещении курсора мыши над ним "убегает" от курсора мыши в произвольном на¬правлении, оставаясь в пределах рабочей области родительского окна.
- 13. При запуске второго экземпляра приложения сообщить о запрете
- ка нескольких экземпляров, на передний план переместить первый экземпляр приложения, 3 раза изменить подсветку его окна, выдавая звуковое предупреждение, и завершить работу второго экземпляра.
- 14. В рабочей области окна приложения рядом друг с другом распо¬ложить 3 временных окна, каждое из которых по-своему реагирует на нажатие левой клавиши мыши.
- 15. Окно первого экземпляра приложения расположить в левом верх¬нем, второго - в правом верхнем, третьего - в левом нижнем, четверто¬го - в правом нижнем углу экрана. Причем все окна равных размеров и вместе занимают весь экран. В заголовке окна указать номер экземпляр ра. Запретить запуск пятого экземпляра.
- 16. Центр рабочей области окна занимает временное окно размером в четверть площади области в свернутом состоянии. После нажатия ле¬вой клавиши мыши над рабочей областью временное окно распахивается в центре области, а после нажатия правой - сворачивается в центре.
- 17. Центр рабочей области окна занимает временное окно размером в четверть площади области. Оно перемещается в тот угол рабочей об¬ласти, где щелкнули левой клавишей мыши. А после щелчка правой клавишей мыши временное окно перемещается в угол, противоположный текущему углу.
- 18. Окно приложения занимает четверть экрана и расположено в левом верхнем углу. Создать временное окно такого же размера в правом нижнем углу экрана. Любое окно после нажатия левой клавиши мыши перемещается в свободный по ходу часовой стрелки угол.
- 19. Окно размером в четверть площади экрана расположено в центре экрана. После нажатия левой клавиши мыши окно несколько раз меняет подсветку и перемещается в угол экрана так, что курсор мыши оказывается за пределами окна.
- 20. При запуске не первого экземпляра приложения выдать преду¬преждающий звуковой сигнал и сообщить о количестве уже работающих копий этого приложения. Запустить экземпляр, только если согласи! пользователь.
- 21. В рабочей области окна приложения рядом друг с другом расположить 4 временных окна, в заголовках которых указан номер окна. После нажатия левой клавиши мыши временное окно выдает сообщение! содержащее номер окна.
- 22. Правый верхний угол рабочей области окна приложения занимает! временное окно размером в четверть этой области. После нажатия левой клавиши мыши над рабочей областью окна приложения временное окно сворачивается в пиктограмму в левом нижнем углу, а после нажатия левой - распахивается в правом верхнем углу рабочей области.
- 23. В углах рабочей области окна приложения созданы невидимые временные окна с заголовком. Каждое окно становится видимым после нажатия левой клавиши мыши над его частью рабочей области и становится невидимым после нажатия левой клавиши мыши над его рабочей областью.
- 24. Окно приложения размером в четверть площади экрана занимает один из углов экрана. После нажатия левой клавиши мыши окно свора¬чивается в пиктограмму. После щелчка по пиктограмме оно восстанав¬ливается в другом углу экрана.
- 25. При запуске приложения показать окна уже существующих копий •того приложения и спросить пользователя, нужно ли запустить еще один экземпляр. Если пользователь ответит "Да", то запустить его. Ина¬че завершить работу приложения.
Add Comment
Please, Sign In to add comment