Discussion:
DrawText function problems
Lee Jenkins
2008-04-12 22:10:46 UTC
Permalink
Hi all,

I'm having a problem with drawing text on an image using the DrawText function
where the area around the text masked out. Please see the attached image.

This same routine works perfectly in Delphi. Maybe the Canvas.Brush.Style :=
bsClear is not working?

procedure TMyImage.DrawCaption;
var
lRect: TRect;
begin
// setup rect
lRect.Left := 10;
lRect.Top := 10;
lRect.Right := Width -10;
lRect.Bottom := Height -10;
//Canvas.Pen.Style := psClear; // <-- tried this as well
Canvas.Font.Assign(FButtonFont);
Canvas.Brush.Style := bsClear;
DrawText(Canvas.Handle, PChar(FCaption), -1, lRect,
DT_WORDBREAK or DT_VCENTER or DT_CENTER or DT_END_ELLIPSIS);
end;
--
Warm Regards,

Lee
Lee Jenkins
2008-04-12 22:44:15 UTC
Permalink
Post by Lee Jenkins
Hi all,
I'm having a problem with drawing text on an image using the DrawText
function where the area around the text masked out. Please see the
attached image.
This same routine works perfectly in Delphi. Maybe the
Canvas.Brush.Style := bsClear is not working?
procedure TMyImage.DrawCaption;
var
lRect: TRect;
begin
// setup rect
lRect.Left := 10;
lRect.Top := 10;
lRect.Right := Width -10;
lRect.Bottom := Height -10;
//Canvas.Pen.Style := psClear; // <-- tried this as well
Canvas.Font.Assign(FButtonFont);
Canvas.Brush.Style := bsClear;
DrawText(Canvas.Handle, PChar(FCaption), -1, lRect,
DT_WORDBREAK or DT_VCENTER or DT_CENTER or DT_END_ELLIPSIS);
end;
As a follow up, Canvas.TextRect() works, but the output is terrible. See
attached image.
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Lee Jenkins
2008-04-12 23:18:15 UTC
Permalink
Post by Lee Jenkins
Post by Lee Jenkins
Hi all,
I'm having a problem with drawing text on an image using the DrawText
function where the area around the text masked out. Please see the
attached image.
This same routine works perfectly in Delphi. Maybe the
Canvas.Brush.Style := bsClear is not working?
procedure TMyImage.DrawCaption;
var
lRect: TRect;
begin
// setup rect
lRect.Left := 10;
lRect.Top := 10;
lRect.Right := Width -10;
lRect.Bottom := Height -10;
//Canvas.Pen.Style := psClear; // <-- tried this as well
Canvas.Font.Assign(FButtonFont);
Canvas.Brush.Style := bsClear;
DrawText(Canvas.Handle, PChar(FCaption), -1, lRect,
DT_WORDBREAK or DT_VCENTER or DT_CENTER or DT_END_ELLIPSIS);
end;
As a follow up, Canvas.TextRect() works, but the output is terrible.
See attached image.
After some thought, maybe it would be better to just ask:

Is there a workable way to draw centered text onto a TImage that has an image
already assigned to it?

I thought about drawing to the bitmap first, but wanted avoid having to
create/destroy bitmap image so many times.

Thanks,
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Felipe Monteiro de Carvalho
2008-04-13 02:15:03 UTC
Permalink
Post by Lee Jenkins
Is there a workable way to draw centered text onto a TImage that has an image
already assigned to it?
You could just put a label on top of it.

I would usually go for either having a fully custom drawn component,
where I manage all paint, like here:

http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Create_a_custom_control_which_draws_itself

Or, if using a TImage, try to put a label on top of it. I've never
needed to draw to the canvas of a TImage, because I usually use
TCustomControl descendents for complex drawing, but there are
instructions here:

