ImageList / Icon Handle [erledigt]

Fragen rund um diverse Windows-Versionen, ihr Verhalten unter Xbase++ und den Umgang mit der API

Moderator: Moderatoren

Antworten
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

ImageList / Icon Handle [erledigt]

Beitrag von AUGE_OHR »

hi,

ich möchte das "richtige" File Icon-Handle für eine ImageList (comctl32.DLL) haben.

da ich hier ot4xb einsetzte ergibt sich ein Unterschied bei der Syntax

Code: Alles auswählen

@comctl32:ImageList_Create(a,b,c,d,e) 
-> 
DLLFUNCTION ImageList_Create(a,b,c,d,e) USING STDCALL FROM comctl32.DLL
also wohl kein grosses Problem zum verstehen.

hier nun die "o:Create()" Methode

Code: Alles auswählen

   ::nRowMax := LEN(::aData) // ::aData -> Directory() Array Struktur

   nhImgList := @comctl32:ImageList_Create( ;
     ::nIcoSmallWidth   ,; // The width, in pixels, of each image
     ::nIcoSmallHeight  ,; // The height, in pixels, of each image
     ILC_MASK           ,; // A set of bit flags that specify the type of image list to create
     0                 ,; // The number of images that the image list initially contains.
     ::nRowMax ) // This parameter represents the number of new images that the resized image list can contain
damit habe ich nun eine ImageList anlegt.

zum "auffüllen" habe ich eine modifizierte XbpIcon() Class benutzt
original siehe C:\ALASKA\XPPW32\Source\SYS\xbparts.prg

Code: Alles auswählen

CLASS MYICON FROM XBPICON
   EXPORTED:
      VAR Handle

INLINE METHOD MyLoad( cDLL, nId, nWidth, nHeight )
LOCAL hModule
   IF ::Status() != XBP_STAT_CREATE
      Exception():RaiseObjectState()
   ENDIF
   IF ::Handle != 0
      @user32:DestroyIcon( ::Handle )
   ENDIF
   IF ValType(cDLL) == "C"
      hModule := @KERNEL32:GetModuleHandleA( cDLL )
   ELSE
      hModule := @KERNEL32:GetModuleHandleA( 0 )
   ENDIF
   IF ValType(nWidth) != "N"
      nWidth  := 32
   ENDIF
   IF ValType(nHeight) != "N"
      nHeight := 32
   ENDIF
   ::Handle := @user32:LoadImageA( hModule,;
                           nId            ,;
                           IMAGE_ICON     ,;
                           nWidth,nHeight ,;
                           LR_DEFAULTCOLOR )

*  ::GetIconInfo() // ich brauche nur das ::Handle
RETURN (::Handle)
welches mir das "Handle" des Icon zurück gibt das ich zum "füllen" benutze

Code: Alles auswählen

 @comctl32:ImageList_ReplaceIcon(;
   nhImgList ,; // A handle to the image list.
   -1 ,; // The index of the image to replace. If i is -1, the function appends the image to the end of the list
   nIcoHandle ) // The handle to the icon or cursor that contains the bitmap and mask for the new image.
Die Icons sind aber in meiner Resource Datei und für eine Directory() Darstellung möchte ich die File Icon haben

Code: Alles auswählen

   FOR nRow = 1 TO ::nRowMax
      nIcoHandle := 0
      oPicture   := NIL
      cFile := ::cStartDir + ::aData[nRow][F_NAME]

      oIcon   := MYICON():new():create()

#IFDEF WARUM
          // nIcoHandle ist > 0 ... aber keine Icon anzeige ...
         nIcoHandle := oIcon:LoadFileIcon(cFile)

#ELSE  
         // so läuft es
         nIcoHandle := oIcon:Myload(,nIcon)
         nIcon++
         IF nIcon >  19
            nIcon := 11
         ENDIF
