Avatar billede michael-schou Novice
06. august 2008 - 14:09 Der er 23 kommentarer og
1 løsning

Kopier en mappe (incl. filer og undermapper) incl progressbar.

Hejsa.

Jeg har læst om alle de progressbar spørgsmål og svar der har været her på Eksperten, men kan stadig ikke få noget af det til at virke.

Det eneste eksempel jeg har fået til at virke er nedenstående eksempel, det kopiere alle Mapper og filer fra C:\Temp til D:\Temp, men uden progress bar.

Spørgsmål : Kan man integrere en progressbar ala. Windows Commander(Viser 2 progressbar 1 til den fil den kopiere og en til hvor langt den er nået i alt.), i nedenstående eksempel og hvis ja hvordan?

Ellers, vil jeg meget gerne have hjælp til at få det til at virker og meget gerne se et funktionsdygtigt eksempel.

EKS:

----------------------------------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, StdCtrls, ExtCtrls, Menus, ShellApi;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    Label1: TLabel;
    Edit1: TEdit;
    Label2: TLabel;
    Edit2: TEdit;
    Panel1: TPanel;
    Memo1: TMemo;
    Memo2: TMemo;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    Files1: TMenuItem;
    Label3: TLabel;
    Label4: TLabel;
    Replikate1: TMenuItem;
    Savereplikalists1: TMenuItem;
    Clearreplikalist1: TMenuItem;
    Exit1: TMenuItem;
    Label5: TLabel;
    Label6: TLabel;
    procedure CopyFolder(src, dest : string );
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CopyFolder(src, dest : string );
var
  sts : Integer ;
  SR: TSearchRec;

begin
  sts := FindFirst(src + '*.*' , faAnyFile , SR );
  if sts = 0 then
    begin
      if ( SR.Name <> '.' ) and ( SR.Name <> '..' ) then
        begin
          //Put User Feedback here if desired
          Application.ProcessMessages;
          if pos('.', SR.Name) = 0 then
            begin
              {$I-}MkDir( dest + SR.Name ) ;{$I+}
            CopyFolder( src + SR.Name + '\', dest +
                                    SR.Name + '\' ) ;
            end
          else
            Copyfile( pchar(src + SR.Name), pchar(dest + sr.name),
                          true );
        end;
      while FindNext( SR ) = 0 do
        begin
          if ( SR.Name <> '.' ) and ( SR.Name <> '..' ) then
            begin
              //Put User Feedback here if desired
              Application.ProcessMessages;
              if Pos('.', SR.Name) = 0 then
                begin
                  {$I-}MkDir( dest + SR.Name );{$I+}
                  CopyFolder( src + SR.Name + '\', dest + SR.Name
                                    + '\' ) ;
                end
              else
                Copyfile( pchar(src + SR.Name), pchar(dest +
                              sr.name), true );
            end;
        end;
      FindClose( SR ) ;
    end ;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
CopyFolder('C:\Temp\', 'D:\Temp\');
end;

end.
----------------------------------------------------------------

På forhånd mange tak.

Mvh

Michael
Avatar billede mbsnet Nybegynder
06. august 2008 - 14:25 #1
Princippet i det vil være først, at lave en filliste, hvor du så kan se hvor mange der er, og bagefter løbe listen igennem, og kopiere en efter en, mens antal procent regnes ud, udfra nummeret i listen. Dette kunne være en TStringList.

Men vil lade en anden om eksemplet for at se hvor langt man er med den aktive fil.
//mbs
Avatar billede pidgeot Nybegynder
06. august 2008 - 14:33 #2
Det med hvor langt man er med den aktuelle fil afhænger helt og aldeles af at ens kopieringsfunktion enten ved hvordan man skal opdatere det der nu skal opdateres, eller at man har mulighed for at give den en callback som bliver kaldt når den har noget at rapportere.

Da du bruger Windows API til at kopiere (det er der intet galt i), skal du derfor i stedet bruge CopyFileEx, der lader dig medsende en callback-funktion som du kan bruge til at opdatere din "denne fil" progressbar.

MSDN har de nødvendige oplysninger om hvad CopyFileex tager, og hvad callbackfunktionen modtager:
http://msdn.microsoft.com/en-us/library/aa363852(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa363854(VS.85).aspx

Da Windows API bruger en anden calling convention (hvordan parametre m.v. overføres mellem funktionerne) end Delphi, skal du huske at markere din callbackfunktion som stdcall.

Der er et eksempel på http://delphicikk.atw.hu/index.php?oldal=5 - som nævnt kan du bruge Int64 i stedet for COMP (hvilket du bør med mindre du har behov for understøttelse i Delphi 3 eller derunder - hvilket er tvivlsomt).
Avatar billede hrc Mester
06. august 2008 - 22:40 #3
Kan se at i den kommende Delphi kan progressbar'en lege løbelys (altså starte forfra).

Hvad mbsnets forslag angår så kan man klare sig med bare at tælle filerne. Det er det simpleste men bliver lidt misvisende hvis der er meget store og meget små filer i samme "batch". Så ville jeg nok lave en liste (TObjectList) og nogle dataklasser der hver indeholdt navn og størrelse på hver fil, men som også var i stand til at kopiere/flytte sig selv til et andet sted - og i processen derved sende data, enten ved callback eller ved en message

type
  TFileList = class;

  TFileData = class
  private
    fName: string;
    fSize: longword;
    fOwner: TFileList;
    fOnCopyStart: TNotifyEvent;
    fOnCopyEnd: TNotifyEvent;
  public
    constructor Create(aOwner: TFileList; aSearchRec: TSearchRec);
    property Name: string read fName;
    property Size: longword read fSize;
    function CopyFile(const aDestPath: string): boolean;
    function MoveFile(const aDestPath: string): boolean;
    procedure Delete;
    property OnCopyStart(Msg: TMessage) read fOnCopyStart write fOnCopyStart;
    property OnCopyEnd(Msg: TMessage) read fOnCopyEnd write fOnCopyEnd;
  end;

  TFileList = class(TObjectList)
  private
    fSourcePath: string;
    procedure Initialize; // Genererer liste vha FindFirst, FindNext ...
  public
    constructor Create(const aSourcePath: string);
    procedure CopyFiles(const aDestinationPath: string);
    procedure MoveFiles(const aDestinationPath: string);
    property SourcePath: string read fSourcePath; // Bruges af TFileData vha. fOwner
    property Items[const aIndex: integer] read TFileData read GetItems; default;
  end;
Avatar billede hrc Mester
06. august 2008 - 22:45 #4
Skal man gå helt amok kan man nedarve TFileData fra TThread og så lade ProgressBar.Max være AntalOprettede og ProgrssBar.Position være (AntalOprettede - LevendeTråde).

Ideen er nok for speget, men det vil være en sjov opgave med load balancing, synkronisering m.v.
Avatar billede mbsnet Nybegynder
07. august 2008 - 09:04 #5
ok bare glem det. det er misvidende at du skal bruge en filliste
Avatar billede borrisholt Novice
07. august 2008 - 12:33 #6
unit FileHandling;

interface

uses
  ShellAPI, Windows, SysUtils;
Function DeleteFiles(  Files : String) : Boolean;
Function CopyFiles( From, Dest : String) : Boolean;
Function MoveFiles( From, Dest : String) : Boolean;
Function RenameFiles( From, Dest : String) : Boolean;
Function GetFileSize(FileName : TFileName) : Integer;




implementation

Function ExecuteOp(From : String; Dest : String; IdOp : Integer) : Boolean;
var
  SHFileOpStruct : TSHFileOpStruct;
  zFrom, zDest : array [0..MAX_PATH+2] of Char;
begin
  From := ExpandFileName(From);
  Dest := ExpandFileName(Dest);
  ZeroMemory(@zFrom, SizeOf(zFrom));
  ZeroMemory(@zDest, SizeOf(zDest));

  StrCopy(zFrom, PChar(From));
  StrCopy(zDest, PChar(Dest));

  SHFileOpStruct.Wnd  := GetActiveWindow();
  SHFileOpStruct.wFunc := IdOp;
  SHFileOpStruct.pFrom := zFrom;
  SHFileOpStruct.pTo  := zDest;

  if IdOp <> FO_DELETE then
    SHFileOpStruct.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR
  else
    SHFileOpStruct.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;

Result := Boolean(SHFileOperation(SHFileOpStruct));
Result := Result and (SHFileOpStruct.fAnyOperationsAborted);
end;


Function CopyFiles( From, Dest : String) : Boolean;
begin
  result := ExecuteOp(From,Dest, FO_COPY);
end;

Function DeleteFiles(  Files : String) : Boolean;
begin
  Result := ExecuteOp(Files,'', FO_DELETE);
end;

Function MoveFiles( From, Dest : String) : Boolean;
begin
  Result := ExecuteOp(From,Dest, FO_MOVE);
end;

Function RenameFiles( From, Dest : String) : Boolean;
begin
  if (ExtractFilePath(From) <> '') and (ExtractFilePath(Dest) = '') then
    Dest := ExtractFilePath(From) + Dest;
  Result := ExecuteOp(From,Dest, FO_RENAME);
end;


Function GetFileSize(FileName : TFileName) : Integer;
var
SearchRec : TSearchRec;
begin
  if FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec) = 0 then
    Result := SearchRec.Size
  else
    Result := -1;
  FindClose (SearchRec);
end;

end.

Kald windows ... det plejer jeg at gøre .. :D

Jens Borrisholt
Avatar billede michael-schou Novice
11. august 2008 - 11:41 #7
Hey Jens.

Hvordan kalder man windows på din unit?

Jeg har allerede din unit liggende som *.pas fil :-) Og det var det første jeg forsøgte mig med :-)