http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Draw_to_a_TImage
Post by Lee Jenkins
I thought about drawing to the bitmap first, but wanted avoid having to
create/destroy bitmap image so many times.
Then cache the TBitmap in the creation of your form and free on it's
destruction.
--
Felipe Monteiro de Carvalho
Lee Jenkins
2008-04-13 02:31:27 UTC
Permalink
Post by Felipe Monteiro de Carvalho
Post by Lee Jenkins
Is there a workable way to draw centered text onto a TImage that has an image
already assigned to it?
You could just put a label on top of it.
I would usually go for either having a fully custom drawn component,
http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Create_a_custom_control_which_draws_itself
Won't I still run into the DrawText problem whether I am having whether I am
trying to draw on a TImage or the canvas of a descendant of TCustomControl?
Post by Felipe Monteiro de Carvalho
Or, if using a TImage, try to put a label on top of it. I've never
needed to draw to the canvas of a TImage, because I usually use
TCustomControl descendents for complex drawing, but there are
http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Draw_to_a_TImage
I had tried this almost 5 days ago I think. The problem is that there is a bug
in TLabel where it does not fire the MouseUp event if you MouseDown and then
move the cursor away from the TLabel before letting go of the mouse.

I'll have a look at the links though. That you very much.
--
Warm Regards,

Lee
Funky Beast
2008-04-13 03:14:13 UTC
Permalink
Post by Lee Jenkins
Post by Felipe Monteiro de Carvalho
I would usually go for either having a fully custom drawn component,
http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Create_a_custom_control_which_draws_itself
Won't I still run into the DrawText problem whether I am having whether I am
trying to draw on a TImage or the canvas of a descendant of TCustomControl?
Nope, TCustomControl provides a canvas for you to draw everything your way and
your style. TImage is a widgetset specific GTKImage or QtImage or Carbon Image or
Win32 Image control (contained in comctrls.dll) component that renders itself
according to the rules of the widgetset it belongs to. So some widgetset's TImage
doesn't have some capabilities that some other widgetset's TImage have. In these
cases its better to draw it yourself with a TCustomControl.

I do many exotic and non-conventional controls by descending from TCustomControl
since Delphi2 days. It obeys you 100% and not the widgetset it binds with.
Its the same concept of fpGUI widgets.


HTH,
Funky Beast
Felipe Monteiro de Carvalho
2008-04-13 09:51:39 UTC
Permalink
Post by Lee Jenkins
I had tried this almost 5 days ago I think. The problem is that there is a bug
in TLabel where it does not fire the MouseUp event if you MouseDown and then
move the cursor away from the TLabel before letting go of the mouse.
Where is the link for the bug report?

Also, this doesn't look like a bug to me, but rather a standard
behavior. Just try any software out there. Clicking, moving the mouse
out and releasing indicates that the user gave up clicking in the
object, so a button, for example, wouldn't be activated by that. The
same for clicking a label.
--
Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho
2008-04-13 09:53:50 UTC
Permalink
On Sun, Apr 13, 2008 at 6:51 AM, Felipe Monteiro de Carvalho > Also,
this doesn't look like a bug to me, but rather a standard
Post by Felipe Monteiro de Carvalho
behavior. Just try any software out there. Clicking, moving the mouse
out and releasing indicates that the user gave up clicking in the
object, so a button, for example, wouldn't be activated by that. The
same for clicking a label.
Clicking and moving away is also a sign for drag and drop, which
doesn't activate the item, but rather places it somewhere else.
--
Felipe Monteiro de Carvalho
Lee Jenkins
2008-04-13 13:26:20 UTC
Permalink
Post by Felipe Monteiro de Carvalho
On Sun, Apr 13, 2008 at 6:51 AM, Felipe Monteiro de Carvalho > Also,
this doesn't look like a bug to me, but rather a standard
Post by Felipe Monteiro de Carvalho
behavior. Just try any software out there. Clicking, moving the mouse
out and releasing indicates that the user gave up clicking in the
object, so a button, for example, wouldn't be activated by that. The
same for clicking a label.
Clicking and moving away is also a sign for drag and drop, which
doesn't activate the item, but rather places it somewhere else.
Even when Auto drag is not set or BeginDrag is not called?
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Lee Jenkins
2008-04-13 13:16:56 UTC
Permalink
Post by Felipe Monteiro de Carvalho
Post by Lee Jenkins
I had tried this almost 5 days ago I think. The problem is that there is a bug
in TLabel where it does not fire the MouseUp event if you MouseDown and then
move the cursor away from the TLabel before letting go of the mouse.
Where is the link for the bug report?
Also, this doesn't look like a bug to me, but rather a standard
behavior. Just try any software out there. Clicking, moving the mouse
out and releasing indicates that the user gave up clicking in the
object, so a button, for example, wouldn't be activated by that. The
same for clicking a label.
My computer went up a few days ago and had to reinstall everything and lost
about 3 weeks worth of emails. If you look back over the last week or so,
you'll see a post that I made about this problem. I think someone (sorry I can
remember exactly who) may have pointed me to a bug report concerning the
SetCapture method in LCL.

As a side note, can anyone tell me where the recent archives are hosted? I
tried googling, but only came up with older messages.

BTW, in Delphi the behavior that I mentioned above is present. Which made it a
simple task to create custom buttons. With the current behavior of Lazarus, it
leave custom buttons made like this in a "visually down" state.
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Felipe Monteiro de Carvalho
2008-04-13 15:35:17 UTC
Permalink
Post by Lee Jenkins
BTW, in Delphi the behavior that I mentioned above is present. Which made it a
simple task to create custom buttons. With the current behavior of Lazarus, it
leave custom buttons made like this in a "visually down" state.
Ahhh ... so this is what this is about?

I would have used a TCustomControl descendent to do that.

Your code works fine in gtk2, the caption is drawn as expected. The
button doesn't go back when the mouse leaves it. Pay attention to how
real system buttons work. It doesn't go back on MouseUp. It goes back
when the mouse leaves the button, so I added a handler for
OnMouseLeave:

procedure TDTImageButton.HandleMouseLeave(Sender: TObject);
begin
HandleMouseUp(Sender, mbLeft, [], 0, 0); // Just a hack, you should
actually have the code from you MouseUp here, and correct your MouseUp
end;

You would also need a handler for OnMouseEnter and some logic to see
again when the mouse goes back to the button to put it down again.

Other hints. You don't need those ifdefs for fpc, so use mode delphi.

In Lazarus you can use LCLIntf and LCLType instead of the WIndows unit.
Post by Lee Jenkins
Even when Auto drag is not set or BeginDrag is not called?
I was just pointing which events may occur with that mouse gesture.
--
Felipe Monteiro de Carvalho
Lee Jenkins
2008-04-13 16:50:21 UTC
Permalink
Post by Felipe Monteiro de Carvalho
Post by Lee Jenkins
BTW, in Delphi the behavior that I mentioned above is present. Which made it a
simple task to create custom buttons. With the current behavior of Lazarus, it
leave custom buttons made like this in a "visually down" state.
Ahhh ... so this is what this is about?
I would have used a TCustomControl descendent to do that.
Probably a better choice, but I have problems using with it with my limited
experience of custom controls so a TImage descendant worked for me, except that
it doesn't paint correctly.
Post by Felipe Monteiro de Carvalho
Your code works fine in gtk2, the caption is drawn as expected. The
button doesn't go back when the mouse leaves it. Pay attention to how
real system buttons work. It doesn't go back on MouseUp. It goes back
when the mouse leaves the button, so I added a handler for
Hmm. Are you saying that OnMouseLeave is called as well when the user releases
the mouse button after clicking down? I didn't know this, I'll give it a try.
Post by Felipe Monteiro de Carvalho
procedure TDTImageButton.HandleMouseLeave(Sender: TObject);
begin
HandleMouseUp(Sender, mbLeft, [], 0, 0); // Just a hack, you should
actually have the code from you MouseUp here, and correct your MouseUp
end;
You would also need a handler for OnMouseEnter and some logic to see
again when the mouse goes back to the button to put it down again.
Other hints. You don't need those ifdefs for fpc, so use mode delphi.
In Lazarus you can use LCLIntf and LCLType instead of the WIndows unit.
Thanks for these tips.
Post by Felipe Monteiro de Carvalho
Post by Lee Jenkins
Even when Auto drag is not set or BeginDrag is not called?
I was just pointing which events may occur with that mouse gesture.
I have managed to use a TImage descendant which doesn't have the problem of not
firing OnMouseUp when the cursor leaves, but the output of DrawText is not
acceptable for some reason. See me post with sample project attachment and
screenshot of the image.
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Lee Jenkins
2008-04-13 14:06:48 UTC
Permalink
Post by Lee Jenkins
Hi all,
I'm having a problem with drawing text on an image using the DrawText
function where the area around the text masked out. Please see the
attached image.
This same routine works perfectly in Delphi. Maybe the
Canvas.Brush.Style := bsClear is not working?
I have attached a small sample application that shows that even though the text
is printed onto the TImage descendant, it is not drawn correctly where the font
is jagged and squeezed together and almost readable.

At first, I couldn't get the Brush.Style to be clear, but after I was able to do
that, the font just will not render correctly. I have attached a screen shot
also that shows what the phone looks like.

