Hi Sam,
The 'Picture' common control is meant to be a simple way to insert a static picture inside a form. It's not meant for advanced bitmap manipulation. Same is true of the BitmapResource class, which provides an easy way to make use of bitmaps in your application. Both the Picture control and the BitmapResource class it works with (The data type of the 'image' property) work with files only.
For more advanced image manipulation, you are supposed to use the Bitmap class directly, and handle the loading/unloading of graphics through the
OnLoadGraphics/OnUnloadGraphics virtual methods of the Window class. The BitmapResource class does this automatically (that is why when using a BitmapResource inside a Window, you specify the window to attach the resource to your window). Ecere supports dynamic mode switching of applications, e.g. if the user changes his graphics mode from 16 bit to 32 while your application is running, or can even switch between GDI, OpenGL, Direct3D. This is why you need to think of needing to load graphics or unload graphics at any time, separate from window creation/destruction.
There are two possible solutions to your problem. I'll start with the original way to do this, we'll make a
BitmapPicture control that will work exactly the way you wanted. The second way is because I've hit myself to the same problem a year or two ago and I came up with a nice hack: a virtual file in memory.
Solution #1: A new class of Picture control
So we'll start with the BitmapPicture control, here's the code for the class:
Code: Select all
class BitmapPicture : Window
{
Bitmap bitmap;
Bitmap ddBitmap { };
public property Bitmap image
{
set
{
delete bitmap;
bitmap = value;
incref bitmap;
if(created)
{
OnUnloadGraphics();
OnLoadGraphics();
}
}
get { return bitmap; }
}
~BitmapPicture()
{
delete bitmap;
}
void OnRedraw(Surface surface)
{
surface.Stretch /*Filter*/(ddBitmap, 0, 0, 0, 0, clientSize.w, clientSize.h, ddBitmap.width, ddBitmap.height);
}
bool OnLoadGraphics()
{
ddBitmap.Copy(bitmap);
ddBitmap.MakeDD(displaySystem);
return true;
}
void OnUnloadGraphics()
{
ddBitmap.Free();
}
}
You see how we define a bitmap property. We take a reference on it, and we'll delete it when the control is destroyed. If the window is already created when we set the bitmap, we manually reload the graphics because the system isn't aware the bitmap needs to be reloaded.
Inside OnLoadGraphics, we make a a Device-Dependent copy of the bitmap in another Bitmap object, '
ddBitmap'. This is going to be in the format most appropriate for the current display driver and mode, for optimal display performance, e.g. a texture loaded on the graphics card in OpenGL or Direct3D mode. We do this by using
Copy() to make a copy, and then
MakeDD() to turn it into a device dependent bitmap. Finally, in OnUnloadGraphics() we free the bitmap with
Free().
We could skip the whole OnLoadGraphics/OnUnloadGraphics/ddBitmap part, and just draw bitmap, but we would lose drawing performance. If we were making an image manipulation program we probably wouldn't do this because the bitmap keeps changing anyways.
We use Surface::Stretch for drawing the bitmap to the control. Filter is a bilinear filtering version of Stretch, it would look nicer but comes with a significant performance cost, especially in GDI mode (Ecere does it in software in that case). At the moment there's no difference between Filter and Stretch in OpenGL/Direct3D mode, Ecere always turns on bilinear filtering for those functions.
Then
'form1.picture1.image=bitmap;' should work.
Solution #2: A Virtual File
To get a virtual File going, we'll need a TempFile object, and we'll use special filename that Ecere understands as being a TempFile, starting with the prefix
"File://" followed by the address of the TempFile object in hexadecimal. We'll use
sprintf with
'%p' (for pointer) to prepare our filename. We can either add a .png extension to our filename, or specify a 'type' when we use the Bitmap::Save method, so that it knows what format to save in. Here is the code:
Code: Select all
class App:GuiApplication
{
TempFile file { };
bool Init()
{
Form1 form1{};
Bitmap bitmap{};
char fileName[100];
sprintf(fileName, "File://%p.png", file);
desktop.Grab(bitmap,null,false);
bitmap.Save(fileName,null,null);
delete bitmap;
form1.picture1.image={fileName};
return true;
}
}
Hope this helps
Regards,
Jerome