I use Delphi7, PageControl with owner-draw. I can't get so plain and nice look of tabs, as I see on not-owner-drawn PageControls. What's bad: when using owner-draw, I can't draw on "entire" tab header area, small 1-2px frame around tab header is painted by OS.
1) Delphi not owner-draw, look is OK too (XPMan used):
2) Delphi owner-draw, you see not entire tab header can be colored (XPMan used):
I draw current tab with blue and others with white, here. Only example. Code:
procedure TForm1.PageControl1DrawTab(Control: TCustomTabControl;
TabIndex: Integer; const Rect: TRect; Active: Boolean);
var
c: TCanvas;
begin
c:= (Control as TPageControl).Canvas;
if Active then
c.Brush.Color:= clBlue
else
c.Brush.Color:= clWhite;
c.FillRect(Rect);
end;
2b) Delphi owner-draw in real app (XPMan used):
Why do i need to use owner-draw? Simple. To draw X button on tab headers, to paint upper-line with custom color, to paint icons from imagelists.
I'm looking for a way to paint ENTIRE rect of tab headers, not decreased rect which is given to PageControl owner-draw events. I tried to increase the rect given by owner-draw events, but this doesn't help, OS repaints this thin 1-2px frame around tab headers anyway.
The tabs of an owner drawn native "tab control" (
TPageControl
in VCL, although its ascendant is appropriately namedTCustomTabControl
- it is anyone's guess why the creative naming..), is expected to be painted by its parent control while processingWM_DRAWITEM
messages, as documented here.The VCL takes the burden from the parent by mutating the message to a
CN_DRAWITEM
message and sending it to the control itself. In this process the VCL has no further intervention. It just calls theOnDrawTab
message handler if it is assigned by user code, passing appropriate parameters.So, it's not the VCL that draws the borders around tabs, but the OS itself. Also, evidently, it doesn't do this during processing of
WM_DRAWITEM
messages but later in the painting process. You can verify this by putting an emptyWM_DRAWITEM
handler on the parent of a page control. Result is, whatever we paint in the event handler, it will later get borders by the OS.What we might try is to try to prevent what the OS draws take effect, we have the device context (as Canvas.Handle) after all. Unfortunately this route also is a dead end because the VCL, after the event handler returns, restores the device context's state.
The only way, then, we have is to completely abandon handling an
OnDrawTab
event, and acting uponCN_DRAWITEM
message. Below sample code use an interposer class, but you can subclass the control any way you like. Make sure thatOwnerDrawn
is set.Here is how the above looks here: