purebasic.info

PureBasic forum
Текущее время: Ср июл 24, 2019 8:07 am

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
 Заголовок сообщения: Круглая кнопка с картинкой
СообщениеДобавлено: Чт апр 04, 2019 8:43 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 59
Благодарил (а): 47 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Всем привет!
Хочу сделать круглую 3D-кнопку и загрузить в неё изображение. Это возможно сделать?


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Круглая кнопка с картинкой
СообщениеДобавлено: Пт апр 05, 2019 10:22 am 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11491
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
viewtopic.php?p=30396#p30396
viewtopic.php?p=30415#p30415

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Круглая кнопка с картинкой
СообщениеДобавлено: Вт май 14, 2019 6:50 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 59
Благодарил (а): 47 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Можно пару вопросов по коду ниже? Хочу понять, как работает программа. Поясните пожалуйста вкратце алгоритм.

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
 
Structure Button_Image
  *Proc
  Im1_ID.i
  Im2_ID.i
  Im3_ID.i
  FocusState.b
  Gadget.i
EndStructure
 
Procedure ButtonImage_CB(hWnd, Msg, wParam, lParam)
  Protected Result, *Button_Image.Button_Image
  Protected tme.TRACKMOUSEEVENT
 
  *Button_Image = GetWindowLongPtr_(hWnd,#GWL_USERDATA)
 
  If Msg = #WM_SETCURSOR Or Msg = #WM_MOUSEMOVE Or Msg = #WM_LBUTTONUP
    If *Button_Image\FocusState <> 1
      *Button_Image\FocusState = 1
      tme\cbSize = SizeOf(TRACKMOUSEEVENT)
      tme\dwFlags = #TME_LEAVE
      tme\dwHoverTime = #HOVER_DEFAULT
      tme\hwndTrack = hWnd
      TrackMouseEvent_(@tme)
      SetGadgetState(*Button_Image\Gadget, *Button_Image\Im2_ID)
    EndIf
    If Msg = #WM_LBUTTONUP
      SetGadgetState(*Button_Image\Gadget, *Button_Image\Im2_ID)
    EndIf
  ElseIf Msg = #WM_MOUSELEAVE
    *Button_Image\FocusState = 0
    SetGadgetState(*Button_Image\Gadget, *Button_Image\Im1_ID)
  ElseIf Msg = #WM_KILLFOCUS
    *Button_Image\FocusState = 0
    SetGadgetState(*Button_Image\Gadget, *Button_Image\Im1_ID)
  ElseIf Msg = #WM_LBUTTONDOWN Or Msg = #WM_LBUTTONDBLCLK
    SetGadgetState(*Button_Image\Gadget, *Button_Image\Im3_ID)
  EndIf
 
  Result = CallWindowProc_(*Button_Image\Proc, hWnd, Msg, wParam, lParam)
  ProcedureReturn Result
EndProcedure
 
Procedure ButtonImage(Gadget, x, y, Width, Height, Im1_ID, Im2_ID, Im3_ID)
  Protected Result, *Button_Image.Button_Image
 
  Result=ImageGadget(Gadget, x, y, Width, Height, Im1_ID)
  If Result
    *Button_Image = AllocateMemory(SizeOf(Button_Image))
    If *Button_Image
      *Button_Image\Gadget = Gadget
      *Button_Image\Im1_ID = Im1_ID
      *Button_Image\Im2_ID = Im2_ID
      *Button_Image\Im3_ID = Im3_ID
      *Button_Image\Proc = GetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC)
      SetWindowLongPtr_(GadgetID(Gadget), #GWL_USERDATA, *Button_Image)
      SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC,  @ButtonImage_CB())
    Else
      FreeGadget(Gadget)
      Result = 0
    EndIf
  EndIf  
   
  ProcedureReturn Result
EndProcedure
 
Procedure FreeButtonImage(Gadget)
  Protected *p.Button_Image
  *p=GetWindowLongPtr_(GadgetID(Gadget), #GWL_USERDATA)
  If *p
    SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC, *p\Proc)
    FreeMemory(*p)
  EndIf
  FreeGadget(Gadget)
EndProcedure
 
CatchImage(0, ?Im1) : CatchImage(1, ?Im2) : CatchImage(2, ?Im3)
 
OpenWindow(0,0,0,200,100,"",#PB_Window_MinimizeGadget|#PB_Window_Invisible|#PB_Window_ScreenCentered)
ButtonImage(1, 10, 10, 32, 32, ImageID(0), ImageID(1), ImageID(2))
ButtonImage(2, 50, 10, 32, 32, ImageID(0), ImageID(1), ImageID(2))
ButtonImage(3, 90, 10, 32, 32, ImageID(0), ImageID(1), ImageID(2))
ButtonImage(4, 130, 10, 32, 32, ImageID(0), ImageID(1), ImageID(2))
 
HideWindow(0,0)
 
Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Gadget
    Debug EventGadget()
  EndIf
Until Event = #PB_Event_CloseWindow
End
 
DataSection
  Im1:
 IncludeBinary "EjectHot.ico"
 
  Im2:
 IncludeBinary "EjectPressed.ico"
 
  Im3:
 IncludeBinary "EjectNormalRed.ico"
EndDataSection
 



Поля *Proc и FocusState.b для чего нужны?

Не могу разобраться как работает процедура ButtonImage_CB(hWnd, Msg, wParam, lParam).
1. Структурная переменная tme.TRACKMOUSEEVENT откуда берется и для чего?
2. АПИ функции SetWindowLongPtr_() и GetWindowLongPtr_() что делают? Их константы #GWL_USERDATA и #GWL_WNDPROC за что отвечают?
3. АПИ функция CallWindowProc_() что делает? Зачем возвращать Result?


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Круглая кнопка с картинкой
СообщениеДобавлено: Вт май 14, 2019 8:23 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 862
Благодарил (а): 2 раз.
Поблагодарили: 41 раз.
Пункты репутации: 9
Как то так. :roll:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
 
Structure Button_Image
  *Proc
  Im1_ID.i;ид иконок
  Im2_ID.i
  Im3_ID.i
  FocusState.b;менять состояние (например смена картинок) в обработчике
  Gadget.i
EndStructure
 
Procedure ButtonImage_CB(hWnd, Msg, wParam, lParam)
  Protected Result, *Button_Image.Button_Image
  Protected tme.TRACKMOUSEEVENT
 
  *Button_Image = GetWindowLongPtr_(hWnd,#GWL_USERDATA)
 
  If Msg = #WM_SETCURSOR Or Msg = #WM_MOUSEMOVE Or Msg = #WM_LBUTTONUP
    If *Button_Image\FocusState <> 1
      *Button_Image\FocusState = 1
      tme\cbSize = SizeOf(TRACKMOUSEEVENT)
      tme\dwFlags = #TME_LEAVE
      tme\dwHoverTime = #HOVER_DEFAULT
      tme\hwndTrack = hWnd
      TrackMouseEvent_(@tme)
      SetGadgetState(*Button_Image\Gadget, *Button_Image\Im2_ID)
    EndIf
    If Msg = #WM_LBUTTONUP
      SetGadgetState(*Button_Image\Gadget, *Button_Image\Im2_ID)
    EndIf
  ElseIf Msg = #WM_MOUSELEAVE
    *Button_Image\FocusState = 0
    SetGadgetState(*Button_Image\Gadget, *Button_Image\Im1_ID)
  ElseIf Msg = #WM_KILLFOCUS
    *Button_Image\FocusState = 0
    SetGadgetState(*Button_Image\Gadget, *Button_Image\Im1_ID)
  ElseIf Msg = #WM_LBUTTONDOWN Or Msg = #WM_LBUTTONDBLCLK
    SetGadgetState(*Button_Image\Gadget, *Button_Image\Im3_ID)
  EndIf
 
  Result = CallWindowProc_(*Button_Image\Proc, hWnd, Msg, wParam, lParam)
  ProcedureReturn Result
EndProcedure
 
Procedure ButtonImage(Gadget, x, y, Width, Height, Im1_ID, Im2_ID, Im3_ID)
  Protected Result, *Button_Image.Button_Image
 
  Result=ImageGadget(Gadget, x, y, Width, Height, Im1_ID);создаём гаджет с первой иконкой
  If Result
    *Button_Image = AllocateMemory(SizeOf(Button_Image));выделяем память под структуру
    If *Button_Image
      *Button_Image\Gadget = Gadget;пишим типа ид ButtonImage()
      *Button_Image\Im1_ID = Im1_ID; ид трёх иконок
      *Button_Image\Im2_ID = Im2_ID
      *Button_Image\Im3_ID = Im3_ID
      *Button_Image\Proc = GetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC);получаем адрес внутреннего калбека(процедуры обратног вызова) ImageGadget()
      SetWindowLongPtr_(GadgetID(Gadget), #GWL_USERDATA, *Button_Image)     ;у ImageGadget() гаджета есть структура api Structure WNDCLASS(ex),пишем туда адрес
      ; на память выделенную под структуру *Button_Image
     
      SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC,  @ButtonImage_CB());назначаем свой калбек ImageGadget(обработчик)
    Else;если терпим неудачу
      FreeGadget(Gadget);удаляем гаджет ImageGadget
      Result = 0
    EndIf
  EndIf  
   
  ProcedureReturn Result
EndProcedure
 
Procedure FreeButtonImage(Gadget)
  Protected *p.Button_Image
  *p=GetWindowLongPtr_(GadgetID(Gadget), #GWL_USERDATA);получаем адрес  на память структуры Button_Image(ранее выделенную)
  If *p;там не 0(в адресе)значит память выделялась
    SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC, *p\Proc);возвращаем адрес внутреннего калбека (что был до переназначения(перехвата))
    FreeMemory(*p);чистим память что ранее выделяли под структуру
  EndIf
  FreeGadget(Gadget);удаляем созданный ImageGadget
EndProcedure
 
CatchImage(0, ?Im1) : CatchImage(1, ?Im2) : CatchImage(2, ?Im3);типа начинаем прогу и качаем с дата секциим иконки
 
OpenWindow(0,0,0,200,100,"",#PB_Window_MinimizeGadget|#PB_Window_Invisible|#PB_Window_ScreenCentered)
ButtonImage(1, 10, 10, 32, 32, ImageID(0), ImageID(1), ImageID(2));получаем ид на иконки и отправляемся в процедуру ButtonImage()
ButtonImage(2, 50, 10, 32, 32, ImageID(0), ImageID(1), ImageID(2))
ButtonImage(3, 90, 10, 32, 32, ImageID(0), ImageID(1), ImageID(2))
ButtonImage(4, 130, 10, 32, 32, ImageID(0), ImageID(1), ImageID(2))
 
HideWindow(0,0)
 
Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Gadget
    Debug EventGadget()
  EndIf
Until Event = #PB_Event_CloseWindow
End
 
DataSection
  Im1:
 IncludeBinary "EjectHot.ico";ссылка на иконку, компилятор её данные разместит в дата секции
 
  Im2:
 IncludeBinary "EjectPressed.ico"
 
  Im3:
 IncludeBinary "EjectNormalRed.ico"
EndDataSection
 


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


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Круглая кнопка с картинкой
СообщениеДобавлено: Вт май 14, 2019 9:03 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11491
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
fil@tov писал(а):
Поля *Proc и FocusState.b для чего нужны?
В коде ведь видно для чего они используются. Первая хранит адрес Callback функции гаджета (осуществляется перехват функции и нужно вызвать предыдущую), а вторая хранит признак что на кнопку наведена мышка.

fil@tov писал(а):
Структурная переменная tme.TRACKMOUSEEVENT откуда берется и для чего?
Видно же что используется с функцией TrackMouseEvent. http://www.vsokovikov.narod.ru/New_MSDN ... eevent.htm
По умолчанию у окон нет события потери фокуса мышки. Для этого обычно используют TrackMouseEvent.

fil@tov писал(а):
АПИ функции SetWindowLongPtr_() и GetWindowLongPtr_() что делают? Их константы #GWL_USERDATA и #GWL_WNDPROC за что отвечают?
За перехват Callback функции. http://vsokovikov.narod.ru/New_MSDN_API ... ongptr.htm

fil@tov писал(а):
3. АПИ функция CallWindowProc_() что делает?
http://vsokovikov.narod.ru/New_MSDN_API ... owproc.htm

fil@tov писал(а):
Зачем возвращать Result?
Это результат выполнения функции. Каков он будет зависит от обрабатываемого сообщения.

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Круглая кнопка с картинкой
СообщениеДобавлено: Вт май 14, 2019 9:37 pm 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 862
Благодарил (а): 2 раз.
Поблагодарили: 41 раз.
Пункты репутации: 9
А чем отличается у класса wnddata от userdata? :roll:
и как я понял сейчас не через userdata делают создание гаджетов а через список setprop?


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Круглая кнопка с картинкой
СообщениеДобавлено: Ср май 15, 2019 9:09 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 59
Благодарил (а): 47 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Не могу понять ход выполнения программы.

Вот как я это понимаю.
Создается гаджет 1 с адресами трех картинок процедурой ButtonImage(Gadget, x, y, Width, Height, Im1_ID, Im2_ID, Im3_ID). 56 строчка вызывает процедуру ButtonImage_CB(hWnd, Msg, wParam, lParam), которая загружает ту или иную картинку в гаджет в зависимости от события. Потом 39 строчка "зацикливает" выполнение процедуры ButtonImage_CB(hWnd, Msg, wParam, lParam). Получается как бы рекурсия?
Затем тоже самое происходит с гаджетами 2, 3, 4.

Получается как бы 4 параллельных потока?
Поправьте, если что-то не так. Спасибо за понимание)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Круглая кнопка с картинкой
СообщениеДобавлено: Чт май 16, 2019 2:48 am 
Не в сети
профессор

Зарегистрирован: Пн июл 22, 2013 11:00 pm
Сообщений: 862
Благодарил (а): 2 раз.
Поблагодарили: 41 раз.
Пункты репутации: 9
В 56 строчки не назначается адрес обработчика а пишется память структуры в (структуру окна)
У окна имагегаджета есть свой обработчик событий он создан пуриком(для облегчения програмить)допустим перересовка окна при сворачивании и восстановлении.
мы его перехватываем в стр 147 GetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC);
записываем в переменную структуры под которую выделили память
соответственно адрес на память структуры записываем в структуру созданного окна
стр 148 SetWindowLongPtr_(GadgetID(Gadget), #GWL_USERDATA, *Button_Image)
дальше назначаем свой обработчик для своих нужд
SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC, @ButtonImage_CB());назначаем свой калбек
соответственно у всех гаджетов он сейчас один на все(определение окна по hWnd),но можно сделать раздельные
Код:
1
2
3
4
5
6
7
8
9
10
11
 
    If Gadget=1  
      SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC,  @ButtonImage_CB());назначаем свой калбек ImageGadget(обработчик)
    ElseIf Gadget=2  
            SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC,  @ButtonImage_CB1());назначаем свой калбек ImageGadget(обработчик)
    ElseIf Gadget=3
            SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC,  @ButtonImage_CB2());назначаем свой калбек ImageGadget(обработчик)
    ElseIf Gadget=4  
           SetWindowLongPtr_(GadgetID(Gadget), #GWL_WNDPROC,  @ButtonImage_CB3());назначаем свой калбек ImageGadget(обработчик)
    EndIf
 


Ход программы такой , сообщение от окна имагегаджета идёт в наш(и)обработчик в котором мы извлекаем адрес
стандартного обработчика что перехватили,выполняем его и идём дальше ProcedureReturn CallWindowProc_(*Button_Image\Proc, hWnd, Msg, wParam, lParam)
PS:поток в данном случае у процесса один.roll:
Сайт для конвертации в формат ico https://converticon.com :D


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Круглая кнопка с картинкой
СообщениеДобавлено: Чт май 16, 2019 10:20 am 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11491
Благодарил (а): 4 раз.
Поблагодарили: 468 раз.
fil@tov писал(а):
56 строчка вызывает процедуру ButtonImage_CB(hWnd, Msg, wParam, lParam), которая загружает ту или иную картинку в гаджет в зависимости от события.
Не вызывает, а заменяет callback функцию на нашу, в которой выполняются некоторые действия, а после вызывается callback функция которая была до замены. Это необходимо для нормально работы.
Вызывает callback функцию система, а не наша программа. Это происходит при выполнении WaitWindowEvent().
https://ru.wikipedia.org/wiki/Callback_(программирование)

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB