views:

317

answers:

3

I'm making a program that takes a snapshot of the screen, and saves it to a folder as a Bitmap picture. I seem to be running into a problem though, the picture just overwrites itself.

Can anyone tell me how I can make it so when it saves, the number will be one higher than the last? For example: Save 1: Screenshot0001.bmp Save 2: Screenshot0002.bmp Save 3: Screenshot0003.bmp

And so on.

+2  A: 

At program startup, iterate all Screenshot*.bmp files, parse out the numeric part and find the highest - assign this value to your counter. When doing a snapshot, go into a loop that tries crreating Screenshot.bmp with "only create if doesn't exist already" (CREATE_NEW) semantics, incrementing the counter until you find an unused name.

Alternately, use timestamp instead of counter :)

snemarch
+1 for the tip to do this atomically (multi-user friendly). But given the experience level of the OP the other answer seems to be more appropriate.
mghie
+14  A: 

There are many ways to accomplish something like this.

  1. Do it like your digital camera does; Have a counter and save it in a file or in the registry. You'll probably run into multi-user problems and you'll still have to handle situations where an image already exists.

  2. Don't use a incrementing number, but write a datetime in the filename. FileName := 'Screenshot_'+FormatDateTime('yyyymmdd-hhnnss-zzz.bmp',now());

  3. Do something like the code below to find the latest number. I think this does what you're describing, but remember that this code will get slower as you write more images. With thousands of pictures and a slow drive or network it could 'hang' your program.

..

i := 0;
while FileExists(Format('%sScreenshot%.04d.bmp',[ImgPath,i])) do
  inc(i);
Wouter van Nifterick
I'm having a problem. I added FileName := +FormatDateTime('yyyymmdd-hhnnss-zzz.bmp',now()); and added [FileName] to the following code: bmp.SaveToFile('C:\Screenshots\ScreenShot[FileName].bmp'); But I don't know if I am doing it right. The FileName:= says that it is undeclared.
PuppyKevin
You need to declare your variables, Kevin. Check the help about that. Also check the help about string concatenation.
Rob Kennedy
I declared the FileName variable as FileName: string;, I re-wrote the FileName := and SaveTo lines as: FileName := 'Screenshot_'+FormatDateTime('yyyymmdd-hhnnss-zzz',now());bmp.SaveToFile('C:\Screenshots\[FileName].bmp');, and now, when it makes and saves the Bitmap, it comes out as [FileName].bmp.
PuppyKevin
@PuppyKevin: Try "bmp.SaveToFile('C:\Screenshots\' + FileName + '.bmp');" instead, or use another Format() call: "bmp.SaveToFile(Format('C:\Screenshots\%s.bmp', [FileName]));"
mghie
mghie, I used your Format() way, and it worked! Thank you everyone for helping me out :)
PuppyKevin
A: 

You need a routine like this which mimics Windows file duplication where the first file is 'My File', the second is 'My File (2)', then 'My File (3)' etc.

function AppendDuplicationNumber( const AStr : string ) : string;
// Used to make strings unique
// This examines the string AStr for trailing '(n)' where
// 'n' is an integer.
// If the (n) part is found, n is incremented, otherwise '(2)' is
// appended to the string.
var
  iLH, iRH, I : integer;
  S           : string;
begin
  Result := AStr;
  iLH    := CharPosBackwards( '(', Result );
  If iLH > 0 then
    begin
    iRH := PosEx( ')', Result, iLH );
    If iRH > 0 then
      begin
      I := StrToIntDef( Copy( Result, iLH+1, iRH-iLH-1 ), 0 );
      If I > 0 then
        begin
        Inc(I);
        S := IntToStr( I );
        Delete( Result, iLH+1, iRH-iLH-1 );
        Insert( S, Result, iLH+1 );
        Exit;
        end;
      end;
    end;

  // Did not increment existing (n), so append it.
  Result := Result + ' (2)';
end;
Brian Frost
This is clearly not what the OP intended, he specifically wants file names with one part being an increasing number.
mghie