Men der var ikke nogen progressbar i :-)

Michael.
Avatar billede borrisholt Novice
11. august 2008 - 11:51 #8
ok...

Det er et spørgsmål om opsætning ... Den record du giver med til SHFileOperation() afgør hvordan tingene ser ud på sækrmen ...

Læs Microsofts dokumentation for en nærmer forklaring :
http://msdn.microsoft.com/en-us/library/bb759795(VS.85).aspx


Jens B
Avatar billede michael-schou Novice
11. august 2008 - 14:12 #9
Hey igen ...

Nu har jeg fået det til at virke med windows progressbar ved at indsætte :

FOF_MULTIDESTFILES i følgende linjer :

  if IdOp <> FO_DELETE then
    SHFileOpStruct.fFlags := FOF_ALLOWUNDO Or FOF_MULTIDESTFILES or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR
  else
    SHFileOpStruct.fFlags := FOF_ALLOWUNDO or FOF_MULTIDESTFILES or FOF_NOCONFIRMATION;

Men den viser jo så kun 1 progressbar, der findes ikke en progressbar ala. Total Commander, hvor den viser en progressbar for filen den kopiere og hvorlangt den er nået ialt?

Michael.
Avatar billede kroning Nybegynder
11. august 2008 - 19:48 #10
Du kan lave din egen progressbar ved at benytte CopyFileEx, se her:
http://www.eksperten.dk/spm/821806
Avatar billede michael-schou Novice
12. august 2008 - 12:34 #11
Hey kroning

Nu har jeg set lidt på dit eksempel og det virker jo fint, men kan simpelthen ikke få en extra progresbar til at virke (ProgressBar2), det er den progressBar der skal vise overall progress, hvor ProgressBar1 skal vise hver enkelt fil, hvad den også gør :-)

Har rodet med det i et stykke tid nu.

