[lazarus] CVS Updates

Andrew Johnson acjgenius at earthlink.net
Fri Oct 3 20:02:17 EDT 2003


On Fri, 2003-10-03 at 14:43, Micha Nelissen wrote:
> Can you explain this a little more detailed? What is the cause of the 
> flickering exactly? The win32 interface also has this problem.

I am not sure its quite the same issue though it might be.. basically
SynEdit calls ExtTextOut on each block of text, for instance on a line
with 

Procedure MyFunction(someclass : TBlah);

would call ExtTextOut something like 8 times. Now since SynEdit supports
using a different background colour for each block of text, then this
means ExtTextOut will get called with ETO_OPAQUE.

This means that most of the time a block of text calls ExtTextOut, that
block of text will get filled with the current brush before drawing the
text. This means the text essentially disapears from the screen and then
reapears. Since there are so many blocks this results in constant
flashing all over the place every time something is invalidated. So in
this case there are 8 potential flashes any time invalidate/repaint etc.
What I have done in the GTK interface, is if ETO_OPAQUE is passed, I
create a buffer pixmap of the size of the passed rectangle, and perform
actual filling and drawing of text on that offset, then draw pixmap,
meaning the block is drawn in one step to the screen.

I don't know how easily this could be done in win32 since you would have
to create a buffer hdc and hbitmap, calculate relative offsets, based on
whether it was buffering or not, then draw to it, which also means
possibly a fair bit more amount of memory needed etc.

And I don't think CreateCompatibleDC copies pen brush and font info does
it? So you might have to get that and assign it to both. 

Assuming I have a clue the appened is an example of what _might_ work. I
probably made mistakes, I am not sure of the offset etc. I just threw it
together in this e-mail without any double checking or even reading msdn
docs so it may not even compile.... But feel free to try (and fix) at
your own risk :)

Andrew

Function TWin32Object.ExtTextOut(DC: HDC; X, Y: Integer; Options:
Longint; Rect: PRect; Str: PChar; Count: Longint; Dx: PInteger):
Boolean;
var
  Buffered : Boolean;

  Buffer : HDC;
  BufferBitmap : HBitmap;

  bX, bY, bWidth, bHeight : Longint

  BufferDrawRect : TRect;
  DrawRect : LPRect;
  OldBrsh, OldPen, OldFont : hObject;
Begin
  Assert(False, Format('trace:> [TWin32Object.ExtTextOut] DC:0x%x, X:%d,
Y:%d, Options:%d, Str:''%s'', Count: %d', [DC, X, Y, Options, Str,
Count]));

  //Check for opaque flag and buffer if there
  if ((Options and ETO_OPAQUE) <> 0) and Assigned(Rect) then
  begin
    //get DC objects
    OldBrush := SelectObject(DC, GetStockObject(NULL_BRUSH));
    OldPen := SelectObject(DC, GetStockObject(NULL_PEN));
    OldFont := SelectObject(DC, GetStockObject(DEFAULT_GUI_FONT));

    //reset DC objects
    SelectObject(DC, OldBrush);
    SelectObject(DC, OldPen);
    SelectObject(DC, OldFont);

    //Calculate relative size/pos
    bX := X - Rect^.Left;
    bY := Y - Rect^.Top;
    bWidth := Rect^.Right - Rect^.Left;
    bHeight := Rect^.Bottom - Rect^.Top;
    BufferDrawRect := Rect(0, 0, bWidth, bHeight); 
    DrawRect := LPRECT(@BufferDrawRect);

    //Create buffer
    Buffer := CreateCompatibleDC(0); 
    BufferBitmap := CreateCompatibleBitmap(0, bWidth, bHeight); 
    SelectObject(Buffer, BufferBitmap);

    //get buffer objects and set DC objects
    OldBrush := SelectObject(Buffer, OldBrush);
    OldPen := SelectObject(Buffer, OldPen);
    OldFont := SelectObject(Buffer, OldFont);

    buffered := True;
  end else begin
    //Just use Defaults
    Buffer := DC;
    bX := X;
    bY := Y;
    If Asigned(Rect) then
      DrawRect := LPRect(DrawRect)
    else 
      DrawRect := nil;

    buffered := False; 
  end;
  
  //Perform Real ExtTextOut
  Result := Windows.ExtTextOut(Buffer, bX, bY, Options, DrawRect, Str,
Count, Dx);

  If Buffered then begin
    //Blt Buffer to screen
    Windows.BitBlt(DC, X, Y, bWidth, bHeight, Buffer, 0, 0, SRCCOPY);

    //reset buffer objects
    SelectObject(Buffer, OldBrush);
    SelectObject(Buffer, OldPen);
    SelectObject(Buffer, OldFont);

    //free bitmap and dc
    DeleteObject(BufferBitmap);
    DeleteDC(Buffer);
  end;  

  Assert(False, Format('trace:< [TWin32Object.ExtTextOut] DC:0x%x, X:%d,
Y:%d, Options:%d, Str:''%s'', Count: %d', [DC, X, Y, Options, Str,
Count]));
End;






More information about the Lazarus mailing list