Escurecer Formulário Delphi

Criado em: 28 de dezembro de 2024

Respondido usando OpenAI 01 por OpenAI01

Pergunta

Em Delphi, usando VCL, tenho um Panel. Como escurecer todo o restante do form, com exceção do panel? E como fazer isso se o panel for um TscGPPanel, que possui cantos arredondados, sem que fique serrilhado?

Pensamento

Implementando a transparência

Estou trabalhando para adicionar uma camada de transparência no Delphi, com a VCL, escurecendo a interface, exceto o painel. Isso inclui lidar com bordas arredondadas para evitar serrilhado.

Criação de overlay modal

Estou usando um formulário semi-transparente para cobrir o principal. Vou excluir o painel, especialmente os com bordas arredondadas, e aplicar uma camada pintada ou controle TShape para suavizar as bordas.

Aplicando transparência

Proponho usar um formulário transparente com um controle TShape para criar uma camada preta semi-transparente, excluindo a área do painel com bordas arredondadas para evitar serrilhado.

Desenhando a camada

Estou pensando em usar um método OnPaint em uma descendência TPanel, desenhando uma camada preta semi-transparente e excluindo o retângulo do painel com bordas arredondadas. Isso está interessante.

Aprimorando a transparência

Estou pensando em usar um formulário TOverlayForm com TPanel descendente e customização de pintura para uma camada semi-transparente, excluindo a área do painel com bordas arredondadas e bordas lisas.

Aprimorando a transparência

Estou ajustando um formulário TOverlayForm para semi-transparência, com bordas arredondadas e exclusão da área do painel para atingir um efeito visual mais sofisticado.

Escolhendo a abordagem certa

Estou pensando em usar TPaintBox ou TGraphicControl para criar um overlay com um buraco transparente para o painel. É importante lidar com a pintura manualmente em VCL para transparência eficaz.

Aplicando GDI+

Estou pensando em usar GDI+ para criar um controle semitransparente com um buraco transparente para o painel, garantindo bordas suaves e transparência eficaz em Delphi com VCL.

Desenhando a camada de sobreposição

Estou mapeando a criação de uma camada semitransparente com GDI+, pintando um retângulo preto semitransparente e expondo a área do painel com bordas arredondadas.

Desenhando formas arredondadas

Estou criando uma função para traçar um retângulo com bordas arredondadas usando Delphi e GDI+, atualizando o método Paint para incorporar esse retângulo ao aliviar a área do painel.

Desenhando a camada

Estou mapeando o método Paint para desenhar uma camada semitransparente e limpar a área do painel com bordas arredondadas, assegurando bordas suaves e composição eficaz em Delphi com GDI+.

Criando uma camada

Estou trabalhando em uma camada semitransparente para cobrir a interface, excluindo o painel, e usando a forma arredondada do TscGPPanel para suavizar a borda.

Desenhando a sobreposição

Estou pintando uma camada semi-transparente no formulário, excluindo a área do painel, e usando GDI+ para suavizar bordas arredondadas com anti-aliasing, garantindo uma aparência mais fluida.

Desenhando e suavizando

Estou criando um controle personalizado em Delphi para pintar uma camada semitransparente sobre o formulário, excluindo o painel com cantos arredondados, usando GDI+ para suavizar as bordas.

Aprimorando a transparência

Estou adicionando TOverlayControl ao formulário principal, ajustando a propriedade Panel para destacar o painel desejado, e implementando métodos para mostrar e ocultar essa camada.

Controlando a sobreposição

Estou vendo que chamar ShowOverlay destaca o painel, enquanto HideOverlay remove a sobreposição. Passagem de eventos de mouse pode ser ajustada conforme necessário.

Pensou por 19 segundos

Resposta

Para escurecer todo o restante do formulário, exceto um Panel (seja um TPanel padrão ou um TscGPPanel com cantos arredondados), você pode criar uma sobreposição semi-transparente que cobre todo o formulário, deixando o Panel destacado. Para evitar serrilhamento nos cantos arredondados do TscGPPanel, utilizaremos GDI+ para desenhar a sobreposição com bordas suaves.

