mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-16 11:42:12 +08:00
598 lines
16 KiB
ObjectPascal
598 lines
16 KiB
ObjectPascal
unit EDBImage;
|
|
{$I compilers.inc}
|
|
{
|
|
TEDBImage 1.4 (Enhaced TDBImage):
|
|
by Sebastián Mayorá - Argentina - DelphiHelper@yahoo.com.ar
|
|
Please read EDBImage.txt or readme.txt for more information
|
|
}
|
|
|
|
interface
|
|
|
|
uses
|
|
DBCtrls {TDataLink}, Windows {HPalette}, db {TField}, graphics, classes {TStream},
|
|
Controls {TCustomControl}, Forms {TBorderStyle},
|
|
Messages {TMessage};
|
|
|
|
type
|
|
//Evento para cargar imágenes personalizadas desde el stream guardado
|
|
TLoadCustomImageEvent = procedure (var B: TGraphic; Stream: TStream)of object;
|
|
|
|
TEDBImage = class(TCustomControl)
|
|
private
|
|
FDataLink: TFieldDataLink;
|
|
FPicture: TPicture;
|
|
FBorderStyle: TBorderStyle;
|
|
FAutoDisplay: Boolean;
|
|
FStretch: Boolean;
|
|
FCenter: Boolean;
|
|
FPictureLoaded: Boolean;
|
|
FQuickDraw: Boolean;
|
|
fOnLoadCustomImage: TLoadCustomImageEvent;
|
|
procedure DataChange(Sender: TObject);
|
|
function GetDataField: string;
|
|
function GetDataSource: TDataSource;
|
|
function GetField: TField;
|
|
function GetReadOnly: Boolean;
|
|
procedure PictureChanged(Sender: TObject);
|
|
procedure SetAutoDisplay(Value: Boolean);
|
|
procedure SetBorderStyle(Value: TBorderStyle);
|
|
procedure SetCenter(Value: Boolean);
|
|
procedure SetDataField(const Value: string);
|
|
procedure SetDataSource(Value: TDataSource);
|
|
procedure SetPicture(Value: TPicture);
|
|
procedure SetReadOnly(Value: Boolean);
|
|
procedure SetStretch(Value: Boolean);
|
|
procedure UpdateData(Sender: TObject);
|
|
procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK;
|
|
procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
|
|
procedure CMExit(var Message: TCMExit); message CM_EXIT;
|
|
procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
|
|
procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
|
|
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
|
|
procedure WMCut(var Message: TMessage); message WM_CUT;
|
|
procedure WMCopy(var Message: TMessage); message WM_COPY;
|
|
procedure WMPaste(var Message: TMessage); message WM_PASTE;
|
|
procedure WMSize(var Message: TMessage); message WM_SIZE;
|
|
protected
|
|
Memoria: TmemoryStream;
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
function GetPalette: HPALETTE; override;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure Paint; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure CopyToClipboard;
|
|
procedure CutToClipboard;
|
|
function ExecuteAction(Action: TBasicAction): Boolean; override;
|
|
procedure LoadPicture;
|
|
procedure PasteFromClipboard;
|
|
function UpdateAction(Action: TBasicAction): Boolean; override;
|
|
property Field: TField read GetField;
|
|
property Picture: TPicture read FPicture write SetPicture;
|
|
procedure LoadFromFile(const FileName: string);{v1.3}
|
|
procedure SaveToFile(const FileName: string); {v1.3}
|
|
published
|
|
property Align;
|
|
property Anchors;
|
|
property AutoDisplay: Boolean read FAutoDisplay write SetAutoDisplay default True;
|
|
property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
|
|
property Center: Boolean read FCenter write SetCenter default True;
|
|
property Color;
|
|
property Constraints;
|
|
property Ctl3D;
|
|
property DataField: string read GetDataField write SetDataField;
|
|
property DataSource: TDataSource read GetDataSource write SetDataSource;
|
|
property DragCursor;
|
|
property DragKind;
|
|
property DragMode;
|
|
property Enabled;
|
|
property Font;
|
|
property ParentColor default False;
|
|
property ParentCtl3D;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
|
|
property QuickDraw: Boolean read FQuickDraw write FQuickDraw default True;
|
|
property ShowHint;
|
|
property Stretch: Boolean read FStretch write SetStretch default False;
|
|
property TabOrder;
|
|
property TabStop default True;
|
|
property Visible;
|
|
property OnClick;
|
|
{$IFDEF DELPHI_5_UP}
|
|
property OnContextPopup;
|
|
{$ENDIF}
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEndDock;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDock;
|
|
property OnStartDrag;
|
|
property OnLoadCustomImage :TLoadCustomImageEvent read fOnLoadCustomImage write fOnLoadCustomImage;
|
|
end;
|
|
|
|
|
|
implementation
|
|
uses clipbrd, JPeg;
|
|
|
|
constructor TEDBImage.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
ControlStyle := ControlStyle + [csOpaque, csReplicatable];
|
|
if not NewStyleControls then ControlStyle := ControlStyle + [csFramed];
|
|
Width := 105;
|
|
Height := 105;
|
|
TabStop := True;
|
|
ParentColor := False;
|
|
FPicture := TPicture.Create;
|
|
FPicture.OnChange := PictureChanged;
|
|
FBorderStyle := bsSingle;
|
|
FAutoDisplay := True;
|
|
FCenter := True;
|
|
FDataLink := TFieldDataLink.Create;
|
|
FDataLink.Control := Self;
|
|
FDataLink.OnDataChange := DataChange;
|
|
FDataLink.OnUpdateData := UpdateData;
|
|
FQuickDraw := True;
|
|
Memoria := TmemoryStream.Create;
|
|
end;
|
|
|
|
destructor TEDBImage.Destroy;
|
|
begin
|
|
FPicture.Free;
|
|
FDataLink.Free;
|
|
FDataLink := nil;
|
|
Memoria.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TEDBImage.GetDataSource: TDataSource;
|
|
begin
|
|
Result := FDataLink.DataSource;
|
|
end;
|
|
|
|
procedure TEDBImage.SetDataSource(Value: TDataSource);
|
|
begin
|
|
if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
|
|
FDataLink.DataSource := Value;
|
|
if Value <> nil then Value.FreeNotification(Self);
|
|
end;
|
|
|
|
function TEDBImage.GetDataField: string;
|
|
begin
|
|
Result := FDataLink.FieldName;
|
|
end;
|
|
|
|
procedure TEDBImage.SetDataField(const Value: string);
|
|
begin
|
|
FDataLink.FieldName := Value;
|
|
end;
|
|
|
|
function TEDBImage.GetReadOnly: Boolean;
|
|
begin
|
|
Result := FDataLink.ReadOnly;
|
|
end;
|
|
|
|
procedure TEDBImage.SetReadOnly(Value: Boolean);
|
|
begin
|
|
FDataLink.ReadOnly := Value;
|
|
end;
|
|
|
|
function TEDBImage.GetField: TField;
|
|
begin
|
|
Result := FDataLink.Field;
|
|
end;
|
|
|
|
function TEDBImage.GetPalette: HPALETTE;
|
|
begin
|
|
Result := 0;
|
|
if FPicture.Graphic <> nil then
|
|
Result := FPicture.Graphic.Palette;
|
|
{TGraphic has a property Pallete read GetPalette. and GetPalette is Virtual
|
|
Desendants re-implements GetPalette so I don't need ask what kind of Graphic is stored}
|
|
end;
|
|
|
|
procedure TEDBImage.SetAutoDisplay(Value: Boolean);
|
|
begin
|
|
if FAutoDisplay <> Value then
|
|
begin
|
|
FAutoDisplay := Value;
|
|
if Value then LoadPicture;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.SetBorderStyle(Value: TBorderStyle);
|
|
begin
|
|
if FBorderStyle <> Value then
|
|
begin
|
|
FBorderStyle := Value;
|
|
RecreateWnd;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.SetCenter(Value: Boolean);
|
|
begin
|
|
if FCenter <> Value then
|
|
begin
|
|
FCenter := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.SetPicture(Value: TPicture);
|
|
begin
|
|
FPicture.Assign(Value);
|
|
end;
|
|
|
|
procedure TEDBImage.SetStretch(Value: Boolean);
|
|
begin
|
|
if FStretch <> Value then
|
|
begin
|
|
FStretch := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.Paint;
|
|
var
|
|
Size: TSize;
|
|
R: TRect;
|
|
S: string;
|
|
DrawPict: TPicture;
|
|
Form: TCustomForm;
|
|
Pal: HPalette;
|
|
begin
|
|
with Canvas do
|
|
begin
|
|
Brush.Style := bsSolid;
|
|
Brush.Color := Color;
|
|
FillRect(ClientRect);
|
|
if FPictureLoaded or (csPaintCopy in ControlState) then
|
|
begin
|
|
DrawPict := TPicture.Create;
|
|
Pal := 0;
|
|
try
|
|
if (csPaintCopy in ControlState) and Assigned(FDataLink.Field) and FDataLink.Field.IsBlob then
|
|
begin
|
|
DrawPict.Assign(FDataLink.Field);
|
|
if DrawPict.Graphic is TBitmap then
|
|
DrawPict.Bitmap.IgnorePalette := QuickDraw;
|
|
end
|
|
else
|
|
begin
|
|
DrawPict.Assign(Picture);
|
|
if Focused and (DrawPict.Graphic <> nil) and (DrawPict.Graphic.Palette <> 0) then
|
|
begin { Control has focus, so realize the bitmap palette in foreground }
|
|
Pal := SelectPalette(Handle, DrawPict.Graphic.Palette, False);
|
|
RealizePalette(Handle);
|
|
end;
|
|
end;
|
|
if Stretch then
|
|
if (DrawPict.Graphic = nil) or DrawPict.Graphic.Empty then
|
|
FillRect(ClientRect)
|
|
else
|
|
StretchDraw(ClientRect, DrawPict.Graphic)
|
|
else
|
|
begin
|
|
SetRect(R, 0, 0, DrawPict.Width, DrawPict.Height);
|
|
if Center then
|
|
OffsetRect(R, (ClientWidth - DrawPict.Width) div 2, (ClientHeight - DrawPict.Height) div 2);
|
|
StretchDraw(R, DrawPict.Graphic);
|
|
ExcludeClipRect(Handle, R.Left, R.Top, R.Right, R.Bottom);
|
|
FillRect(ClientRect);
|
|
SelectClipRgn(Handle, 0);
|
|
end;
|
|
finally
|
|
if Pal <> 0 then SelectPalette(Handle, Pal, True);
|
|
DrawPict.Free;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
Font := Self.Font;
|
|
if FDataLink.Field <> nil then
|
|
S := FDataLink.Field.DisplayLabel
|
|
else
|
|
S := Name;
|
|
S := '(' + S + ')';
|
|
Size := TextExtent(S);
|
|
R := ClientRect;
|
|
TextRect(R, (R.Right - Size.cx) div 2, (R.Bottom - Size.cy) div 2, S);
|
|
end;
|
|
Form := GetParentForm(Self);
|
|
if (Form <> nil) and (Form.ActiveControl = Self) and
|
|
not (csDesigning in ComponentState) and not (csPaintCopy in ControlState) then
|
|
begin
|
|
Brush.Color := clWindowFrame;
|
|
FrameRect(ClientRect);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.PictureChanged(Sender: TObject);
|
|
begin
|
|
if FPictureLoaded then FDataLink.Modified;
|
|
FPictureLoaded := True;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TEDBImage.Notification(AComponent: TComponent; Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if (Operation = opRemove) and (FDataLink <> nil) and
|
|
(AComponent = DataSource) then DataSource := nil;
|
|
end;
|
|
|
|
procedure TEDBImage.LoadPicture;
|
|
var B: TGraphic;
|
|
Buf: word;
|
|
begin
|
|
with fDatalink do
|
|
if (Field = nil) or not Field.IsBlob or Field.IsNull then
|
|
begin
|
|
Picture.Assign(Nil);
|
|
Exit;
|
|
end;
|
|
|
|
if not FPictureLoaded and (not Assigned(FDataLink.Field)
|
|
or FDataLink.Field.IsBlob) then
|
|
try
|
|
Memoria.Clear;
|
|
TBlobField(Field).SaveToStream(Memoria);
|
|
Memoria.Position :=0;
|
|
B:= nil;
|
|
if Memoria.Size > SizeOf(buf) then
|
|
begin
|
|
Memoria.read(buf, SizeOf(buf));
|
|
case buf of
|
|
$0000 : B := TIcon.Create;
|
|
$0001 : begin
|
|
Picture.Assign(FDataLink.Field);
|
|
Exit;
|
|
end;
|
|
$4D42 : B := TBitmap.Create;
|
|
$CDD7 : B := TMetafile.Create;
|
|
$D8FF : B := TJPEGImage.Create;
|
|
end;
|
|
end;
|
|
Memoria.Position := 0;
|
|
if B <> nil then
|
|
try
|
|
B.LoadFromStream(Memoria);
|
|
except
|
|
B:= nil;
|
|
end;
|
|
//if the stored image is not ico, bmp, wmf, emf, jpg, jpeg
|
|
//or I cant load it then fire the event
|
|
if (b = nil) and Assigned(fonloadCustomImage) then
|
|
try
|
|
memoria.Position := 0;
|
|
fOnLoadCustomImage(B, Memoria);
|
|
except
|
|
B:= nil;
|
|
end;
|
|
|
|
Picture.Assign(B);//B can be NIL, no problem with that
|
|
finally
|
|
B.Free;
|
|
Memoria.Clear;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.DataChange(Sender: TObject);
|
|
begin
|
|
Picture.Graphic := nil;
|
|
FPictureLoaded := False;
|
|
if FAutoDisplay then LoadPicture;
|
|
end;
|
|
|
|
procedure TEDBImage.UpdateData(Sender: TObject);
|
|
var MS: TMemoryStream;
|
|
begin
|
|
if (Picture.Graphic is TBitmap) then
|
|
FDataLink.Field.Assign(Picture.Graphic)
|
|
else
|
|
begin
|
|
MS := TMemoryStream.Create;
|
|
try
|
|
try
|
|
Ms.Clear;
|
|
Picture.Graphic.SaveToStream(MS);
|
|
Ms.Position := 0;
|
|
TBlobField(Fdatalink.field).LoadFromStream(MS);
|
|
except
|
|
FDataLink.Field.Clear;
|
|
end;
|
|
finally
|
|
Ms.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.CopyToClipboard;
|
|
var TempBMP: tbitmap;
|
|
begin
|
|
if Picture.Graphic <> nil then
|
|
if Picture.Graphic is TICon then
|
|
begin
|
|
Tempbmp := Tbitmap.Create;
|
|
tempbmp.Width := Picture.graphic.width;
|
|
tempbmp.Height:= Picture.graphic.Height;
|
|
tempbmp.Canvas.Draw(0,0, Picture.Graphic);
|
|
clipboard.Assign(tempBmp);
|
|
tempbmp.Free;
|
|
end
|
|
else
|
|
Clipboard.Assign(Picture);
|
|
end;
|
|
|
|
procedure TEDBImage.CutToClipboard;
|
|
begin
|
|
if Picture.Graphic <> nil then
|
|
if FDataLink.Edit then
|
|
begin
|
|
CopyToClipboard;
|
|
Picture.Graphic := nil;
|
|
PictureChanged(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.PasteFromClipboard;
|
|
begin
|
|
if fDatalink.edit then
|
|
if ClipBoard.HasFormat(CF_BITMAP) then
|
|
Picture.Bitmap.Assign(Clipboard)
|
|
else
|
|
if ClipBoard.HasFormat(CF_METAFILEPICT)or ClipBoard.HasFormat(CF_ENHMETAFILE) then
|
|
picture.Metafile.Assign(ClipBoard)
|
|
else
|
|
if ClipBoard.hasformat(Cf_picture) then
|
|
picture.Assign(ClipBoard);
|
|
PictureChanged(Self);
|
|
end;
|
|
|
|
procedure TEDBImage.CreateParams(var Params: TCreateParams);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
with Params do
|
|
begin
|
|
if FBorderStyle = bsSingle then
|
|
if NewStyleControls and Ctl3D then
|
|
ExStyle := ExStyle or WS_EX_CLIENTEDGE
|
|
else
|
|
Style := Style or WS_BORDER;
|
|
WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
case Key of
|
|
VK_INSERT: if ssShift in Shift then
|
|
PasteFromClipBoard
|
|
else
|
|
if ssCtrl in Shift then
|
|
CopyToClipBoard;
|
|
VK_DELETE: if ssShift in Shift then
|
|
CutToClipBoard;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.KeyPress(var Key: Char);
|
|
begin
|
|
inherited KeyPress(Key);
|
|
case Key of
|
|
^X: CutToClipBoard;
|
|
^C: CopyToClipBoard;
|
|
^V: PasteFromClipBoard;
|
|
#13: LoadPicture;
|
|
#27: FDataLink.Reset;
|
|
end;
|
|
end;
|
|
|
|
procedure TEDBImage.CMGetDataLink(var Message: TMessage);
|
|
begin
|
|
Message.Result := Integer(FDataLink);
|
|
end;
|
|
|
|
procedure TEDBImage.CMEnter(var Message: TCMEnter);
|
|
begin
|
|
Invalidate; { Draw the focus marker }
|
|
inherited;
|
|
end;
|
|
|
|
procedure TEDBImage.CMExit(var Message: TCMExit);
|
|
begin
|
|
try
|
|
FDataLink.UpdateRecord;
|
|
except
|
|
SetFocus;
|
|
raise;
|
|
end;
|
|
Invalidate; { Erase the focus marker }
|
|
inherited;
|
|
end;
|
|
|
|
procedure TEDBImage.CMTextChanged(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
if not FPictureLoaded then Invalidate;
|
|
end;
|
|
|
|
procedure TEDBImage.WMLButtonDown(var Message: TWMLButtonDown);
|
|
begin
|
|
if TabStop and CanFocus then SetFocus;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TEDBImage.WMLButtonDblClk(var Message: TWMLButtonDblClk);
|
|
begin
|
|
LoadPicture;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TEDBImage.WMCut(var Message: TMessage);
|
|
begin
|
|
CutToClipboard;
|
|
end;
|
|
|
|
procedure TEDBImage.WMCopy(var Message: TMessage);
|
|
begin
|
|
CopyToClipboard;
|
|
end;
|
|
|
|
procedure TEDBImage.WMPaste(var Message: TMessage);
|
|
begin
|
|
PasteFromClipboard;
|
|
end;
|
|
|
|
procedure TEDBImage.WMSize(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
Invalidate;
|
|
end;
|
|
|
|
function TEDBImage.ExecuteAction(Action: TBasicAction): Boolean;
|
|
begin
|
|
Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
|
|
FDataLink.ExecuteAction(Action);
|
|
end;
|
|
|
|
function TEDBImage.UpdateAction(Action: TBasicAction): Boolean;
|
|
begin
|
|
Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
|
|
FDataLink.UpdateAction(Action);
|
|
end;
|
|
|
|
procedure TEDBImage.LoadFromFile(const FileName: string);
|
|
begin
|
|
if Assigned(fDatalink.Field) and fDatalink.Field.IsBlob and fDatalink.Edit then
|
|
begin
|
|
TBlobField(fDatalink.Field).LoadFromFile(FileName);
|
|
PictureChanged(Self);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TEDBImage.SaveToFile(const FileName: string);
|
|
begin
|
|
if FPictureLoaded and Assigned(FDataLink.Field) and FDataLink.Field.IsBlob then
|
|
TBlobField(fDatalink.Field).SaveToFile(FileName);
|
|
end;
|
|
|
|
end.
|