36 votes

Les formulaires wsMaximized n'apparaissent pas agrandis

Définition d'un formulaire d' WindowState = wsMaximized peut parfois entraîner le formulaire pour être maximisée, mais non:

enter image description here

Long-temps bug: c'est une question que j'ai d'abord demandé dans le Borland groupes de discussion en 2003:

et puis à nouveau en 2006:

et puis de nouveau en 2008:

Quelqu'un a demandé sur l'Embarcadero forums en 2012:

Maintenant, il est temps de port de 18 ans d'un bug de Stackoverflow. Peut-être que quelqu'un a enfin trouvé une solution de contournement.

Étapes pour reproduire:

Mes messages contenait une demi-douzaine de modes de défaillance, mais le plus simple est:

  • Déposez un Label et Edit sur un formulaire:

    enter image description here

  • Ajouter un OnEnter événement pour l' TEdit:

    procedure TForm1.Edit1Enter(Sender: TObject);
    begin
       Label1.Font.Style := Label1.Font.Style + [fsBold];
    end;
    
  • et de définir la forme:

    • WindowState de wsMaximized
    • AutoScroll de Faux

Et bazinga, échoue.

L'une des autres étapes de l'2008 post:

  1. Créez une nouvelle application et une forme.
  2. Définir la forme de maximisée (WindowState = wsMaximized) au moment de la conception.
  3. Déposez un contrôle ListView sur la forme
  4. Au cours de OnShow, ajouter 20 éléments vides à l'affichage de la liste:

    procedure TForm1.FormShow(Sender: TObject);
    var
         i: Integer;
    begin
         for i := 1 to 20 do
              ListView1.Items.Add;
    
    end;
    
  5. Définir la forme de l'AutoScroll valeur false à la propriété (AutoScroll = False) au moment de la conception

Bien sûr que je suis de ne pas avoir "corrigé dans la version n de RadStudio. L'utiliser". Je suis à la recherche d'une véritable correction (si il y en a un); ce qui pourrait inclure citant les modifications apportées à la CLASSIFICATION de la source lors de CodeGear finalement fait le fixer. (Si elle est encore fixé).

Remarque: Évolution des Position de poDesigned à rien d'autre ne résout pas le problème.

Solution de contournement

Un horrible, horrible, horrible, dégoûtant, solution de contournement que j'avais utilisé était de démarrer une minuterie pendant OnShow, et puis quand le compte à rebours incendies, de maximiser la forme:

procedure TForm1.tmrVclMaximizeHackTimer(Sender: TObject);
begin
   Self.WindowState := wsMaximized;
end;

Plus tard, j'ai amélioré ce hack pour poster un message lors de la OnShow; ce qui est essentiellement le même comme un message de la minuterie, sans avoir à utiliser un timer:

const
  WM_MaximizeWindow = WM_APP + $03;

procedure TForm1.FormShow(Sender: TObject);
begin
  if (Self.WindowState = wsMaximized) then
  begin
     Self.WindowState := wsNormal;
     PostMessage(Self.Handle, WM_MaximizeWindow , 0, 0);
  end;
end;

private
   procedure WMMaximizeWindow(var Message: TMessage); message WM_MaximizeWindow;

procedure TForm1.WMMaximizeWindow(var Message: TMessage);
begin
   Self.WindowState := wsMaximized;
end;

Parfois j'invente l' OnAfterShow événement que Delphi n'a jamais fait:

const
  WM_AfterShow = WM_APP + $02;

procedure TForm1.FormShow(Sender: TObject);
begin
  PostMessage(Self.Handle, WM_AfterShow, 0, 0);
  if (Self.WindowState = wsMaximized) then
  begin
     Self.WindowState := wsNormal;
     FMaximizeNeeded := True;
  end;
end;

private
   procedure WMAfterShow(var Message: TMessage); message WM_AfterShow;

procedure TForm1.WMAfterShow(var Message: TMessage);
begin
   if FMaximizeNeeded then
   begin    
      FMaximizeNeeded := False;
      Self.WindowState := wsMaximized;
   end;
end;

Mais pas de hacks sont mieux que les hacks.

13voto

kobik Points 10922

Je Peux reproduire avec D7/Win7.

Je n'utilise pas d' wsMaximized à tous (similaire aléatoire des problèmes que vous décrivez).

Solution de contournement: utiliser OnActivate -> ShowWindow(Handle, SW_MAXIMIZE) par exemple:

procedure TForm1.FormActivate(Sender: TObject);
begin
  // Maximize only once when the Form is first activated
  if not FMaxsimized then
  begin
    FMaxsimized := True;
    ShowWindow(Handle, SW_MAXIMIZE);
  end;
end;

Cette méthode va pas travailler pendant OnShow.

Meilleure Solution: utiliser ShowWindowAsync cours OnShow ou OnCreate e.g:

procedure TForm1.FormCreate(Sender: TObject);
begin
  ShowWindowAsync(Handle, SW_MAXIMIZE);
end;