A seguir, apresento um passo a passo detalhado para implementar essa funcionalidade no Delphi utilizando VCL:

1. Criar um Controle de Sobreposição Personalizado

Primeiro, criaremos um controle personalizado que será responsável por desenhar a sobreposição semi-transparente. Esse controle irá cobrir todo o formulário e excluir a área ocupada pelo Panel.

a. Crie uma nova unidade chamada OverlayControl.pas e adicione o seguinte código:

unit OverlayControl; interface uses System.Classes, Vcl.Controls, Vcl.Graphics, Winapi.Windows, Vcl.ExtCtrls, Winapi.GDIPOBJ, Winapi.GDIPAPI, System.Types; type TOverlayControl = class(TCustomControl) private FPanel: TWinControl; procedure SetPanel(const Value: TWinControl); function CreateRoundedRectPath(const Rect: TGPRectF; Radius: Single): TGPGraphicsPath; protected procedure Paint; override; public constructor Create(AOwner: TComponent); override; property Panel: TWinControl read FPanel write SetPanel; end; implementation uses System.SysUtils; constructor TOverlayControl.Create(AOwner: TComponent); begin inherited Create(AOwner); // Alinha o controle para cobrir todo o formulário Align := alClient; // Garante que o controle fique acima dos demais Parent := TWinControl(AOwner); // Inicializa sem um Panel FPanel := nil; // Habilita double buffering para evitar flicker DoubleBuffered := True; // Torna o controle opaco para poder desenhar ControlStyle := ControlStyle + [csOpaque]; end; procedure TOverlayControl.SetPanel(const Value: TWinControl); begin if FPanel <> Value then begin FPanel := Value; Invalidate; // Redesenha o controle quando o Panel for alterado end; end; function TOverlayControl.CreateRoundedRectPath(const Rect: TGPRectF; Radius: Single): TGPGraphicsPath; begin Result := TGPGraphicsPath.Create; Result.AddArc(Rect.X, Rect.Y, Radius * 2, Radius * 2, 180, 90); Result.AddArc(Rect.X + Rect.Width - Radius * 2, Rect.Y, Radius * 2, Radius * 2, 270, 90); Result.AddArc(Rect.X + Rect.Width - Radius * 2, Rect.Y + Rect.Height - Radius * 2, Radius * 2, Radius * 2, 0, 90); Result.AddArc(Rect.X, Rect.Y + Rect.Height - Radius * 2, Radius * 2, Radius * 2, 90, 90); Result.CloseFigure; end; procedure TOverlayControl.Paint; var Graphics: TGPGraphics; RectFull, RectPanel: TGPRectF; SolidBrush: TGPSolidBrush; PanelBounds: TRect; Path: TGPGraphicsPath; Radius: Single; begin if not Assigned(FPanel) then Exit; // Inicializa GDI+ Graphics := TGPGraphics.Create(Canvas.Handle); try Graphics.SetSmoothingMode(SmoothingModeAntiAlias); // Define o retângulo completo RectFull := MakeRect(0, 0, Width, Height); // Cria um pincel preto semi-transparente (50% opacidade) SolidBrush := TGPSolidBrush.Create($7F000000); // AABBGGRR try Graphics.FillRectangle(SolidBrush, RectFull); finally SolidBrush.Free; end; // Obtém os limites do Panel relativo ao controle de sobreposição PanelBounds := FPanel.BoundsRect; RectPanel := MakeRect(PanelBounds.Left, PanelBounds.Top, PanelBounds.Width, PanelBounds.Height); // Determina o raio dos cantos arredondados if FPanel is TscGPPanel then Radius := (FPanel as TscGPPanel).CornerRadius // Supondo que TscGPPanel tenha uma propriedade CornerRadius else Radius := 0; // Para um Panel padrão sem cantos arredondados // Cria o caminho para a área do Panel Path := CreateRoundedRectPath(RectPanel, Radius); try // Define o modo de composição para DestinationOut para remover a área do Panel Graphics.SetCompositingMode(CompositingModeDestinationOut); // Cria um pincel transparente SolidBrush := TGPSolidBrush.Create($00000000); try Graphics.FillPath(SolidBrush, Path); finally SolidBrush.Free; end; finally Path.Free; end; finally Graphics.Free; end; end; end.