#ENDIF
ich beide Methoden ausprobiert aber nur die Resource Lösung bringt das gewünschte Ergebniss :(

hier die Methode LoadFileIcon

Code: Alles auswählen

INLINE METHOD LoadFileIcon( cFile, lBigIcon ,cFileAttributes)
**************************************************************************
*
*  SHFILEINFO psfi;
*
* hImageList = (HIMAGELIST)SHGetFileInfo(szFileName, 0, &psfi,
*         sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_SYSICONINDEX | HGFI_SMALLICON );
*
* ListView_SetImageList(hList, hImageList, LVSIL_SMALL);
*
**************************************************************************

LOCAL pBuf
LOCAL nFlags
LOCAL nFileAttributes := 0

  DEFAULT lBigIcon TO .T.

  IF ::Status() != XBP_STAT_CREATE
      Exception():RaiseObjectState()
  ENDIF
  IF ::Handle != 0
      @user32:DestroyIcon( ::Handle )
  ENDIF

  IF lBigIcon == .T.
     nFlags := SHGFI_ICON
  ELSE
  /* nFlags := SHGFI_SMALLICON */  // SHGFI_SMALLICON allein geht nicht
     nFlags := nOr(SHGFI_ICON,SHGFI_SMALLICON)
*    nFlags := SHGFI_ICON+SHGFI_SMALLICON
  ENDIF

  IF cFileAttributes != NIL  /* .AND. ! ".exe" $ lower( cFile ) */   // Will man das individuelle
                                                                     // Exe-Icon oder nicht ?
     nFlags += SHGFI_USEFILEATTRIBUTES  // 0x10
     IF "D" $ cFileAttributes
        nFileAttributes := FILE_ATTRIBUTE_DIRECTORY   // 0x10
     ELSE
        nFileAttributes := FILE_ATTRIBUTE_NORMAL // 0x80
     ENDIF
  ENDIF

* pBuf := Replicate( Chr(0), 348 ) //  lt. MSDN braucht man 352 Bytes
* IF @SHELL32:SHGetFileInfoA(cFile, 0, @pBuf, 348, nFlags) == 0

  pBuf := Replicate( Chr(0), 352 )
  IF @SHELL32:SHGetFileInfoA(cFile, nFileAttributes, @pBuf, 352, nFlags) == 0
     RETURN 0
  ENDIF
  //
  // was ist das nun für ein Handle ?
  //  
  ::Handle := Bin2L( Left(pBuf,4) )

  ::GetIconInfo() // 

RETURN (::Handle)
wenn ich nun "das" Handle ( ist > 0 ) übergebe kommt nichts ... :banghead:

nun habe aber ich genau die selbe Routine zusammen mit Alaska´s ImageList am laufen ...

Code: Alles auswählen

   oIcon   := MYICON():new():create()
   nFileHandle := oIcon:LoadFileIcon(cFile)
   oPicture := oIcon:getIPicture()
wobei Alaska´s Imagelist ein "Picture" haben will.

an der Routine selbst liegt es also IMHO nicht ... aber irgendwas "fehlt" mir noch ...
wer hat eine Idee ?
Zuletzt geändert von AUGE_OHR am Do, 02. Jun 2011 23:06, insgesamt 1-mal geändert.
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: ImageList / Icon Handle

Beitrag von AUGE_OHR »

hi,

nun hat Pablo in seiner "latest" Version auch eine ImageList eingebaut.
auch dort bedient er sich bei "vorhandenen" Icon als File oder Resource.

Code: Alles auswählen

#xtranslate ImageList.<fn>( [<params,...>])  => nFpCall({"comctl32","ImageList_"+<(fn)>}  [ , <params> ] )

   hIco32 := @user32:LoadImageA(hApp,;
                             MAKEINTRESOURCE(nIcon),;
                             IMAGE_ICON,;
                             32,;
                             32,;
                             LR_VGACOLOR)
   ImageList.ReplaceIcon(::hImgLstLarge,-1,hIco32)
   @user32:DestroyIcon(hIco32)
es gleicht also meiner modifizierten XbpIcon() Class METHOD MyLoad().

warum geht es nun mit Alaska´s ImageList was ein iPicture haben will ?

Code: Alles auswählen

c:\ALASKA\XPPW32\SOURCE\SYS\XBPARTS.PRG
METHOD GetIPicture()
...
   // diese Zeilen gibt es in der v1.9.355 Version
   hIcon     := CopyIcon( ::Handle )
   cPictDesc := L2Bin( 20 )           + ;
                L2Bin( PICTYPE_ICON ) + ;
                L2Bin( hIcon )        + ;
                L2Bin( 0 )            + ;
                L2Bin( 0 )


// und das steht in der v1.9.331 Version

   cPictDesc := L2Bin( 20 )           + ;
                L2Bin( PICTYPE_ICON ) + ;
                L2Bin( ::Handle )     + ;
                L2Bin( 0 )            + ;
                L2Bin( 0 )
...
wenn ich mir nun den Unterschied ansehe "denke" ich zu erkennen was der Unterschied ist...

nach weiteren Nachforschungen komme ich zum Ergebniss das ich zwar mit SHGetFileInfoA ein Handle bekomme ... aber das ist auch "alles".
ich "denke" der Unterschied liegt beim "übertragen" in die ImageList wobei die Icons "kopiert" werden.

Code: Alles auswählen

STATIC DLLFUNCTION CopyIcon( hIcon ) ;
       USING STDCALL                 ;
       FROM  USER32.DLL
mal sehen ob meine Vermutung stimmt ... muss es nur noch "umsetzten" ...

p.s. ich weiss inzwischen das man auch auf die "System"- ImageList zugreifen könnte ...
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: ImageList / Icon Handle [erledigt]

Beitrag von AUGE_OHR »

Code: Alles auswählen

   FOR nRow = 1 TO ::nRowMax
      cFile := ::cStartDir + ::aData[nRow][F_NAME]

      oIcon   := MYICON():new():create()
      //
      // load "File" Icon Handle
      //
      nFileHandle := oIcon:LoadFileIcon(cFile)
      //
      // make a "Copy" from Icon
      //
      nIcoHandle  := @USER32:CopyIcon( nFileHandle )
      // LargeIcon List 
      @comctl32:ImageList_ReplaceIcon(;
         ::hImgLstLarge ,; 
         -1                  ,; 
         nIcoHandle      )
      // Smallicon List
      @comctl32:ImageList_ReplaceIcon(;
         ::hImgLstSmall ,;
         -1                  ,; 
         nIcoHandle      )

      // delete "Copy" 
      @user32:DestroyIcon(nIcoHandle)
      // destroy Object 
      oIcon:destroy()
   NEXT
\:D/
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: ImageList / Icon Handle [erledigt]

Beitrag von AUGE_OHR »

hi,

bei meine "funktionierenden" Methode wird ja jede Datei "angefasst" und das passende Icon gesucht welches ich dann in eine "seperate" ImageList aufnehme.

Nun gibt es aber auch die System ImageList ... und die hat Pablo hier benutzt:

Code: Alles auswählen

function file2IconIndex( cFile )
local buffer := ChrR(0,352)
local result := @shell32:SHGetFileInfoA(cFile,0,@buffer,352,SHGFI_SYSICONINDEX)
if Empty(result) ; return 0 ; end
return PeekDWord(buffer,4)
aber Vorsicht mit der System ImageList, die darf man NICHT löschen !!!
gruss by OHR
Jimmy
Antworten