mdlittle
asked on
How to add events / properties to a TImage control
I want to add the following events to a TImage control and have never done it before:
OnKeyDown
OnKeyPress
OnKeyUp
and the following properties:
TabStop
TabOrder
Code sample please.
OnKeyDown
OnKeyPress
OnKeyUp
and the following properties:
TabStop
TabOrder
Code sample please.
Strange question... TImage is not a control and it could never receive focus for user input. This meand that you could never implement such properties with TImage.
Please explain in details what task you are working with and I'll try to provide a solution...
ASKER
OK, I have an image button that I like and works fine. However, my application will use the keyboard more than the mouse and I can not "tab" to this image button or use the enter key to simulate a mouse click.
If you have a solution (keep in mind I have 40 or 50 of these buttons in my application), I will award you the points.
What about the OnKey events?
If you have a solution (keep in mind I have 40 or 50 of these buttons in my application), I will award you the points.
What about the OnKey events?
You should use another component instead of TImage if you wont to handle keyboard events. I'll explore this problem and tell you when I'll get some results. It is interesting for me.
A quick solution. Use TBitBtn instead of TImage. Image must be placed in Glyph property. Define the size of an image such way that it could be larger than the button at least by 1 pixel (have an invisible margin). The button will look like a single image and a color found in the lower left corner if an image will be transparent (it is why the picture must be larger than a button). If you don't wont the picture to be transparent you must use a different color to a border.
Another way is to place a button on the form and set it's Left property to negative value. This will lead the button to hide from user, but it remains active and still could process user input. The next you should specify button's TabOrder and TabStop properties and OnKeyDown, OnKeyPress, OnKeyUp as if it were the image. Also process OnEnter event to make your TImage display a focus (simply using DrawFocusRect(Rect(2, 2, Image1.Width - 2, Image1.Height - 2)) method or another way) and OnExit event to hide focus (may be also DrawFocusRect(Rect(2, 2, Image1.Width - 2, Image1.Height - 2))).
Another way is to place a button on the form and set it's Left property to negative value. This will lead the button to hide from user, but it remains active and still could process user input. The next you should specify button's TabOrder and TabStop properties and OnKeyDown, OnKeyPress, OnKeyUp as if it were the image. Also process OnEnter event to make your TImage display a focus (simply using DrawFocusRect(Rect(2, 2, Image1.Width - 2, Image1.Height - 2)) method or another way) and OnExit event to hide focus (may be also DrawFocusRect(Rect(2, 2, Image1.Width - 2, Image1.Height - 2))).
hi, I haven't tried this before but maybe is possible to this situation: try and create a custom component deriving from TImage and then add the TControl events and properties that you want. I am sorry for not being more specific but I haven't tried this before, and I don't know if it will work. I'll try and find some time to try it out and let you know.
good luck
good luck
The sample Delphi 6 code is here: http://www.serge.dsip.net/downloads/image-button.zip
You could also ask me to re-make it to Delphi 4 (this will take a time).
You could also ask me to re-make it to Delphi 4 (this will take a time).
ysd: Sorry, you are not right. It would be ideal to create a component deriving from both TImage and TControl, but Delphi does not allow multiple inheritance. Another way is to create TImage descendant (component) and implement low-level windows API functions to represent a windowed control. But it is too complex. I suppose that linking TImage to invisible button like I did in my example is an easiest way.
P. S. This idea could be also implemented as component. But now I have no enough time to realize it. Maybe, later...
P. S. This idea could be also implemented as component. But now I have no enough time to realize it. Maybe, later...
Are you just working with a TImage or is it some other sort of control? The problem is a TImage (and other non TWinControls) cannot get focus. (BTW msa2003 TImage apready descends from TControl) I could really easily write you one that could if you like, but if you are using some other type of control (beyond TImage) then that wouldn't help.
A work around you can do without creating descended controls would be to put the TImage on a TPanel and then hide the borders. Then place an TEdit (use Edit / Send to Back) under the TPanel. The reason for the TPanel is your cannot place an image on top of a TWinControl. Now code the TEdit to handle the keyboard events. Since it is behind the TPanel it will never get seen. I would make the image change (maybe put the borders on the TPanel) when the TEdit has focus so the user will know where their cursor is.
That should provide you with the functionality you need and the flexability to use any control for your image rendering you want. If you want a TWinControl descendant Image control that can accept focus, let me know.
A work around you can do without creating descended controls would be to put the TImage on a TPanel and then hide the borders. Then place an TEdit (use Edit / Send to Back) under the TPanel. The reason for the TPanel is your cannot place an image on top of a TWinControl. Now code the TEdit to handle the keyboard events. Since it is behind the TPanel it will never get seen. I would make the image change (maybe put the borders on the TPanel) when the TEdit has focus so the user will know where their cursor is.
That should provide you with the functionality you need and the flexability to use any control for your image rendering you want. If you want a TWinControl descendant Image control that can accept focus, let me know.
JimMcKeeth: your solution is too complex. First, uf the image plays a role of button, maybe it is better to use TButton as an event handler (just like I realized in http://www.serge.dsip.net/downloads/image-button.zip ). Next, my example TImage IS NOT a TWinControl descendant, it just uses TButton component as an event handler, no more (a small trick ;) ). Finally, there is no matter where an event handler component (either TButton or TEdit, or any other TWinControl descendant) is located within the form. But if you will hide it with a TPanel component it will be harder to move/resize it in design-time.
I suggest you to use TGraphicControl.
Hi ginsonic, I'm back at least. Seems you have some Q for me.
sorry for off-topic.
___
Igor
sorry for off-topic.
___
Igor
unit eoImage;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, ExtCtrls;
type
TeoImage = class(TImage)
private { Private declarations }
FTabStop: Boolean;
FTabOrder: Integer;
procedure SetTabStop(Value: Boolean);
procedure SetTabOrder(Value: Integer);
protected { Protected declarations }
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
public { Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published { Published declarations }
property TabStop: Boolean read FTabStop write SetTabStop default False;
property TabOrder: Integer read FTabOrder write SetTabOrder default 0;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('EsoftB G', [TeoImage]);
end;
constructor TeoImage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
with Constraints do
begin
MinHeight := 32;
MinWidth := 32;
end;
Height := 64;
Width := 96;
end;
procedure TeoImage.SetTabStop(Value: Boolean);
begin
FTabStop := Value;
end;
procedure TeoImage.SetTabOrder(Value : Integer);
begin
// you need to write code here ......
FTabOrder := Value;
end;
procedure TeoImage.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
// you need to write code here ......
end;
procedure TeoImage.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
BringToFront; // may be
// you need to write code here ......
end;
procedure TeoImage.MouseMove(Shift: TShiftState; X, Y: Integer); //override;
begin
// you need to write code here ......
end;
destructor TeoImage.Destroy;
begin
inherited Destroy;
end;
end.
interface
uses
Windows, Messages, SysUtils, Classes, Controls, ExtCtrls;
type
TeoImage = class(TImage)
private { Private declarations }
FTabStop: Boolean;
FTabOrder: Integer;
procedure SetTabStop(Value: Boolean);
procedure SetTabOrder(Value: Integer);
protected { Protected declarations }
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
public { Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published { Published declarations }
property TabStop: Boolean read FTabStop write SetTabStop default False;
property TabOrder: Integer read FTabOrder write SetTabOrder default 0;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('EsoftB
end;
constructor TeoImage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
with Constraints do
begin
MinHeight := 32;
MinWidth := 32;
end;
Height := 64;
Width := 96;
end;
procedure TeoImage.SetTabStop(Value:
begin
FTabStop := Value;
end;
procedure TeoImage.SetTabOrder(Value
begin
// you need to write code here ......
FTabOrder := Value;
end;
procedure TeoImage.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
// you need to write code here ......
end;
procedure TeoImage.MouseDown(Button:
begin
BringToFront; // may be
// you need to write code here ......
end;
procedure TeoImage.MouseMove(Shift: TShiftState; X, Y: Integer); //override;
begin
// you need to write code here ......
end;
destructor TeoImage.Destroy;
begin
inherited Destroy;
end;
end.
esofdbg: oops... "You need to write code here" does not seem to be a complete solution ;)
ASKER
All great solutions but not really work for me. msa2000, your solution would not work because I cannot have 50 duplicate buttons as your code suggests. esoftbg, I already have mouseover, etc. I need OnKeyDown, Press and Up as my question states. JimMcKeeth, I am using ImgBtn already and was wondering if the envents I listed above could be added to this control:
http://www.delphi32.com/vcl/248/
This button works great execpt for the above events/properties.
Suggestions??
http://www.delphi32.com/vcl/248/
This button works great execpt for the above events/properties.
Suggestions??
mdlittle wants to add the following events to a TImage control and have never done it before:
OnKeyDown
OnKeyPress
OnKeyUp
and the following properties:
TabStop
TabOrder
Code sample please.
I HAVE NOT BEEN WRITE A COMPLETE SOLUTION ! I JUST HAVE BEEN SHOW THE EXAMPLE. I DON'T KNOW WHAT HE WANTS TO DO WITH EVENTS AND PROPERTIES. I JUST HAVE BEEN SHOW THE WAY FOR CREATING NEW EVENTS AND PROPERTIES.
OnKeyDown
OnKeyPress
OnKeyUp
and the following properties:
TabStop
TabOrder
Code sample please.
I HAVE NOT BEEN WRITE A COMPLETE SOLUTION ! I JUST HAVE BEEN SHOW THE EXAMPLE. I DON'T KNOW WHAT HE WANTS TO DO WITH EVENTS AND PROPERTIES. I JUST HAVE BEEN SHOW THE WAY FOR CREATING NEW EVENTS AND PROPERTIES.
here will be component I made for you:
http://www.grava.lv/files/pro/imgex.zip
you should only change in you units and dfm's class name from TImage to TImageEx - all properties must remain (at least I think so).
it's half an hour work - if something don't work tell me and I will fix it.
wbr, mo.
http://www.grava.lv/files/pro/imgex.zip
you should only change in you units and dfm's class name from TImage to TImageEx - all properties must remain (at least I think so).
it's half an hour work - if something don't work tell me and I will fix it.
wbr, mo.
ASKER
How about this - If someone can add the events and properties to this control then I will award them 2000 points. I will create 3 other questions worth 2000 points if you can add:
OnKeyDown
OnKeyPress
OnKeyUp
and the following properties:
TabStop
TabOrder
to this control:
http://www.delphi32.com/vcl/248/
OnKeyDown
OnKeyPress
OnKeyUp
and the following properties:
TabStop
TabOrder
to this control:
http://www.delphi32.com/vcl/248/
Ok, I changed it to descend from TBitBtn instead of TImage. I think this satisfies what you are looking for. If not let me know because I have another idea for how to do it, but it would require more changes.
http://www.bsdg.org/downloads/ImgBtn.zip
http://www.bsdg.org/downloads/ImgBtn.zip
My sample http://www.serge.dsip.net/downloads/image-button.zip has already implemented two solutions: TImage and TBitBtn.
Now I have no time... sorry. I'll be back.
Now I have no time... sorry. I'll be back.
ASKER
Jim ,the pic, picdown and picup don't seem to work?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I'll continue testing.
ASKER
msa2000:
This is EXACTLY what I needed. Very Cool. Double click is not working. Is this something I can fix.
I will award you the points and create 3 more question worth 500 points each. Can you fix the double click?
send me your email address to mike@little.tv and I will send you the 3 other question numbers. You will need to post a response to the question so I can award the points.
Thanks so much for you help.
This is EXACTLY what I needed. Very Cool. Double click is not working. Is this something I can fix.
I will award you the points and create 3 more question worth 500 points each. Can you fix the double click?
send me your email address to mike@little.tv and I will send you the 3 other question numbers. You will need to post a response to the question so I can award the points.
Thanks so much for you help.
mdlittle: I disabled doubleclicks myself to fix the following bug: if the user double clicks on the image and does not release a mouse button the image turns to initial state unlike a default TButton. If you need to remove this fix, just comment a string in ImgBtn.pas (#114, in TImgBtn constructor):
Self.ControlStyle := Self.ControlStyle - [csDoubleClicks];
Also I found a little bug and I'll fix it soon. Now TImgBtn does not process OnKeyDown, OnKeyPress and OnKeyUp events if it had received "focus" by mouseclick (because actually it is not a control).
Another bug I found (inherited from http://www.delphi32.com/vcl/248/ original unit) is that the button becomes initially "PicUp" if "Picture" property is not defined until you move a mouse pointer over it. Please respond if you had experienced such problem.
My e-mail address is msa@dsip.net (also declared in the head of updated ImgBtn.pas). Prior to give me extra points please assure that it is 100% legal. Sorry for this comment, but I'm new to this site and don't know some rules. I had already declined Mocarts's points (sorry and thanx) because I was not sure what to do with'em.
Self.ControlStyle := Self.ControlStyle - [csDoubleClicks];
Also I found a little bug and I'll fix it soon. Now TImgBtn does not process OnKeyDown, OnKeyPress and OnKeyUp events if it had received "focus" by mouseclick (because actually it is not a control).
Another bug I found (inherited from http://www.delphi32.com/vcl/248/ original unit) is that the button becomes initially "PicUp" if "Picture" property is not defined until you move a mouse pointer over it. Please respond if you had experienced such problem.
My e-mail address is msa@dsip.net (also declared in the head of updated ImgBtn.pas). Prior to give me extra points please assure that it is 100% legal. Sorry for this comment, but I'm new to this site and don't know some rules. I had already declined Mocarts's points (sorry and thanx) because I was not sure what to do with'em.
I guess I'm a little late to this party. . . but you might can get some Ideas from this
unit PicButton;
interface
uses
Windows, Messages, Classes, Graphics, Controls, Buttons;
type
TMyState = (bsUp, bsDown, bsHigh, bsDisabled);
TPicButton = class(TBitBtn)
private
FCanvas: TCanvas;
FOver: Boolean;
Fbk: TBitBtnKind;
FLayout: TButtonLayout;
FMargin: Integer;
FStyle: TButtonStyle;
FNormalPic, FHiLightPic, FDownPic, FDisabledPic, FGbmp: TBitmap;
procedure setNormal(Value : TBitMap);
procedure setHiLight(Value : TBitMap);
procedure setDown(Value : TBitMap);
procedure setDisabled(Value : TBitmap);
procedure DrawItem(const DrawItemStruct: TDrawItemStruct);
procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
protected
property Action;
property Cancel;
property Default;
property Glyph: TBitmap read FGbmp write FGbmp;
property Kind: TBitBtnKind read Fbk write Fbk;
property Layout: TButtonLayout read FLayout write FLayout default blGlyphLeft;
property Margin: Integer read FMargin write FMargin;
property ModalResult;
property NumGlyphs: Integer read FMargin write FMargin;
property Style: TButtonStyle read FStyle write FStyle;
property Spacing: Integer read FMargin write FMargin;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property PicNormal : TBitMap read FNormalPic write setNormal;
property PicHiLight : TBitMap read FHiLightPic write setHiLight;
property PicPushed : TBitMap read FDownPic write setDown;
property PicDisabled : TBitmap read FDisabledPic write setDisabled;
property Caption;
property Enabled;
property ParentShowHint;
property ParentBiDiMode;
property ShowHint;
property TabOrder;
property TabStop;
property Visible;
property OnEnter;
property OnExit;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Sample s', [TPicButton]);
end;
constructor TPicButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle:= ControlStyle - [csSetCaption];
FCanvas := TCanvas.Create;
FOver := False;
FNormalPic := TBitMap.Create;
FHiLightPic := TBitmap.Create;
FDownPic := TBitmap.Create;
FDisabledPic := TBitmap.Create;
end;
destructor TPicButton.Destroy;
begin
inherited Destroy;
FCanvas.Free;
FNormalPic.Free;
FHiLightPic.Free;
FDownPic.Free;
FDisabledPic.Free;
end;
procedure TPicButton.setNormal(Value : TBitMap);
begin
FNormalPic.Assign(Value);
if not FNormalPic.Empty then
begin
Height := FNormalPic.Height;
Width := FNormalPic.Width;
end;
Invalidate;
end;
procedure TPicButton.setHiLight(Valu e: TBitMap);
begin
FHiLightPic.Assign(Value);
end;
procedure TPicButton.setDown(Value: TBitMap);
begin
FDownPic.Assign(Value);
end;
procedure TPicButton.setDisabled(Val ue: TBitMap);
begin
FDisabledPic.Assign(Value) ;
end;
procedure TPicButton.CNMeasureItem(v ar Message: TWMMeasureItem);
begin
with Message.MeasureItemStruct^ do
begin
itemWidth := Width;
itemHeight := Height;
end;
end;
procedure TPicButton.CNDrawItem(var Message: TWMDrawItem);
begin
DrawItem(Message.DrawItemS truct^);
end;
procedure TPicButton.CMTextChanged(v ar Message: TMessage);
begin
Invalidate;
end;
procedure TPicButton.CMMouseLeave(va r Message: TMessage);
begin
FOver := False;
if Enabled then
Invalidate;
end;
procedure TPicButton.CMMouseEnter(va r Message: TMessage);
begin
FOver := True;
if Enabled then
Invalidate;
end;
procedure TPicButton.DrawItem(const DrawItemStruct: TDrawItemStruct);
var
IsDown, IsFocus: Boolean;
State: TMyState;
cRect: TRect;
Pic: TBitmap;
begin
FCanvas.Handle := DrawItemStruct.hDC;
cRect := ClientRect;
with DrawItemStruct do
begin
IsDown := itemState and ODS_SELECTED <> 0;
IsFocus := itemState and ODS_FOCUS <> 0;
if not Enabled then State := bsDisabled
else if IsDown then State := bsDown
else if FOver then
State := bsHigh else
State := bsUp;
end;
FCanvas.Font := Self.Font;
FCanvas.Brush.Style := bsClear;
case State of
bsUp: Pic := FNormalPic;
bsDown: begin
if FDownPic.Empty then Pic := FHiLightPic else Pic := FDownPic;
cRect := Rect(2,2,Width+2,Height+2)
end;
bsHigh: Pic := FHiLightPic;
bsDisabled: begin
Pic := FDisabledPic;
FCanvas.Font.Color := clSilver;
end;
else Pic := FNormalPic;
end;
if Pic.Empty and (Not FNormalPic.Empty) then
Pic := FNormalPic;
if not Pic.Empty then
FCanvas.Draw(0,0,Pic);
if Length(Caption) > 0 then
DrawText(FCanvas.Handle,PC har(Captio n),-1,cRec t,DT_SINGL ELINE or DT_VCENTER or DT_CENTER);
if IsFocus then
begin
cRect := ClientRect;
InflateRect(cRect, -4, -4);
FCanvas.Pen.Color := clWindowFrame;
FCanvas.Brush.Color := clBtnFace;
DrawFocusRect(FCanvas.Hand le, cRect);
end;
FCanvas.Handle := 0;
end;
procedure TPicButton.CMFontChanged(v ar Message: TMessage);
begin
inherited;
Invalidate;
end;
procedure TPicButton.CMEnabledChange d(var Message: TMessage);
begin
inherited;
Invalidate;
end;
end.
- - - - - - - - - - - - - - - - - - - - - - - -
This is sort of put together, but gives you something to look at, for double clicks you might use the -
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk);
message WM_LBUTTONDBLCLK;
unit PicButton;
interface
uses
Windows, Messages, Classes, Graphics, Controls, Buttons;
type
TMyState = (bsUp, bsDown, bsHigh, bsDisabled);
TPicButton = class(TBitBtn)
private
FCanvas: TCanvas;
FOver: Boolean;
Fbk: TBitBtnKind;
FLayout: TButtonLayout;
FMargin: Integer;
FStyle: TButtonStyle;
FNormalPic, FHiLightPic, FDownPic, FDisabledPic, FGbmp: TBitmap;
procedure setNormal(Value : TBitMap);
procedure setHiLight(Value : TBitMap);
procedure setDown(Value : TBitMap);
procedure setDisabled(Value : TBitmap);
procedure DrawItem(const DrawItemStruct: TDrawItemStruct);
procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
protected
property Action;
property Cancel;
property Default;
property Glyph: TBitmap read FGbmp write FGbmp;
property Kind: TBitBtnKind read Fbk write Fbk;
property Layout: TButtonLayout read FLayout write FLayout default blGlyphLeft;
property Margin: Integer read FMargin write FMargin;
property ModalResult;
property NumGlyphs: Integer read FMargin write FMargin;
property Style: TButtonStyle read FStyle write FStyle;
property Spacing: Integer read FMargin write FMargin;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property PicNormal : TBitMap read FNormalPic write setNormal;
property PicHiLight : TBitMap read FHiLightPic write setHiLight;
property PicPushed : TBitMap read FDownPic write setDown;
property PicDisabled : TBitmap read FDisabledPic write setDisabled;
property Caption;
property Enabled;
property ParentShowHint;
property ParentBiDiMode;
property ShowHint;
property TabOrder;
property TabStop;
property Visible;
property OnEnter;
property OnExit;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Sample
end;
constructor TPicButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle:= ControlStyle - [csSetCaption];
FCanvas := TCanvas.Create;
FOver := False;
FNormalPic := TBitMap.Create;
FHiLightPic := TBitmap.Create;
FDownPic := TBitmap.Create;
FDisabledPic := TBitmap.Create;
end;
destructor TPicButton.Destroy;
begin
inherited Destroy;
FCanvas.Free;
FNormalPic.Free;
FHiLightPic.Free;
FDownPic.Free;
FDisabledPic.Free;
end;
procedure TPicButton.setNormal(Value
begin
FNormalPic.Assign(Value);
if not FNormalPic.Empty then
begin
Height := FNormalPic.Height;
Width := FNormalPic.Width;
end;
Invalidate;
end;
procedure TPicButton.setHiLight(Valu
begin
FHiLightPic.Assign(Value);
end;
procedure TPicButton.setDown(Value: TBitMap);
begin
FDownPic.Assign(Value);
end;
procedure TPicButton.setDisabled(Val
begin
FDisabledPic.Assign(Value)
end;
procedure TPicButton.CNMeasureItem(v
begin
with Message.MeasureItemStruct^
begin
itemWidth := Width;
itemHeight := Height;
end;
end;
procedure TPicButton.CNDrawItem(var Message: TWMDrawItem);
begin
DrawItem(Message.DrawItemS
end;
procedure TPicButton.CMTextChanged(v
begin
Invalidate;
end;
procedure TPicButton.CMMouseLeave(va
begin
FOver := False;
if Enabled then
Invalidate;
end;
procedure TPicButton.CMMouseEnter(va
begin
FOver := True;
if Enabled then
Invalidate;
end;
procedure TPicButton.DrawItem(const DrawItemStruct: TDrawItemStruct);
var
IsDown, IsFocus: Boolean;
State: TMyState;
cRect: TRect;
Pic: TBitmap;
begin
FCanvas.Handle := DrawItemStruct.hDC;
cRect := ClientRect;
with DrawItemStruct do
begin
IsDown := itemState and ODS_SELECTED <> 0;
IsFocus := itemState and ODS_FOCUS <> 0;
if not Enabled then State := bsDisabled
else if IsDown then State := bsDown
else if FOver then
State := bsHigh else
State := bsUp;
end;
FCanvas.Font := Self.Font;
FCanvas.Brush.Style := bsClear;
case State of
bsUp: Pic := FNormalPic;
bsDown: begin
if FDownPic.Empty then Pic := FHiLightPic else Pic := FDownPic;
cRect := Rect(2,2,Width+2,Height+2)
end;
bsHigh: Pic := FHiLightPic;
bsDisabled: begin
Pic := FDisabledPic;
FCanvas.Font.Color := clSilver;
end;
else Pic := FNormalPic;
end;
if Pic.Empty and (Not FNormalPic.Empty) then
Pic := FNormalPic;
if not Pic.Empty then
FCanvas.Draw(0,0,Pic);
if Length(Caption) > 0 then
DrawText(FCanvas.Handle,PC
if IsFocus then
begin
cRect := ClientRect;
InflateRect(cRect, -4, -4);
FCanvas.Pen.Color := clWindowFrame;
FCanvas.Brush.Color := clBtnFace;
DrawFocusRect(FCanvas.Hand
end;
FCanvas.Handle := 0;
end;
procedure TPicButton.CMFontChanged(v
begin
inherited;
Invalidate;
end;
procedure TPicButton.CMEnabledChange
begin
inherited;
Invalidate;
end;
end.
- - - - - - - - - - - - - - - - - - - - - - - -
This is sort of put together, but gives you something to look at, for double clicks you might use the -
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk);
message WM_LBUTTONDBLCLK;
Now please check an updated version at http://www.serge.dsip.net/downloads/ImgBtn.zip . I fixed two bugs in my code (one of them is listed below, another one was related to picture-changing logic). I still could not fix two bugs inherited from the original version: doubleclick bug and the bug of empty "Picture" property. First of them could be fixed by disabling double clicking (which will allow the control to process last MouseDown). Last of them is related to Delphi internal bug (I tried Delphi 6/7) which leads the "Picture" property to change at design-time.
ASKER
MSA:
New button is broken. When the mouse is over one button the previous button still shows focused. It appears that the mouse and keys are working independant of each other. Also, key press does not change the image to the picdown image. Am I doing something wrong?
New button is broken. When the mouse is over one button the previous button still shows focused. It appears that the mouse and keys are working independant of each other. Also, key press does not change the image to the picdown image. Am I doing something wrong?
just a sugestion, you should really not use a TImage for a picture button component, you may have lots of problems trying to get normal button behavior, if you want button behavior then derive your component from a some button,
ASKER
Slick812,
I really dont care what it is derived from. I just cant believe that there are no buttons available that support the following:
Transparent png images (not just bitmaps)
I use TPNGImage (get it at http://pngdelphi.sourceforge.net) and it turns any image desendant into supporting PNG images. I really need this. I also need mouse enter and leave events, tab, keypress, keyup,etc. The control I linked above support this but does not support key enter, etc.
HELP!!!!!
I really dont care what it is derived from. I just cant believe that there are no buttons available that support the following:
Transparent png images (not just bitmaps)
I use TPNGImage (get it at http://pngdelphi.sourceforge.net) and it turns any image desendant into supporting PNG images. I really need this. I also need mouse enter and leave events, tab, keypress, keyup,etc. The control I linked above support this but does not support key enter, etc.
HELP!!!!!
mdlittle: I will process your request in 2-4 hours. You may send me a source with a bug so it could be not so complex for me to locate it.
mdlittle:
> When the mouse is over one button the previous button still shows focused
It is a normal state. When you move mouse over the button it doesn't receive focus. Any control receives focus after mouse left button click or "Tab" key press. I also realized this.
If you would like the "MouseOver" event to cause the button to get focus, try the following in ImgBtn.pas:
procedure TImgBtn.WMMouseEnter( var Msg: TWMMouse );
begin
if not FSupported then Exit;
FEntered := True;
if FDown then Picture := FPicDown else Picture := FPicUp;
if Assigned( FOnMouseEnter ) then FOnMouseEnter( Msg );
FButton.SetFocus;
end;
> I use TPNGImage (get it at http://pngdelphi.sourceforge.net) and it turns any image desendant into supporting PNG images. I really need this.
The easy way is to use BMP's with ImgBtn "Transparency" property turned to "true". Also this will decrease calculation times and increase stability. If you care about executable size, just pack it usind UPX or another Win32 EXE-packer.
I had also downloaded pngimage143.zip from http://pngdelphi.sourceforge.net/ but did not explored it yet.
> When the mouse is over one button the previous button still shows focused
It is a normal state. When you move mouse over the button it doesn't receive focus. Any control receives focus after mouse left button click or "Tab" key press. I also realized this.
If you would like the "MouseOver" event to cause the button to get focus, try the following in ImgBtn.pas:
procedure TImgBtn.WMMouseEnter( var Msg: TWMMouse );
begin
if not FSupported then Exit;
FEntered := True;
if FDown then Picture := FPicDown else Picture := FPicUp;
if Assigned( FOnMouseEnter ) then FOnMouseEnter( Msg );
FButton.SetFocus;
end;
> I use TPNGImage (get it at http://pngdelphi.sourceforge.net) and it turns any image desendant into supporting PNG images. I really need this.
The easy way is to use BMP's with ImgBtn "Transparency" property turned to "true". Also this will decrease calculation times and increase stability. If you care about executable size, just pack it usind UPX or another Win32 EXE-packer.
I had also downloaded pngimage143.zip from http://pngdelphi.sourceforge.net/ but did not explored it yet.
ASKER
OK Here is a test project. Also I tried your new code and it does not work. Check out the test project here. You only need the ImgBtn control.
http://67.114.155.61/project1.zip
Let me know if you have any problems.
http://67.114.155.61/project1.zip
Let me know if you have any problems.
> Also I tried your new code and it does not work - what the way it does not work?
I'll check your test project.
I'll check your test project.
ASKER
During design time it causes Delphi to crash.
> During design time it causes Delphi to crash.
Strange... I tested it, and all seemed to be OK... It look like a Delphi internal bug.
Strange... I tested it, and all seemed to be OK... It look like a Delphi internal bug.
ASKER
I am talking about the new code you posted above:
procedure TImgBtn.WMMouseEnter( var Msg: TWMMouse );
begin
if not FSupported then Exit;
FEntered := True;
if FDown then Picture := FPicDown else Picture := FPicUp;
if Assigned( FOnMouseEnter ) then FOnMouseEnter( Msg );
FButton.SetFocus;
end;
procedure TImgBtn.WMMouseEnter( var Msg: TWMMouse );
begin
if not FSupported then Exit;
FEntered := True;
if FDown then Picture := FPicDown else Picture := FPicUp;
if Assigned( FOnMouseEnter ) then FOnMouseEnter( Msg );
FButton.SetFocus;
end;
ASKER
I am talking about the new code you posted above:
procedure TImgBtn.WMMouseEnter( var Msg: TWMMouse );
begin
if not FSupported then Exit;
FEntered := True;
if FDown then Picture := FPicDown else Picture := FPicUp;
if Assigned( FOnMouseEnter ) then FOnMouseEnter( Msg );
FButton.SetFocus;
end;
procedure TImgBtn.WMMouseEnter( var Msg: TWMMouse );
begin
if not FSupported then Exit;
FEntered := True;
if FDown then Picture := FPicDown else Picture := FPicUp;
if Assigned( FOnMouseEnter ) then FOnMouseEnter( Msg );
FButton.SetFocus;
end;
Yes. I understand you. I tested this code with Delphi 7 instead of Delphi 6 and found the same problem you described when moving the mouse pointer over the button. It happens because of the same problem I described later. This problem also leads to "Picture" property change from normal "Pic" value to "PicUp" when developer moves mouse pointer over the button at design-time. This problem is inherited from the original version and I still didn't found a solution. I had already placed myself a question https://www.experts-exchange.com/questions/20544204/Determining-if-method-runs-at-design-time.html . If I'll get the answer it is the way to solve the problem.
When I posted a comment you graded as answer, I posted EXACTLY what you asked. A didn't think about the bugs in original code and/or Delphi. Now I need to go deeper and it is complex enough.
When I posted a comment you graded as answer, I posted EXACTLY what you asked. A didn't think about the bugs in original code and/or Delphi. Now I need to go deeper and it is complex enough.
ASKER
I appreciate your help and if you want will award more points. No problem.
you might try a TPicture, instead of a TBitmap in my control
property PicNormal : TPicture read FNormalPic write setNormal;
property PicHiLight : TPicture read FHiLightPic write setHiLight;
property PicPushed : TPicture read FDownPic write setDown;
property PicDisabled : TPicture read FDisabledPic write setDisabled;
I beleave that the TPicture will accept the variour ADD ON Image types like GIF and PNG
property PicNormal : TPicture read FNormalPic write setNormal;
property PicHiLight : TPicture read FHiLightPic write setHiLight;
property PicPushed : TPicture read FDownPic write setDown;
property PicDisabled : TPicture read FDisabledPic write setDisabled;
I beleave that the TPicture will accept the variour ADD ON Image types like GIF and PNG
mdlittle: Don't mention it, I do not need more points. I just wont to say what I do, no more. I'll help you. No problem. I found an answer on my question https://www.experts-exchange.com/questions/20544204/Determining-if-method-runs-at-design-time.html but still had no time to implement if. I'll tell when I do.
Michael:
Well, I put updated version here: http://www.serge.dsip.net/downloads/ImgBtn.zip . Check it. I fixed ALL bugs that I had found. So now it is not a draft. I had COMPLETELY rewritten original functions so now it seems to work more stable. Also I added new properties:
TImgBtn.Default - specifies if the button is default. Now this property is only for design-time (I'll improve it in the future versions). If you will specify a number of default buttons actually only the last will be default allthrough Default property will indicate "True". In future versions I'll add a new PicDefault property which will separately store a picture of a default button state thus letting change "Default" state at runtime.
TImgBtn.MouseFocus - if "true" leads the button to receive focus when the mouse pointer is moved over it. If "true" TImgBtn.PicFocused property is ignored. TImgBtn.PicUp property used instead.
TImgBtn.ProcessDblClicks - if "true" (default) leads a control to procedss double mouse clicks. When "false" makes control interpretate double click as two separate clicks.
P. S. I viewed your example and found it very huge. It seems that internally TPNGImage component stores images like a default BMP's. I suppose that you could use TBitmap or TJPEGImage with TImgBtn.Transparency property to get the same or better results.
Slick812: usage of a descendant of TBitBtn is not the best way. I think that direct TWinControl descendant is better.
Well, I put updated version here: http://www.serge.dsip.net/downloads/ImgBtn.zip . Check it. I fixed ALL bugs that I had found. So now it is not a draft. I had COMPLETELY rewritten original functions so now it seems to work more stable. Also I added new properties:
TImgBtn.Default - specifies if the button is default. Now this property is only for design-time (I'll improve it in the future versions). If you will specify a number of default buttons actually only the last will be default allthrough Default property will indicate "True". In future versions I'll add a new PicDefault property which will separately store a picture of a default button state thus letting change "Default" state at runtime.
TImgBtn.MouseFocus - if "true" leads the button to receive focus when the mouse pointer is moved over it. If "true" TImgBtn.PicFocused property is ignored. TImgBtn.PicUp property used instead.
TImgBtn.ProcessDblClicks - if "true" (default) leads a control to procedss double mouse clicks. When "false" makes control interpretate double click as two separate clicks.
P. S. I viewed your example and found it very huge. It seems that internally TPNGImage component stores images like a default BMP's. I suppose that you could use TBitmap or TJPEGImage with TImgBtn.Transparency property to get the same or better results.
Slick812: usage of a descendant of TBitBtn is not the best way. I think that direct TWinControl descendant is better.
ASKER
msa20003,
Very nice. Thanks for all you help. I am very happy with the performance of the button. If you decide to update the button in the future please email me a copy.
Slick812, I too appreciate all you help but I really can't use a TBitBtn control.
Very nice. Thanks for all you help. I am very happy with the performance of the button. If you decide to update the button in the future please email me a copy.
Slick812, I too appreciate all you help but I really can't use a TBitBtn control.
OK. I think to create a special page within my site. I like this component because it is the first Delphi component I ever made :o)
Good luck!
Good luck!