API и FreeBasic. (замена стиля окна часть 1)

Создав окно, может так получиться, что нужно будет поменять его атрибуты в процессе выполнения программы. Многие установленные вами поля структуры WNDCLASSEX можно менять. Для этого существуют великолепные функции SetWindowLong (изменение атрибутов для одного окна) и SetClassLong(изменение атрибутов для всех окон класса). У каждой из них три параметра. Давайте рассмотрим для функции SetClassLong:

  • hWnd - хендл окна, у которого следует делать замену атрибута
  • nIndex - индекс заменяемого атрибута, может быть:
    • GCL_CBCLSEXTRA     Устанавливает размер дополнительной памяти, связанной с классом, в байтах.
    • GCL_CBWNDEXTRA     Устанавливает размер дополнительной памяти окна, связанной с каждым окном в классе, в байтах. Установка этого значения не изменяет число дополнительных байт, назначенных ранее. За информацией о том, как получить доступ к этой памяти, обратитесь к функции GetWindowLong.
    • GCL_HBRBACKGROUND     Заменяет дескриптор кисти фона, связанной с классом.
    • GCL_HCURSOR     Заменяет дескриптор курсора, связанного с классом.
    • GCL_HICON     Заменяет дескриптор значка, связанного с классом.
    • GCL_HICONSM     Заменяет дескриптор маленького значка, связанного с классом.
    • GCL_HMODULE     Заменяет дескриптор модуля, который зарегистрировал класс.
    • GCL_MENUNAME     Заменяет адрес строки с именем меню. Строка идентифицирует ресурс меню, связанный с классом.
    • GCL_STYLE     Заменяет данные о битах стиля класса окна.
    • GCL_WNDPROC     Заменяет адрес оконной процедуры связанной с классом .
  • dwNewLong -  новый атрибут

А теперь для функции SetWindowLong:

  • hWnd - хендл окна, у которого следует делать замену атрибута
  • nIndex - индекс заменяемого атрибута, может быть:
    • GWL_EXSTYLE - Устанавливает новый расширенный стиль окна.
    • GWL_STYLE - Устанавливает новый стиль окна.
    • GWL_WNDPROC - Устанавливает новый адрес для оконной процедуры.
    • GWL_HINSTANCE - Устанавливает новый дескриптор экземпляра прикладной программы.
    • GWL_ID - Устанавливает новый идентификатор окна.
    • GWL_USERDATA - Устанавливает 32-разрядное значение, связанное с окном. Каждое окно имеет соответствующее 32-разрядное значение, предназначенное для использования прикладной программой, которая создала окно.

      Следующие значения также доступны, когда параметр hWnd идентифицирует диалоговое окно:

    • DWL_DLGPROC - Устанавливает новый адрес процедуры диалогового окна.
    • DWL_MSGRESULT - Устанавливает возвращаемое значение сообщения, обработанного в процедуре диалогового окна
    • DWL_USER - Устанавливает новую дополнительную информацию, которая является частной для прикладной программы, типа дескрипторов или указателей.
  • dwNewLong -  новый атрибут

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

А теперь давайте с помощью этих функций превратим рассмотренное нами ранее диалоговое окно класса #32770 в практически полноценное окно. Ведь разница была только в обработке сообщений. То есть нам нужно создать свою процедуру и с помощью SetWindowLong установить для диалогового окна новую процедуру. В результате мы уже сами будем отвечать за обработку сообщений этого окна. А так же поменяем цвет окна. Ведь в нащей процедуре нет ограничений на используемый цвет диалога(в отличии от системной процедуры)

#INCLUDE "windows.bi"

Dim msg As MSG 'структурированная переменная MSG
Dim hwnd As HWND  'хендл окна
Dim hbr As  HBRUSH 'кисть

' функция класса
Function wndproc(hwnd As HWND, msg As Uinteger, wparam As WPARAM, lparam As LPARAM) As Integer
    Select Case msg
        Case WM_DESTROY
            PostQuitMessage(0)
    End Select
    Return DefWindowProc(hwnd,msg,wparam,lparam)
End Function

'Создание окна
hwnd=CreateWindowEx(0,"#32770","Первое окно",WS_VISIBLE Or WS_OVERLAPPEDWINDOW, _
100,100,300,300,0,0,0,0)

'Заменяем процедуру на свою
SetWindowLong(hwnd,GWL_WNDPROC,Cast(Long,@wndproc))

'Создаем кисть синего цвета
hbr=CreateSolidBrush(&hff0000)

'Меняем цвет окна
SetClassLong(hwnd,GCL_HBRBACKGROUND,Cast(Long,hbr))