Michael.
Avatar billede kroning Nybegynder
12. august 2008 - 14:08 #12
Dette ser ud til at virke.
----------------------

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ProgressBar1: TProgressBar;
    ProgressBar2: TProgressBar;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure CopyFolder(src, dest : string );
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function CopyProgressRoutine(
    TotalFileSize : Int64;    // total file size, in bytes
    TotalBytesTransferred : Int64;    // total number of bytes transferred
    StreamSize : Int64;    // total number of bytes for this stream
    StreamBytesTransferred : Int64;    // total number of bytes transferred for this stream
    dwStreamNumber : DWORD;    // the current stream
    dwCallbackReason : DWORD;    // reason for callback
    hSourceFile : THandle;    // handle to the source file
    hDestinationFile : THandle;    // handle to the destination file
    lpData : pointer) : DWORD; stdcall; // passed by CopyFileEx
begin
  with Form1 do
  begin
    ProgressBar1.Max:=TotalFileSize;
    ProgressBar1.Position:=TotalBytesTransferred;
    ProgressBar1.Update;
    ProgressBar2.Position:=ProgressBar2.Max-integer(lpData);
    ProgressBar2.Update;
  end;
end;

procedure TForm1.CopyFolder(src, dest : string );
var
  fl : TStringList;
  i : integer;

procedure MakeList(src, dest : string);
var
  sts : Integer ;
  SR: TSearchRec;
begin
  sts := FindFirst(src + '*.*' , faAnyFile , SR );
  while sts = 0 do
  begin
    if ( SR.Name <> '.' ) and ( SR.Name <> '..' ) then
    begin
      if Pos('.', SR.Name) = 0 then
      begin
        {$I-}MkDir( dest + SR.Name );{$I+}
        MakeList( src + SR.Name + '\', dest + SR.Name+ '\' ) ;
      end
      else
        fl.Add(src + SR.Name+'='+dest + sr.name);
    end;
    sts:=FindNext( SR );
  end;
  FindClose( SR ) ;
end;

begin
  fl:=TStringList.Create;
  MakeList(src, dest);
  ProgressBar2.Max:=fl.Count;
  ProgressBar2.Position:=0;
  for i:=0 to fl.Count-1 do
    CopyfileEx(PChar(fl.Names[i]), pchar(fl.ValueFromIndex[i]), @CopyProgressRoutine, pointer(fl.count-i-1), nil, 0);
  fl.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CopyFolder('C:\Temp\', 'D:\Temp\');
end;

end.
Avatar billede kroning Nybegynder
12. august 2008 - 14:19 #13
Hov, har lavet noget vrøvl, ret disse 2 linier:
ProgressBar2.Position:=ProgressBar2.Max-integer(lpData);
CopyfileEx(PChar(fl.Names[i]), pchar(fl.ValueFromIndex[i]), @CopyProgressRoutine, pointer(fl.count-i-1), nil, 0);

til dette:
ProgressBar2.Position:=integer(lpData);
CopyfileEx(PChar(fl.Names[i]), pchar(fl.ValueFromIndex[i]), @CopyProgressRoutine, pointer(i), nil, 0);

begge løsninger virker men det første er bare noget vrøvl.
Avatar billede kroning Nybegynder
12. august 2008 - 14:40 #14
Nu har jeg lige læst tråden igennem og som hrc nævner så bliver ProgressBar2 misvisende hvis der er meget store og små filer blandet, men det kan dog let rettes til så ProgressBar2 kører på samlet antal byte i stedet.
Avatar billede michael-schou Novice
12. august 2008 - 15:07 #15
kroning, det virker som det skal nu fantastisk :-) og har rettet de 2 linjer.

En lille ting mere .. hehe ... Vill gerne have en label på også der viser hvilken fil der bliver kopiret som du har i dit først eksempel du linkede til :-)

Michael.
Avatar billede kroning Nybegynder
12. august 2008 - 15:15 #16
Det kan du sætte ind før CopyFileEx således:

