Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Прозрачный компонент

Delphi , Компоненты и Классы , Создание компонент

Прозрачный компонент

Автор: Robert Wittig

При выводе прозрачного окна, окна или элементы управления, расположенные под ним, также видны. При перемещении невидимого окна, при условии, что оно не скрывается/выводится вновь, оно сохраняет "снимок" графической области, которая была расположена под ним в момент вывода (а именно: окна или видимые компоненты).

Взгляните на модуль, приведенный ниже, в нем предлагается решение проблемы невидимого окна.


{  Начните с нового проекта.

Разместите на форме 4 кнопки и 1 компонент CheckBox.
Создайте обработчик события OnClick как показано ниже

Во время выполнения программы, если вы нажимаете на Button3,
щелчок по Button1 будет перехватываться InvWin; если вы
нажимаете на Button4, щелчок по Button2 будет перехватываться
InvWin. Поскольку "невидимое" окно первоначально представляет
собой простой дескриптор, элемент управления, расположенный
под ним, должен быть перерисован. Из-за этого существует
проблема мерцания, происходящая по сценарию как, будто вы
щелкнули по Button3 и Button4. При щелчке на CheckBox1,
InvWin.Invisible устанавливается в True. Это позволяет окну
не перерисовываться. Поскольку окно у нас теперь истинно
невидимое, то для устранения мерцания мы целенаправленно
посылаем необходимым окнам сообщение WM_SETREDRAW. }

unit Invwin1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;

type
  TInvWin = class(TWinControl)
  private
    fOnControl: TControl;
    fInvisible: Boolean;

    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;

    procedure SetOnControl(Value: TControl); virtual;
  public
    constructor Create(aOwner: TComponent);

    property OnControl: TControl read fOnControl write SetOnControl;
    property Invisible: Boolean read fInvisible write fInvisible;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    CheckBox1: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    InvWin: TInvWin;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

constructor TInvWin.Create(aOwner: TComponent);
begin
  inherited Create(aOwner);

  ControlStyle := ControlStyle + [csOpaque];
end;

procedure TInvWin.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);

  Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT;
end;

procedure TInvWin.WMPaint(var Message: TWMPaint);
var
  DC: THandle;
  PS: TPaintStruct;
begin
  if not Invisible then
  begin
    if Message.DC = 0 then
      DC := BeginPaint(Handle, PS)
    else
      DC := Message.DC;

    PatBlt(DC, 0, 0, 5, 5, BLACKNESS);
    PatBlt(DC, Width - 6, 0, 5, 5, BLACKNESS);
    PatBlt(DC, 0, Height - 6, 5, 5, BLACKNESS);
    PatBlt(DC, Width - 6, Height - 6, 5, 5, BLACKNESS);

    if Message.DC = 0 then
      EndPaint(Handle, PS);
  end;
end;

procedure TInvWin.MouseDown(Button: TMouseButton; Shift:
  TShiftState; X, Y
  : Integer);
begin
  ShowMessage('MouseDown над невидимым окном');
end;

procedure TInvWin.SetOnControl(Value: TControl);
var
  Rect: TRect;
begin
  if Value <> fOnControl then
  begin
    { Используйте только WM_SETREDRAW, если окно полностью невидимо }
    if Invisible and (Parent <> nil) then
      Parent.Perform(WM_SETREDRAW, 0, 0);

    if fOnControl <> nil then
      Visible := False;

    if Value <> nil then
    begin
      Rect := Value.BoundsRect;
      InflateRect(Rect, 2, 2);
      BoundsRect := Rect;
    end;
    fOnControl := Value;

    if fOnControl <> nil then
      Visible := True;

    { Используйте только WM_SETREDRAW, если окно полностью невидимо }
    if Invisible and (Parent <> nil) then
      Parent.Perform(WM_SETREDRAW, 1, 0);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  InvWin := TInvWin.Create(Self);
  InvWin.Visible := False;
  InvWin.Parent := Self;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage('MouseClick над Button1');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ShowMessage('MouseClick над Button2');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  InvWin.OnControl := Button1;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  InvWin.OnControl := Button2;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  InvWin.OnControl := nil;
  InvWin.Invisible := CheckBox1.Checked;
end;

end.

Перевод контента на русский язык:

Это реализация компонента прозрачного окна в Delphi, который позволяет пользователю создавать прозрачное окно, которое может перехватывать клики мыши над другими контролами ниже него.

Класс TInvWin - это пользовательский контроль, наследующийся от TWinControl. Он имеет несколько свойств и методов:

  • Invisible: булевое свойство, указывающее, должен ли быть окно невидимым или нет.
  • OnControl: свойство, которое specifies which control should receive mouse clicks when the transparent window is clicked.
  • MouseDown: override standard MouseDown method, which displays a message box when the user clicks on the transparent window.
  • WMPaint: override standard WMPaint method, which paints a black rectangle around the edges of the window to create a transparent effect.
  • CreateParams: override standard CreateParams method, which sets the extended style of the window to include transparency.
  • SetOnControl: метод, который sets the OnControl property and adjusts the visibility of the window accordingly.

Класс TForm1 - это форма, содержащая несколько кнопок и чекбокс. Когда пользователь кликнет на одну из кнопок, она установит свойство OnControl прозрачного окна в эту кнопку. Когда пользователь включит или отключит чекбокс, он будет переключать видимость окна.

Некоторые предложения по улучшению кода:

  • Вместо использования функции PatBlt для рисования черного прямоугольника вокруг краев окна, вы могли бы использовать более эффективный метод,such as drawing a border around the window.
  • Метод WMPaint вызывается только когда окно нужно перерисовать. Вы можете оптимизировать этот метод, рисуя только необходимые части окна.
  • Метод SetOnControl является quite complex и выполняет несколько задач одновременно. Вам может быть полезно разбить его на отдельные методы, которые выполняют конкретные задачи, such as setting the OnControl property and adjusting the visibility of the window.
  • Код мог бы быть улучшен с помощью использования более описательных имен переменных и комментариев для объяснения того, что каждый часть кода делает.

Альтернативное решение:

Вместо создания пользовательского контрола, который перехватывает клики мыши над другими контролами, вы могли бы использовать прозрачный панель с таймером. Когда пользователь кликнет на панель, таймер будет запущен, который затем установит свойство OnControl в желаемый контроль.

Пример кода:

unit TransparentPanel;
interface
uses
  Windows, Messages, Controls, Forms, Graphics, StdCtrls;
type
  TTransparentPanel = class(TPanel)
  private
    FTimer: TTimer;
    FOnControl: TControl;
  public
    constructor Create(AOwner: TComponent); override;
    procedure SetOnControl(Value: TControl);
  end;
var
  TransparentPanel: TTransparentPanel;
implementation
constructor TTransparentPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  TimerInterval := 100; // adjust the timer interval as needed
end;
procedure TTransparentPanel.SetOnControl(Value: TControl);
begin
  FOnControl := Value;
  if Assigned(FOnControl) then
    FTimer.Enabled := True
  else
    FTimer.Enabled := False;
end;
procedure TTransparentPanel.TimerTick(Sender: TObject);
begin
  if Assigned(FOnControl) then
    FOnControl.Perform(WM_LBUTTONDOWN, 0, 0);
end;

В этом коде класс TTransparentPanel - это пользовательский панель с таймером. Когда пользователь кликнет на панель, таймер будет запущен, который затем установит свойство OnControl в желаемый контроль и симулирует событие нажатия левой кнопки мыши на этом контроле.

Обратите внимание, что это код использует сообщение WM_LBUTTONDOWN для симуляции клика мыши над целевым контролом. Это может не работать правильно, если целевой контроль имеет custom mouse handler или не виден на экране.

В статье описано решение проблемы мерцания в Delphi, вызванное невидимым окном с обработчиком события OnClick, которое перехватывает события с других элементов управления на форме. Для решения этой проблемы автор предложил модуль TInvWin, который позволяе


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Создание компонент ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 13:28:17/0.0065391063690186/1