The task was set to the maximum from standard components and elements, to make it “beautiful”.

I made a box with drop-down panels from the memo, painted the Canvas with it, so that it is uniform, but adding a Label to the panel to write at least something, a Label with text is displayed under the canvas and no labels are visible. How to pull the inscription up? Writing on canvas outside will be oh so awkward ...

unit ToggledPanels; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls; type TstorageMemo = class(TMemo) private { Private declarations } PCount: word; {количество Toggl-ов} procedure PPanelCount(Count:word);{заводим количество панелей} procedure WMPaint(var Msg: TMessage); message WM_Paint;{отрисовка} protected { Protected declarations } public { Public declarations } TGLineHeight: Word; published { Published declarations } property PanelCount: word write PPanelCount; constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; TToggledLabel = class; TToggledPanel = class(TPanel){сами панельки} private Opened: boolean;{статус открыт/закрыт} TGLineHeight: Word;{пока не используется, высота тогла} ToglText:TToggledLabel;{сюда будем снаружи пихать текст в лэйбл} { Private declarations } procedure WMPaint(var Msg: TMessage); message WM_Paint; protected { Protected declarations } public // Width: word; { Public declarations } published { Published declarations } destructor Destroy; override; constructor Create(AOwner: TComponent); override; procedure Click; override; end; TToggledLabel = class(TLabel) private { Private declarations } protected { Protected declarations } public // Width: word; { Public declarations } published { Published declarations } end; implementation var CountBuf : array of TToggledPanel;{храним количество тогглов} { TstorageMemo } constructor TstorageMemo.Create(AOwner: TComponent); begin inherited; Self.Cursor:= crArrow;{начальные конструкции} Self.Top:= 40; Self.Left:= 40; Self.Height:= 200; Self.Width:= 500; Self.ScrollBars:= ssVertical; Self.Ctl3D:=false; Self.ReadOnly:=true; end; procedure TstorageMemo.PPanelCount(Count: word); var i: word; begin inherited; { собственно создадим и забьем панельками} setlength(CountBuf, Count); PCount:=Count; if Count>0 then for i := 1 to Count do begin CountBuf[i]:= TToggledPanel.Create(Self); CountBuf[i].Parent:= Self; CountBuf[i].AutoSize:=false; CountBuf[i].Width:=Self.Width; CountBuf[i].TGLineHeight:=20; CountBuf[i].Name:='TogglePanel'+inttostr(i); if i > 1 then CountBuf[i].Top:=20*(i-1) else CountBuf[i].Top:=0; end; end; procedure TstorageMemo.WMPaint(var Msg: TMessage); var i: word; begin HideCaret(Self.Handle);{прячем каретку в мемо, она не нужна} for i := 1 to length(CountBuf) do begin{и закрашиваем после раскрытия} тогла if i > 1 then begin CountBuf[i].Top:=CountBuf[i-1].Height+CountBuf[i-1].Top+2; CountBuf[i].ToglText.BringToFront;{попытка выдернуть лэйбл наверх/не работает} end else CountBuf[i].Top:=0; end; inherited; end; constructor TToggledPanel.Create(AOwner: TComponent); begin inherited; Self.Height:=20; Self.Opened:= false; Self.Caption:=''; Self.AutoSize:=True; Self.ParentShowHint:=false; Self.ParentColor:=false; Self.ParentCustomHint:=false; {выставили параметры при создании, теперь создадим внутри лейбл} ToglText:= TToggledLabel.Create(Self); ToglText.Parent:= Self; ToglText.BringToFront; with ToglText do begin Top:=20+5; AutoSize:=true; Width:=Self.Width-20; Height:=40; Left:=10; {текст для примера} Text:='11111111111111111'+#13#10+'2222222222222'+#13#10+'333333333333'; ParentFont:=true; ParentColor:=False; end; end; destructor TToggledPanel.Destroy; begin inherited; end; procedure TToggledPanel.WMPaint(var Msg: TMessage); begin inherited; {заливка после раскрытия} with Self.Canvas do begin Brush.Color:= $00f4a142; end; ExtFloodFill(Self.Canvas.Handle, 0, 0, $00f4a142, FLOODFILLBORDER); end; destructor TstorageMemo.Destroy; var i: word; begin for i := 1 to PCount do CountBuf[i].Destroy; inherited; end; procedure TToggledPanel.Click; var i: word; t:byte; begin {тут собственно раскрытие} if self.Opened then begin self.Height:= self.Height div 7; self.Opened:=false; end else begin i:=self.Height*7; t:=0; while self.Height<i do begin Self.Height:=Self.Height+(t div 2); inc(t); sleep(10); Self.ToglText.BringToFront; Application.ProcessMessages; end; Self.ToglText.BringToFront; self.Opened:=true; end; inherited; end; end. 

Add to the form

 procedure TForm3.FormCreate(Sender: TObject); begin ToggledPanel:= TstorageMemo.Create(Form3); ToggledPanel.Parent:= Form3; ToggledPanel.PanelCount:=2; ToggledPanel.TGLineHeight:=20; end; 

Variant draft, therefore sizes, sv-va, par-ry, etc. in large numbers while exhibited from the inside ... Do not pay attention.

    2 answers 2

    TLabel is inherited from TControl , it has no handle (HWND), it is drawn on the parent's HDC and overlapped by any TWinControl on the same parent. TPanel is the successor of TWinControl -a, with its handle and drawing context.

    Use TStaticText , which is a successor of TWinControl -a.

    • Thanks, as I didn’t do it myself in 10 hours .... And please tell TStaticText , is TStaticText standard? Just put this condition so that all of the standard - Sergey
    • @ Sergey Yes, this is standard Delphi control. - Igor
    • hmm ... the question may not necessarily be in the subject, but with the help of NeedHandle or the like. teams, you can't label get a handle? - Sergey
    • one
      @ Sergey, TLabel is a graphic component - it does not have its own Handle , respectively, it is absolutely impossible to get it. You have already been answered with a recommendation to use TStaticText , which has its own Handle . If there is an irresistible TLabel to use TLabel , then the only way out is to redraw TLabel after each rendering of the panels, which will be very, very dreary. - Dima
    • @ Sergey, note: the TPanel component has the Caption property. It may be possible to use it without increasing the number of components. - Dima

    No, label can lie only in the picture or form. I just put the labels in the array and another 1 did f [1..n] array of bolean recorded their values ​​with clicks. Then I made 0x0 buttons dynamically and wrote code on them. But this is a superstructure, etc.