Плавный переход между двумя формами в VCL - PullRequest
0 голосов
/ 18 марта 2020

Я несколько часов играл с этим, но не могу заставить его работать. У меня есть приложение из двух форм, и я хочу перейти с одной формы на другую. Я хочу, чтобы этот переключатель был «плавным» (ie эффект наложения).

Я пришел к этому решению, которое работает частично: с помощью функции AnimateWindow в методе ShowForm (). Это прекрасно работает, когда я переключаюсь с Form1 на Form2. Но переключение обратно в Form1 не работает. Форма 1 закрашена «позади» формы 2, и когда форма 2 скрывается, переход уже выполнен.

Ниже приведен очень простой код для формы 1:

#include <vcl.h>
#pragma hdrstop

#include "main_form.h"
#include "child_form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Form2 -> Show();
    Form1 -> Hide();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
    const int speed = 1000;
    AnimateWindow(Handle, speed, AW_BLEND);
}

и здесь код для формы 2:

#include <vcl.h>
#pragma hdrstop

#include "child_form.h"
#include "main_form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
    Form1 -> Show();
    Form2 -> Hide();

}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormShow(TObject *Sender)
{
    const int speed = 1000;
    AnimateWindow(Handle, speed, AW_BLEND);
}

Я пытался инвертировать операторы Form1->Show() и Form2->Hide() в коде для Form2, чтобы принудительно скрыть Form2 перед рисованием Form1, но это также не работает: Form2 скрыт, тогда ничего не отображается во время анимации, а затем внезапно отображается Form1.

Есть идеи?

Спасибо.

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Как вы и просили, вот мое мнение по этому вопросу, но, как я неуверен с C ++ Builder, в Delphi pascal.

Проблема, которую вы описываете (разница в поведении в зависимости от того, выводится ли Form1 или Form2 на передний план) из-за того, что Form1 является главной формой. Проблема не существует, если ни одна форма не является основной формой.

Если одна форма является основной формой, проблема становится менее заметной, если вы используете AlphaBlendValue для одновременного изменения видимости обеих форм, то есть повышения значение для формы, чтобы привести и уменьшить значение для другой. Поскольку обе формы частично видны, их порядок z не так очевиден, как если бы вы изменили только одну из форм.

Начните с проекта с двумя формами (TForm25 и TForm26 в моем коде).

TForm25
  property AlphaBlend = True
  property AlphaBlendValue = 255
  property Visible = True

TForm26
  property AlphaBlend = True
  property AlphaBlendValue = 0
  property Visible = True

Добавьте следующий код где-нибудь, где обе формы имеют к нему доступ.

procedure FadeOutIn(FOut, FIn: TForm);
var
  i: integer;
begin
  FIn.BringToFront;
  for i := 1 to 255 do
  begin
    FOut.AlphaBlendValue := 255-i;
    FIn.AlphaBlendValue := i;
    sleep(1); // use 20 for a really slow transition, just to demonstrate
              // or remove if not needed
  end;
end;

В моем тесте обе формы создаются автоматически, и Visible = True для обеих, но Form26 не виден, так как его AlphaBlendValue = 0. У каждой формы есть кнопка для вызова FadeOutIn() для ее постепенного исчезновения (скрытия) и появления (отображения) другой формы.

procedure TForm25.Button1Click(Sender: TObject);
begin
  FadeOutIn(Form25, Form26);
end;

procedure TForm26.Button1Click(Sender: TObject);
begin
  FadeOutIn(Form26, Form25);
end;

Предупреждение: - Поскольку обе формы являются полупрозрачными одновременно, независимо от Лежа позади также просвечивает во время перехода.

0 голосов
/ 19 марта 2020

Следуя советам @TomBrunberg, вот возможное решение. Основная проблема здесь в том, что одна из форм - это MainForm, которая всегда остается позади другой. Чтобы обойти это, можно создать третью пустую форму и объявить ее основной. Это свойство формы Visible имеет значение False. Код для этой 3-й формы следующий:


#include <vcl.h>
#pragma hdrstop

#include "background.h"
#include "main_form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm3 *Form3;
//---------------------------------------------------------------------------
__fastcall TForm3::TForm3(TComponent* Owner)
    : TForm(Owner)
{

}
//---------------------------------------------------------------------------

void __fastcall TForm3::FormShow(TObject *Sender)
{
     Form1->Show();
}
//---------------------------------------------------------------------------

, и код в двух других формах изменен так, что метод Hide() вызывается перед Show(), как показано ниже. Форма 1:

#include <vcl.h>
#pragma hdrstop

#include "main_form.h"
#include "child_form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Form1 -> Visible = false;
    Form2 -> Visible = true;
}

void __fastcall TForm1::FormShow(TObject *Sender)
{
    int const sleep = 500;
    AnimateWindow(Handle, sleep, AW_BLEND);
}

и Форма 2

#include <vcl.h>
#pragma hdrstop

#include "child_form.h"
#include "main_form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
    Form2 -> Visible = false;
    Form1 -> Visible = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm2::FormShow(TObject *Sender)
{
    int const sleep = 500;
    AnimateWindow(Handle, sleep, AW_BLEND);
}

Это работает только частично: при первом запуске отображается Форма 1 без эффекта перехода, но это не очень важно. Но когда Form2 вызывается в первый раз, эффект перехода также не работает, и пустая форма Form3 видна во время действия эффекта перехода. После этого он работает, и обе формы могут отображаться с эффектами перехода.

...