Solved

Controlling the available client area of a control

Posted on 2002-07-23
5
551 Views
Last Modified: 2010-10-05
I'm writing a new control that inherits from TCustomPanel and it will draw a Caption area similar to a Form at the top of the panel. However when components are dropped on the panel they can overwrite this Caption area.
Is there someway of controlling the available client area of a control

Thanks

Jo
0
Comment
Question by:nnbbb09
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 7

Expert Comment

by:Cynna
ID: 7172487
Didn't test it, but reducing your component client area should work. To do this, override GetClientRect method like this:



// .....

protected
 function GetClientRect: TRect; override;


// .....

function TmyPanel.GetClientRect: TRect;
begin
  with Result do begin
       Left     := Self.Left;
       Top      := CaptionAreaHeight; // <- this will reduce components client area
       Right    := Self.Width;
       Bottom   := Self.Height;
  end;
end

0
 
LVL 3

Author Comment

by:nnbbb09
ID: 7172830
Tried it for a descendent of TPanel but the painting of the control was very unpredictable.

Jo
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 7173275
An easier way would be to add another TPanel, align it to Top. :)
0
 
LVL 7

Accepted Solution

by:
Cynna earned 100 total points
ID: 7174558

DragonSlayer,

I'm afraid adding another panel, won't prevent other controls from showing on top of it...
This "compound" alternative could for example be made by using 3 panels:
one as a base, second as a caption area (top aligned), and third as
actuall panel body (client aligned). But this, on the other hand,
induces various other complications; for example, "caption area" will
still accept components.

But, if you don't want to use multiple components, caption area must be
a non-client one.


Jo,

OK, let's give it one more try...
It boils down to separating client from non-client area on your panel.

You can choose between two solutions:

a) Easy - let the OS draw fixed caption area for you. You do it like this:

TmyPanel = class(TCustomPanel)
protected
   procedure CreateParams(var Params: TCreateParams); override;

//.....

procedure TmyPanel.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do Style := Style or WS_CAPTION;
end;


b) Harder - you define your own non-client area using WM_NCCALCSIZE (Non-client calculate size) message:

TmyPanel = class(TCustomPanel)
protected
   procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;

//.....

procedure TmyPanel.WMNCCalcSize(var Message: TWMNCCalcSize);
begin
  inherited;
  // Increase non-client area, thus reducing component client area:
  with Message do Inc(CalcSize_Params.rgrc[0].Top, CaptionAreaHeight);
end;

Either solution will add a non-client area to your panel, but solution b)
will let you choose its size (through CaptionAreaHeight variable).
Anyway you choose, you'll have to draw your title bar on this area,
using WM_NCPAINT (Non-client paint) message.


Below is the demo code that exposes you a non-client area canvas that
you can draw on (using b) solution, for example):

TmyPanel = class(TCustomPanel)
protected
   procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
   procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT;

//.....

procedure TmyPanel.WMNCPaint(var Message: TMessage); // handle paint of NC area
var dc:  HDC;
    CACanvas: TCanvas;
begin
  inherited;
  dc := GetWindowDC(Handle);
  CACanvas:=TCanvas.Create;
  with CACanvas do begin
       Handle:=DC;
       // ----- < drawing on Caption area Canvas > -------
       // Do your stuff here...for example:
          Brush.Color := clNavy;
          Rectangle(0, 0, Width, CaptionAreaHeight);
          with Font do begin
              Color:=clYellow;
              Name:='Arial';
              Height:=CaptionAreaHeight-1;
          end;
          TextOut(1,1, 'My special caption');
       // ----- </ drawing on Caption area Canvas > -------
       Handle:=0;
  end;
  ReleaseDC(Handle, dc);
  CACanvas.Free;
end;
0
 
LVL 3

Author Comment

by:nnbbb09
ID: 7175082
Cynna,

I went for the second option. It's a great solution and exactly what I'm looking for.

Thanks

Jo
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question