Explicação do Código:

  • TOverlayControl: É um controle personalizado que herda de TCustomControl. Ele desenha uma sobreposição semi-transparente cobrindo todo o formulário, exceto a área ocupada pelo Panel especificado.

  • Propriedade Panel: Permite definir qual Panel será excluído da sobreposição.

  • Método Paint: Utiliza GDI+ para desenhar a sobreposição. Primeiro, preenche todo o controle com uma cor preta semi-transparente. Em seguida, cria um caminho que corresponde à área do Panel (com cantos arredondados, se aplicável) e utiliza o modo de composição DestinationOut para "apagar" essa área da sobreposição, deixando o Panel visível.

2. Adicionar o Controle de Sobreposição ao Formulário

No formulário principal onde você deseja aplicar a sobreposição, adicione uma instância de TOverlayControl e configure-a para excluir o Panel desejado.

a. No seu formulário principal (Form1), adicione o seguinte código:

unit MainFormUnit; interface uses Vcl.Forms, Vcl.Controls, Vcl.ExtCtrls, OverlayControl, System.Classes; type TForm1 = class(TForm) Panel1: TscGPPanel; // Supondo que você tenha um TscGPPanel private Overlay: TOverlayControl; public procedure ShowOverlay; procedure HideOverlay; end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.ShowOverlay; begin if not Assigned(Overlay) then begin Overlay := TOverlayControl.Create(Self); Overlay.Panel := Panel1; Overlay.BringToFront; Overlay.Visible := True; end; end; procedure TForm1.HideOverlay; begin if Assigned(Overlay) then begin Overlay.Free; Overlay := nil; end; end; end.

Explicação do Código:

  • Procedimento ShowOverlay: Cria e exibe a sobreposição, especificando qual Panel deve ser excluído da sobreposição.

  • Procedimento HideOverlay: Remove a sobreposição quando não for mais necessária.

3. Utilizar o Overlay

Chame os procedimentos ShowOverlay e HideOverlay conforme a lógica da sua aplicação. Por exemplo, você pode exibir a sobreposição ao abrir um diálogo modal ou ao ativar uma determinada funcionalidade.

Exemplo de Uso:

procedure TForm1.ButtonShowOverlayClick(Sender: TObject); begin ShowOverlay; end; procedure TForm1.ButtonHideOverlayClick(Sender: TObject); begin HideOverlay; end;

4. Considerações Adicionais

  • Passagem de Eventos de Mouse: O controle de sobreposição atual captura todos os eventos de mouse, impedindo interações com os controles abaixo. Se desejar que os eventos passem para o Panel, você pode ajustar o estilo do controle ou manipular os eventos de mouse conforme necessário.

  • Compatibilidade com TscGPPanel: Certifique-se de que o TscGPPanel possui uma propriedade que define o raio dos cantos arredondados (como CornerRadius). Se não, você pode definir um valor fixo ou ajustar conforme necessário.

  • Desempenho: O uso de GDI+ pode afetar o desempenho se houver muitas atualizações ou se o formulário for grande. Teste para garantir que o desempenho esteja aceitável.

  • Compatibilidade de Unidades: Assegure-se de que a unidade OverlayControl esteja corretamente referenciada no seu projeto e que as bibliotecas GDI+ estejam disponíveis.

5. Conclusão

Com essa abordagem, você consegue escurecer todo o formulário, destacando o Panel desejado, seja ele um TPanel padrão ou um TscGPPanel com cantos arredondados. A utilização de GDI+ garante que os cantos arredondados fiquem suaves, evitando o serrilhamento indesejado.

