1 /******************************************************************************
2 *
3 * Copyright (C) 2004-2007, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * ID: vis.menuitem 18.07.07 0.0.A.
11 *
12 * Author: Alexander Krivonogov ( gentee )
13 *
14 ******************************************************************************/
15 /* Компонента vMenuItem, порождена от vComp
16 События
17 OnClick - вызывается при нажатии на пункт меню
18 */
19
20 type vMenuItem <inherit=vCustomMenu>
21 {
22 //Hidden fields
23 uint pEnabled //Доступность элемента меню
24 uint pSeparator //Элемент меню - разделитель
25 locustr pCaption //Заголовок
26 uint pChecked //Выбран
27 uint pRadioCheck //В виде флажка
28 uint pVisible //Видимый
29 uint pAutoCheck //Автоматический выбор
30 shortkey pShortKey //Комбинация клавиш
31 ustr pImage //Имя иконки
32 uint ptrImage //Иконка если есть
33 uint pEllipsis //Показывать троеточие
34 //Public fields
35
36 //Events
37 evEvent OnClick
38 }
39
40 /* Компонента vFakeMenuItem, порождена от vComp
41 Фиктивный пункт меню, нужен для отображения иконок
42 */
43 type vFakeMenuItem <inherit=vComp>
44 {
45 uint pMenu//Указатель на vCustomMenu содержащее пункты меню
46 }
47
48
49 extern {
50 method vCustomMainMenu.FreeShortKey( vMenuItem item )
51 method vCustomMainMenu.SetShortKey( vMenuItem item )
52 }
53 //Virtual Method Identifiers
54 /*define {
55 mMenuClick = $vComp_last
56 vMenuItem_last
57 }*/
58
59 /*------------------------------------------------------------------------------
60 Internal Methods
61 */
62 /*Метод vMenuItem.iUpdate()
63 Обновить визуальное представление меню
64 */
65 method vMenuItem.iUpdate()
66 {
67 ustr caption
68 MENUITEMINFO mi
69 mi.cbSize = sizeof( MENUITEMINFO )
70 mi.fMask = $MIIM_TYPE | $MIIM_STATE | $MIIM_DATA | $MIIM_CHECKMARKS | $MIIM_SUBMENU
71 mi.fType = ?( .pSeparator, $MFT_SEPARATOR, $MFT_STRING ) | ?( .pRadioCheck, $MFT_RADIOCHECK, 0 )
72 mi.fState = ?( .pEnabled, $MFS_ENABLED, $MFS_GRAYED ) | ? ( .pChecked, $MFS_CHECKED, $MFS_UNCHECKED )
73 mi.hSubMenu = .phMenu
74
75 caption = this.pCaption.Text( this )
76 if .pEllipsis : caption += "..."
77 if *this.pShortKey.caption : caption += "\t".ustr() + this.pShortKey.caption
78 mi.dwTypeData = caption.ptr()
79 SetMenuItemInfo( .Owner->vCustomMenu.phMenu, &this, 0, mi )
80
81 if .Owner.Owner.TypeIs( vForm )
82 {
83 DrawMenuBar( .Owner.Owner->vForm.hwnd )
84 }
85 }
86
87 /*------------------------------------------------------------------------------
88 Properties
89 */
90
91 /* Свойство uint AutoCheck - Get Set
92 1 - Пункт меню автоматически помечается флажком при нажатии
93 */
94 property vMenuItem.AutoCheck( uint val )
95 {
96 .pAutoCheck = val
97 .iUpdate()
98 }
99
100 property uint vMenuItem.AutoCheck
101 {
102 return .pAutoCheck
103 }
104
105 /* Свойство ustr Caption - Get Set
106 Устанавливает или получает заголовок пункта меню
107 */
108 property vMenuItem.Caption( ustr val )
109 {
110 .pCaption.Value = val
111 .iUpdate()
112 }
113
114 property ustr vMenuItem.Caption <result>
115 {
116 result = this.pCaption.Value
117 }
118
119 /* Свойство ustr Enabled - Get Set
120 0 - пункт меню не доступен, отображается серым цветом
121 1 - пункт меню доступен
122 */
123 property vMenuItem.Enabled( uint val )
124 {
125 if .pEnabled != val
126 {
127 .pEnabled = val
128 .iUpdate()
129 }
130 }
131
132 property uint vMenuItem.Enabled
133 {
134 return .pEnabled
135 }
136
137 /* Свойство ustr Separator - Get Set
138 0 - пункт меню имеет обычный вид
139 1 - пункт меню представляет собой разделитель
140 */
141 property vMenuItem.Separator( uint val )
142 {
143 .pSeparator = val
144 .iUpdate()
145 }
146
147 property uint vMenuItem.Separator
148 {
149 return .pSeparator
150 }
151
152 /* Свойство ustr RadioCheck - Get Set
153 1 - слева от пункта меню отображается флажок-точка, если пункт выбран (checked)
154 */
155 property vMenuItem.RadioCheck( uint val )
156 {
157 .pRadioCheck = val
158 .iUpdate()
159 }
160
161 property uint vMenuItem.RadioCheck
162 {
163 return .pRadioCheck
164 }
165
166 /* Свойство uint Visible - Get Set
167 0 - пункт меню не видим
168 1 - пункт меню видим
169 */
170 property uint vMenuItem.Visible
171 {
172 return .pVisible
173 }
174
175 property vMenuItem.Visible( uint val )
176 {
177 if .pVisible != val
178 {
179 .pVisible = val
180 if .pVisible
181 {
182 MENUITEMINFO mi
183 uint i, pos
184 fornum i = 0, (this.CompIndex + 0)
185 {
186 if .Owner.Comps[i]->vMenuItem.Visible
187 {
188 pos++
189 }
190 }
191 mi.cbSize = sizeof( MENUITEMINFO )
192 mi.fMask = $MIIM_ID
193 mi.wID = &this
194 InsertMenuItem( .Owner->vCustomMenu.phMenu, pos, 1, mi )
195 .iUpdate()
196 }
197 else
198 {
199 RemoveMenu( .Owner->vCustomMenu.phMenu, &this, 0 )
200 .iUpdate()
201 }
202 }
203 }
204
205 /* Свойство ustr Index - Get Set
206 Позволяет получить или изменить порядковый номер пункта меню, порядковый номер
207 учитывает также и невидимые элементы
208 */
209 property vMenuItem.Index( uint val )
210 {
211 uint curvisible = .Visible
212 .Visible = 0
213 this.CompIndex = val
214 .Visible = curvisible
215 }
216
217 property uint vMenuItem.Index()
218 {
219 return this.CompIndex
220 }
221
222 /* Свойство ustr Checked - Get Set
223 0 - пункт меню не выбран
224 1 - пункт меню выбран, слева от заголовка пункта меню отображается флажок в виде
225 галочки, если установлено свойство RadioCheck, то флажок в виде точки.
226 Если установлено свойство AutoCheck, то свойство Checked будет устанавливаться
227 или сниматься при каждом нажатии на пункт меню. Если установлено свойство
228 RadioCheck у группы близлежащих пунктов, то Checked устанавливается только у
229 одно пункта из группы, а у остальных пунтов оно автоматически убирается
230 */
231 property vMenuItem.Checked( uint val )
232 {
233 if .pChecked != val
234 {
235 .pChecked = val
236 if val && .RadioCheck
237 {
238 uint i
239 for i = .Index - 1, int(i) >= 0, i--
240 {
241 if .Owner.Comps[i]->vMenuItem.RadioCheck
242 {
243 .Owner.Comps[i]->vMenuItem.Checked = 0
244 }
245 else : break
246 }
247 fornum i = .Index + 1, *(.Owner.Comps)
248 {
249 if .Owner.Comps[i]->vMenuItem.RadioCheck
250 {
251 .Owner.Comps[i]->vMenuItem.Checked = 0
252 }
253 else : break
254 }
255 }
256 .iUpdate()
257 }
258 }
259
260 property uint vMenuItem.Checked
261 {
262 return .pChecked
263 }
264
265 /* Свойство ustr ShortKey - Get Set
266 Горячие клавиши
267 */
268 property vMenuItem.ShortKey( ustr val )
269 {
270 if .pShortKey.caption != val
271 {
272 uint mainmenu as .iMainMenu()
273 mainmenu.FreeShortKey( this )
274 .pShortKey.caption = val.str()
275 .iUpdate()
276 mainmenu.SetShortKey( this )
277 }
278 }
279
280 property ustr vMenuItem.ShortKey<result>
281 {
282 result = .pShortKey.caption
283 }
284
285 /* Свойство ustr Image - Get Set
286 Имя иконки
287 */
288 property ustr vMenuItem.Image <result>
289 {
290 result = this.pImage
291 }
292
293 property vMenuItem.Image( ustr val )
294 {
295 if val != this.pImage
296 {
297 this.pImage = val
298 .ptrImage = &this.GetImage( .pImage )
299 .iUpdate()
300 }
301 }
302
303 /* Свойство ustr Image - Get Set
304 Показывать троеточие
305 0 - не показывать
306 1 - показывать
307 */
308 property uint vMenuItem.Ellipsis
309 {
310 return this.pEllipsis
311 }
312
313 property vMenuItem.Ellipsis( uint val )
314 {
315 if val != this.pEllipsis
316 {
317 this.pEllipsis = val
318 .iUpdate()
319 }
320 }
321
322 /*------------------------------------------------------------------------------
323 Virtual methods
324 */
325
326 method vMenuItem.mMenuClick <alias=vMenuItem_mMenuClick>( )
327 {
328 if .AutoCheck
329 {
330 if .RadioCheck
331 {
332 if !.Checked : .Checked = 1
333 }
334 else : .Checked = !.Checked
335 }
336 this.OnClick.Run( this )
337 }
338
339 method vMenuItem.mInsert <alias=vMenuItem_mInsert>( vComp comp )
340 {
341
342 if !this.phMenu
343 {
344 this.phMenu = CreatePopupMenu()
345 }
346 this->vCustomMenu.mInsert( comp )
347 .iUpdate()
348 }
349
350 method uint vMenuItem.mLangChanged <alias=vMenuItem_mLangChanged>()
351 {
352 .iUpdate()
353 this->vComp.mLangChanged()
354 return 0
355 }
356
357 method vFakeMenuItem.mWinMeasureItem <alias=vFakeMenuItem_mWinMeasureItem>(MEASUREITEMSTRUCT ms)
358 {
359 ms.itemWidth = 0
360 ms.itemHeight = 0
361 }
362
363 method vFakeMenuItem.mWinDrawItem <alias=vFakeMenuItem_mWinDrawItem>(DRAWITEMSTRUCT ds)
364 {
365 uint menu as .pMenu->vCustomMenu
366 uint i
367 uint hwnd = FindWindowEx( 0, 0,32768, 0 )//Находим окно всплывающего меню
368 SetBkMode( ds.hDC, $TRANSPARENT )
369 fornum i = 0, *menu.Comps
370 {
371 if menu.Comps[i]->vComp.TypeIs( vMenuItem )
372 {
373 uint menuitem as menu.Comps[i]->vMenuItem
374 if menuitem.Visible && menuitem.ptrImage
375 {
376 POINT p
377 RECT r
378 uint off //Сдвиг для центрирования
379
380 GetMenuItemRect( hwnd, menu.phMenu, i, r )
381 off = ( r.bottom - r.top - menuitem.ptrImage->Image.Height)/2
382 p.x = r.left + off - 2
383 p.y = r.top + off
384
385 ScreenToClient( hwnd, p )
386 //IntersectClipRect( ds.hDC, 0, 0, 200, 200 )
387 DrawIconEx( ds.hDC, p.x, p.y, ?( menuitem.Enabled, menuitem.ptrImage->Image.hImage, menuitem.ptrImage->Image.hDisImage ), menuitem.ptrImage->Image.Width, menuitem.ptrImage->Image.Height, 0, 0, $DI_NORMAL | $DI_MASK)
388 }
389 }
390 }
391 return
392 }
393
394 /*------------------------------------------------------------------------------
395 Registration
396 */
397 method vMenuItem vMenuItem.init( )
398 {
399 this.pTypeId = vMenuItem
400 this.pEnabled = 1
401 this.pVisible = 1
402 return this
403 }
404
405 method vFakeMenuItem vFakeMenuItem.init( )
406 {
407 this.pTypeId = vFakeMenuItem
408 return this
409 }
410
411
412
413
414