ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 DrawTo never works
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

tvdien

11 Posts

Posted - Jan 06 2012 :  18:15:46  Show Profile  Reply
Hello,

With 4.0.2, no matter what I do, DrawTo never gets ImageEnView2 to show anything:

ImageEnView1.IO.LoadFromFile('c:\pic\prod.jpg');
ImageEnView1.LayersAdd;
ImageEnView1.IO.LoadFromFile('c:\pic\clos.jpg');
ImageEnView1.DrawTo(ImageEnView2.Bitmap.Canvas);
ImageEnView2.Update;

It doesn't work with TImage either; then it paints all white. What am I doing wrong?

fab

1310 Posts

Posted - Jan 07 2012 :  03:20:37  Show Profile  Reply
Hello,
DrawTo doesn't work because nothing has been still painted in TImageEnView canvas. Painting of loaded images occurs when Paint messages are processed. For example, you could write:
ImageEnView1.IO.LoadFromFile('c:\pic\prod.jpg');
ImageEnView1.LayersAdd;
ImageEnView1.IO.LoadFromFile('c:\pic\clos.jpg');
Application.ProcessMessages();    // <<<<<<<<<<<
ImageEnView1.DrawTo(ImageEnView2.Bitmap.Canvas);
ImageEnView2.Update;
Go to Top of Page

tvdien

11 Posts

Posted - Jan 07 2012 :  05:35:05  Show Profile  Reply
I see, but I'm afraid that there are some risks to calling ProcessMessages(). Is there another way to copy just what the ImageEnView1 looks like now (like DrawTo() does)?
Go to Top of Page

fab

1310 Posts

Posted - Jan 07 2012 :  05:53:45  Show Profile  Reply
Yes, just replace ProcessMessages with:

ImageEnView1.Paint();

Anyway there are several ways to do this task.
Go to Top of Page

tvdien

11 Posts

Posted - Jan 07 2012 :  06:22:35  Show Profile  Reply
I'll give you some background information.

I need to create a composite image; let's say it will be a photo and two logos on top of it. The composite image always has to be 640x640 and the logos have a fixed place. The only thing that can vary, is how the photo is placed within this frame; it can be both scaled and moved.

Perhaps I might be able to do this by only putting a TImageEnView on a form, adding fixed layers for the logos. However, there are more other methods that I would like to add related to these logos, and encapsulation into one TBrandedImage (or so) would be nice.

For that, I could inherit from TImageEnView, but I would have a lot of behavior to take care of, and some separation between GUI and business logic would be nice. Therefore I'm thinking of making a simple TBrandedImage that encapsulates a TImageEnView, and can be shown on another one that I will drop on my form. The TBrandedImage has no parent (Nil), which seems to spoil the Paint() option.

Simply put, I'm looking for the best way to create a new image of what TBrandedImage.TImageEnView would look like on a form, which I can then show on the form. Zooming in on TBrandedImage.TImageEnView, for example, should cause a change in output of TBrandedImage's copy/draw method.

Am I trying do something weird or is this quite simple to do?
Go to Top of Page

fab

1310 Posts

Posted - Jan 07 2012 :  12:20:28  Show Profile  Reply
quote:
Therefore I'm thinking of making a simple TBrandedImage that encapsulates a TImageEnView, and can be shown on another one that I will drop on my form.


Encapsulation is my preferred way (rather than inheritance), especially if you don't want to expose all TImageEnView methods/properties. However, this is your choice.

I can only suggest to look at TImageEnView.BackBuffer (a TBitmap) property, that contains the result of the rendering.

Go to Top of Page

tvdien

11 Posts

Posted - Jan 08 2012 :  14:51:06  Show Profile  Reply
Thanks for your suggestions.

In the end I decided to make it a component, inherited from TCustomControl, which embeds a TImageEnView. In its constructor I initialize it as follows:

FImageEnView := TImageEnView.Create(Self);
FImageEnView.Parent := Self;
FImageEnView.Align := alClient;

In this way, I never need to do any copying between canvases and so on. However, double buffering doesn't work properly now. I set FImageEnView.DoubleBuffer to True and also on the inherited DoubleBuffered property of my own component. Still, when I put TMyComponent on a form and set anchors, resizing the window looks all but smooth. Why is this happening? I haven't done anything with the Paint procedure; should I implement some other layer of my own double buffering, unlikely of doing a better job than you guys did with TImageEnView?
Go to Top of Page

tvdien

11 Posts

Posted - Jan 09 2012 :  17:11:40  Show Profile  Reply
Ignoring WM_ERASEBKGND seems to do a good job of solving this. Other thoughts are still welcome, though.
Go to Top of Page

fab

1310 Posts

Posted - Jan 11 2012 :  14:21:08  Show Profile  Reply
Here is my thoughts (I don't know if these suggestions can actually help):

- TImageEnView inherits from TCustomControl, so maybe you could do the same.

- in the constructor ControlStyle is changed with:
ControlStyle := ControlStyle + [csOpaque, csAcceptsControls, csReplicatable, csNeedsBorderPaint];

- In CreateParams overload WindowsClass.Style is set as:
WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);

- WM_ERASEBKGND is handled with:
procedure TImageEnView.WMEraseBkgnd(var Message: TMessage);
begin
Message.Result := 0;
end;
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: