WPCubed Product Support

OnTextObjectPaint canvas problem

When I use SendMessage(..) in an OnTextObjectPaint event then the drawing on the canvas is all screwed up and/or not visible. I am using WPTools VCL Demo 5.18.1 for Delphi 5.

procedure TFormMain.ButtonInsertImageClick(Sender: TObject);
var
  WPOImage : TWPOImage;
begin
  // insert image
  WPOImage := TWPOImage.Create( WPRichText.Memo.RTFData);
  WPOImage.LoadFromFile( 'test.bmp');
  WPRichText.TextObjects.Insert( WPOImage);
end;

procedure TFormMain.WPRichTextTextObjectPaint(Sender: TObject;
  pobj: TWPTextObj; toCanvas: TCanvas; XRes, YRes, X, Y, W, H,
  BASE: Integer; PageRef: TWPVirtPage; Modes: TWPTextObjectPaintModes;
  const CanvasExtraAttr: TWPPaintExtraParams;
  var ContinueMode: TWPTextObjectPaintResult);
begin
  // enable/disable bug
  if (CheckBoxBug.Checked) then begin
    SendMessage( Self.Handle, WM_USER + 50, 0, 0);
  end;
  // paint object
  if Assigned( pobj) and Assigned( pobj.ObjRef) then begin
    pobj.ObjRef.Paint( toCanvas, Rect( X, Y, X + W, Y + H), pobj, []);
  end;
  // draw red cross over object
  toCanvas.Pen.Color := clRed;
  toCanvas.Pen.Width := MulDiv( 3, XRes, WPScreenPixelsPerInch);
  toCanvas.MoveTo( X, Y);
  toCanvas.LineTo( X + W, Y + H);
  toCanvas.MoveTo( X + W, Y);
  toCanvas.LineTo( X, Y + H);
  // tell WPTools not to paint contents and selection
  ContinueMode := ContinueMode - [wpObjPaintContents] - [wpobjPaintSelection];
end;
#1 ♥ 0
3.6k Views 3 users read 3 min
support

Hi,

Yes, this is not possible. I also had a problem with accessing a litbox (window control) from within this event. I don't know what is causing it but it should be not problem to avoid it.

Julian

#2 ♥ 0

@wpsupport:
Yes, this is not possible. I also had a problem with accessing a litbox (window control) from within this event. I don't know what is causing it but it should be not problem to avoid it.

I decided to look further into this problem now that I have WPTools source code (5.18.1)...

Here is a small snippet of code to show you what is happening.

Bitmap := TBitmap.Create;Handle1 := Bitmap.Canvas.Handle;SendMessage( Self.Handle, xxx, xxx, xxx);Handle2 := Bitmap.Canvas.Handle;Bitmap.Free;

In the code above the value of Handle1 will be different from the value of Handle2. The reason for this is located in the delphi unit graphics.pas and goes by the name of FreeMemoryContexts.

And I quote...

FreeMemoryContexts is called by the VCL main winproc to release memory DCs after every message is processed (garbage collection). Only memory DCs not locked by other threads will be freed.

I tested the "not locked by other threads will be freed" by adding an OutCanvas.Lock and Unlock pair around the PaintRTFPage( xxx, xxx, ...) function call somewhere in unit WPRTEPaint.pas and it worked. The canvas drawing problem was gone.

Do you think that you can apply this solution (lock/unlock) to WPTools?

An alternate solution (I think) would be not to cache the device context handle in a variable but rather access the canvas' handle property directly. That way you are always sure that the handle is valid.

dc := DestCanvas.Handle; // not SendMessage(..) safe!
#3 ♥ 0

Hi,

Thanks for the insight about FreeMemoryContexts.

I think it is best to lock the canvas handle. I use a cached handle because I also use SaveDC/RestoreDC. (Although I have a fallback function which avoids that routines on Win9😎

in PaintDesktop:

OutCanvas.Lock;
try
while startpage < Length(_PaintPages) do
.....
inc(startpage);
end;
finally
OutCanvas.Unlock;
end;

Julian

#4 ♥ 0
This category is archived. No new posts are possible.