Cela définit l'état d'affichage d'une fenêtre sans attendre la fin de l'opération.

10voto

Sertac Akyuz Points 32656

J'ai testé uniquement le premier cas de reproduction (avec D7, D2007, XE2), et je suis en mesure de reproduire le problème avec la D7 et D2007 mais pas avec XE2.

Le problème, comme je le vois, c'est que l'étiquette, avoir sa police changé, demande à sa mère de ré-aligner. Ceci conduit finalement à un SetWindowPos appel sur le formulaire (en TWinControl.AdjustSize) avec restauré largeur/hauteur même si la forme est déjà à son maximum - ce qui conduit à l'étrange, sur le plan comportemental maximisée, mais pas visuellement agrandie, forme, assis sur l'écran.


J'ai tracé le code dans D2007 et XE2 à être en mesure de venir avec ce qui est différent. Le code en TWinControl.AlignControls qui est différent entre les deux versions. Ce qui importe, c'est la dernière instruction.

D2007:

procedure TWinControl.AlignControls(AControl: TControl; var Rect: TRect);

  ..
  { Apply any constraints }
  if Showing then AdjustSize;
end;

XE2:

procedure TWinControl.AlignControls(AControl: TControl; var Rect: TRect);

  ..
    // Apply any constraints
    if FAutoSize and Showing then
      DoAdjustSize;
end;

J'espère que ce n', en quelque sorte, vous aide à concevoir/décider quelle solution utiliser.



La solution de contournement que j'ai pu suggérer (bien que je n'ai pas testé beaucoup) est à force de montrer la forme agrandie au début:

procedure TForm1.FormCreate(Sender: TObject);
var
  wplc: TWindowPlacement;
begin
  if not AutoScroll and (WindowState = wsMaximized) then begin
    wplc.length := SizeOf(wplc);
    GetWindowPlacement(Handle, @wplc);
    wplc.rcNormalPosition.Right := wplc.rcNormalPosition.Left + Width;
    wplc.rcNormalPosition.Bottom := wplc.rcNormalPosition.Top + Height;
    wplc.showCmd := SW_MAXIMIZE;
    SetWindowPlacement(Handle, @wplc);
  end;
end;

Les travaux ci-dessus, parce que ça oblige à définir le focus sur le contrôle d'édition (OnEnter cas) avant la VCL définit le visible drapeau pour la forme. À son tour, l'étiquette de l'alignement de la demande n'aboutit pas à la formule d'ajustement de la taille. Aussi, depuis le temps de la VCL appels ShowWindow de la fenêtre du formulaire est déjà visible, il ne cause pas la forme pour être montré dans un état restauré à tout moment.

Cependant, je ne sais pas si cela peut aider avec différents scénarios de reproduction.


Enfin, bien que je ne peux voir que le problème est corrigé dans les plus récentes versions de Delphi, je n'aurais pas considérer cela comme un bug dans la VCL. À mon avis, le code de l'utilisateur devrait être responsable de ne pas causer de la fenêtre d'ajustement lors de la fenêtre montrant l'état est en train de changer. Le cours de l'action que je voudrais prendre pour le scénario consisterait à reporter à modifier l'étiquette de police jusqu'à ce que la VCL est fait de l'affichage de la forme.

1voto

gordy Points 2653

Je ne pense pas que ce soit un bug dans Delphi, mais plutôt d'un bug (ou juste étrange comportement) dans les Fenêtres de la fonction CreateWindow. Si vous recherchez CreateWindow et WS_MAXIMIZE ne fonctionne pas, vous trouverez de même très vieux fils et discussions avec des gens en les appelant CreateWindow ou CreateWindowEx passant WS_MAXIMIZE dans le paramètre de style et de ne pas voir une fenêtre agrandie lors de l'exécution de l'application.

Extrait d'un vieux gamedev.net fil

le problème est que WS_MAXIMIZE apparemment ne s'applique pas lors de l'utilisation de WS_OVERLAPPEDWINDOW. si vous remplacez WS_OVERLAPPEDWINDOW avec WS_POPUP, vous obtiendrez une fenêtre agrandie. bien sûr, cela peut ne pas s'appliquer à toutes les versions de Windows, ou même toutes les versions de Windows, l'INTERFACE utilisateur du shell pour cette question.

WS_OVERLAPPEDWINDOW est MS de l'ancienne fenêtre par défaut "type" et, apparemment, ils codé CreateWindow/Ex à ignorer certains styles, pensant que ShowWindow serait appelé à SW_SHOWDEFAULT, ce qui provoque la fenêtre à afficher en fonction de la CreateProcess de démarrage info parms. finalement, cela donne à l'utilisateur le contrôle de la façon dont une application de la fenêtre principale sera affiché en utilisant le shell le raccourci de paramètres.

La solution de contournement est juste pour appeler ShowWindow. Il faut travailler dans Delphi, trop:

procedure TForm1.FormShow(Sender: TObject);
begin
   ShowWindow(Handle, SW_MAXIMIZE);
end;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X