Caso precise de personalizações adicionais ou encontre algum problema específico, sinta-se à vontade para fornecer mais detalhes para que possamos ajudar de forma mais direcionada.


Espero que essa solução atenda às suas necessidades!

Pergunta

[dcc32 Error] OverlayControl.pas(79): E2010 Incompatible types: 'TGPRectF' and 'TGPRect'
[dcc32 Error] OverlayControl.pas(91): E2010 Incompatible types: 'TGPRectF' and 'TGPRect'
[dcc32 Error] OverlayControl.pas(95): E2003 Undeclared identifier: 'CornerRadius'
[dcc32 Error] OverlayControl.pas(103): E2003 Undeclared identifier: 'CompositingModeDestinationOut'

Pensamento

Ajustando tipos e identificadores

Estou trabalhando em compatibilizar 'TGPRectF' e 'TGPRect' em Delphi. Também ajustando identificadores 'CornerRadius' e 'CompositingModeDestinationOut' que estão sendo ignorados.

Ajustando o código

Estou analisando propriedades e identificadores do TscGPPanel e GDI+, e verificando tipos e funções apropriados para correções. Provavelmente, 'CornerRadius' e 'CompositingModeDestinationOut' precisam de ajustes.

Ajustando identificadores

Estou ajustando 'MakeRect' para 'MakeRectF', revisando 'CornerRadius' e 'CompositingModeDestinationOut' para garantir que os nomes e propriedades corretos estejam sendo utilizados.

Pensou por 4 segundos

Resposta

Peço desculpas pelos erros no código fornecido anteriormente. Vamos resolver cada um dos problemas apontados e ajustar o código para que funcione corretamente.

Resumo dos Erros e Soluções

  1. Tipos Incompatíveis: 'TGPRectF' e 'TGPRect'

    • Erro: E2010 Incompatible types: 'TGPRectF' and 'TGPRect' nas linhas 79 e 91.
    • Solução: Utilizar MakeRectF em vez de MakeRect para criar instâncias de TGPRectF, já que MakeRect retorna TGPRect, que é incompatível com TGPRectF.
  2. Identificador Indefinido: 'CornerRadius'

    • Erro: E2003 Undeclared identifier: 'CornerRadius' na linha 95.
    • Solução: Verificar se TscGPPanel realmente possui a propriedade CornerRadius. Caso contrário, definir manualmente o raio dos cantos ou utilizar a propriedade correta.
  3. Identificador Indefinido: 'CompositingModeDestinationOut'

    • Erro: E2003 Undeclared identifier: 'CompositingModeDestinationOut' na linha 103.
    • Solução: Utilizar o valor correto da enumeração TCompositingMode. O valor apropriado é cmDestinationOut.

Código Corrigido

A seguir, apresento o código corrigido com comentários explicativos para cada modificação necessária:

1. Unidade OverlayControl.pas Corrigida

unit OverlayControl; interface uses System.Classes, Vcl.Controls, Vcl.Graphics, Winapi.Windows, Vcl.ExtCtrls, Winapi.GDIPOBJ, Winapi.GDIPAPI, System.Types; type TOverlayControl = class(TCustomControl) private FPanel: TWinControl; procedure SetPanel(const Value: TWinControl); function CreateRoundedRectPath(const Rect: TGPRectF; Radius: Single): TGPGraphicsPath; protected procedure Paint; override; public constructor Create(AOwner: TComponent); override; property Panel: TWinControl read FPanel write SetPanel; end; implementation uses System.SysUtils, ScGPControl; // Assegure-se de que a unidade que define TscGPPanel esteja incluída constructor TOverlayControl.Create(AOwner: TComponent); begin inherited Create(AOwner); // Alinha o controle para cobrir todo o formulário Align := alClient; // Garante que o controle fique acima dos demais Parent := TWinControl(AOwner); // Inicializa sem um Panel FPanel := nil; // Habilita double buffering para evitar flicker DoubleBuffered := True; // Torna o controle opaco para poder desenhar ControlStyle := ControlStyle + [csOpaque]; end; procedure TOverlayControl.SetPanel(const Value: TWinControl); begin if FPanel <> Value then begin FPanel := Value; Invalidate; // Redesenha o controle quando o Panel for alterado end; end; function TOverlayControl.CreateRoundedRectPath(const Rect: TGPRectF; Radius: Single): TGPGraphicsPath; begin Result := TGPGraphicsPath.Create; Result.AddArc(Rect.X, Rect.Y, Radius * 2, Radius * 2, 180, 90); Result.AddArc(Rect.X + Rect.Width - Radius * 2, Rect.Y, Radius * 2, Radius * 2, 270, 90); Result.AddArc(Rect.X + Rect.Width - Radius * 2, Rect.Y + Rect.Height - Radius * 2, Radius * 2, Radius * 2, 0, 90); Result.AddArc(Rect.X, Rect.Y + Rect.Height - Radius * 2, Radius * 2, Radius * 2, 90, 90); Result.CloseFigure; end; procedure TOverlayControl.Paint; var Graphics: TGPGraphics; RectFull, RectPanel: TGPRectF; SolidBrush: TGPSolidBrush; PanelBounds: TRect; Path: TGPGraphicsPath; Radius: Single; begin if not Assigned(FPanel) then Exit; // Inicializa GDI+ Graphics := TGPGraphics.Create(Canvas.Handle); try Graphics.SetSmoothingMode(SmoothingModeAntiAlias); // Define o retângulo completo usando MakeRectF para TGPRectF RectFull := MakeRectF(0, 0, Width, Height); // Cria um pincel preto semi-transparente (50% opacidade) SolidBrush := TGPSolidBrush.Create($7F000000); // ARGB: 50% transparente try Graphics.FillRectangle(SolidBrush, RectFull); finally SolidBrush.Free; end; // Obtém os limites do Panel relativo ao controle de sobreposição PanelBounds := FPanel.BoundsRect; // Converter as coordenadas relativas se necessário RectPanel := MakeRectF(PanelBounds.Left, PanelBounds.Top, PanelBounds.Width, PanelBounds.Height); // Determina o raio dos cantos arredondados if FPanel is TscGPPanel then begin // Verifique se TscGPPanel possui uma propriedade para o raio dos cantos // Substitua 'CornerRadius' pelo nome correto da propriedade, se diferente if Assigned(TscGPPanel(FPanel).FindComponent('CornerRadius')) then Radius := (FPanel as TscGPPanel).CornerRadius else Radius := 20; // Valor padrão ou ajustado conforme necessário end else Radius := 0; // Para um Panel padrão sem cantos arredondados // Cria o caminho para a área do Panel Path := CreateRoundedRectPath(RectPanel, Radius); try // Define o modo de composição para DestinationOut para remover a área do Panel Graphics.SetCompositingMode(CompositingModeDestinationOut); // Corrigido para usar enumeração correta // Cria um pincel transparente SolidBrush := TGPSolidBrush.Create($00000000); try Graphics.FillPath(SolidBrush, Path); finally SolidBrush.Free; end; finally Path.Free; end; finally Graphics.Free; end; end; end.

2. Unidade Principal MainFormUnit.pas Corrigida

unit MainFormUnit; interface uses Vcl.Forms, Vcl.Controls, Vcl.ExtCtrls, OverlayControl, System.Classes, ScGPControl; // Assegure-se de que a unidade que define TscGPPanel esteja incluída type TForm1 = class(TForm) Panel1: TscGPPanel; // Supondo que você tenha um TscGPPanel ButtonShowOverlay: TButton; ButtonHideOverlay: TButton; procedure ButtonShowOverlayClick(Sender: TObject); procedure ButtonHideOverlayClick(Sender: TObject); private Overlay: TOverlayControl; public procedure ShowOverlay; procedure HideOverlay; end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.ShowOverlay; begin if not Assigned(Overlay) then begin Overlay := TOverlayControl.Create(Self); Overlay.Panel := Panel1; Overlay.BringToFront; Overlay.Visible := True; end; end; procedure TForm1.HideOverlay; begin if Assigned(Overlay) then begin Overlay.Free; Overlay := nil; end; end; procedure TForm1.ButtonShowOverlayClick(Sender: TObject); begin ShowOverlay; end; procedure TForm1.ButtonHideOverlayClick(Sender: TObject); begin HideOverlay; end; end.

Detalhes das Correções

  1. Uso de MakeRectF em vez de MakeRect

    Substituímos as chamadas para MakeRect por MakeRectF para criar instâncias de TGPRectF, que são necessárias para operações com GDI+ que utilizam coordenadas de ponto flutuante.

    RectFull := MakeRectF(0, 0, Width, Height);
    RectPanel := MakeRectF(PanelBounds.Left, PanelBounds.Top, PanelBounds.Width, PanelBounds.Height);
  2. Acesso Correto à Propriedade CornerRadius

    Verificamos se TscGPPanel possui realmente uma propriedade chamada CornerRadius. Caso contrário, podemos definir um valor padrão ou ajustar conforme necessário.

    if FPanel is TscGPPanel then begin // Verifique se TscGPPanel possui uma propriedade para o raio dos cantos // Substitua 'CornerRadius' pelo nome correto da propriedade, se diferente if Assigned(TscGPPanel(FPanel).FindComponent('CornerRadius')) then Radius := (FPanel as TscGPPanel).CornerRadius else Radius := 20; // Valor padrão ou ajustado conforme necessário end else Radius := 0; // Para um Panel padrão sem cantos arredondados

    Nota: Substitua 'CornerRadius' pelo nome correto da propriedade, se ela for diferente. Se TscGPPanel não possuir essa propriedade, você precisará ajustá-la conforme a implementação específica do componente.

  3. Uso Correto de CompositingModeDestinationOut

    A enumeração correta para o modo de composição é cmDestinationOut, que faz parte do tipo TCompositingMode. Portanto, ajustamos a chamada para utilizar a enumeração correta:

    Graphics.SetCompositingMode(cmDestinationOut);

    Observação: Certifique-se de que a unidade que define TCompositingMode esteja incluída. Geralmente, isso é gerenciado pelas unidades GDIPAPI e GDIPOBJ que já estão incluídas.

  4. Inclusão da Unidade Correta para TscGPPanel

    Assegure-se de que a unidade que define TscGPPanel (por exemplo, ScGPControl) esteja incluída nas cláusulas uses tanto de OverlayControl.pas quanto de MainFormUnit.pas.

    uses System.SysUtils, ScGPControl; // Para TscGPPanel
  5. Configuração da Propriedade CornerRadius

    Se TscGPPanel não possui uma propriedade CornerRadius, você pode precisar definir manualmente o raio ou consultar a documentação do componente para identificar a propriedade correta.

    // Exemplo de definição manual do raio Radius := 20; // Ajuste conforme necessário

Passos Adicionais para Garantir o Funcionamento

  1. Verifique as Unidades e Dependências

    • Assegure-se de que todas as unidades necessárias estejam incluídas no seu projeto.
    • Se estiver utilizando bibliotecas de terceiros (como TscGPPanel), verifique se estão corretamente instaladas e referenciadas.
  2. Gerenciamento de Eventos de Mouse

    O controle de sobreposição atualmente intercepta todos os eventos de mouse, impedindo interações com os controles abaixo. Se desejar que os eventos passem para o Panel, você pode ajustar o comportamento conforme necessário. Uma abordagem comum é sobrescrever os métodos de evento de mouse e direcioná-los ao Panel.

  3. Teste de Performance

    O uso de GDI+ pode afetar o desempenho, especialmente em formulários grandes ou em dispositivos com recursos limitados. Teste a aplicação para garantir que o desempenho esteja aceitável e ajuste conforme necessário.

  4. Ajuste do Valor de Transparência

    O valor $7F000000 representa 50% de opacidade. Você pode ajustar esse valor para aumentar ou diminuir o nível de escurecimento.

    • Mais Transparente (menos escurecido): $3F000000 (25% opacidade)
    • Mais Opaco (mais escurecido): $BF000000 (75% opacidade)
  5. Compatibilidade com Diferentes Resoluções e Escalas de DPI

    Certifique-se de que a sobreposição funcione corretamente em diferentes resoluções e configurações de DPI, ajustando o layout conforme necessário.

Código Completo Corrigido

Para facilitar, aqui está o código completo corrigido para ambas as unidades:

OverlayControl.pas

unit OverlayControl; interface uses System.Classes, Vcl.Controls, Vcl.Graphics, Winapi.Windows, Vcl.ExtCtrls, Winapi.GDIPOBJ, Winapi.GDIPAPI, System.Types; type TOverlayControl = class(TCustomControl) private FPanel: TWinControl; procedure SetPanel(const Value: TWinControl); function CreateRoundedRectPath(const Rect: TGPRectF; Radius: Single): TGPGraphicsPath; protected procedure Paint; override; public constructor Create(AOwner: TComponent); override; property Panel: TWinControl read FPanel write SetPanel; end; implementation uses System.SysUtils, ScGPControl; // Inclua a unidade correta para TscGPPanel constructor TOverlayControl.Create(AOwner: TComponent); begin inherited Create(AOwner); // Alinha o controle para cobrir todo o formulário Align := alClient; // Garante que o controle fique acima dos demais Parent := TWinControl(AOwner); // Inicializa sem um Panel FPanel := nil; // Habilita double buffering para evitar flicker DoubleBuffered := True; // Torna o controle opaco para poder desenhar ControlStyle := ControlStyle + [csOpaque]; end; procedure TOverlayControl.SetPanel(const Value: TWinControl); begin if FPanel <> Value then begin FPanel := Value; Invalidate; // Redesenha o controle quando o Panel for alterado end; end; function TOverlayControl.CreateRoundedRectPath(const Rect: TGPRectF; Radius: Single): TGPGraphicsPath; begin Result := TGPGraphicsPath.Create; Result.AddArc(Rect.X, Rect.Y, Radius * 2, Radius * 2, 180, 90); Result.AddArc(Rect.X + Rect.Width - Radius * 2, Rect.Y, Radius * 2, Radius * 2, 270, 90); Result.AddArc(Rect.X + Rect.Width - Radius * 2, Rect.Y + Rect.Height - Radius * 2, Radius * 2, Radius * 2, 0, 90); Result.AddArc(Rect.X, Rect.Y + Rect.Height - Radius * 2, Radius * 2, Radius * 2, 90, 90); Result.CloseFigure; end; procedure TOverlayControl.Paint; var Graphics: TGPGraphics; RectFull, RectPanel: TGPRectF; SolidBrush: TGPSolidBrush; PanelBounds: TRect; Path: TGPGraphicsPath; Radius: Single; begin if not Assigned(FPanel) then Exit; // Inicializa GDI+ Graphics := TGPGraphics.Create(Canvas.Handle); try Graphics.SetSmoothingMode(SmoothingModeAntiAlias); // Define o retângulo completo usando MakeRectF para TGPRectF RectFull := MakeRectF(0, 0, Width, Height); // Cria um pincel preto semi-transparente (50% opacidade) SolidBrush := TGPSolidBrush.Create($7F000000); // ARGB: 50% transparente try Graphics.FillRectangle(SolidBrush, RectFull); finally SolidBrush.Free; end; // Obtém os limites do Panel relativo ao controle de sobreposição PanelBounds := FPanel.BoundsRect; // Converter as coordenadas relativas se necessário RectPanel := MakeRectF(PanelBounds.Left, PanelBounds.Top, PanelBounds.Width, PanelBounds.Height); // Determina o raio dos cantos arredondados if FPanel is TscGPPanel then begin // Verifique se TscGPPanel possui uma propriedade para o raio dos cantos // Substitua 'CornerRadius' pelo nome correto da propriedade, se diferente if Assigned(TscGPPanel(FPanel).FindComponent('CornerRadius')) then Radius := (FPanel as TscGPPanel).CornerRadius else Radius := 20; // Valor padrão ou ajustado conforme necessário end else Radius := 0; // Para um Panel padrão sem cantos arredondados // Cria o caminho para a área do Panel Path := CreateRoundedRectPath(RectPanel, Radius); try // Define o modo de composição para DestinationOut para remover a área do Panel Graphics.SetCompositingMode(cmDestinationOut); // Corrigido para usar enumeração correta // Cria um pincel transparente SolidBrush := TGPSolidBrush.Create($00000000); try Graphics.FillPath(SolidBrush, Path); finally SolidBrush.Free; end; finally Path.Free; end; finally Graphics.Free; end; end; end.

MainFormUnit.pas

unit MainFormUnit; interface uses Vcl.Forms, Vcl.Controls, Vcl.ExtCtrls, OverlayControl, System.Classes, ScGPControl, Vcl.StdCtrls; // Inclua Vcl.StdCtrls para TButton type TForm1 = class(TForm) Panel1: TscGPPanel; // Supondo que você tenha um TscGPPanel ButtonShowOverlay: TButton; ButtonHideOverlay: TButton; procedure ButtonShowOverlayClick(Sender: TObject); procedure ButtonHideOverlayClick(Sender: TObject); private Overlay: TOverlayControl; public procedure ShowOverlay; procedure HideOverlay; end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.ShowOverlay; begin if not Assigned(Overlay) then begin Overlay := TOverlayControl.Create(Self); Overlay.Panel := Panel1; Overlay.BringToFront; Overlay.Visible := True; end; end; procedure TForm1.HideOverlay; begin if Assigned(Overlay) then begin Overlay.Free; Overlay := nil; end; end; procedure TForm1.ButtonShowOverlayClick(Sender: TObject); begin ShowOverlay; end; procedure TForm1.ButtonHideOverlayClick(Sender: TObject); begin HideOverlay; end; end.

Considerações Finais

  1. Verifique a Propriedade CornerRadius

    • Se TscGPPanel não possui a propriedade CornerRadius, você precisará ajustá-la conforme a implementação do componente. Consulte a documentação ou o código fonte do TscGPPanel para identificar a propriedade correta ou para implementar a funcionalidade de cantos arredondados.
  2. Gerenciamento de Recursos

    • Assegure-se de que todos os objetos GDI+ (TGPGraphics, TGPSolidBrush, TGPGraphicsPath) sejam corretamente liberados para evitar vazamentos de memória.
  3. Testes em Diferentes Ambientes

    • Teste a aplicação em diferentes resoluções de tela e configurações de DPI para garantir que a sobreposição funcione conforme o esperado.
  4. Ajuste do Valor de Transparência

    • Se a sobreposição estiver muito escura ou muito clara, ajuste o valor de transparência no TGPSolidBrush. Por exemplo, $7F000000 representa 50% de opacidade. Você pode aumentar ou diminuir esse valor conforme necessário.
  5. Compatibilidade com Outras Versões do Delphi

    • Certifique-se de que as unidades GDI+ (GDIPAPI e GDIPOBJ) estejam disponíveis e sejam compatíveis com a versão do Delphi que você está utilizando.
  6. Depuração Adicional

    • Se você encontrar outros erros ou comportamentos inesperados, utilize ferramentas de depuração do Delphi para identificar e resolver problemas específicos.

Espero que essas correções resolvam os problemas que você encontrou e que a funcionalidade desejada seja implementada com sucesso. Se precisar de mais assistência ou encontrar novos problemas, sinta-se à vontade para perguntar!

Compartilhar esta Q&A