for i:=0 to fl.Count-1 do
begin
  Label1.Caption:='Kopierer '+fl.Names[i]+' til '+fl.ValueFromIndex[i];
    CopyfileEx(PChar(fl.Names[i]), pchar(fl.ValueFromIndex[i]), @CopyProgressRoutine, pointer(fl.count-i-1), nil, 0);
end;
Avatar billede kroning Nybegynder
12. august 2008 - 15:34 #17
Du skal nok have en Label1.Update; ind efter Caption er sat. Altså:

for i:=0 to fl.Count-1 do
begin
  Label1.Caption:='Kopierer '+fl.Names[i]+' til '+fl.ValueFromIndex[i];
  Label1.Update;
    CopyfileEx(PChar(fl.Names[i]), pchar(fl.ValueFromIndex[i]), @CopyProgressRoutine, pointer(fl.count-i-1), nil, 0);
end;
Avatar billede michael-schou Novice
13. august 2008 - 08:32 #18
Hey kroning.

Jeg har lige testet det med Label1 og jeg får en fejl : class EStringListError with message "List index out of bounds(93)"

Ville høre om man også kan få Label2 og Label3 til at vise procent :
Label 2 = Procent for kopieret fil
Label 3 = procent for samlet kopiering

Kan man det?

Michael.
Avatar billede kroning Nybegynder
13. august 2008 - 13:47 #19
Hvis du får en fejl er det fordi du ikke har skrevet det som jeg har.
Jeg kikker lige på det med %
Avatar billede kroning Nybegynder
13. august 2008 - 14:01 #20
Så skulle det virke.
---------------------

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ProgressBar1: TProgressBar;
    ProgressBar2: TProgressBar;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure CopyFolder(src, dest : string );
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function CopyProgressRoutine(
    TotalFileSize : Int64;    // total file size, in bytes
    TotalBytesTransferred : Int64;    // total number of bytes transferred
    StreamSize : Int64;    // total number of bytes for this stream
    StreamBytesTransferred : Int64;    // total number of bytes transferred for this stream
    dwStreamNumber : DWORD;    // the current stream
    dwCallbackReason : DWORD;    // reason for callback
    hSourceFile : THandle;    // handle to the source file
    hDestinationFile : THandle;    // handle to the destination file
    lpData : pointer) : DWORD; stdcall; // passed by CopyFileEx
begin
  with Form1 do
  begin
    ProgressBar1.Max:=TotalFileSize;
    ProgressBar1.Position:=TotalBytesTransferred;
    ProgressBar1.Update;
    ProgressBar2.Position:=ProgressBar2.Max-integer(lpData);
    ProgressBar2.Update;
    Label2.Caption:='Fil '+IntToStr(round((TotalBytesTransferred/TotalFileSize)*100));
    Label2.Update;
  end;
end;

procedure TForm1.CopyFolder(src, dest : string );
var
  fl : TStringList;
  i : integer;

procedure MakeList(src, dest : string);
var
  sts : Integer ;
  SR: TSearchRec;
