[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Controlling the available client area of a control

Posted on 2002-07-23
5
Medium Priority
?
567 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
  • 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 400 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

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

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

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Suggested Courses
Course of the Month19 days, 3 hours left to enroll

834 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