I'm on Lazarus 9.24 Vista Business (same behavior on XP Pro though).
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Lee Jenkins
2008-04-13 14:43:47 UTC
Permalink
Post by Lee Jenkins
Post by Lee Jenkins
Hi all,
I'm having a problem with drawing text on an image using the DrawText
function where the area around the text masked out. Please see the
attached image.
This same routine works perfectly in Delphi. Maybe the
Canvas.Brush.Style := bsClear is not working?
I have attached a small sample application that shows that even though
the text is printed onto the TImage descendant, it is not drawn
correctly where the font is jagged and squeezed together and almost
readable.
At first, I couldn't get the Brush.Style to be clear, but after I was
able to do that, the font just will not render correctly. I have
attached a screen shot also that shows what the phone looks like.
Sorry, that should have been "what the image looks like", someone was ringing me
when I was typing. ;)
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Lee Jenkins
2008-04-13 17:58:10 UTC
Permalink
Post by Lee Jenkins
Post by Lee Jenkins
Hi all,
I'm having a problem with drawing text on an image using the DrawText
function where the area around the text masked out. Please see the
attached image.
This same routine works perfectly in Delphi. Maybe the
Canvas.Brush.Style := bsClear is not working?
I have attached a small sample application that shows that even though
the text is printed onto the TImage descendant, it is not drawn
correctly where the font is jagged and squeezed together and almost
readable.
At first, I couldn't get the Brush.Style to be clear, but after I was
able to do that, the font just will not render correctly. I have
attached a screen shot also that shows what the phone looks like.
I'm on Lazarus 9.24 Vista Business (same behavior on XP Pro though).
On closer inspection, it looks like the text is being drawn more than once, but
offset a little. Not sure how that could happen as my code is only being called
once.
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Luiz Americo Pereira Camara
2008-04-12 23:24:33 UTC
Permalink
Post by Lee Jenkins
Hi all,
I'm having a problem with drawing text on an image using the DrawText
function where the area around the text masked out. Please see the
attached image.
This same routine works perfectly in Delphi. Maybe the
Canvas.Brush.Style := bsClear is not working?
There's a bug in Delphi regarding bsClear (
http://www.efg2.com/Lab/OtherProjects/PrinterDemo2.htm
<http://www.lockproxy.info/unblock-sites/index.php?q=uggc%3A%2F%2Fjjj.rst2.pbz%2FYno%2FBgureCebwrpgf%2FCevagreQrzb2.ugz>).
See issues 8455 and 8340 in bug tracker for more info.

Maybe this can help you.

Luiz
Lee Jenkins
2008-04-13 01:57:55 UTC
Permalink
Post by Luiz Americo Pereira Camara
Post by Lee Jenkins
Hi all,
I'm having a problem with drawing text on an image using the DrawText
function where the area around the text masked out. Please see the
attached image.
This same routine works perfectly in Delphi. Maybe the
Canvas.Brush.Style := bsClear is not working?
There's a bug in Delphi regarding bsClear (
http://www.efg2.com/Lab/OtherProjects/PrinterDemo2.htm
<http://www.lockproxy.info/unblock-sites/index.php?q=uggc%3A%2F%2Fjjj.rst2.pbz%2FYno%2FBgureCebwrpgf%2FCevagreQrzb2.ugz>).
See issues 8455 and 8340 in bug tracker for more info.
Maybe this can help you.
Luiz
Thanks for responding, Luiz. I'm not sure what Lazarus is doing here because I
swear sometimes it works and sometimes it doesn't. There doesn't seem to be any
consistency with these kinds of routines.

When it works, the output looks like crap, fat text with jagged edges, ignoring
the Canvas.Font settings completely and when it doesn't work, well it doesn't
work, lol.

I get this kind of off/on functionality with lazarus many times, inexplicable
things that work sometimes and sometimes do not work.

I think the writing is on the wall. I just cannot do this particular
application that I'm trying to do with lazarus because it strays strays too far
from basic components like TEdit, TListBox, TComboBox to be a workable solution
for me with lazarus.

Maybe fpGUI will be workable, I've been playing around with it for the last
couple of days.
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Martin Schreiber
2008-04-13 08:26:09 UTC
Permalink
Post by Lee Jenkins
Maybe fpGUI will be workable, I've been playing around with it for the last
couple of days.
Another alternative is MSEide+MSEgui:
http://sourceforge.net/projects/mseide-msegui

In MSEgui you could use for example a tbutton and assign the image to the
face.image property. To render your custom frame you could use the frame
property where it is possible to define four imagelist items for the corners
and four imagelist items which will be stretched to form the edges of the
button. Every button state has its own group of frame imagelist items. For
even more funky buttons there is trichbutton with additional faces for the
different button states.
Every MSEgui widget has the frame and the face property. There are
tfacetemplate, tframetemplate and tskincontroller in order to centralize skin
settings.

Julio developed a POS system with MSEide+MSEgui with success BTW.
Questions and Bug reports please to NNTP:
news://news.grid-sky.com/public.mseide-msegui.talk

I'd like to repeat the message to the Lazarus devels:
Feel free to use any piece of code out of MSEgui for Lazarus if you find it
useful.

Martin
Lee Jenkins
2008-04-13 19:07:01 UTC
Permalink
Post by Martin Schreiber
Julio developed a POS system with MSEide+MSEgui with success BTW.
news://news.grid-sky.com/public.mseide-msegui.talk
Feel free to use any piece of code out of MSEgui for Lazarus if you find it
useful.
Neat, is that the application used for screenshots on the MSEide & MSEgui/FPC
wiki page?
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Martin Schreiber
2008-04-14 04:48:40 UTC
Permalink
Post by Lee Jenkins
Post by Martin Schreiber
Julio developed a POS system with MSEide+MSEgui with success BTW.
news://news.grid-sky.com/public.mseide-msegui.talk
Feel free to use any piece of code out of MSEgui for Lazarus if you find
it useful.
Neat, is that the application used for screenshots on the MSEide &
MSEgui/FPC wiki page?
No, there is a screenshot in the thread "PNGImageException" from 2008-02-15:
news://news.grid-sky.com/public.mseide-msegui.talk

Martin

Lee Jenkins
2008-04-13 18:46:48 UTC
Permalink
Post by Lee Jenkins
Hi all,
I'm having a problem with drawing text on an image using the DrawText
function where the area around the text masked out. Please see the
attached image.
This same routine works perfectly in Delphi. Maybe the
Canvas.Brush.Style := bsClear is not working?
procedure TMyImage.DrawCaption;
var
lRect: TRect;
begin
// setup rect
lRect.Left := 10;
lRect.Top := 10;
lRect.Right := Width -10;
lRect.Bottom := Height -10;
//Canvas.Pen.Style := psClear; // <-- tried this as well
Canvas.Font.Assign(FButtonFont);
Canvas.Brush.Style := bsClear;
DrawText(Canvas.Handle, PChar(FCaption), -1, lRect,
DT_WORDBREAK or DT_VCENTER or DT_CENTER or DT_END_ELLIPSIS);
end;
Here is the problem that I was having with:

procedure TDTImageButton.HandleMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
lBmp: TBitmap;
begin
if Button = mbLeft then
begin
lBmp := FImageManager.ImageByName(FUpImageName);
Picture.Bitmap.Assign(lBmp);
DrawCaption;
end;
end;

Notice the line:
Picture.Bitmap.Assign(lBmp);

Changing it to
Canvas.Draw(0,0,lBmp);

Fixed the problem. Odd because it works in Delphi, but the .Canvas.Draw
methods doesn't seem to work well in delphi so I ended with this:

procedure TDTImageButton.HandleMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
lBmp: TBitmap;
begin
if Button = mbLeft then
begin
lBmp := FImageManager.ImageByName(FUpImageName);
{$IFDEF fpc}
Canvas.Draw(0,0,lBmp);
{$ELSE}
picture.Bitmap.Assign(lBmp);
{$endif}
DrawCaption;
end;
end;

procedure TDTImageButton.DrawCaption;
var
lRect: TRect;
lBmp: TBitmap;
begin
// setup rect
lRect.Left := 10;
lRect.Top := 10;
lRect.Right := Width -10;
lRect.Bottom := Height -10;
Canvas.Brush.Style := bsClear;
Canvas.Font.Assign(FButtonFont);
DrawText(Picture.Bitmap.Canvas.Handle, PChar(FCaption), -1, lRect,
DT_WORDBREAK or DT_CENTER);

end;

This works well and both methods are fast!
--
Warm Regards,

Lee

"When my company started out, we were really, really, really, really small.
Now...we're just really small."
Loading...