Delphi + Прозрачные формы с родителем - PullRequest
0 голосов
/ 04 декабря 2009

Я хочу создать форму, но просто использовать ее, чтобы сохранить изображение. (Как всплеск)

Чтобы создать такую ​​форму, я использую следующие строки:

SetWindowLong(Handle, GWL_EXSTYLE, LexStyle or WS_EX_LAYERED);
UpdateLayeredWindow(Handle, 0, nil, @LBitmapSize, LBitmap.Canvas.Handle, 0,
  @LBlendFunction, ULW_ALPHA);

Это изображение в формате PNG с прозрачным слоем.

Форма должна иметь родительскую форму или поведение формы, в которой она есть.

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

Но мне нужно добавить компоненты и установить родителя для формы.

Кто-нибудь знает другой способ сделать это?

Ответы [ 3 ]

2 голосов
/ 05 декабря 2009

Вы не можете использовать стиль WS_EX_LAYERED в дочерних окнах, таких как Форма с назначенным родителем. Вместо этого вам придется использовать SetWindowRgn ().

2 голосов
/ 22 декабря 2009

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

Предположим, что TParentForm является родительской формой, а TAlphaForm - формой с изображением.

При создании экземпляра TAlphaForm передайте экземпляр TParentForm в качестве параметра Owner и измените WndProc формы владельца в конструкторе.

Далее приведен пример кода для TAlphaForm:

type
  TAlphaForm = class(TForm)
  private
    FParentWndProc : TWndMethod;
    FParentForm    : TCustomForm;

    procedure HookWindowProc(var Message: TMessage);

  public
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
  end;

Реализация:

constructor TAlphaForm.Create(AOwner: TComponent);
begin
  inherited;

  if(Assigned(AOwner) and (Owner is TCustomForm)) then begin

    FParentForm := TCustomForm(Owner);
    // Subclass owner window 
    FParentWndProc := FParentForm.WindowProc;
    FParentForm.WindowProc := HookWindowProc;
    // Need to repaint to show initial picture
    if(FParentForm.HandleAllocated) then FParentForm.Invalidate;

  end else begin

    FParentForm := nil;
    FParentWndProc := nil;

  end;

end;

destructor TAlphaForm.Destroy;
begin
  if(Assigned(FParentForm)) then begin
    // Restore original WndProc and repaint to restore original look if available  
    FParentForm.WindowProc := FParentWndProc;
    if(FParentForm.HandleAllocated) then FParentForm.Invalidate;
    FParentForm := nil;
    FParentWndProc := nil;
  end;
  inherited;
end;

procedure TAlphaForm.HookWindowProc(var Message: TMessage);
begin

  if( not (Assigned(FParentForm) and Assigned(FParentWndProc)) )
    then exit;

  FParentWndProc(Message);

  if(Message.Msg = WM_PAINT) then begin
    // Paint alpha image here on Owner's form canvas
    // Here is sample painting
    FParentForm.Canvas.Pen.Width := 3;
    FParentForm.Canvas.Pen.Color := clRed;
    FParentForm.Canvas.Ellipse(FParentForm.ClientRect);
  end else if(Message.Msg = WM_SIZE) then begin 
    // Needed because the whole form must be repainted
    FParentForm.Invalidate;
  end;

end;

Для меня решение работает с кодом родительской формы:

type
  TForm1 = class(TForm)
    Button2: TButton;
    Button3: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
    FAlpha : TForm;
  public
    { Public declarations }
    constructor Create(AOwner : TComponent); override;
  end;

Реализация:

procedure TForm1.Button2Click(Sender: TObject);
begin
  if(not Assigned(FAlpha)) then FAlpha := TAlphaForm.Create(Self);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  FreeAndNil(FAlpha);
end;

constructor TForm1.Create(AOwner: TComponent);
begin
  inherited;
  FAlpha := nil;
end;
0 голосов
/ 04 декабря 2009

Предполагая, что обе формы находятся в одном приложении, вы пытались создать публичный метод, который может выступать в качестве обработчика ваших опций? Что-то вроде:

function TForm1.UpdateForm(Action: Integer/[Enumerated Type]/[etc]; Parameters: TStringList): Boolean;

с соответствующим кодом обработки внутри должен получить то, что вам нужно, без необходимости прибегать к обратным вызовам API или требовать информацию о дескрипторе.

...