///////////////////////////////////////////////////////////////////////
//  BitDirFile.PRG
//
//  BitView aus AKDialogVHs.PRG
//
//  Inhalt:
//      Klassen BitView, DirWahl, FileWahl
//////////////////////////////////////////////////////////////////////
///////////////////////////////////
#include "Gra.ch"
#include "Xbp.ch"
#include "Dmlb.ch"
#include "Common.ch"
#include "Appevent.ch"
#include "AKDialog.ch"
#include "Dll.ch"
#include "Thread.ch"
#include "FileIO.ch"

//********************************************************************************
//================================================================
/*
 * Klasse zum Anzeigen von Bitmaps oder Metadateien - und jetzt auch Bitmap-Variablen (FOX-Memos)
 */
CLASS BitView FROM XbpStatic, DataRef     // 26.02.2006: DataRef siehe Beispiel MDI: CLASS BitmapRef
   PROTECTED:
   VAR oFrame   // wird nicht gebraucht
   VAR oCanvas    // ist die Parent-BEArea
   VAR HinterGrund   //+05.08.2008 09:13 Farbe des Hintergrunds der BEArea, auf der gezeichnet wird
   VAR oPS
   VAR oBitmap
   VAR oMetafile
   VAR nMode
   VAR lIsEmpty   // 26.02.2006

   EXPORTED:
   VAR autoScale
   VAR file
   METHOD init, create, load, DISPLAY
   METHOD setdata, getdata, editbuffer
   METHOD killDisplay
ENDCLASS



/*
 * Objekt initialisieren. Self ist Parent fr zwei XbpStatic Objekte
 */
