Board index » delphi » How do I always paint the ENTIRE client area?

How do I always paint the ENTIRE client area?

I have this MDI form that gets a shaded gradient painted on the client
area when I start the app.  Good enough.  Now, when I create a child
form and move it down far enough to where the scroll bars appear AND I
scroll downward, the repainting does not work.

I subclassed the main form creation and trapped the WM_ERASEBKGD.  On
this message, I execute FillRect on the entire client space (using
TForm.ClientWidth and TForm.ClientHeight).  For some reason, the client
area is not redrawn properly when I scroll.  I get the parts that are
newly shown drawn properly, but not the old parts.

Here is how I call the function(This is the subclassed process):

procedure TfrmMain.ClientWndProc(var Message: TMessage);

  procedure Default;
  begin
    with Message do
      Result := CallWindowProc(FDefClientProc, ClientHandle, Msg,
wParam, lParam);
  end;

begin
    with Message do
        case Msg of
            wm_EraseBkGnd:
                begin
                    PaintGradient(wParam);
                end;
            else
                Default;
        end;
end;

And here is the PaintGradient function:

procedure PaintGradient(DC: hDC);
const
    Shades = 64;
var
    CRect: TRect;
    NewBrush, OldBrush: hBrush;
    x, FillBoxHeight, FillBoxWidth: Integer;
    RectArray: array[1..Shades] of TRect;
    Pen, OldPen: hPen;
    NewShade:           Integer;
    i,j,k,l:            Integer;
begin
    CRect.Left := 0;
    CRect.Right := frmMain.ClientWidth;
    CRect.Top := 0;
    CRect.Bottom := frmMain.ClientHeight;

    // Fill the entire background with a black box
    // The pen is changed to invisible so that the ellipses look smooth
    NewBrush := CreateSolidBrush(RGB(0,0,0));
    Pen := CreatePen(PS_NULL,0,clBlack);
    OldPen := SelectObject(DC,Pen);
    OldBrush := SelectObject(DC, NewBrush);
    FillRect(DC, CRect, NewBrush);

    SelectObject(DC, OldBrush);
    DeleteObject(NewBrush);
    FillBoxHeight := ((frmMain.ClientHeight) div 2) div Shades;
    FillBoxWidth := (((frmMain.ClientWidth) div 2) - 10) div Shades;
    for x := 1 to Shades do begin
        i := ((x - 1) * FillBoxWidth);
        k := frmMain.ClientWidth - ((x - 1) * FillBoxWidth);
        j := ((x - 1) * FillBoxHeight);
        l := frmMain.ClientHeight - ((x - 1) * FillBoxHeight);
        NewShade := ((x * 4) - 1);
        NewBrush := CreateSolidBrush(RGB(0,NewShade,NewShade));
        OldBrush := SelectObject(DC, NewBrush);
        Ellipse(DC, i,j,k,l);
        SelectObject(DC, OldBrush);
        DeleteObject(NewBrush);
    end;
    SelectObject(DC,OldPen);
    DeleteObject(Pen);
end;

I create an ellipsoid burst, where the center of the client area is
brightest.  It looks cool, until I do the scrolling thing I mentioned
above.  The black box that erases all is what I mentioned, but the
ellipses are also left unrefreshed.

Anyone have any ideas?

 

Re:How do I always paint the ENTIRE client area?


Try to subclass WM_PAINT rather than WM_ERASEBKGD.

James Jensen <jjens...@midsouth.rr.com> a crit dans l'article
<3657BE45.DD690...@midsouth.rr.com>...

Quote

> I subclassed the main form creation and trapped the WM_ERASEBKGD.

Re:How do I always paint the ENTIRE client area?


Well, that doesn't work with a MDI form.  WM_Paint doesn't occur often
enough.  Plus, it only paints the area of the screen that is
invalidated.  I was able, however, to get it to work by trapping
WM_ERASEBKGD and WM_SYSCOMMAND in this code:

        case Msg of
            wm_EraseBkGnd:
                begin
                    PaintGradient(wParam);
                end;
            wm_Syscommand:
                begin
                    Default;
                    SysMsg := TWMSysCommand(Message);
                    If ((SysMsg.CmdType and $FFF0) = SC_HSCROLL) or
((SysMsg.CmdType and $FFF0) = SC_VSCROLL) then begin
                        R := Self.ClientRect;
                        p := @R;
                        if InvalidateRect(ClientHandle,PRect(p),true)
then
                            PaintGradient(Canvas.Handle);
                     end;
                end;

PaintGradient is the routine that paints the pattern on the MDI form.  I
can get most everything, until the screen is scrolled.  THen, I have to
trap that action via the wm_Syscommand message.  If I InvalidateRect the
client area in a wm_Paint message, I do nothing more than send another
wm_Paint message to the application -- infinite paints!

So, this works.  If you have code that works by trapping wm_Paint,
please let me know what you did.

Quote
Arnaud JAN wrote:
> Try to subclass WM_PAINT rather than WM_ERASEBKGD.

Other Threads