1 include
2 {
3 "grey.g"
4 "..\\olecom\\olecom.g"
5 }
6 type ICONDIRENTRY
7 {
8 byte bWidth
9 byte bHeight
10 byte bColorCount
11 byte bReserved
12 ushort wPlanes
13 ushort wBitCount
14 uint dwBytesInRes
15 uint dwImageOffset
16 }
17
18 type RESICONDIRENTRY
19 {
20 byte bWidth
21 byte bHeight
22 byte bColorCount
23 byte bReserved
24 ushort wPlanes
25 ushort wBitCount
26 uint dwBytesInRes
27 ushort nID
28 }
29
30 type ICONDIR
31 {
32 ushort idReserved//0 всегда
33 ushort idType //1 для иконки, 2 для курсора
34 ushort idCount
35 ICONDIRENTRY idEntries
36 }
37
38 type icsize
39 {
40 uint Width
41 uint Height
42 }
43
44 type Image
45 {
46 uint hImage
47 uint hDisImage
48 uint Width
49 uint Height
50 int NumIml
51 int PosInIml
52 int DisPosInIml
53 }
54
55 type ImageListIml
56 {
57 uint hIml
58 uint Width
59 uint Height
60 uint pImageList
61 }
62
63 type ImageList <inherit=hash> //index=Image
64 {
65 arr arrIml of ImageListIml
66 }
67
68 type ImageManager <inherit=hash index=ImageList>
69 {
70 str pMainDir
71 str pCurName
72 hash FileIcons of uint
73 uint FileIconsIdx
74 }
75
76
77 define {
78 // MAX_PATH = 260
79
80 SHGFI_ICON = 0x00000100
81 SHGFI_SYSICONINDEX = 0x00004000
82 SHGFI_LARGEICON = 0x00000000
83 SHGFI_SMALLICON = 0x00000001
84 SHGFI_USEFILEATTRIBUTES = 0x00000010
85 }
86
87 type SHFILEINFO {
88 uint hIcon
89 int iIcon
90 uint dwAttributes
91 reserved szDisplayName[ $MAX_PATH ]
92 reserved szTypeName[ 80 ]
93 }
94
95 import "shell32.dll" {
96 uint SHGetFileInfoA( uint, uint, SHFILEINFO, uint, uint ) -> SHGetFileInfo
97 }
98
99 //-------------------------------------------------
100
101 func uint shell_iconfile( str filename, uint large )
102 {
103 uint reticon flag
104 SHFILEINFO shfi
105 str ext
106
107 flag = ?( large, $SHGFI_LARGEICON, $SHGFI_SMALLICON )
108 if SHGetFileInfo( filename.ptr(), 0 , shfi, sizeof( SHFILEINFO ),
109 /*$SHGFI_SYSICONINDEX |*/ $SHGFI_ICON | flag )
110 {
111 return shfi.hIcon
112 }
113 reticon = SHGetFileInfo( filename.ptr(), $FILE_ATTRIBUTE_NORMAL, shfi, sizeof( SHFILEINFO ), $SHGFI_SYSICONINDEX | $SHGFI_USEFILEATTRIBUTES | $SHGFI_ICON | flag )
114 return shfi.hIcon
115 }
116
117
118
119 method ImageManager.init()
120 {
121 this->hash.oftype( ImageList )
122 }
123
124
125 method ImageList ImageList.init
126 {
127 return this
128 }
129
130 method Image.ReadFromFile( str filename )
131 {
132 /*uint hbmp
133 hbmp = LoadImage( 0, filename.ptr(), $IMAGE_BITMAP, 0, 0, $LR_LOADFROMFILE | $LR_LOADTRANSPARENT )
134 if hbmp
135 {
136 .hbmp = hbmp
137 } */
138 }
139
140 method Image.Clear()
141 {
142 // if .hbmp : DeleteObject( .hbmp )
143 }
144
145 method Image.delete()
146 {
147 DestroyIcon( .hImage )
148 DestroyIcon( .hDisImage )
149 }
150
151
152
153 method ImageListIml.delete()
154 {
155 ImageList_Destroy( .hIml )
156 }
157
158 method ImageList.delete()
159 {
160 //print( "ImageList \(&this) .Delete 1\n" )
161 foreach arrim, this
162 {
163 //arrim as arr of Image
164 //print( "ImgList destroy \(arrim->uint)\n" )
165 if arrim->uint : destroy( arrim->uint )
166 //getch()
167 }
168 //print( "ImageList.Delete 2\n" )
169 }
170
171 method ImageManager.delete
172 {
173 //print( "ImageManager.Delete \(&this)\n" )
174 // destroy( ImageList
175 }
176
177 /*method ImageManager.LoadDir( str dir, str listname, uint flgclear )
178 {
179 uint il as this[listname]//->ImageList
180
181 ffind fdi
182 fdi.init( "\( dir )\\*.ico", $FIND_FILE )
183 foreach finfo ico, fdi
184 {
185 uint arrim as ( il[ico.name]->arr of Image )
186 if !&arrim
187 {
188 str name
189 ico.fullname.fgetparts( 0->str, name, 0->str )
190 arrim as new( arr, Image, 0 )->arr of Image
191 //print( "NEW ARRIM \(&il) \( &arrim ) )\n" )
192 //arrim.itype = Image
193 //arrim.isize = sizeof( Image )
194 arr arrim2 of Image
195 il[name] = &arrim
196 }
197 elif flgclear
198 {
199 arrim.clear()
200 }
201 buf bicon
202 bicon.read( ico.fullname )
203 uint header as bicon.data->ICONDIR
204 if !header.idReserved && header.idType == 1
205 {
206 uint count = header.idCount
207 uint entry as header.idEntries
208 uint i, j
209 arr sizes of icsize
210 fornum i=0, count
211 { //
212 fornum j=0, *sizes
213 {
214 if sizes[j].Width > entry.bWidth &&
215 sizes[j].Height > entry.bHeight : break
216 }
217 sizes.insert( j )
218 sizes[j].Width = entry.bWidth
219 sizes[j].Height = entry.bHeight
220 entry as uint
221 entry += sizeof(ICONDIRENTRY)
222 }
223
224 if !*il.arrIml
225 {
226 il.arrIml.expand(*sizes)
227 fornum i=0, *sizes
228 {
229 il.arrIml[i].hIml = ImageList_Create (
230 sizes[i].Width, sizes[i].Height, 0x000000FF, 10, 10 )
231 il.arrIml[i].Width = sizes[i].Width
232 il.arrIml[i].Height = sizes[i].Height
233 il.arrIml[i].pImageList = &il
234 }
235 }
236 if *sizes > *arrim
237 {
238 arrim.expand( *sizes - *arrim )
239 }
240 fornum i=0, *sizes
241 {
242 if arrim[i].hImage : DestroyIcon( arrim[i].hImage )
243
244 arrim[i].Width = sizes[i].Width
245 arrim[i].Height = sizes[i].Height
246 arrim[i].hImage = LoadImage( 0, ico.fullname.ustr().ptr(), $IMAGE_ICON,
247 sizes[i].Width, sizes[i].Height, $LR_LOADFROMFILE | $LR_DEFAULTCOLOR )
248
249 ICONINFO II
250 GetIconInfo( arrim[i].hImage, II )
251 BitmapColorsToGrey( II.hbmColor, II.hbmMask, arrim[i].Width,arrim[i].Height)
252 arrim[i].hDisImage = CreateIconIndirect( II )
253
254 // print( "load image \(arrim.itype) \(arrim.isize) \(arrim[i].hImage) \( ico.fullname ) \( arrim[i].Width ), \( arrim[i].Height)\n" )
255 arrim[i].PosInIml = -1
256 fornum j=0, *il.arrIml
257 {
258 if il.arrIml[j].Width == sizes[i].Width &&
259 il.arrIml[j].Height == sizes[i].Height
260 {
261 arrim[i].PosInIml =
262 ImageList_ReplaceIcon( il.arrIml[j].hIml, -1, arrim[i].hImage )
263 arrim[i].DisPosInIml =
264 ImageList_ReplaceIcon( il.arrIml[j].hIml, -1, arrim[i].hDisImage )
265 arrim[i].NumIml = j
266 }
267 }
268 }
269 }
270 }
271 }*/
272 method ImageList.SetIco( Image img, uint himage width height )
273 {
274 if img.hImage
275 {
276 DestroyIcon( img.hImage )
277 DestroyIcon( img.hDisImage )
278 }
279 img.Width = width
280 img.Height = height
281 img.hImage = himage
282 ICONINFO II
283 GetIconInfo( img.hImage, II )
284 //print( "gi \(img.hImage) \(II.hbmColor), \(II.hbmMask)\n")
285 //if img.Width <= 100 || img.Height <= 100
286 BitmapColorsToGrey( II.hbmColor, II.hbmMask, img.Width,img.Height)
287 img.hDisImage = CreateIconIndirect( II )
288 //print( "li \(img.hImage) \(img.hDisImage)\n" )
289 //if !img.hDisImage : print( "Xerror \(GetLastError())\n" )
290 // print( "load image \(arrim.itype) \(arrim.isize) \(img.hImage) \( ico.fullname ) \( img.Width ), \( img.Height)\n" )
291
292 DeleteObject( II.hbmColor )
293 DeleteObject( II.hbmMask )
294 img.PosInIml = -1
295 uint j
296 fornum j=0, *this.arrIml
297 {
298 if this.arrIml[j].Width == width &&
299 this.arrIml[j].Height == height
300 {
301 img.PosInIml =
302 ImageList_ReplaceIcon( this.arrIml[j].hIml, -1, img.hImage )
303 img.DisPosInIml =
304 ImageList_ReplaceIcon( this.arrIml[j].hIml, -1, img.hDisImage )
305 img.NumIml = j
306
307 }
308 }
309 }
310
311 method ImageList.LoadIco( str path, uint flgres, uint hmod, uint flgclear, str setname )
312 {
313 str name
314 if flgres : name = path
315 else
316 {
317 if &setname : name = setname
318 else : path.fgetparts( 0->str, name, 0->str )
319 }
320 uint arrim as ( this[name]->arr of Image )
321 if !&arrim
322 {
323 arrim as new( arr, Image, 0 )->arr of Image
324 arr arrim2 of Image
325 this[name] = &arrim
326 }
327 elif flgclear
328 {
329 arrim.clear()
330 }
331 buf bicon
332 if flgres
333 {
334 uint handle = FindResource( hmod, path.ustr().ptr(), 14 )
335 uint mem = LockResource( LoadResource( hmod, handle ))
336 bicon.copy( mem, SizeofResource( hmod, handle ))
337 }
338 else : bicon.read( path )
339 if !*bicon: return
340 uint header as bicon.data->ICONDIR
341 //print( "zzzzzzzz \(header.idReserved) \( header.idType ) \(header.idCount) \((&header.idCount+2)->uint)\n" )
342 if !header.idReserved && header.idType == 1
343 {
344 uint count = header.idCount
345 uint entry as header.idEntries
346 uint i, j
347 arr sizes of icsize
348 fornum i=0, count
349 { //
350 fornum j=0, *sizes
351 {
352 if sizes[j].Width > entry.bWidth &&
353 sizes[j].Height > entry.bHeight : break
354 }
355 sizes.insert( j )
356 sizes[j].Width = entry.bWidth
357 sizes[j].Height = entry.bHeight
358 entry as uint
359 if flgres : entry += sizeof(RESICONDIRENTRY)
360 else : entry += sizeof(ICONDIRENTRY)
361 }
362 if !*this.arrIml
363 {
364 this.arrIml.expand(*sizes)
365 fornum i=0, *sizes
366 {
367 this.arrIml[i].hIml = ImageList_Create (
368 sizes[i].Width, sizes[i].Height, 0x000000FF, 10, 10 )
369 this.arrIml[i].Width = sizes[i].Width
370 this.arrIml[i].Height = sizes[i].Height
371 this.arrIml[i].pImageList = &this
372 }
373 }
374 if *sizes > *arrim
375 {
376 arrim.expand( *sizes - *arrim )
377 }
378 fornum i=0, *sizes
379 {
380 .SetIco( arrim[i], LoadImage( ?( hmod, hmod, GetModuleHandle( 0 )), path.ustr().ptr(), $IMAGE_ICON,
381 sizes[i].Width, sizes[i].Height, ?( flgres, 0, $LR_LOADFROMFILE ) | $LR_DEFAULTCOLOR ), sizes[i].Width, sizes[i].Height )
382 }
383 }
384 }
385
386 method ImageManager.LoadDir( str dir, str listname, uint flgclear )
387 {
388 uint il as this[listname]//->ImageList
389
390 ffind fdi
391 fdi.init( "\( dir )\\*.ico", $FIND_FILE )
392 foreach finfo ico, fdi
393 {
394 il.LoadIco( ico.fullname, 0, 0, flgclear, 0->str )
395 }
396 }
397
398 import "Oleaut32.dll"
399 {
400 uint OleLoadPicturePath( uint, uint, uint, uint, uint, uint )
401 }
402 global {
403 buf IID_IPicture = '\h4 7BF80980 \h2 BF32 101A \h 8B BB 00 AA 00 30 0C AB'
404 }
405
406 //global { uint ppv }
407 method uint ImageList.LoadPicture( str path, str name, uint flgclear, uint flgaddimagelist )
408 {
409 uint ppv
410 uint res
411 buf un
412
413 if ole.flginit
414 {
415 res = OleLoadPicturePath( un.unicode( path ).ptr(), 0, 0, 0, IID_IPicture.ptr(), &ppv )
416 if !(res & 0x80000000) && ppv
417 {
418 uint handle
419 BITMAP bmpinfo
420 handle = 0
421 ((ppv->uint + 12)->uint)->stdcall(ppv, &handle)
422
423 GetObject(handle,sizeof(BITMAP),&bmpinfo)
424
425 uint width = bmpinfo.bmWidth
426 uint height = bmpinfo.bmHeight
427 uint arrim as ( this[name]->arr of Image )
428 if !&arrim
429 {
430 arrim as new( arr, Image, 0 )->arr of Image
431 this[name] = &arrim
432 }
433 elif flgclear
434 {
435 arrim.clear()
436 }
437 if !*this.arrIml
438 {
439 this.arrIml.expand(1)
440 this.arrIml[0].hIml = ImageList_Create (
441 width, height, 0x000000FF, 10, 10 )
442 this.arrIml[0].Width = width
443 this.arrIml[0].Height = height
444 this.arrIml[0].pImageList = &this
445 }
446 /*fornum i = 0, *arrim
447 {
448 if arrim[i].Width == width &&
449 arrim[i].Height == height
450 {
451 break
452 }
453 if arrim[i].Width >= width &&
454 arrim[i].Height > height
455 }*/
456 /*if *sizes > *arrim
457 {
458 arrim.expand( *sizes - *arrim )
459 }*/
460 if !*arrim : arrim.expand(1)
461 ICONINFO II
462 II.fIcon = 1
463 II.hbmColor = handle
464
465 buf bits
466 uint w
467 bits.reserve( w = (( width +15 / 16 ) * height * 2))//*( width / 8 + ?(( width % 8 ),1,0 )) * height * 2*/ )
468 mzero( bits.data, w )
469 /*uint i
470 fornum i = 0, w
471 {
472 //bits[i] = 0//0xAA
473 if bits[i] : print("\(i) XXX\n" )
474 }*/
475 II.hbmMask = CreateBitmap( width, height, 1, 1, bits.ptr() )
476 handle=CreateIconIndirect( II )
477 DeleteObject( II.hbmMask )
478 DeleteObject( II.hbmColor )
479 ((ppv->uint + 8)->uint)->stdcall(ppv)
480 //arrim[0].hImage = handle
481 .SetIco( arrim[0], handle , width, height )
482 return handle
483 }
484 }
485 return 0
486 }
487
488
489 method uint ImageManager.LoadImg( str filename, str listname, str imgname )
490 {
491 uint il as this[listname]
492
493 str ext
494 filename.fgetparts( 0->str, 0->str, ext )
495 if ext == "ico"
496 {
497 il.LoadIco( filename, 0, 0, 1, imgname )
498 return 1
499 }
500 else
501 {
502 return il.LoadPicture( filename, imgname, 1, 0 )
503 }
504
505 }
506
507
508 type EnumResInfo
509 {
510 uint imagelist
511 uint flgclear
512 }
513
514 func uint EnumResNameProc( uint hModule, uint lpszType, uint lpszName, uint lParam )
515 {
516 uint il as lParam->EnumResInfo.imagelist->ImageList
517 ustr s
518 if lpszName > 0xFFFF
519 {
520 s.copy( lpszName )
521 }
522 else : s = "#" + str( lpszName )
523 il.LoadIco( s.str(), 1, hModule, lParam->EnumResInfo.flgclear, 0->str )
524 return 1
525 }
526
527
528 method ImageManager.LoadRes( str filename, str listname, uint flgclear )
529 {
530 uint hres
531 EnumResInfo eri
532 eri.imagelist = &this[listname]
533 eri.flgclear = flgclear
534
535 if *filename
536 {
537 hres = LoadLibraryEx( filename.ptr(), 0, 0x00000002/*$LOAD_LIBRARY_AS_DATAFILE*/ )
538 if !hres : return
539 }
540 EnumResourceNames( hres, 14, callback(&EnumResNameProc,4), &eri )
541 if hres : FreeLibrary( hres )
542 }
543
544
545 method ImageManager.LoadFileIcons( str listname )
546 {
547 uint imagelist as this[listname]
548 .FileIcons.ignorecase()
549 .FileIcons[ "exe" ] = 0xFFFFFFFF
550 .FileIcons[ "pif" ] = 0xFFFFFFFF
551 .FileIcons[ "lnk" ] = 0xFFFFFFFF
552 .FileIcons[ "ico" ] = 0xFFFFFFFF
553 .FileIcons[ "drive" ] = 0xFFFFFFFE
554
555 if !*imagelist.arrIml
556 {
557 imagelist.arrIml.expand(2)
558 uint size = 16
559 uint i
560 fornum i=0, 2
561 {
562 imagelist.arrIml[i].hIml = ImageList_Create (
563 size, size, 0x000000FF, 10, 10 )
564 imagelist.arrIml[i].Width = size
565 imagelist.arrIml[i].Height = size
566 imagelist.arrIml[i].pImageList = &this
567 size *= 2
568 }
569 }
570 }
571
572 method ImageManager.Load( str name, uint flgclear )
573 {
574 ffind fd
575 fd.init( "\(.pMainDir)\\\(name)\\*", $FIND_DIR )
576 foreach finfo cur, fd
577 {
578 .LoadDir( cur.fullname, cur.name, flgclear )
579 /*if !&il
580 {
581 il as new( ImageList )->ImageList
582 this[cur.name] = &il
583 }
584 el*/
585 /*if flgclear
586 {
587
588 il.arrIml.clear()
589 } */
590
591 /*foreach arrim, il
592 {
593 //arrim as arr of Image
594 uint x = arrim->uint
595 print( "ImgList Check \(arrim->uint) \(x)\n" )
596 //destroy( &arrim )
597 getch()
598 }*/
599 }
600 //.LoadRes( $"C:\Delphi7\Bin\delphi32.exe", "resources", flgclear )
601 //.LoadRes( $"K:\Gentee\Open Source\gentee\exe\gentee2.exe", "resources", flgclear )
602 //.LoadRes( $"K:\main.exe", "resources", flgclear )
603 .LoadRes( "", "resources", flgclear )
604 .LoadFileIcons( "files" )
605 //.LoadRes( $"C:\Program Files\7-Zip\7zFM.exe", "resouces", flgclear )
606
607 }
608
609 property str ImageManager.CurName <result>
610 {
611 result = .pCurName
612 }
613
614 property ImageManager.CurName( str value )
615 {
616 if value != .pCurName
617 {
618 //this.Clear()
619 .Load( "default", 1 )
620 //.Load( value, 0 )
621 }
622 }
623
624 property str ImageManager.MainDir <result>
625 {
626 result = .pMainDir
627 }
628
629 property ImageManager.MainDir( str value )
630 {
631 if value != .pMainDir
632 {
633 //this.Clear()
634 .pMainDir = value
635 }
636 }
637
638 method Image ImageManager.GetImage( ustr name )
639 {
640 // print( "GetImage\n" )
641 arrstr path
642 str sname = name
643 sname.split( path, '\', 0 )
644 if *path == 2
645 {
646 // print( "b \(path[0])\n" )
647 uint il as this.find(path[0])->ImageList
648 if &il
649 {
650 sname = path[1]
651 sname.split( path, '[', 0 )
652 uint im as il[path[0]]->arr of Image
653 if &im
654 {
655 uint idx
656 if *path == 2
657 {
658 idx = min( max( 0, int( path[1] ) ), *im )
659 }
660 return im[idx]
661 }
662 }
663 }
664 return 0->Image
665 }
666
667 method uint ImageManager.GetImageNum( ustr name, uint width, uint height )
668 {
669 arrstr path
670 str sname = name
671 sname.split( path, '\', 0 )
672 if *path == 2
673 {
674 uint il as this.find(path[0])->ImageList
675 if &il
676 {
677 uint im as il[path[1]]->arr of Image
678 uint i
679 fornum i, *im
680 {
681 if im[i].Width == width && im[i].Height == height
682 {
683 return i
684 }
685 }
686 }
687 }
688 return -1
689 }
690
691 method int ImageList.GetImageIdx( uint numiml, ustr name, uint disabled )
692 {
693 //print( "GetImageIdx\n" )
694 if &this && *name
695 {
696 uint arrim as this[name.str()]->arr of Image
697 if &arrim
698 {
699 if numiml < *arrim
700 {
701 uint i
702 fornum i = 0, *arrim
703 {
704 if arrim[i].NumIml == numiml
705 {
706 if disabled : return arrim[i].DisPosInIml
707 else : return arrim[i].PosInIml
708 }
709 }
710 }
711 }
712 }
713 return -1
714 }
715
716 method ImageList ImageManager.GetImageList( ustr name, uint pnumiml )
717 {
718 //print( "GetImageList\n" )
719 arrstr path
720 str sname = name
721 sname.split( path, '\', 0 )
722 if *path == 1
723 {
724 sname = path[0]
725 sname.split( path, '[', 0 )
726 uint il as this.find(path[0])->ImageList
727 if &il
728 {
729 uint num
730 if *path > 1 : num= min( uint( path[1] ), *il.arrIml - 1 )
731 if pnumiml: pnumiml->uint = num
732 return il
733 }
734 }
735 return 0->ImageList
736 }
737
738
739 method str ImageManager.GetFileIcon<result>( str filename )
740 {
741 uint hicon
742 str ext fname
743 uint ret i// x y
744
745 filename.fgetparts( 0->str, 0->str, ext )
746
747 ret = .FileIcons[ ext ]
748
749 if ret && ret < 0xFFFFFFF0 : goto end
750
751 if ret == 0xFFFFFFFF
752 {
753 if .FileIcons.find( filename )
754 {
755 ret = .FileIcons[ filename ]
756 goto end
757 }
758 }
759 elif ret == 0xFFFFFFFE
760 {
761 filename = filename.fsetext( filename, 0->str )
762 if .FileIcons.find( filename )
763 {
764 ret = .FileIcons[ filename ]
765 goto end
766 }
767 }
768 result = .FileIconsIdx.str()
769 uint imagelist as this[ "files"]
770 uint arrim as ( imagelist[.FileIconsIdx.str()]->arr of Image )
771 if !&arrim
772 {
773 arrim as new( arr, Image, 0 )->arr of Image
774 imagelist[result] = &arrim
775 }
776 /*elif flgclear
777 {
778 arrim.clear()
779 }*/
780 uint size = 16
781 if 2 > *arrim
782 {
783 arrim.expand( 2 - *arrim )
784 }
785 fornum i=0, 2
786 {
787 uint hicon
788 imagelist.SetIco( arrim[i], hicon = shell_iconfile( filename, i ), size, size )
789 //DestroyIcon( hicon )
790 size *= 2
791 }
792
793 if !ret : .FileIcons[ ext ] = .FileIconsIdx
794 else : .FileIcons[ filename ] = .FileIconsIdx
795 .FileIconsIdx++
796
797 return
798 label end
799 result = ret.str()
800 }