ckaneta
asked on
Scrolling Bitmaps
is there a good component out there that will scroll a Bitmap continuously.
I have one, but it will only scroll it across and then when it is done, start over again
I've checked out Torry's pages and the
Delphi Superpage and couldn't find one
that would do
so any help here would be appreciated.
I have one, but it will only scroll it across and then when it is done, start over again
I've checked out Torry's pages and the
Delphi Superpage and couldn't find one
that would do
so any help here would be appreciated.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I already had this going with canvas.copyrect ,what I was looking
for was a way to scroll the bitmap
continuously, i.e.
bitmap is 4 chars long(for simplicity)
[ a]
[ ab]
[ abc]
[ abcd]
[ abcd ]
[abcd a]
[bcd ab]
....
instead of
[ a]
[ ab]
[ abc]
[ abcd]
[ abcd ]
[abcd ]
[bcd ]
[cd ]
[d ]
[ ]
[ a]
[ ab]
[ abc]
[ abcd]
[ abcd ]
do you see what I mean?
for was a way to scroll the bitmap
continuously, i.e.
bitmap is 4 chars long(for simplicity)
[ a]
[ ab]
[ abc]
[ abcd]
[ abcd ]
[abcd a]
[bcd ab]
....
instead of
[ a]
[ ab]
[ abc]
[ abcd]
[ abcd ]
[abcd ]
[bcd ]
[cd ]
[d ]
[ ]
[ a]
[ ab]
[ abc]
[ abcd]
[ abcd ]
do you see what I mean?
Sorry, I didn't understand what your meaning?
Example:
unit hugeviewunit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, ExtCtrls, ComCtrls, Menus, ImgList, ToolWin;
type
TViewMode = (vm1x1, vmZoom, vmStretch);
pbmi = ^TBmi;
TBMI = record
bminfo : TBitmapInfo;
colors : array[0..255] of TRGBQuad;
end;
type
TMainForm = class(TForm)
OpenDialog1: TOpenDialog;
ScrollBox1: TScrollBox;
PaintBox: TPaintBox;
MainMenu1: TMainMenu;
OpenItem: TMenuItem;
N1: TMenuItem;
ExitItem: TMenuItem;
FileMenu: TMenuItem;
ToolBar1: TToolBar;
WholeToolButton: TToolButton;
V1x1ToolButton: TToolButton;
ZoomToolButton: TToolButton;
ToolButton4: TToolButton;
ScaleComboBox: TComboBox;
ImageList1: TImageList;
procedure PaintMe(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure WholeButtonClick(Sender: TObject);
procedure V1x1ButtonClick(Sender: TObject);
procedure ZoomButtonClick(Sender: TObject);
procedure Open1Click(Sender: TObject);
procedure ExitItemClick(Sender: TObject);
procedure ScaleComboBoxChange(Sender : TObject);
private
{ Private declarations }
procedure CloseFileMapping;
public
{ Public declarations }
ViewMode : TViewMode;
bmi : TBmI;
end;
var
MainForm: TMainForm;
Palette : hPalette;
wDC : hDC;
implementation
{$R *.DFM}
const scales: array[0..4] of single = (0.25,0.5,1,2,4);
var ec : Integer;
hf, hm : THandle;
Bits : pointer;
procedure TMainForm.FormCreate(Sende r: TObject);
begin
ScaleComboBox.ItemIndex := 2;
Palette := CreateHalftonePalette(Pain tBox.Canva s.Handle);
Bits := nil;
end;
procedure TMainForm.FormDestroy(Send er: TObject);
begin
if palette <> 0 then DeleteObject(Palette);
CloseFileMapping;
end;
procedure TMainForm.Open1Click(Sende r: TObject);
var
pb: pByteArray;
bmFile : pBitmapFileHeader;
begin
CloseFileMapping;
if not OpenDialog1.execute then Exit;
try
hf := CreateFile(pChar(OpenDialo g1.FileNam e), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hf=INVALID_HANDLE_VALUE then
raise EAbort.CreateFmt('Îøèáêà îòêðûòèÿ ôàéëà %d',[GetLastError]);
hm := CreateFileMapping(hf, nil, PAGE_READWRITE, 0,0,nil);
if hm=0 then
raise EAbort.CreateFmt('Îøèáêà ñîçäàíèÿ îáúåêòà îòîáðàæåíèÿ %d',[GetLastError]);
pb := MapViewOfFile(hm, FILE_MAP_ALL_ACCESS, 0,0,0);
if pb=nil then
raise EAbort.CreateFmt('Îøèáêà îòîáðàæåíèÿ â ïàìÿòü %d',[GetLastError]);
bmFile := pBitmapFileHeader(pb);
if (bmFile^.bfType<>$4D42) then BEGIN Exit; END;
bits := pointer(@pByteArray(bmFile )^[bmFile^ .bfOffBits ]);
bmi := pBmi(@pb^[SizeOf(TBitmapFi leHeader)] )^;
except
on E:EAbort do
begin
CloseFileMapping;
ShowMessage(E.Message);
end;
end;
MainForm.Caption := OpenDialog1.FileName;
V1x1ToolButton.Click;
V1x1ToolButton.Down := True;
end;
procedure TMainForm.CloseFileMapping ;
var ec: Integer;
begin
if (Bits <> nil) and
not UnMapViewOfFile(Bits) then
begin
ec:=GetLastError;
ShowMessage('Îøèáêà çàêðûòèÿ îòîáðàæàåìîãî ôàéëà '+IntToStr(ec));
end;
if (hm<>0) and (hm<>INVALID_HANDLE_VALUE) then CloseHandle(hm);
if (hf<>0) and (hf<>INVALID_HANDLE_VALUE) then CloseHandle(hf);
end;
procedure TMainForm.PaintMe(Sender: TObject);
var OldP : hPalette;i : integer;
begin
if not Assigned(Bits) then Exit;
OldP := SelectPalette(PaintBox.Can vas.Handle , Palette, False);
RealizePalette(PaintBox.Ca nvas.Handl e);
SetStretchBltMode(PaintBox .Canvas.Ha ndle, STRETCH_DELETESCANS);
case ViewMode of
vmStretch:
with bmi.bminfo.bmiHeader do
i := StretchDIBits(PaintBox.Can vas.Handle ,0,0,Paint Box.Height ,PaintBox. Width,
0,0,biWidth,Abs(biHeight),
Bits, pBitmapInfo(@bmi.bminfo)^, DIB_RGB_COLORS,
PaintBox.Canvas.CopyMode);
vm1x1:
with bmi.bminfo.bmiHeader,Paint Box.Client Rect do
i := SetDIBitsToDevice(PaintBox .Canvas.Ha ndle,Left, Top,Right- Left,Botto m-Top,
Left,Top,Top,Bottom-top,
Bits, pBitmapInfo(@bmi.bminfo)^, DIB_RGB_COLORS);
vmZoom:
with bmi.bminfo.bmiHeader,Paint Box.Client Rect do
i := StretchDIBits(PaintBox.Can vas.Handle ,Left,Top, Right-Left ,Bottom-To p,
0,0,biWidth,Abs(biHeight),
Bits, pBitmapInfo(@bmi.bminfo)^, DIB_RGB_COLORS,
PaintBox.Canvas.CopyMode);
end;
if (i=0) or (i=GDI_ERROR) then
begin
ec :=GetLastError;
MainForm.Caption := 'Îøèáêà '+IntToStr(ec);
end;
SelectPalette(PaintBox.Can vas.Handle , OldP, False);
end;
procedure TMainForm.WholeButtonClick (Sender: TObject);
var px,py, sx,sy : Integer;
kx, ky : single;
begin
if not Assigned(Bits) then Exit;
ViewMode := vmStretch;
px := PaintBox.Parent.ClientWidt h - 1;
py := PaintBox.Parent.ClientHeig ht - 1;
sx := bmi.bminfo.bmiHeader.biWid th;
sy := Abs(bmi.bminfo.bmiHeader.b iHeight);
kx := px / sx; ky := py / sy;
if kx > ky then
begin
PaintBox.Width := Round ( sx * ky );
PaintBox.Height := py;
end
else
begin
PaintBox.Width := px;
PaintBox.Height := Round ( sy * kx );
end;
end;
procedure TMainForm.V1x1ButtonClick( Sender: TObject);
begin
if not Assigned(Bits) then Exit;
ViewMode := vm1x1;
PaintBox.Width := bmi.bminfo.bmiHeader.biWid th;
PaintBox.Height := Abs(bmi.bminfo.bmiHeader.b iHeight);
end;
procedure TMainForm.ZoomButtonClick( Sender: TObject);
var x : single;
begin
if not Assigned(Bits) then Exit;
ViewMode := vmZoom;
x := Scales[ScaleComboBox.ItemI ndex];
PaintBox.Width := Round(Integer(bmi.bminfo.b miHeader.b iWidth)*x) ;
PaintBox.Height := Round(Integer(Abs(bmi.bmin fo.bmiHead er.biHeigh t))*x);
end;
procedure TMainForm.ExitItemClick(Se nder: TObject);
begin
Close;
end;
procedure TMainForm.ScaleComboBoxCha nge(Sender : TObject);
begin
if ZoomToolButton.Down then ZoomButtonClick(Sender);
end;
end.
unit hugeviewunit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, ExtCtrls, ComCtrls, Menus, ImgList, ToolWin;
type
TViewMode = (vm1x1, vmZoom, vmStretch);
pbmi = ^TBmi;
TBMI = record
bminfo : TBitmapInfo;
colors : array[0..255] of TRGBQuad;
end;
type
TMainForm = class(TForm)
OpenDialog1: TOpenDialog;
ScrollBox1: TScrollBox;
PaintBox: TPaintBox;
MainMenu1: TMainMenu;
OpenItem: TMenuItem;
N1: TMenuItem;
ExitItem: TMenuItem;
FileMenu: TMenuItem;
ToolBar1: TToolBar;
WholeToolButton: TToolButton;
V1x1ToolButton: TToolButton;
ZoomToolButton: TToolButton;
ToolButton4: TToolButton;
ScaleComboBox: TComboBox;
ImageList1: TImageList;
procedure PaintMe(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure WholeButtonClick(Sender: TObject);
procedure V1x1ButtonClick(Sender: TObject);
procedure ZoomButtonClick(Sender: TObject);
procedure Open1Click(Sender: TObject);
procedure ExitItemClick(Sender: TObject);
procedure ScaleComboBoxChange(Sender
private
{ Private declarations }
procedure CloseFileMapping;
public
{ Public declarations }
ViewMode : TViewMode;
bmi : TBmI;
end;
var
MainForm: TMainForm;
Palette : hPalette;
wDC : hDC;
implementation
{$R *.DFM}
const scales: array[0..4] of single = (0.25,0.5,1,2,4);
var ec : Integer;
hf, hm : THandle;
Bits : pointer;
procedure TMainForm.FormCreate(Sende
begin
ScaleComboBox.ItemIndex := 2;
Palette := CreateHalftonePalette(Pain
Bits := nil;
end;
procedure TMainForm.FormDestroy(Send
begin
if palette <> 0 then DeleteObject(Palette);
CloseFileMapping;
end;
procedure TMainForm.Open1Click(Sende
var
pb: pByteArray;
bmFile : pBitmapFileHeader;
begin
CloseFileMapping;
if not OpenDialog1.execute then Exit;
try
hf := CreateFile(pChar(OpenDialo
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hf=INVALID_HANDLE_VALUE then
raise EAbort.CreateFmt('Îøèáêà îòêðûòèÿ ôàéëà %d',[GetLastError]);
hm := CreateFileMapping(hf, nil, PAGE_READWRITE, 0,0,nil);
if hm=0 then
raise EAbort.CreateFmt('Îøèáêà ñîçäàíèÿ îáúåêòà îòîáðàæåíèÿ %d',[GetLastError]);
pb := MapViewOfFile(hm, FILE_MAP_ALL_ACCESS, 0,0,0);
if pb=nil then
raise EAbort.CreateFmt('Îøèáêà îòîáðàæåíèÿ â ïàìÿòü %d',[GetLastError]);
bmFile := pBitmapFileHeader(pb);
if (bmFile^.bfType<>$4D42) then BEGIN Exit; END;
bits := pointer(@pByteArray(bmFile
bmi := pBmi(@pb^[SizeOf(TBitmapFi
except
on E:EAbort do
begin
CloseFileMapping;
ShowMessage(E.Message);
end;
end;
MainForm.Caption := OpenDialog1.FileName;
V1x1ToolButton.Click;
V1x1ToolButton.Down := True;
end;
procedure TMainForm.CloseFileMapping
var ec: Integer;
begin
if (Bits <> nil) and
not UnMapViewOfFile(Bits) then
begin
ec:=GetLastError;
ShowMessage('Îøèáêà çàêðûòèÿ îòîáðàæàåìîãî ôàéëà '+IntToStr(ec));
end;
if (hm<>0) and (hm<>INVALID_HANDLE_VALUE)
if (hf<>0) and (hf<>INVALID_HANDLE_VALUE)
end;
procedure TMainForm.PaintMe(Sender: TObject);
var OldP : hPalette;i : integer;
begin
if not Assigned(Bits) then Exit;
OldP := SelectPalette(PaintBox.Can
RealizePalette(PaintBox.Ca
SetStretchBltMode(PaintBox
case ViewMode of
vmStretch:
with bmi.bminfo.bmiHeader do
i := StretchDIBits(PaintBox.Can
0,0,biWidth,Abs(biHeight),
Bits, pBitmapInfo(@bmi.bminfo)^,
PaintBox.Canvas.CopyMode);
vm1x1:
with bmi.bminfo.bmiHeader,Paint
i := SetDIBitsToDevice(PaintBox
Left,Top,Top,Bottom-top,
Bits, pBitmapInfo(@bmi.bminfo)^,
vmZoom:
with bmi.bminfo.bmiHeader,Paint
i := StretchDIBits(PaintBox.Can
0,0,biWidth,Abs(biHeight),
Bits, pBitmapInfo(@bmi.bminfo)^,
PaintBox.Canvas.CopyMode);
end;
if (i=0) or (i=GDI_ERROR) then
begin
ec :=GetLastError;
MainForm.Caption := 'Îøèáêà '+IntToStr(ec);
end;
SelectPalette(PaintBox.Can
end;
procedure TMainForm.WholeButtonClick
var px,py, sx,sy : Integer;
kx, ky : single;
begin
if not Assigned(Bits) then Exit;
ViewMode := vmStretch;
px := PaintBox.Parent.ClientWidt
py := PaintBox.Parent.ClientHeig
sx := bmi.bminfo.bmiHeader.biWid
sy := Abs(bmi.bminfo.bmiHeader.b
kx := px / sx; ky := py / sy;
if kx > ky then
begin
PaintBox.Width := Round ( sx * ky );
PaintBox.Height := py;
end
else
begin
PaintBox.Width := px;
PaintBox.Height := Round ( sy * kx );
end;
end;
procedure TMainForm.V1x1ButtonClick(
begin
if not Assigned(Bits) then Exit;
ViewMode := vm1x1;
PaintBox.Width := bmi.bminfo.bmiHeader.biWid
PaintBox.Height := Abs(bmi.bminfo.bmiHeader.b
end;
procedure TMainForm.ZoomButtonClick(
var x : single;
begin
if not Assigned(Bits) then Exit;
ViewMode := vmZoom;
x := Scales[ScaleComboBox.ItemI
PaintBox.Width := Round(Integer(bmi.bminfo.b
PaintBox.Height := Round(Integer(Abs(bmi.bmin
end;
procedure TMainForm.ExitItemClick(Se
begin
Close;
end;
procedure TMainForm.ScaleComboBoxCha
begin
if ZoomToolButton.Down then ZoomButtonClick(Sender);
end;
end.
If you want to scroll fast you should'nt use such things as DIBs and stretch functions. Use only DDBs and functions like BitBlt and ScrollWindow. The DIBs are device independent and your CPU has to calculate a lot to make it device dependend so it can display it...
Regards, ptm.
Regards, ptm.
> i.e. bitmap is 4 chars long(for simplicity)
> [ a]
> [ ab]
> [ abc]
> [ abcd]
> [ abcd ]
> [abcd a]
> [bcd ab]
Doesnt my code wrap around like you want?
Tim...
> [ a]
> [ ab]
> [ abc]
> [ abcd]
> [ abcd ]
> [abcd a]
> [bcd ab]
Doesnt my code wrap around like you want?
Tim...
ASKER
scroll a Bitmap
not enlarge
not enlarge
ASKER
Good enough for government work!!
I guess this'll have to do
I guess this'll have to do
I agree with AttarSoftware but to make this faster you can use ScrollWindowEx so only the scrolled in regions are invalidated the rest has not to be repainted.
Regards, aacrg.