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 if /*&.Owner.Owner &&*/ .Owner.Owner.TypeIs( vForm )
81 {
82 DrawMenuBar( .Owner.Owner->vForm.hwnd )
83 }
84 }
85
86 /*------------------------------------------------------------------------------
87 Properties
88 */
89
90 /* Свойство uint AutoCheck - Get Set
91 1 - Пункт меню автоматически помечается флажком при нажатии
92 */
93 property vMenuItem.AutoCheck( uint val )
94 {
95 .pAutoCheck = val
96 .iUpdate()
97 }
98
99 property uint vMenuItem.AutoCheck
100 {
101 return .pAutoCheck
102 }
103
104 /* Свойство ustr Caption - Get Set
105 Устанавливает или получает заголовок пункта меню
106 */
107 property vMenuItem.Caption( ustr val )
108 {
109 .pCaption.Value = val
110 .iUpdate()
111 }
112
113 property ustr vMenuItem.Caption <result>
114 {
115 result = this.pCaption.Value
116 }
117
118 /* Свойство ustr Enabled - Get Set
119 0 - пункт меню не доступен, отображается серым цветом
120 1 - пункт меню доступен
121 */
122 property vMenuItem.Enabled( uint val )
123 {
124 if .pEnabled != val
125 {
126 .pEnabled = val
127 .iUpdate()
128 }
129 }
130
131 property uint vMenuItem.Enabled
132 {
133 return .pEnabled
134 }
135
136 /* Свойство ustr Separator - Get Set
137 0 - пункт меню имеет обычный вид
138 1 - пункт меню представляет собой разделитель
139 */
140 property vMenuItem.Separator( uint val )
141 {
142 .pSeparator = val
143 .iUpdate()
144 }
145
146 property uint vMenuItem.Separator
147 {
148 return .pSeparator
149 }
150
151 /* Свойство ustr RadioCheck - Get Set
152 1 - слева от пункта меню отображается флажок-точка, если пункт выбран (checked)
153 */
154 property vMenuItem.RadioCheck( uint val )
155 {
156 .pRadioCheck = val
157 .iUpdate()
158 }
159
160 property uint vMenuItem.RadioCheck
161 {
162 return .pRadioCheck
163 }
164
165 /* Свойство uint Visible - Get Set
166 0 - пункт меню не видим
167 1 - пункт меню видим
168 */
169 property uint vMenuItem.Visible
170 {
171 return .pVisible
172 }
173
174 property vMenuItem.Visible( uint val )
175 {
176 if .pVisible != val
177 {
178 uint i, pos
179 fornum i = 0, (this.CompIndex + 0)
180 {
181 if .Owner.Comps[i]->vMenuItem.Visible
182 {
183 pos++
184 }
185 }
186 .pVisible = val
187 if .pVisible
188 {
189 MENUITEMINFO mi
190 /*uint i, pos
191 fornum i = 0, (this.CompIndex + 0)
192 {
193 if .Owner.Comps[i]->vMenuItem.Visible
194 {
195 pos++
196 }
197 }*/
198 mi.cbSize = sizeof( MENUITEMINFO )
199 mi.fMask = $MIIM_ID | $MIIM_DATA
200 mi.wID = &this
201 mi.dwItemData = pos
202 InsertMenuItem( .Owner->vCustomMenu.phMenu, pos * 2, 1, mi )
203
204 mi.cbSize = sizeof( MENUITEMINFO )
205 mi.fMask = $MIIM_ID | $MIIM_TYPE | $MIIM_DATA
206 mi.fType = $MFT_SEPARATOR | $MFT_OWNERDRAW
207 mi.dwItemData = pos
208 mi.wID = .Owner->vCustomMenu.pFake
209 InsertMenuItem( .Owner->vCustomMenu.phMenu, pos * 2 + 1, 1, mi )
210 .iUpdate()
211 }
212 else
213 {
214 RemoveMenu( .Owner->vCustomMenu.phMenu, &this, 0 )
215 RemoveMenu( .Owner->vCustomMenu.phMenu, pos * 2, 0x400 )
216 .iUpdate()
217 }
218 }
219 }
220
221 /* Свойство ustr Index - Get Set
222 Позволяет получить или изменить порядковый номер пункта меню, порядковый номер
223 учитывает также и невидимые элементы
224 */
225 property vMenuItem.Index( uint val )
226 {
227 uint curvisible = .Visible
228 .Visible = 0
229 this.CompIndex = val
230 .Visible = curvisible
231 }
232
233 property uint vMenuItem.Index()
234 {
235 return this.CompIndex
236 }
237
238 /* Свойство ustr Checked - Get Set
239 0 - пункт меню не выбран
240 1 - пункт меню выбран, слева от заголовка пункта меню отображается флажок в виде
241 галочки, если установлено свойство RadioCheck, то флажок в виде точки.
242 Если установлено свойство AutoCheck, то свойство Checked будет устанавливаться
243 или сниматься при каждом нажатии на пункт меню. Если установлено свойство
244 RadioCheck у группы близлежащих пунктов, то Checked устанавливается только у
245 одно пункта из группы, а у остальных пунтов оно автоматически убирается
246 */
247 property vMenuItem.Checked( uint val )
248 {
249 if .pChecked != val
250 {
251 .pChecked = val
252 if val && .RadioCheck
253 {
254 uint i
255 for i = .Index - 1, int(i) >= 0, i--
256 {
257 if .Owner.Comps[i]->vMenuItem.RadioCheck
258 {
259 .Owner.Comps[i]->vMenuItem.Checked = 0
260 }
261 else : break
262 }
263 fornum i = .Index + 1, *(.Owner.Comps)
264 {
265 if .Owner.Comps[i]->vMenuItem.RadioCheck
266 {
267 .Owner.Comps[i]->vMenuItem.Checked = 0
268 }
269 else : break
270 }
271 }
272 .iUpdate()
273 }
274 }
275
276 property uint vMenuItem.Checked
277 {
278 return .pChecked
279 }
280
281 /* Свойство ustr ShortKey - Get Set
282 Горячие клавиши
283 */
284 property vMenuItem.ShortKey( ustr val )
285 {
286 if .pShortKey.caption != val
287 {
288 uint mainmenu as .iMainMenu()
289 mainmenu.FreeShortKey( this )
290 .pShortKey.caption = val.str()
291 .iUpdate()
292 mainmenu.SetShortKey( this )
293 }
294 }
295
296 property ustr vMenuItem.ShortKey<result>
297 {
298 result = .pShortKey.caption
299 }
300
301 /* Свойство ustr Image - Get Set
302 Имя иконки
303 */
304 property ustr vMenuItem.Image <result>
305 {
306 result = this.pImage
307 }
308
309 property vMenuItem.Image( ustr val )
310 {
311 if val != this.pImage
312 {
313 this.pImage = val
314 .ptrImage = &this.GetImage( .pImage )
315 .iUpdate()
316 }
317 }
318
319 /* Свойство ustr Image - Get Set
320 Показывать троеточие
321 0 - не показывать
322 1 - показывать
323 */
324 property uint vMenuItem.Ellipsis
325 {
326 return this.pEllipsis
327 }
328
329 property vMenuItem.Ellipsis( uint val )
330 {
331 if val != this.pEllipsis
332 {
333 this.pEllipsis = val
334 .iUpdate()
335 }
336 }
337
338 /*------------------------------------------------------------------------------
339 Virtual methods
340 */
341
342 method vMenuItem.mMenuClick <alias=vMenuItem_mMenuClick>( )
343 {
344 if .AutoCheck
345 {
346 if .RadioCheck
347 {
348 if !.Checked : .Checked = 1
349 }
350 else : .Checked = !.Checked
351 }
352 this.OnClick.Run( this )
353 }
354
355 method vMenuItem.mInsert <alias=vMenuItem_mInsert>( vComp comp )
356 {
357
358 if !this.phMenu
359 {
360 this.phMenu = CreatePopupMenu()
361 }
362 this->vCustomMenu.mInsert( comp )
363 .iUpdate()
364 }
365
366 method uint vMenuItem.mLangChanged <alias=vMenuItem_mLangChanged>()
367 {
368 .iUpdate()
369 this->vComp.mLangChanged()
370 return 0
371 }
372
373 method vFakeMenuItem.mWinMeasureItem <alias=vFakeMenuItem_mWinMeasureItem>(MEASUREITEMSTRUCT ms)
374 {
375 ms.itemWidth = 0
376 ms.itemHeight = 0
377 }
378
379 method vFakeMenuItem.mWinDrawItem <alias=vFakeMenuItem_mWinDrawItem>(DRAWITEMSTRUCT ds)
380 {
381 uint menu as .pMenu->vCustomMenu
382 uint i, pos
383 uint hwnd = FindWindowEx( 0, 0,32768, 0 )//Находим окно всплывающего меню
384
385 fornum i = 0, *menu.Comps
386 {
387 if menu.Comps[i]->vComp.TypeIs( vMenuItem )
388 {
389 uint menuitem as menu.Comps[i]->vMenuItem
390 if menuitem.Visible
391 {
392 if pos == ds.itemData
393 {
394 if menuitem.ptrImage
395 {
396 POINT p
397 RECT r
398 uint off //Сдвиг для центрирования
399 SetBkMode( ds.hDC, $TRANSPARENT )
400 GetMenuItemRect( hwnd, menu.phMenu, pos * 2, r )
401
402 off = ( r.bottom - r.top - menuitem.ptrImage->Image.Height)/2
403 p.x = r.left + off
404 p.y = r.top + off
405 ScreenToClient( hwnd, p )
406
407 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)
408 }
409 break
410 }
411 pos++
412 }
413 }
414 }
415 return
416 /* uint menu as .pMenu->vCustomMenu
417 uint i
418 uint visi
419 uint hwnd = FindWindowEx( 0, 0,32768, 0 )//Находим окно всплывающего меню
420 SetBkMode( ds.hDC, $TRANSPARENT )
421
422 fornum i = 0, *menu.Comps
423 {
424 if menu.Comps[i]->vComp.TypeIs( vMenuItem )
425 {
426 uint menuitem as menu.Comps[i]->vMenuItem
427 if menuitem.Visible
428 {
429 if menuitem.ptrImage
430 {
431 POINT p
432 RECT r
433 uint off //Сдвиг для центрирования
434
435 GetMenuItemRect( hwnd, menu.phMenu, visi, r )
436
437 off = ( r.bottom - r.top - menuitem.ptrImage->Image.Height)/2
438 p.x = r.left + off - 1
439 p.y = r.top + off
440
441 ScreenToClient( hwnd, p )
442 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)
443 }
444 visi++
445 visi++
446 }
447 }
448 }
449 return*/
450 }
451
452 /*------------------------------------------------------------------------------
453 Registration
454 */
455 method vMenuItem vMenuItem.init( )
456 {
457 this.pTypeId = vMenuItem
458 this.pEnabled = 1
459 this.pVisible = 1
460 return this
461 }
462
463 method vFakeMenuItem vFakeMenuItem.init( )
464 {
465 this.pTypeId = vFakeMenuItem
466 return this
467 }
468
469
470
471
472
473