Hi,
The reason your not seeing immediate changes to the Image is because
you're directing your output to a *memory* device context. Specifically,
when you use Image->Canvas->Handle, your accessing the Canvas property of
the TBitmap object contained in the Image; if the Image is empty, a TBitmap
is created for you. The Canvas property of TBitmap returns a pointer to
TBitmapCanvas object whose Handle property returns a handle to a memory
device context (DC). If you then call BitBlt() with this memory DC as the
target DC, you won't see the changes on the screen; rather, you'll need to
instruct the Image to redraw its TBitmap (and thus the changes you made) by
using, e.g., the TImage::Refresh() method or by inciting a redraw the
Image's parent window (e.g., by minimizing and then restoring your form).
In general, it's best to use a TImage only for very simple (and small)
bitmaps. The TImage class is particularly inefficient when rendering
stretched and non-screen-format bitmaps. In your specific case, you don't
really need a TImage because you already have a TBitmap in memory (your
pBitmap's object). As I mentioned, the TImage will create its own bitmap
when you access its Canvas property (unless it contains another TGraphic
type, in which case it will throw an exception upon accessing the Canvas),
and it's a waste of resources to have two bitmaps in memory unless you
really need the second bitmap for processing/restoring. Instead, I'd
suggest you use a TPaintBox object, and then call BitBlt() using the
TPaintBox::Canvas::Handle property. Here's a rough example...
//
// in header...
//
#include <memory>
class TForm1 : public TForm
{
__published:
TPaintBox *PaintBox1;
void __fastcall PaintBox1MouseMove(TObject* Sender,
TShiftState Shift, int X, int Y);
void __fastcall PaintBox1Paint(TObject* Sender);
public:
__fastcall TForm1(TComponent* Owner);
private:
std::auto_ptr<Graphics::TBitmap>Bitmap_;
};
//
// in source...
//
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner), Bitmap_(new Graphics::TBitmap())
{
Bitmap_->PixelFormat = pf24bit;
Bitmap_->Width = 350;
Bitmap_->Height = 350;
PaintBox1->SetBounds(
10, 10, Bitmap_->Width, Bitmap_->Height
);
}
// PaintBox1's OnMouseMove event handler
void __fastcall TForm1::PaintBox1MouseMove(
TObject* Sender,
TShiftState Shift,
int X, int Y
)
{
// draw the stuff to your bitmap...
TCanvas& BmpCanvas = *Bitmap_->Canvas;
BmpCanvas.Pen->Color = clRed;
BmpCanvas.MoveTo(X, Y);
BmpCanvas.LineTo(X + 31, Y);
BmpCanvas.Pen->Color = clBlack;
// define the minimal bounding rect of the area to update
X += PaintBox1->Left; Y += PaintBox1->Top;
TRect const RUpdate(X, Y, X + 31, Y + 1);
// invalidate the window (invokes PaintBox1's OnPaint event)
RedrawWindow(PaintBox1->Parent->Handle, &RUpdate, NULL,
RDW_INVALIDATE | RDW_UPDATENOW);
}
// PaintBox1's OnPaint event handler
void __fastcall TForm1::PaintBox1Paint(
TObject* Sender
)
{
// grab the coordinates of the update rect
TRect const RUpdate = PaintBox1->Canvas->ClipRect;
// render Bitmap_ to PaintBox1
BitBlt(
PaintBox1->Canvas->Handle,
RUpdate.Left, RUpdate.Top,
RUpdate.Width(), RUpdate.Height(),
Bitmap_->Canvas->Handle,
RUpdate.Left, RUpdate.Top,
SRCCOPY
);
}
Note that if you need to deploy your application on systems that might use
256-color mode (or less), you'll need to add code to support palettes. In
addition, tou should also have a look at these two articles in the May '02
issue of the C++Builder Dev. Journal...
* Display-optimal DIB section bitmaps
* Fast bitmap zooming and scrolling
They're available here...
www.bridgespublishing.com/articles/articleindex.htm.
Best of luck,
--
Damon (TeamB)
BCBCAQ -
bcbcaq.bytamin-c.com
b wrote:
Quote
i can see the drawing produced immediatley, i can see it just after
i scroll the image or i cover the TImage by another window...
It seem that it draw really not just with the calling to BitBlt but
after when the form redraw itself...
[...]
BitBlt(Image->Canvas->Handle, 0, 0, row, col, pCanvas->Handle, 0, 0,
SRCCOPY);
{smallsort}