METHOD BitView:init( oParent, oOwner, aPos, aSize, aPresParam, lVisible, nType, cVarR, y, nA )
   ::dataref:INIT()  // 26.02.2006  
   IF aPos != NIL //19.10.2006 12:10
      ::xbpStatic:init( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
      ::xbpStatic:type := XBPSTATIC_TYPE_RAISEDRECT
   
      ::oFrame         := XbpStatic():new( self )
      ::oFrame:type    := XBPSTATIC_TYPE_RECESSEDRECT
   
      ::oCanvas        := XbpStatic():new( self )
      ::Hintergrund    := GRA_CLR_BACKGROUND
   ELSE
      ::oCanvas        := oParent  // wenn schon als Parent erzeugt
      ::Hintergrund    := oParent:setColorBG()     //+05.08.2008 09:16 Hintergrund der BEArea
   ENDIF
   ::autoScale      := .T.
   ::nMode          := 0
   ::lIsEmpty       := .T.    // 26.02.2006  noch ist nichts zugewiesen
   ::oPS            := XbpPresSpace():new()
   ::oBitmap        := XbpBitmap():new()  // 26.02.2006  frher bei ::loadfile() erzeugt
// Test:
//   ::dataLink := {|x| IIf( PCOUNT()==0, cVarR, cVarR := x ) }     //18.10.2006 17:40
   ::dataLink := {|x| IIf( PCOUNT()==0, (nA)->&((nA)->(FieldName(y))), ;
                                    (nA)->&((nA)->(FieldName(y))) := IIf(DbRLock(),x,x) ) }
RETURN self



/*
 * Systemresourcen anfordern. Self ist der „uáere Rahmen, ::oFrame ist der
 * innere Rahmen und in ::oCanvas wird das Bild gezeichnet
 */
METHOD BitView:create( oParent, oOwner, aPos, aSize, aPresParam, lVisible, nFaktor )   //+16.05.2009 17:44 nFaktor=Verkleinerung
   LOCAL aAttr[ GRA_AA_COUNT ]

   IF aPos != NIL //19.10.2006 12:10
      ::xbpStatic:create( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
      aSize    := ::currentSize()
      aSize[1] -= 8
      aSize[2] -= 8
   
      ::oFrame:create(self,, {4,4}, aSize )
   
      aSize[1] -= 2
      aSize[2] -= 2
   
      ::oCanvas:create(::oFrame,, {1,1}, aSize )
   ENDIF
  /*
   * Presentation Space mit dem Device Kontext von XbpStatic verbinden
   */
   ::oPS:create( ::oCanvas:winDevice() )
   ::oBitmap:CREATE( ::oPS )     // 26.02.2006  jetzt schon hier
      //+16.05.2009 17:32 verkleinern:
      IF !Empty(nFaktor)
         ::oBitmap := GraSaveScreen( ::oPS, {0,0}, {::oBitmap:xsize,::oBitmap:ysize}, nFaktor )
      ENDIF
   aAttr[ GRA_AA_COLOR ] := ::HinterGrund       //+ 05.08.2008 09:17 GRA_CLR_BACKGROUND
   ::oPS:setAttrArea( aAttr )
   ::oCanvas:paint := {| aClip | ::display( aClip ) }

RETURN self


/*
 * Bitmapdaten aus Feld in Puffer bertragen    // 26.02.2006  aus MDI:BitmapRef
 */
METHOD BitView:setdata( cBuffer )
   IF cBuffer == NIL
      cBuffer := Eval( ::dataLink )
   ENDIF

   IF ! Empty( cBuffer )
      ::oBitmap:setBuffer( cBuffer, XBPBMP_FORMAT_WIN3X )
      ::lIsEmpty := .F.
      ::nMode := 1
   ELSE
      ::lIsEmpty := .T.
      ::nMode := 0
   ENDIF
   ::changed :=  .F.
   ::DISPLAY()
RETURN cBuffer



/*
 * Gepufferte Bitmap in Feld bertragen    // 26.02.2006  aus MDI:BitmapRef
 */
METHOD BitView:getdata()
   LOCAL cBuffer := ::oBitmap:setBuffer()

   IF Valtype( ::dataLink ) == "B" .AND. .NOT. ::lIsEmpty
      Eval( ::dataLink, cBuffer )
   ENDIF
RETURN cBuffer


METHOD BitView:editbuffer()                // 26.02.2006  aus MDI:BitmapRef
RETURN ::oBitmap:setBuffer()


/*
 * Bilddatei laden
 */
METHOD BitView:load( cFile )
   LOCAL lSuccess := .F.

   IF Valtype( cFile ) <> "C" .OR. ! File( cFile )
      RETURN lSuccess
   ENDIF

   ::nMode := 0
   ::file  := ""

   IF ".BMP" $ Upper( cFile ) .OR. ;
      ".GIF" $ Upper( cFile ) .OR. ;
      ".JPG" $ Upper( cFile ) .OR. ;
      ".PNG" $ Upper( cFile )

      IF ::oBitmap == NIL        // ist jetzt (26.02.2006) schon in ::init() erzeugt
         ::oBitmap := XbpBitmap():New():create( ::oPS )
      ENDIF

      IF ( lSuccess := ::oBitmap:loadFile( cFile ) )
         ::nMode := 1
         ::file := cFile
         ::lIsEmpty := .F.    // 26.02.2006
      ENDIF

   ELSEIF ".EMF" $ Upper( cFile ) .OR. ".MET" $ Upper( cFile )
      IF ::oMetafile == NIL
         ::oMetafile := XbpMetafile():New():create()
      ENDIF

      IF ( lSuccess := ::oMetafile:load( cFile ) )
         ::nMode := 2
         ::file := cFile
         ::lIsEmpty := .F.    // 26.02.2006
      ENDIF
   ENDIF

RETURN lSuccess



/*
 * Bilddatei anzeigen
 */
METHOD BitView:display( aClip )
   LOCAL lSuccess := .F.
   LOCAL aSize    := ::oCanvas:currentSize()
   LOCAL aTarget, aSource, nAspect

   ThreadObject():setPriority(PRIORITY_TIME_CRITICAL)    //+13.11.2008 15:26

   /*
    * Clip Bereich vorbereiten
    */
   DEFAULT aClip TO { 1, 1, aSize[1]-1, aSize[2]-1 }
   GraPathBegin( ::oPS )
   GraBox( ::oPS, { aClip[1]-1, aClip[2]-1 }, { aClip[3]+1, aClip[4]+1 }, GRA_OUTLINE )
   GraPathEnd( ::oPS )
   GraPathClip( ::oPS, .T. )

   GraBox( ::oPS, {0,0}, aSize, GRA_FILL )

   DO CASE
   CASE ::nMode == 1
     /*
      * Eine Bitmap Datei ist geladen
      */
      aSource := {0,0,Max(::oBitmap:xSize,1),Max(::oBitmap:ySize,1)} // 07.09.2006 19:07  wg. '/0'
      aTarget := {1,1,aSize[1]-2,aSize[2]-2}

      IF ::autoScale
        /*
         * Bitmap wird auf die Gr”áe von ::oCanvas skaliert
         */
         nAspect    := aSource[3] / aSource[4]
//         IF nAspect > 1 
         IF nAspect > aTarget[3]/aTarget[4]     //21.10.2007 14:12
            aTarget[4] := aTarget[3] / nAspect  // ???21.10.2007 13:22    //25.11.2006 13:06 original:[4]=[3]/nA.. ist falsch!!
         ELSE
            aTarget[3] := aTarget[4] * nAspect  // ???21.10.2007 13:22    //25.11.2006 13:07 original:[3]=[4]*nA.. ist falsch!!
         ENDIF
      ELSE
         aTarget[3] := aSource[3]
         aTarget[4] := aSource[4]
      ENDIF


     /*
      * Bitmap in ::oCanvas horizontal oder vertikal zentrieren
      */
      IF aTarget[3] < aSize[1]-2
         nAspect := ( aSize[1]-2-aTarget[3] ) / 2
         aTarget[1] += nAspect
         aTarget[3] += nAspect
      ENDIF

      IF aTarget[4] < aSize[2]-2
         nAspect := ( aSize[2]-2-aTarget[4] ) / 2
         aTarget[2] += nAspect
         aTarget[4] += nAspect
      ENDIF

      ::oBitmap:draw( ::oPS, aTarget, aSource, , GRA_BLT_BBO_IGNORE )
//      ::oBitmap:draw( ::oPS, aTarget, aSource, , GRA_BLT_BBO_OR )  // 9.7.04
      Sleep(1)

   CASE ::nMode == 2
     /*
      * Eine Metadatei ist geladen
      */
      IF ::autoScale
         ::oMetafile:draw( ::oPS, XBPMETA_DRAW_SCALE )
      ELSE
         ::oMetafile:draw( ::oPS, XBPMETA_DRAW_DEFAULT )
      ENDIF

   ENDCASE

   GraPathClip( ::oPS, .F. )
   ThreadObject():setPriority(PRIORITY_NORMAL)    //+13.11.2008 15:26

RETURN lSuccess

METHOD BitView:killDisplay()
   IF ValType(::oBitmap) == "O"
      ::oBitmap:setBuffer("")
   ENDIF
RETURN self
//RETURN ::DISPLAY()
///////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////


#include "Directry.ch"
#include "\bestatt\muellx\prgx\Ezscan.ch"

#define  xbeDS_DirChanged           xbeP_User + 100
#define  xbeFS_FileMarked           xbeP_User + 101
#define  xbeFS_FileSelected         xbeP_User + 102

/*
 * Klasse zur Auswahl von Laufwerken und Verzeichnissen
 */
CLASS DirWahl FROM XbpStatic
   PROTECTED:
   VAR aDrives
   VAR oItem

   EXPORTED:
   VAR startDir
   VAR dirTree
   VAR driveList
   VAR oWin       //+ Window, das die Eventschleife verwaltet

   METHOD init, create, fillTree, curDir
ENDCLASS



/*
 * Objekt initialisieren
 */
METHOD DirWahl:init( oParent, oOwner, aPos, aSize, aPresParam, lVisible, nHelpBase )   //+24.10.2008 13:16

   ::xbpStatic:init( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
   ::xbpStatic:type    := XBPSTATIC_TYPE_RAISEDRECT

   ::dirTree           := XbpTreeView():new( self )
   ::dirTree:tabStop   := .T.
   ::dirTree:hasLines  := .T.
   ::dirTree:hasButtons:= .T.
   ::dirTree:alwaysShowSelection := .T.      //+13.12.2008 15:08
   ::dirTree:helplink := nHelpBase + 1      //+24.10.2008 13:15

   ::driveList         := XbpComboBox():new( self )
   ::driveList:tabStop := .T.
   ::driveList:type    := XBPCOMBO_DROPDOWNLIST
   ::driveList:helplink := nHelpBase + 2      //+24.10.2008 13:15

   ::startDir          := CurDrive() + ":\" + CurDir()   //+ "\Scans2" wird eh' berschieben in FileView
   ::oWin := oParent
RETURN self



/*
 * Systemresourcen anfordern und Daten fr das aktuelle Verzeichnis
 * in die Treeview eintragen
 */
METHOD DirWahl:create( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
   ::xbpStatic:create( oParent, oOwner, aPos, aSize, aPresParam, lVisible )

   aSize := ::currentSize()

  /*
   * Die Treeview erzeugt ein benutzerdefiniertes Ereignis und
   * fgt das gew„hlte Verzeichnis als ersten Message-Parameter hinzu
   */
   ::dirTree:create  (,, {4, 30}, {aSize[1]-8, aSize[2]-30-4 } )
   ::dirTree:itemSelected := {|oItem| ::fillTree( oItem ) }
   ::dirTree:itemMarked   := {|oItem| PostAppEvent( xbeDS_DirChanged, oItem:getData(),.F., ::oWin ) }

   ::dirTree:rootItem:setData( ::startDir )

   ::driveList:create(,, {4, 30-4-24-96}, {aSize[1]-8, 24+96 } )

   ::aDrives := AvailDrives()
   AEval( ::aDrives, {|c| ::driveList:xbpListBox:addItem( c+":" ) } )

   IF At( ":", ::startDir ) == 2
      ::driveList:xbpListBox:setData( { AScan( ::aDrives, Left(::startDir,1) ) } )
   ELSE
      ::driveList:xbpListBox:setData( { AScan( ::aDrives, CurDrive() ) } )
   ENDIF
   ::driveList:xbpListBox:itemSelected := {|| ::fillTree() }

   ::fillTree( ::dirTree:rootItem )
RETURN self



/*
 * Treeview mit den Daten des gew„hlten Verzeichnisses aufbauen.
 * Jedes XbpTreeViewItem enth„lt eine Zeichenkette mit dem Verzeichnis,
 * das es anzeigt
 */
METHOD DirWahl:fillTree( oItem )
   LOCAL aItems    := ::dirTree:rootItem:getChildItems()
   LOCAL cDrive    := AllTrim( ::driveList:xbpSLE:getData() )
   LOCAL cDir, aDir, i, imax, nLen, oParent, oTemp, cTemp, oNewParent
//   DEFAULT oItem TO ::oItem      //+29.07.2008 22:26
   IF oItem <> NIL .AND. ::isVisible() .AND. Len( Directory( oItem:getData() + "\*.", "D" ) ) == 2
//+12.06.2010 17:27 testweise fr RaguseX n„chstes IF-ELSE-ENDIF geremt:
//      IF Len(Directory(oItem:getData()+"\*"))>0
         ::oItem := oItem
         PostAppEvent( xbeDS_DirChanged, ::CurDir(),.T., ::oWin )   
//      ELSE
//         Tone(1000)
//         RETURN self
//      ENDIF
   ENDIF

   ::dirTree:LockUpdate( .T. )

   AEval( aItems, {|obj| ::dirTree:rootItem:delItem(obj) } )
   cDir    := cDrive

  /*
   * Die Treeview beginnt mit dem Laufwerksbuchstaben
   */
   oParent := ::dirTree:rootItem:addItem( cDrive, ICON_DRIVE, ICON_DRIVE, ICON_DRIVE,, cDrive )

   IF oItem == NIL
      oItem := oParent
   ENDIF

   ::oItem := oItem

  /*
   * Fr jedes Unterverzeichnis wird ein XbpTreeviewItem erzeugt
   */
   DO WHILE Upper(cDir) <> Upper(oItem:getData())
      cTemp := SubStr( oItem:getData(), Len(cDir)+2 )
      nLen := At( "\", cTemp ) - 1
      IF nLen < 0
          nLen := len(cTemp)
      ENDIF
      cTemp := SubStr( cTemp, 1, nLen)

      aDir := Directory( cDir + "\", "D" )
      imax := Len( aDir )
      FOR i:=1 TO imax
         IF "D" $ aDir[i,F_ATTR]        .AND. ;
            .NOT. aDir[i,F_NAME] == "." .AND. ;
            .NOT. aDir[i,F_NAME] == ".."
            oTemp := oParent:addItem( aDir[i,F_NAME]   , ;
                                      ICON_CLOSEDFOLDER, ;
                                      ICON_MARKEDFOLDER, ;
                                      ICON_OPENFOLDER  , ;
                                      "MUSTER.DLL"   , ;
                                      cDir + "\" + aDir[i,F_NAME] )
            IF Upper( cDir + "\" + aDir[i,F_NAME] ) == Upper( SubStr( oItem:getData(), 1, Len(cDir + "\" + cTemp) ) )
               oNewParent := oTemp
            ENDIF
         ENDIF
      NEXT
      cDir += "\" + cTemp
      oParent:expand(.T.)
      IF oNewParent <> NIL
         oParent := oNewParent
      ENDIF
   ENDDO


  /*
   * XbpTreeViewItems fr die Dateien im untersten Verzeichnis erzeugen
   */
   aDir := Directory( cDir + "\", "D" )

   imax := Len( aDir )
   FOR i:=1 TO imax
      IF "D" $ aDir[i,F_ATTR]        .AND. ;
         .NOT. aDir[i,F_NAME] == "." .AND. ;
         .NOT. aDir[i,F_NAME] == ".."

         oParent:addItem( aDir[i,F_NAME]   , ;
                          ICON_CLOSEDFOLDER, ;
                          ICON_MARKEDFOLDER, ;
                          ICON_OPENFOLDER  , ;
                          "MUSTER.DLL"   , ;
                          cDir + "\" + aDir[i,F_NAME] )
      ENDIF
   NEXT

   oParent:expand( .T. )
   ::dirTree:SetData( oParent )

   ::dirTree:LockUpdate( .F. )
   ::dirTree:InvalidateRect()

//   PostAppEvent( xbeDS_DirChanged, oParent:getData(),, ::oWin )   
   PostAppEvent( xbeDS_DirChanged, ::CurDir(),.T., ::oWin )   
RETURN self   



/*
 * Aktuelles ausgew„hltes Verzeichnis zurckgeben
 */
METHOD DirWahl:curDir
RETURN IIf(::oItem!=NIL,::oItem:getData(), ::startDir )  //15.11.2010 19:18CurDir())


/*
 * Klasse zur Auswahl von Dateien mit bestimmten Erweiterungen
 */
CLASS FileWahl FROM XbpStatic
   PROTECTED:
   VAR aFiles
   VAR aExtensions
   VAR oItem
   VAR cDir

   EXPORTED:
   VAR fileList
   VAR extList
   VAR oWin       //+ Window, das die Eventschleife verwaltet
   VAR aFileMark  //+31.07.2008 15:53  die markierte Datei
   VAR aFileExt   //+31.07.2008 15:54  die markierte Extension

   METHOD init, create, setFilesTo, fillFileList, fileMarked, fileSelected
   METHOD aFiles  //+15.03.2009 22:24 Array mit den markierten Filenamen erzeugen
ENDCLASS



/*
 * Objekt initialisieren
 */
METHOD FileWahl:init( oParent, oOwner, aPos, aSize, aPresParam, lVisible, nHelpBase )  //+24.10.2008 13:15

   ::xbpStatic:init( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
   ::xbpStatic:type := XBPSTATIC_TYPE_RAISEDRECT

   ::fileList         := XbpListBox():new( self )
   ::fileList:tabStop := .T.
   ::fileList:helplink := nHelpBase + 3      //+24.10.2008 13:15
   ::extList          := XbpComboBox():new( self )
   ::extList:tabStop  := .T.
   ::extList:type     := XBPCOMBO_DROPDOWNLIST
   ::extList:helplink := nHelpBase + 4       //+24.10.2008 13:15
   ::oWin := oParent
   ::aFileMark := IIf(Empty(P_aFileMark),{1},P_aFileMark)    //+31.07.2008 15:55
   ::aFileExt  := IIf(Empty(P_aFileExt),IIf("SCANS2"$::setparent():cargo:title,{1},{2}),P_aFileExt)     //+02.11.2008 12:17
   
RETURN self



/*
 * Systemresourcen anfordern
 */
METHOD FileWahl:create( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
   ::xbpStatic:create( oParent, oOwner, aPos, aSize, aPresParam, lVisible )

   aSize := ::currentSize()
   ::fileList:markMode := XBPLISTBOX_MM_EXTENDED   //+15.03.2009 21:55
   ::fileList:create  (,, {4, 30}        , {aSize[1]-8, aSize[2]-30-4 } )
   ::fileList:itemMarked   := {|| ::fileMarked() }
   ::fileList:itemSelected := {|| ::fileSelected() }
   ::extList:create(,, {4, 30-4-34-96}, {aSize[1]-8, 34+96 } )

   ::aExtensions := { "*.*" }
   AEval( ::aExtensions, {|c| ::extList:xbpListBox:addItem( c ) } )

   ::extList:xbpListBox:setData( { 1 } )
   ::extList:xbpListBox:itemSelected := {|| ::fillFileList(P_aFileMark) }

RETURN self



/*
 * Verzeichnis und Dateierweiterungen fr die Dateiliste definieren
 */
METHOD FileWahl:setFilesTo( cDir, aExtensions )

   IF Valtype( aExtensions ) == "A"
      ::extList:xbpListBox:clear()
      AEval( aExtensions, {|c| ::extList:xbpListBox:addItem( c ) } )
//      ::extList:xbpListBox:setData( { 1 } )
      ::extList:xbpListBox:setData( ::aFileExt )      //+31.07.2008 15:57
   ENDIF

   IF Valtype( cDir ) == "C"
      ::cDir := cDir
   ENDIF

   ::fillFileList()      //+31.07.2008 15:33
RETURN self



/*
 * Listbox mit bereinstimmenden Dateien fllen
 */
METHOD FileWahl:fillFileList()            //+31.07.2008 15:12
   LOCAL i, imax, j, jmax, aExtensions := {}
   LOCAL nOffset, cExtension


  /*
   * Liste der Erweiterungen aus der Combobox holen.
   * Als Trennzeichen dient das Leerzeichen
   */
   cExtension := AllTrim( ::extList:xbpSLE:getData() )

   DO WHILE ! Empty( cExtension )
      i := At( " ", cExtension )
      IF i > 0
         AAdd( aExtensions, AllTrim( SubStr( cExtension, 1, i-1 ) ) )
         cExtension := AllTrim( SubStr( cExtension, i+1 ) )
      ELSE
         AAdd( aExtensions, cExtension )
         cExtension := ""
      ENDIF
   ENDDO

   jmax := Len( aExtensions )

   ::fileList:clear()
   ::aFiles  := {}


  /*
   * Listbox mit Dateinamen fllen
   */
   FOR j:=1 TO jmax
      aDir    := Directory( ::cDir + "\" + aExtensions[j] )
      nOffset := Len( ::aFiles )
      imax    := Len( aDir )

      ASize( ::aFiles, nOffset + imax )

      FOR i:=1 TO imax
         ::aFiles[nOffset+i] := aDir[i,F_NAME]
         ::fileList:addItem( aDir[i,F_NAME] )
         sleep(1)                //+05.01.2011 12:45 Vista-Problem (siehe KSO + oBest:letzte30())
      NEXT
   NEXT
  //+31.07.2008 14:45 markiert beim Neustart den vorigen Eintrag:
   IF !Empty(::aFileMark)
      //+10.12.2008 16:06 zu markierender Dateiname wird in ::aFileMark bergeben:
      IIf( ValType(::aFileMark)=="C", ::aFileMark := AScan( ::afiles, {|x| Upper(X) == Upper(::aFileMark) } ), ) 
      ::FileList:setData(::aFileMark)
      ::FileMarked()
   ENDIF

RETURN self



/*
 * Benutzerdefiniertes Ereignis "Datei ist markiert" plus Dateinamen senden
 */
METHOD FileWahl:fileMarked
   LOCAL aItems := ::fileList:getData()

   IF ! Empty( aItems ) .AND. ! Empty( ::aFiles )
      PostAppEvent( xbeFS_FileMarked, ::cDir + "\" + ::aFiles[ aItems[1] ],, ::oWin )
   ELSE
      PostAppEvent( xbeFS_FileMarked, ,.F., ::oWin )
   ENDIF
RETURN self



/*
 * Benutzerdefiniertes Ereignis "Datei ist gew„hlt" plus Dateinamen senden
 */
METHOD FileWahl:fileSelected
   LOCAL aItems := ::fileList:getData()

   IF ! Empty( aItems ) .AND. ! Empty( ::aFiles )
      PostAppEvent( xbeFS_FileSelected, ::cDir + "\" + ::aFiles[ aItems[1] ],, ::oWin )
   ENDIF

RETURN self

//+15.03.2009 22:25 erzeugt ein Array mit allen/markierten Dateien:
METHOD FileWahl:aFiles(lMark)
   LOCAL aArray := ::FileList:getData() // Numerische Indizes 
   LOCAL i := 0, imax := Len(aArray)
   LOCAL cDir := oEdit:oDirs:CurDir() + "\" 
   DEFAULT lMark TO .T.
   IF lMark
      DO WHILE ++i <= imax               // Eintr„ge lesen 
         aArray[i] := cDir + ::FileList:getItem( aArray[i] ) 
      ENDDO 
   ELSE
      aArray := AClone( ::aFiles )
      FOR i:=1 TO Len(aArray)
         aArray[i] := cDir + aArray[i]
      NEXT
   ENDIF
RETURN aArray 


/*
 * Die Funktion gibt ein Array mit den Buchstaben aller verfgbarer
 * Laufwerken auáer Diskettenlaufwerke zurck
 */
#define DRIVE_NOT_READY  21

FUNCTION AvailableDrives()
   LOCAL cDrive := CurDrive()
   LOCAL aDrives:= { cDrive }
   LOCAL bError := ErrorBlock( {|oErr| LaufwerkFehler( oErr, aDrives ) } )

   FOR i:=3 TO 26
      BEGIN SEQUENCE
        Curdrive( Chr(64+i) ) 
        CurDir()
        IF AScan( aDrives, CurDrive() ) == 0
           AAdd( aDrives, Curdrive() )
        ENDIF
      ENDSEQUENCE
   NEXT

   CurDrive( cDrive )

   ErrorBlock( bError )   
RETURN ASort( aDrives )

/*
 * Laufzeitfehler abfangen, wenn ein Laufwerk nicht bereit ist
 */
STATIC PROCEDURE LaufwerkFehler( oError, aDrives )
   IF oError:osCode == DRIVE_NOT_READY
      AAdd( aDrives, oError:args[1] )
   ENDIF
   BREAK
RETURN

//+22.11.2008 11:07+ImageView ////////////////////////////////////////////////////////////////
//+von EzScan.prg hierher verschoben und erg„nzt:
/*
 * Klasse zum Anzeigen von Bitmaps oder Metadateien
 */
CLASS ImageView FROM XbpStatic
   PROTECTED:
   VAR oFrame
   VAR oCanvas
   VAR oPS
   VAR oBitmap
   VAR oMetafile
   VAR nMode

   EXPORTED:
   VAR autoScale
   VAR FILE
   VAR Resolution       //+29.09.2008 15:10 tats„chliche Aufl”sung in Px/m
   VAR aPhysSize        //+29.09.2008 15:10 tats„chliche Abmessung in 1/10 mm {h,v}
   
   METHOD init, create, load, DISPLAY, autoscale
   METHOD killDisplay         //+08.12.2008 13:53 l”scht die Anzeige
ENDCLASS



/*
 * Objekt initialisieren. Self ist Parent fr zwei XbpStatic Objekte
 */
METHOD ImageView:init( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
   ::xbpStatic:init( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
   ::xbpStatic:type := XBPSTATIC_TYPE_RAISEDRECT

   ::oFrame         := XbpStatic():new( self )
   ::oFrame:type    := XBPSTATIC_TYPE_RECESSEDRECT

   ::oCanvas        := XbpStatic():new( self )
   ::autoScale      := .T.
   ::nMode          := 0
   ::oPS            := XbpPresSpace():new()
   ::file  := ""
RETURN self



/*
 * Systemresourcen anfordern. Self ist der „uáere Rahmen, ::oFrame ist der
 * innere Rahmen und in ::oCanvas wird das Bild gezeichnet
 */
METHOD ImageView:create( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
   LOCAL aAttr[ GRA_AA_COUNT ]

   ::xbpStatic:create( oParent, oOwner, aPos, aSize, aPresParam, lVisible )
   aSize    := ::currentSize()
   aSize[1] -= 8
   aSize[2] -= 8

   ::oFrame:create(self,, {4,4}, aSize )

   aSize[1] -= 2
   aSize[2] -= 2

   ::oCanvas:create(::oFrame,, {1,1}, aSize )

  /*
   * Presentation Space mit dem Device Kontext von XbpStatic verbinden
   */
   ::oPS:create( ::oCanvas:winDevice() )
   aAttr[ GRA_AA_COLOR ] := GRA_CLR_BACKGROUND
   ::oPS:setAttrArea( aAttr )
   ::oCanvas:paint := {| aClip | ::display( aClip ) }

RETURN self

/*
 * Bilddatei laden
 */
METHOD ImageView:load( cFile )
   LOCAL lSuccess := .F.
   LOCAL nHandle, cBuffer := Space(50)

   IF Valtype( cFile ) <> "C" .OR. ! File( cFile )
      RETURN lSuccess
   ENDIF

   ::nMode := 0
   ::file  := ""

   IF ".BMP" $ Upper( cFile ) .OR. ;
      ".GIF" $ Upper( cFile ) .OR. ;
      ".JPG" $ Upper( cFile ) .OR. ;       
      ".PNG" $ Upper( cFile )

      IF ::oBitmap == NIL
         ::oBitmap := XbpBitmap():New():create( ::oPS )
      ENDIF

      IF ( lSuccess := ::oBitmap:loadFile( cFile ) )
         ::nMode := 1
         ::file := cFile
       //+29.09.2008 15:14: Resolution und Abmessung bestimmen:
         nHandle := FOpen(::FILE,FO_READ)
         IF FRead(nHandle,@cBuffer,50) == 50
            ::Resolution := Max(Bin2I(SubStr(cBuffer,39,4)),1)     //+ Aufl”sung in Px/m (1m=10000* 1/10mm)
            ::aPhysSize  := {::oBitmap:xsize * 10000 / ::Resolution, ;
                             ::oBitmap:ysize * 10000 / ::Resolution }   //+ Gr”áe in 1/10 mm
            FClose(nHandle)
         ENDIF
      ENDIF

   ELSEIF ".EMF" $ Upper( cFile ) .OR. ".MET" $ Upper( cFile )
      IF ::oMetafile == NIL
         ::oMetafile := XbpMetafile():New():create()
      ENDIF

      IF ( lSuccess := ::oMetafile:load( cFile ) )
         ::nMode := 2
         ::file := cFile
      ENDIF
   ENDIF

RETURN lSuccess



/*
 * Bilddatei anzeigen
 */
METHOD ImageView:display( aClip )
   LOCAL lSuccess := .F.
   LOCAL aSize    := ::oCanvas:currentSize()
   LOCAL aTarget, aSource, nAspect

   /*
    * Clip Bereich vorbereiten
    */
   DEFAULT aClip TO { 1, 1, aSize[1]-1, aSize[2]-1 }
   GraPathBegin( ::oPS )
   GraBox( ::oPS, { aClip[1]-1, aClip[2]-1 }, { aClip[3]+1, aClip[4]+1 }, GRA_OUTLINE )
   GraPathEnd( ::oPS )
   GraPathClip( ::oPS, .T. )

   GraBox( ::oPS, {0,0}, aSize, GRA_FILL )

   DO CASE
   CASE ::nMode == 1
     /*
      * Eine Bitmap Datei ist geladen
      */
      aSource := {0,0,::oBitmap:xSize,::oBitmap:ySize}
      aTarget := {1,1,aSize[1]-2,aSize[2]-2}

      IF ::autoScale
        /*
         * Bitmap wird auf die Gr”áe von ::oCanvas skaliert
         */
         aTarget := ::autoscale( aTarget, ::oBitmap )
////////         nAspect    := aSource[3] / aSource[4]
////////         IF nAspect > 1
////////            aTarget[4] := aTarget[3] / nAspect
////////         ELSE
////////            aTarget[3] := aTarget[4] * nAspect
////////         ENDIF
      ELSE
         aTarget[3] := aSource[3]
         aTarget[4] := aSource[4]


     /*
      * Bitmap in ::oCanvas horizontal oder vertikal zentrieren
      */
      IF aTarget[3] < aSize[1]-2
         nAspect := ( aSize[1]-2-aTarget[3] ) / 2
         aTarget[1] += nAspect
         aTarget[3] += nAspect
      ENDIF

      IF aTarget[4] < aSize[2]-2
         nAspect := ( aSize[2]-2-aTarget[4] ) / 2
         aTarget[2] += nAspect
         aTarget[4] += nAspect
      ENDIF
      ENDIF

      ::oBitmap:draw( ::oPS, aTarget, aSource, , GRA_BLT_BBO_IGNORE )
      Sleep(1)

   CASE ::nMode == 2
     /*
      * Eine Metadatei ist geladen
      */
      IF ::autoScale
         ::oMetafile:draw( ::oPS, XBPMETA_DRAW_SCALE )
      ELSE
         ::oMetafile:draw( ::oPS, XBPMETA_DRAW_DEFAULT )
      ENDIF

   ENDCASE

   GraPathClip( ::oPS, .F. )

RETURN lSuccess

//+ gibt es doch schon als Function hier im PRG-File (s.o.)
METHOD ImageView:autoscale(ASize,oBitmap)
   LOCAL nAspect
   LOCAL aSource := {0,0,Max(oBitmap:xSize,1),Max(oBitmap:ySize,1)}
   LOCAL aTargetUr := IIf(Len(aSize)=2,{1,1,aSize[1]-2,aSize[2]-2},ASize)
   LOCAL aTarget := AClone(aTargetUr)
      IF ::autoScale
        /*
         * Bitmap wird auf die Gr”áe von ::oCanvas skaliert
         */
         nAspect    := aSource[3] / aSource[4]
//         IF nAspect > 1
         IF nAspect > (aTarget[3]-aTarget[1]) / (aTarget[4]-aTarget[2])   //21.10.2007 14:14
            aTarget[4] := (aTarget[3]-aTarget[1]) / nAspect + aTarget[2]      //[3]! 21.10.2007 13:19
         ELSE
            aTarget[3] := (aTarget[4]-aTarget[2]) * nAspect + aTarget[1]      //[4]! 21.10.2007 13:19
         ENDIF
      ELSE
         aTarget[3] := aSource[3]
         aTarget[4] := aSource[4]
      ENDIF
     /*
      * Bitmap in ::oCanvas horizontal oder vertikal zentrieren
      */
      IF aTarget[3] < aTargetUr[3]
         nAspect := (aTargetUr[3]-aTarget[3])/2
         aTarget[1] += nAspect
         aTarget[3] += nAspect
      ENDIF
      IF aTarget[4] < aTargetUr[4]
         nAspect := (aTargetUr[4]-aTarget[4])/2
         aTarget[2] += nAspect
         aTarget[4] += nAspect
      ENDIF
RETURN aTarget

METHOD ImageView:killDisplay()
   IF ValType(::oBitmap) == "O"
      ::oBitmap:setBuffer("")
   ENDIF
RETURN ::DISPLAY()