'Перерисовываем окно
InvalidateRect (hwnd,NULL,TRUE)

'Обработка сообщений в цикле
While GetMessage(@msg,0,0,0)
    DispatchMessage(@msg)
Wend
'удаляем кисть
DeleteObject(hbr)


В данном примере мы создали кисть с помощью CreateSolidBrush , у которой один параметр: значение цвета в формате BGR (BLUE , GREEN, RED). А далее передали созданную нами кисть в 3 параметр функции SetClassLong , а во втором параметре передали индекс GCL_HBRBACKGROUND. Для того, чтобы изменения вступили в силу немедленно, окно надо перерисовать. Это мы сделали с помощью функции InvalidateRect. Она имеет три параметра:

  • hWnd - хендл окна, которое надо перерисовать
  • lpRect - прямоугольник перерисовки, если 0, то всю область окна
  • bErase - режим перерисовки. Если 1 , то стирать фон, если 0, то не стирать

Для замены процедуры мы использовали функцию SetWindowLong, у которой во втором параметре передали атрибут GWL_WNDPROC , а в третьем адрес нашей процедуры. Для замены процедуры мы не можем применить функцию SetClassLong, поскольку она меняет процедуру только для следующих созданных окон с этим классом.

Очень часто требуется дополнить стиль окна. Делается это с помощью двух функций GetWindowLong и SetWindowLong. У функции GetWindowLong имеющиеся два параметра такие же как два первых параметра SetWindowLong. Ее назначение - получать значения заданного атрибута. В примере ниже, для изменения стиля окна, надо щелкнуть левой кнопкой мыши по клиентской области окна.

#INCLUDE "windows.bi"

Dim msg As MSG 'структурированная переменная MSG
Dim hwnd As HWND  'хендл окна
Dim Shared style As Integer ' стиль окна

' функция класса
Function wndproc(hwnd As HWND, msg As Uinteger, wparam As WPARAM, lparam As LPARAM) As Integer
    Select Case msg
        Case WM_LBUTTONDOWN
            ' получаем стиль нашего окна
            style=GetWindowLong(hwnd,GWL_STYLE)
            ' установим новый стиль нашего окна
            SetWindowLong(hwnd,GWL_STYLE,style Or WS_OVERLAPPEDWINDOW)
        Case WM_DESTROY
            PostQuitMessage(0)
    End Select
    Return DefWindowProc(hwnd,msg,wparam,lparam)
End Function

'Создание окна
hwnd=CreateWindowEx(0,"#32770","Первое окно",WS_VISIBLE,100,100,300,300,0,0,0,0)

'Заменяем процедуру на свою
SetWindowLong(hwnd,GWL_WNDPROC,Cast(Long,@wndproc))

'Обработка сообщений в цикле
While GetMessage(@msg,0,0,0)
    DispatchMessage(@msg)
Wend


В примере сначала создается окно со стилем видимое, но без кнопочек (свернуть, максимизировать и закрыть). Далее в оконной процедуре сделан обработчик левой кнопки мыши. В результате нажатия левой кнопки мышки, происходит изменение стиля окна и появляется возможность закрыть окно. Как вы поняли, мы попросту получили имеющийся стиль с помощью GetWindowLong и объединили его с новым стилем при помощи функции SetWindowLong и оператора OR.

И конечно давайте поменяем курсор и иконку у окна:

#INCLUDE "windows.bi"

Dim msg As MSG 'структурированная переменная MSG
Dim hwnd As HWND  'хендл окна
Dim Shared style As Integer ' стиль окна

' функция класса
Function wndproc(hwnd As HWND, msg As Uinteger, wparam As WPARAM, lparam As LPARAM) As Integer
    Select Case msg
        Case WM_DESTROY
            PostQuitMessage(0)
    End Select
    Return DefWindowProc(hwnd,msg,wparam,lparam)
End Function

'Создание окна
hwnd=CreateWindowEx(0,"#32770","Первое окно",WS_VISIBLE Or WS_OVERLAPPEDWINDOW,100,100,300,300,0,0,0,0)

'Заменяем процедуру на свою
SetWindowLong(hwnd,GWL_WNDPROC,Cast(Long,@wndproc))

' загружаем иконку и курсор
Var icon=LoadIcon(0,IDI_EXCLAMATION)
Var cursor=LoadCursor(0,IDC_CROSS)

' устанавливаем иконку и курсор
SetClassLong(hwnd,GCL_HICON,icon)
SetClassLong(hwnd,GCL_HCURSOR,cursor)

'Обработка сообщений в цикле
While GetMessage(@msg,0,0,0)
    DispatchMessage(@msg)
Wend


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

содержание | назад | вперед