API и FreeBasic. (дочерние окна-static)
Основные и главные особенности дочерних окон:
- имеют окно - владельца, которое может изменяться
- могут и чаще всего имеют идентификатор (ID)
- некоторые события от дочерних окон проходят через процедуру окна владельца
- автоматически уничтожаются после уничтожения окна владельца
Все что видит пользователь в основном окне: кнопки, надписи, ползунки,
скролы и пр., чаще всего это дочерние окна. Почему пишу чаще всего? В реале все
что мы видим на экране - это всего лишь результат рисования. Именно поэтому
не сложно сэмулировать кнопку, нарисовав ее в нужном месте , но она
может не являться дочерним окном.
В системе Windows разработчики сделали
встроенные классы окон. Из-за чего процесс разработки программ резко упростился.
Хотя бы из-за этой особенности, большинство программистов выбирает Windows.
Встроенные классы имеют свою процедуру событий, и нам не надо заботиться
о перерисовке в этом окне. За нас это делает система. Для
нас приготовлены удобные и проверенные временем методы для реализации
нужных задач(получить событие от нажатия кнопки, сдвигать ползунок по требованию
и др.).
В этой статье я хочу коснуться класса Static. Данный класс позволяет
создать окно, в котором можно выводить текст или картинку. Создаются дочерние
окна, в том числе и Static все той же функцией CreateWindowEx (или CreateWindow)
. Однако вы наверное поняли , что регистрировать класс уже не
нужно. Достаточно только при создании окна указать правильно имя класса, в
стилях окна прописать стиль WS_CHILD и в один из параметров функции
CreateWindowEx записать хендл окна владельца. Так же по желанию или точнее в
зависимости от поставленной задачи можно указать идентификатор этого дочернего
окна (далее буду писать КОНТРОЛА). В примере ниже реализованы два
контрола с классом Static. Один будет отображать надпись, а другой
рисунок (в папке с исходным текстом программы должен быть рисунок с именем
1.bmp):
#INCLUDE "windows.bi" Dim msg As MSG 'структурированная переменная MSG Dim As WNDCLASSEX wc 'структурированная переменная WNDCLASSEX Dim As String NameClass="MyClass" ' переменная имени класса Dim As HINSTANCE Hinst=GetModuleHandle(0) ' хендл модуля ' функция класса Function wndproc(hwnd As HWND, msg As Uinteger,_ wparam As WPARAM, lparam As LPARAM) As Integer Dim As HBITMAP bmp Dim image As HWND Select Case msg Case WM_CREATE CreateWindowEx(0,"Static","Надпись",WS_VISIBLE Or WS_CHILD,10,10,100,20,hwnd,Cast(HMENU,1),0,0) image=CreateWindowEx(0,"Static","",WS_VISIBLE Or SS_BITMAP Or WS_CHILD,10,50,100,100,hwnd,Cast(HMENU,2),0,0) bmp=LoadImage(0,"1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE) SendMessage(image,STM_SETIMAGE,IMAGE_BITMAP,Cast(LPARAM,bmp)) Case WM_DESTROY DeleteObject(bmp) PostQuitMessage(0) End Select Return DefWindowProc(hwnd,msg,wparam,lparam) End Function ' Заполнение структуры WNDCLASSEX With wc .cbSize=SizeOf(WNDCLASSEX) .style=CS_HREDRAW Or CS_VREDRAW .lpfnWndProc=@wndproc .hInstance=Hinst .hIcon=LoadIcon(0,IDI_QUESTION) .hCursor=LoadCursor(0,IDC_ARROW) .hbrBackground=Cast(HBRUSH,COLOR_WINDOW) .lpszClassName=StrPtr(NameClass) .hIconSm=.hIcon End With ' Регистрация класса окна If RegisterClassEx(@wc)=0 Then Print "Register error, press any key" Sleep End Endif 'Создание окна CreateWindowEx(0,NameClass,"Главное окно",_ WS_VISIBLE Or WS_OVERLAPPEDWINDOW,100,100,170,220,0,0,Hinst,0) ' Цикл сообщений While GetMessage(@msg,0,0,0) TranslateMessage(@msg) DispatchMessage(@msg) Wend
При отлове сообщения WM_CREATE , мы создали 2 контрола с помощью
функции CreateWindowEx. Обоим в 9 параметре функции присвоили хендл нашего
главного окна. А в 10 параметре для каждого указали свой идентификатор. Хотя по
сути именно для этой программы, можно было вместо идентификаторов указать ноль.
Если присмотритесь, то поймете , что существенная разница в создании указывается
при установке стиля окна. Так во втором контроле мы указали стиль SS_BITMAP , он
даст понять системе, что мы будем в контроле размещать рисунок(битмап).
В данном параметре любого дочернего окна предусмотрены дополнительные стили
к имеющимся стилям при создании обычного окна. Они обычно начинаются с
абревиатуры контрола и знака нижнего подчеркивания. Так например:
SS_BITMAP , можно расшифровать: Static Style
Bitmap
ES_CENTER ,можно расшифровать: Editor Style
Center
BS_RIGHT ,можно расшифровать: Button Style Right
Даже из расшифрованного часто удается понять что делает данный стиль. Но
конечно правильно всегда иметь справочник по функциям API , при том лучше
оригинальный английский вариант.
Давайте рассмотрим какие стили можно
использовать с Static контролом:
- SS_BITMAP - Определяет, что в статическом элементе управления должен отобразиться точечный рисунок. Текст кода ошибки - имя точечного рисунка (не имя файла) определенного в другом месте файла ресурса. Стиль игнорирует параметры nWidth и nHeight; элемент управления автоматически устанавливает собственные размеры, чтобы поместить точечный рисунок.
- SS_BLACKFRAME - Определяет окно с рамкой, использующей тот же самый цвет, как и у рамки основного окна. Этот цвет черный по умолчанию в системе цветов Windows.
- SS_BLACKRECT - Определяет прямоугольник, заполненный текущим цветом рамки окна. По умолчанию этот цвет черный в системе цветов Windows.
- SS_CENTER - Определяет простой прямоугольник и выравнивает по центру текст кода ошибки в прямоугольнике. Текст форматируется перед отображением его на экране. Слова, которые выходят за пределы конца строки автоматически переносятся в начало следующей центрированной строки.
- SS_CENTERIMAGE - Определяет, что средняя точка статического элемента управления со стилем SS_BITMAP или SS_ICON должна остаться фиксированной, когда элемент управления изменяется. Четыре стороны корректируются так, чтобы поместить новый точечный рисунок или пиктограмму. Если статический элемент управления имеет стиль SS_BITMAP, а точечный рисунок меньше чем рабочая область элемента управления, рабочая область заполняется цветом пикселя левого верхнего угла точечного рисунка. Если статический элемент управления имеет стиль SS_ICON, пиктограмма появляется, но не окрашивает рабочую область.
- SS_GRAYFRAME - Определяет поле окна с рамкой, выведенной тем же самым цветом, что и экранный фон (рабочий стол). По умолчанию в системе цветов Windows этот цвет серый.
- SS_GRAYRECT - Определяет прямоугольник, заполненный текущим экранным цветом фона. По умолчанию в системе цветов Windows этот цвет серый.
- SS_ICON - Определяет пиктограмму, отображаемую в диалоговом окне. Данный текст - имя пиктограммы (не имя файла) определенный в другом месте файла ресурса. Стиль игнорирует параметры nWidth и nHeight; пиктограмма автоматически устанавливает свою величину.
- SS_LEFT - Определяет простой прямоугольник и выравнивание по левому краю текста, помещенного в прямоугольнике. Текст форматируется перед его отображением. Слова, которые выходят за пределы конца строки автоматически переносятся в начало следующей выровненной по левой границе строки.
- SS_LEFTNOWORDWRAP - Определяет простой прямоугольник и выравнивание по левому краю текста, помещенного в прямоугольнике. Планшеты расширяются, но слова не переносятся. Текст, который выходит за пределы конца строки, отсекается.
- SS_METAPICT - Определяет, что изображение метафайла должно отобразиться в статическом элементе управления. Данный текст - имя изображения метафайла (не имя файла) определенный в другом месте в файле ресурса. Статический элемент управления метафайла имеет фиксированный размер; изображение метафайла масштабируется, чтобы приспособить рабочую область статического элемента управления.
- SS_NOPREFIX - Предотвращает интерпретацию любого символа амперсанта (&) в тексте элемента управления как символа префикса акселератора. Они отображаются с удаленным амперсантом и следующим за ним подчеркнутым символом в строке. Этот стиль статического элемента управления может быть включен с любым из определенных статических элементов управления. Прикладная программа может объединять SS_NOPREFIX с другими стилями, используя поразрядный оператор OR = ИЛИ (|). Это может быть полезно, когда имена файлов или другие строки, которые могут содержать амперсант (&) должны отображаться в статическом элементе управления диалогового окна.
- SS_NOTIFY - Посылает родительскому окну уведомительные сообщения STN_CLICKED и STN_DBLCLK, когда пользователь щелкает или дважды щелкает мышью по элементу управления.
- SS_RIGHT - Определяет простой прямоугольник и выравнивает по правому краю текста помещенный в прямоугольнике. Текст форматируется перед его отображением на экране. Слова, которые выходят за пределы конца строки автоматически переносятся в начало следующей выровненной по правой границе строки.
- SS_RIGHTIMAGE - Определяет, что угол правой нижней части статического элемента управления со стилем SS_BITMAP или SS_ICON должен остаться фиксированным, когда элемент управления изменяется. Только верхняя и левая стороны корректируются, чтобы поместить новый точечный рисунок или пиктограмму.
- SS_SIMPLE - Определяет простой прямоугольник и отображает одиночную строку выровненного по левой границе текста в прямоугольнике. Текстовая строка не может быть, сокращена или изменена в любом случае. Родительское окно панели управления или диалоговое окно не должны обрабатывать сообщение WM_CTLCOLORSTATIC.
- SS_WHITEFRAME - Определяет поле окна с рамкой, выведенной тем же самым цветом как фон окна. По умолчанию, в системе цветов Windows - этот цвет белый.
- SS_WHITERECT - Определяет прямоугольник, заполненный текущим цветом фона окна. По умолчанию, в системе цветов Windows - этот цвет белый.
Как видите , одни стили можно использовать с изображениями, другие с текстом. Часто встречаются стили, которые несовместимы друг с другом. И в том числе поэтому нужно иметь хороший справочник.
Давайте вернемся к коду. Что касается текстового контрола, то тут должно быть все ясно. Тот текст который мы хотим видеть в контроле, нужно указать в 3 параметре функции CreateWindowEx. Что касается изображений, то тут следует понять, что перед тем как разместить изображение в контроле, нужно загрузить его в память компьютера. При удачной загрузке, система возвратит его хендл. В данном случае мы используем функцию LoadImage. Она способна загружать форматы bmp,ico,cur. После того, как удачно получен хендл изображения, мы привязываем этот хендл к нашему контролу с помощью функции SendMessage, отправляя сообщение STM_SETIMAGE .
В любой момент работы программы, вы можете менять рисунок в контроле с помощью этого сообщения. Как вы понимаете , для замены рисунка нужно указать хендл нового рисунка, который будет загружен перед этим.
Подробнее о функции SendMessage:
Одна из самых часто используемых функций API. Способна отправлять заданное сообщение окну или окнам. Функция вызывает оконную процедуру для заданного окна и не возвращает значение до тех пор, пока оконная процедура не обработает сообщение. В нашем случае мы отправили сообщение окну нашего контрола, зная его хендл и передавая этот хендл в первом параметре. Во втором параметре мы указали константу STM_SETIMAGE. Именно это событие должно обработаться системой в оконной процедуре контрола Static. В третьем параметре так же указана константа IMAGE_BITMAP , указывающая, что передается хендл битмапа, который в свою очередь так же передается в 4 параметре функции. Общий синтаксис SendMessage:
- hWnd - Дескриптор окна, оконная процедура которого примет сообщение. Если этот параметр - HWND_BROADCAST, сообщение отправляется всем окнам верхнего уровня в системе, включая заблокированные или невидимые, не имеющие владельца, перекрывающие и выскакивающие окна; но сообщение не отправляется дочерним окнам.
- Msg - Определяет сообщение, которое будет отправлено.
- wParam - Определяет дополнительную конкретизирующую сообщение информацию.
- lParam - Определяет дополнительную конкретизирующую сообщение информацию.
Подробнее о функции LoadImage:
Это очень удобная функция, если вам нужно загрузить рисунок формата bmp. Она способна загружать рисунок не только напрямую из файла, но и из ресурсов.Сейчас я не хочу касаться работы с ресурсами(это отдельная большая тема). В первом параметре функции мы передаем ноль, поскольку НЕ будем использовать стандартные изображения, а так же изображения из ресурсов. Во втором параметре передаем путь к нашему рисунку. В третьем указываем тип загружаемого изображения. В 4 и 5 параметрах передаем нули, поскольку нам нужны реальные размеры рисунка. И в 6 параметре передаем флаг LR_LOADFROMFILE, сигнализирующий системе, что загрузка будет из файла. Синтаксис функции:
- hinst - Дескриптор экземпляра модуля, который содержит загружаемое изображение. Чтобы загрузить OEM изображение, установите этот параметр в нуль.
- lpszName - Устанавливает загружаемое изображение. Если параметр
hinst - не ПУСТО (NULL), а параметр fuLoad не включает LR_LOADFROMFILE,
параметр lpszName устанавливает ресурс изображения в модуле hinst.
Если ресурс изображения загружается по имени, параметр lpszName -
указатель на символьную строку с нулем в конце, которая содержит имя ресурса
изображения. Если ресурс изображения загружается по порядковому номеру,
используя макрос MAKEINTRESOURCE, то порядковый номер изображения
преобразуется в форму, которая может быть передана в функцию LoadImage. Если
параметр hinst - ПУСТО (NULL), а параметр fuLoad не включает
значение LR_LOADFROMFILE, lpszName устанавливает загружаемое OEM
изображение. Идентификаторы OEM изображения определены в
Winuser.bi и имеют нижеследующие префиксы:
- OBM_ OEM точечные рисунки
- OIC_ OEM значки
- OCR_ OEM курсоры
- uType - Устанавливает тип загружаемого изображения. Этим параметром может
быть одно из ниже перечисленных значений:
- IMAGE_BITMAP Загружает точечный рисунок
- IMAGE_CURSOR Загружает курсор
- IMAGE_ICON
- cxDesired - Устанавливает ширину значка или курсора, в пикселях. Если этот параметр равняется нулю, а параметр fuLoad - LR_DEFAULTSIZE, функция, чтобы установить ширину, использует системное значение размера SM_CXICON или SM_CXCURSOR. Если этот параметр равняется нулю и LR_DEFAULTSIZE не используется, функция использует фактическую ширину ресурса.
- cyDesired - Устанавливает высоту значка или курсора, в пикселях. Если этот параметр равняется нулю, а параметр fuLoad - LR_DEFAULTSIZE, функция, чтобы установить высоту, использует системное значение размера SM_CYICON или SM_CYCURSOR. Если этот параметр равняется нулю и LR_DEFAULTSIZE не используется, функция использует фактическую высоту ресурса.
- fuLoad - Этот параметр может состоять из одного или нескольких
нижеследующих значений:
- LR_DEFAULTCOLOR Задаваемый по умолчанию флажок; он ничего не делает. Все, что это означает - это "не LR_MONOCHROME".
- LR_CREATEDIBSECTION Когда параметр uType устанавливает IMAGE_BITMAP, то заставляет функцию возвращать точечный рисунок DIB секции, а не совместимый точечный рисунок. Этот флажок полезен чтобы загрузить точечный рисунок без отображения его в цвете устройства вывода на экран.
- LR_DEFAULTSIZE Использует ширину или высоту, определенную системными значениями размеров для курсоров или значков, если параметры cxDesired или cyDesired устанавливаются в нуль. Если этот флажок не определен, а cxDesired и cyDesired установлены в нуль, функция использует фактический размер ресурса. Если ресурс содержит несколько изображений, функция использует размер первого изображения.
- LR_LOADFROMFILE Загружает изображение из файла, указанного параметром lpszName. Если этот флажок не определен, lpszName - имя ресурса.
- LR_LOADMAP3DCOLORS Ищет таблицу цветов изображения и заменяет
нижеследующие оттенки серого соответствующим трехмерным цветом:
- Темно-серый, RGB (128,128,128) COLOR_3DSHADOW
- Серый,RGB(192,192,192) COLOR_3DFACE
- Светло-серый RGB(223,223,223) COLOR_3DLIGHT
- LR_LOADTRANSPARENT Извлекает код цвета первого пикселя в
изображении и заменяет соответствующую запись в таблице цветов с заданным по
умолчанию цветом окна (COLOR_WINDOW). Все пиксели в изображении, которые
используют эту запись, становятся заданным по умолчанию цветом окна. Это
значение применяется только к изображениям, которые имеют соответствующие
таблицы цветов. Не используйте этот параметр, если Вы загружаете точечный
рисунок с глубиной цвета больше чем 8 bpp (битов на пиксель).
Если параметр fuLoad включает в себя значения и LR_LOADTRANSPARENT, и LR_LOADMAP3DCOLORS, то LR_LOADTRANSPARENT имеет приоритет. Однако, запись таблицы цветов заменяется на COLOR_3DFACE, а не COLOR_WINDOW. - LR_MONOCHROME Загружает изображение в черно-белом цвете.
- LR_SHARED Совместно использует дескриптор изображения, если
изображение загружено несколько раз. Если LR_SHARED не установлен,
второй вызов функции LoadImage для одного и того же ресурса загрузит
изображение снова и возвратит другой дескриптор. Когда Вы используете этот
флажок, система уничтожает ресурс, когда он больше не нужен.
Не используйте LR_SHARED для изображений, которые имеют нестандартные размеры, которые могут измениться после загрузки, или которые загружаются из файла. При загрузке системного значка или курсора, Вы должны использовать флажок LR_SHARED, или функция будет не в состоянии загрузить ресурс. Windows 95/98/Me: функция находит первое изображение с затребованным именем ресурса в кэше, независимо от затребованного размера. - LR_VGACOLOR Используются истинные VGA цвета.
Для того, чтобы сменить текст у первого контрола , можно так же воспользоваться функцией SendMessage , отправляя сообщение WM_SETTEXT. При этом в третьем параметре передается 0, а в четвертом указатель на строковую переменную. Если нужно получить текст из контрола, то есть похожее сообщение WM_GETTEXT. В этом случае в четвертом параметре указатель на принимающий буфер, а в третьем параметре передается кол-во принимаемых символов. Кроме функции SendMessage, можно использовать специально-предназначенные для этих целей функции: SetWindowText и GetWindowText. У этих функций вычеркнуты лишние параметры, которые приходится прописывать у универсальной функции SendMessage. Синтаксис этих функций:
SetWindowText
- hWnd, хендл окна
- lpString указатель на строку
GetWindowText
- hWnd хендл окна
- lpString указатель на буфер
- maxCount максимальное кол-во символов для помещения в буфер
Пример:
#INCLUDE "windows.bi" Dim msg As MSG 'структурированная переменная MSG Dim As WNDCLASSEX wc 'структурированная переменная WNDCLASSEX Dim As String NameClass="MyClass" ' переменная имени класса Dim As HINSTANCE Hinst=GetModuleHandle(0) ' хендл модуля Dim Shared As HWND Mhwnd,STText ' функция класса Function wndproc(hwnd As HWND, msg As Uinteger,_ wparam As WPARAM, lparam As LPARAM) As Integer Dim As String*32 text,textM Select Case msg Case WM_CREATE STText=CreateWindowEx(0,"Static","Надпись",WS_VISIBLE Or WS_CHILD,10,10,100,20,hwnd,Cast(HMENU,1),0,0) Case WM_LBUTTONDOWN SendMessage(STText,WM_GETTEXT,32,Cast(lparam,@text)) GetWindowText(Mhwnd,Cast(LPSTR,@textM),32) SendMessage(STText,WM_SETTEXT,0,Cast(lparam,@textM)) SetWindowText(Mhwnd,Cast(LPSTR,@text)) Case WM_DESTROY PostQuitMessage(0) End Select Return DefWindowProc(hwnd,msg,wparam,lparam) End Function ' Заполнение структуры WNDCLASSEX With wc .cbSize=SizeOf(WNDCLASSEX) .style=CS_HREDRAW Or CS_VREDRAW .lpfnWndProc=@wndproc .hInstance=Hinst .hIcon=LoadIcon(0,IDI_QUESTION) .hCursor=LoadCursor(0,IDC_ARROW) .hbrBackground=Cast(HBRUSH,COLOR_WINDOW) .lpszClassName=StrPtr(NameClass) .hIconSm=.hIcon End With ' Регистрация класса окна If RegisterClassEx(@wc)=0 Then Print "Register error, press any key" Sleep End Endif 'Создание окна Mhwnd=CreateWindowEx(0,NameClass,"Главное окно",_ WS_VISIBLE Or WS_OVERLAPPEDWINDOW,100,100,250,100,0,0,Hinst,0) ' Цикл сообщений While GetMessage(@msg,0,0,0) TranslateMessage(@msg) DispatchMessage(@msg) Wend
В примере при нажатии на левую кнопку мыши по клиентской области окна, происходит обмен надписями у заголовка окна и контрола Static. Здесь я использовал оба вышеописанных способа получения и установки текста при помощи SendMessage и функций SetWindowText , GetWindowText. Хотя если честно, всегда для получения и установки текста, пользуюсь функциями SetWindowText и GetWindowText. В обработке сообщения WM_LBUTTONDOWN первые две строчки получают текстовые значения в буфер, следующие две отправляют новые значения окнам.
Беря данные примеры как основу, вы можете эксперементировать с разными стилями контрола Static. Не забывайте что у функции CreateWindowEx есть первый параметр дополнительных стилей, который тоже кое-что визуально меняет у контрола Static...
Изменять размеры контрола можно точно так же как и с обычным окном с помощью MoveWindow. Если пропустили , читаем в этой статье Что касается изменения цвета текста или шрифта, то для этого возможно будет отдельная статья. На этом все, всего доброго!
содержание | назад | вперед