begin
  sts := FindFirst(src + '*.*' , faAnyFile , SR );
  while sts = 0 do
  begin
    if ( SR.Name <> '.' ) and ( SR.Name <> '..' ) then
    begin
      if Pos('.', SR.Name) = 0 then
      begin
        {$I-}MkDir( dest + SR.Name );{$I+}
        MakeList( src + SR.Name + '\', dest + SR.Name+ '\' ) ;
      end
      else
        fl.Add(src + SR.Name+'='+dest + sr.name);
    end;
    sts:=FindNext( SR );
  end;
  FindClose( SR ) ;
end;

begin
  fl:=TStringList.Create;
  MakeList(src, dest);
  ProgressBar2.Max:=fl.Count;
  ProgressBar2.Position:=0;
  for i:=0 to fl.Count-1 do
  begin
    Label1.Caption:='Kopierer '+fl.Names[i]+' til '+fl.ValueFromIndex[i];
    Label1.Update;
    Label3.Caption:='Samlet '+IntToStr(Round(((i+1)/fl.Count)*100));
    Label3.Update;
    CopyfileEx(PChar(fl.Names[i]), pchar(fl.ValueFromIndex[i]), @CopyProgressRoutine, pointer(fl.count-i-1), nil, 0);
  end;
  fl.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CopyFolder('C:\Temp\', 'D:\Temp\');
end;

end.
Avatar billede kroning Nybegynder
13. august 2008 - 14:04 #21
Nu glemte jeg at rette det vrøvl jeg lavede tidligere så her kommer det lige igen.
-------------------------

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ProgressBar1: TProgressBar;
    ProgressBar2: TProgressBar;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure CopyFolder(src, dest : string );
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function CopyProgressRoutine(
    TotalFileSize : Int64;    // total file size, in bytes
    TotalBytesTransferred : Int64;    // total number of bytes transferred
    StreamSize : Int64;    // total number of bytes for this stream
    StreamBytesTransferred : Int64;    // total number of bytes transferred for this stream
    dwStreamNumber : DWORD;    // the current stream
    dwCallbackReason : DWORD;    // reason for callback
    hSourceFile : THandle;    // handle to the source file
    hDestinationFile : THandle;    // handle to the destination file
    lpData : pointer) : DWORD; stdcall; // passed by CopyFileEx
begin
  with Form1 do
  begin
    ProgressBar1.Max:=TotalFileSize;
    ProgressBar1.Position:=TotalBytesTransferred;
    ProgressBar1.Update;
    ProgressBar2.Position:=integer(lpData);
    ProgressBar2.Update;
    Label2.Caption:='Fil '+IntToStr(round((TotalBytesTransferred/TotalFileSize)*100));
    Label2.Update;
  end;
end;

procedure TForm1.CopyFolder(src, dest : string );
var
  fl : TStringList;
  i : integer;

procedure MakeList(src, dest : string);
var
  sts : Integer ;
  SR: TSearchRec;
begin
  sts := FindFirst(src + '*.*' , faAnyFile , SR );
  while sts = 0 do
  begin
    if ( SR.Name <> '.' ) and ( SR.Name <> '..' ) then
    begin
      if Pos('.', SR.Name) = 0 then
      begin
        {$I-}MkDir( dest + SR.Name );{$I+}
        MakeList( src + SR.Name + '\', dest + SR.Name+ '\' ) ;
      end
      else
        fl.Add(src + SR.Name+'='+dest + sr.name);
    end;
    sts:=FindNext( SR );
  end;
  FindClose( SR ) ;
end;

begin
  fl:=TStringList.Create;
  MakeList(src, dest);
  ProgressBar2.Max:=fl.Count;
  ProgressBar2.Position:=0;
  for i:=0 to fl.Count-1 do
  begin
    Label1.Caption:='Kopierer '+fl.Names[i]+' til '+fl.ValueFromIndex[i];
    Label1.Update;
    Label3.Caption:='Samlet '+IntToStr(Round(((i+1)/fl.Count)*100));
    Label3.Update;
    CopyfileEx(PChar(fl.Names[i]), pchar(fl.ValueFromIndex[i]), @CopyProgressRoutine, pointer(i), nil, 0);
  end;
  fl.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CopyFolder('C:\Temp\', 'D:\Temp\');
end;

end.
Avatar billede michael-schou Novice
13. august 2008 - 14:53 #22
FANTASTISK kroning.

Det virker bare som det skal, helt fantastisk .. takker mange gange :-)

Smid også lige et svar :-)

Michael.
Avatar billede michael-schou Novice
13. august 2008 - 15:05 #23
Og Selvfølgelig også tak til :

mbsnet, pidgeot, hrc og Borrisholt :-)

Michael.
Avatar billede kroning Nybegynder
13. august 2008 - 15:10 #24
ok
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester