Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/VCL/Core VCL Classes/TWinControl    [ Add a report in this area ]  
Report #:  50919   Status: Closed
Issues with WM_PAINT handling on Windows Vista
Project:  Delphi Build #:  11.0.2709.7128
Version:    11.0 Submitted By:   Remko Bonte
Report Type:  Basic functionality failure Date Reported:  8/22/2007 12:49:05 PM
Severity:    Infrequently encountered problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    All platforms Internal Tracking #:   254700
Resolution: Fixed (Resolution Comments) Resolved in Build: : 11.0.2791.8981
Duplicate of:  None
Voting and Rating
Overall Rating: (1 Total Rating)
5.00 out of 5
Total Votes: None
Description
Controls derived from the TWinControl control can receive WM_ERASEBKGND and WM_PRINTCLIENT messages send by the VCL, with no device context as the wParam part of the message.

This can cause problems in 3rd party controls that implement the message handler as follows (code from Virtual treeview):

procedure TBaseVirtualTree.WMPrintClient(var Message: TWMPrintClient);
var
  Canvas: TCanvas;
begin
  [..]
  Canvas := TCanvas.Create;
  try
    Canvas.Handle := Message.DC;
  [..]
  
This will raise the 'Canvas does not allow drawing' error.

It only applies to controls with property DoubleBuffered set to true, in themed applications on Windows Vista.
Steps to Reproduce:
Analysis:

A wincontrol receives a WM_PAINT message. If the application is themed, runs on Vista, and the control has DoubleBuffered set to true, then the following code is executed in TWinControl.WMPaint:

[..]
      DC := BeginPaint(Handle, PS);
      try
        PaintBuffer := BeginBufferedPaint(DC, PS.rcPaint,
          BPBF_COMPOSITED, nil, MemDC);
        Perform(WM_ERASEBKGND, MemDC, MemDC);
        Perform(WM_PRINTCLIENT, MemDC, PRF_CLIENT);
[..]

On Vista it is (apparantly) possible that BeginPaint returns a paint struct with an empty rcPaint rectangle.
When this empty rectangle is passed to the BeginBufferedPaint, the function fails and returns a NULL device
context in the MemDC variable. So in the next steps, a WM_ERASEBKGND and a WM_PRINTCLIENT message is sent with no
device context as the wParam part of the message.

I don't know under which circumstances the BeginPaint returns a paint struct with an empty rcPaint rectangle.

Attached to this bugreport is an application that can reproduce this.
Workarounds
Ignore WM_ERASEBKGND and WM_PRINTCLIENT messages with no device context as the wParam part of the message.
Attachment
50919.zip
Comments

None

Server Response from: ETNACODE01