IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API, COM et SDKs Delphi Discussion :

THintWindow, DrawText DT_CALCRECT


Sujet :

API, COM et SDKs Delphi

  1. #1
    rbh
    rbh est déconnecté
    Membre confirmé Avatar de rbh
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    384
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2004
    Messages : 384
    Points : 473
    Points
    473
    Par défaut THintWindow, DrawText DT_CALCRECT
    Bonjour,
    (Delphi 11.3; appli VCL)

    Je dois modifier l'aspect des bulles d'aide dans mon programme, et je n'ai pas de résultat consistant avec DrawText et DT_CALCRECT.

    Je reproduis exactement les même bugs avec un projet presque vide (juste des TButton avec des Hint contenant plusieurs mots).

    Dans CalcHintRect, je récupère le clientRect, j'appelle DrawTExt avec CALCRECT pour que la fonction modifie le Rect qui est passé en VAR et ensuite j'Inflate le Rect pour avoir les marges voulue.
    Puis dans le Paint je récupère le ClientRect Inflate inverse pour prendre en compte les marges puis je dessine le texte.

    Le premier appel calcul un rect qui fait (0,0,0,0) mais ne renvoie pas 0 pour indiquer un échec, et même ensuite, le résultat du DrawText appelé dans le PAINT est différent avec une bulle souvent trop petite mais parfois trop grande, le saut de ligne à un endroit différent, ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
      TMyHintWindow = class(THintWindow)
      protected
        procedure Paint; override;
      public
        function CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect; override;
      end;
     
    implementation
     
     
    { TMyHintWindow }
    const
      MargeVert  = 4;
      MargeHorz  = 8;
      FontName   = 'Segoe UI';
      FontHeight = -14;
     
    function TMyHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect;
    begin
      MaxWidth := 1000;
     
      Result := inherited CalcHintRect(MaxWidth, AHint, AData);
     
      if DrawText(Canvas.Handle, PChar(Caption), -1, Result, DT_LEFT or DT_NOPREFIX or DT_WORDBREAK or DT_CALCRECT) = 0 then
        Raise Exception.create('échec DrawText');
      Result.Inflate(MargeHorz, MargeVert, MargeHorz, MargeVert);
    end;
     
    procedure TMyHintWindow.Paint;
    var
      ARect: TRect;
    begin
      //inherited;
      ARect := ClientRect;
     
      Canvas.Brush.Color := clTeal;
      Canvas.RoundRect(ARect, 4, 4);
     
      ARect.Inflate(-MargeHorz, -MargeVert, -MargeHorz, -MargeVert);
      DrawText(Canvas.Handle, PChar(Caption), -1, ARect, DT_LEFT or DT_NOPREFIX or DT_WORDBREAK or DT_NOCLIP);
    end;
     
    initialization
      HintWindowClass := TMyHintWindow;
      Screen.HintFont.Name := FontName;
      Screen.HintFont.Height := FontHeight;
     
    end.
    EDIT : Dans le code ci dessus, remplacer PChar(Caption) par PChar(AHint) dans la fonction CalcHintRect.
    Merci dvp.com

    Nom : infobulle.png
Affichages : 118
Taille : 14,4 Ko

    Comme vous pouvez le voir, le résultat n'est pas toujours identique.

    J'ai essayé de modifier Screen.HintFont à d'autres endroits, ça ne change rien. Avant de trouver HintFont j'assignais Canvas.Font.name et Canvas.Font.Height dans les 2 procédures avant le DrawText, même résultat.
    Qu'est ce que je peux faire différemment pour résoudre mon problème ?

    Bonus : comment bloquer le dessin de l'ancêtre ?
    Je pensais que commenter le inherited dans le Paint suffirait.

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 522
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 522
    Points : 25 049
    Points
    25 049
    Par défaut
    J'ai constaté le même défaut avec le TSysTooltipsStyleHook de Rodrigo Ruz V. - https://github.com/RRUZ/vcl-styles-utils/

    le changement de font fait que cela dépasse du cadre.

    Tu dois faire un TextHeight et TextWidth pour calculer la nouvelle taille du texte + bordure et tout redessiner mais tu perdras l'ombrage
    C'est ce que tu fais via DT_WORDBREAK

    Le problème c'est clairement que la hauteur calculée n'est pas la même que la hauteur réelle, tu devrais modifier le rectangle limite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function TMyHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect;
    begin
      MaxWidth := 1000;
     
      Result := inherited CalcHintRect(MaxWidth, AHint, AData);
      Result.width := Result.width - MargeHorz * 2; // en particulier la largeur qui impact DT_WORDBREAK 
     
      if DrawText(Canvas.Handle, PChar(Caption), -1, Result, DT_LEFT or DT_NOPREFIX or DT_WORDBREAK or DT_CALCRECT) = 0 then
        Raise Exception.create('échec DrawText');
      Result.width := Result.width + MargeHorz * 2;
      Result.Inflate(MargeHorz, MargeVert, MargeHorz, MargeVert);
    end;

    Dans un autre code j'avais totalement bidouillé MaxWidth pour éviter le retour à la ligne en favorisant un hint plus large

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    //---------------------------------------------------------------------------
    void __fastcall TVCLManipForm::ApplicationEventsHint(TObject *Sender)
    {
      StatusBarVCLManip->Panels->Items[0]->Text = Application->Hint; // ApplicationEvents OnHint annule ce comportement par défaut
     
      for (int i = this->ComponentCount - 1; i >= 0; i--)
      {
        if (this->Components[i]->InheritsFrom(__classid(THintWindow)))
        {
          ((THintWindow*)this->Components[i])->ReleaseHandle();
          delete this->Components[i];
        }
      }
     
      if ( ! Application->Hint.IsEmpty())
      {
        TPoint PM;
        if (GetCursorPos(&PM))
        {
          HWND HandleControl = WindowFromPoint(PM);
          if (HandleControl)
          {
            char lpRes[255];
            if (GetClassName(HandleControl, lpRes, sizeof(lpRes)))
            {
              if (SameText(StrPas(lpRes), "#32768"))
              {
                TRect MenuRect;
                if (GetWindowRect(HandleControl, &MenuRect))
                {
                  MenuRect.Left = MenuRect.Left + MenuRect.Width();
     
                  THintWindow * HintForm = new THintWindow(this); // ne pas oublier de faire un ReleaseHandle et Free dans un Timer par exemple
                  HintForm->Color = clInfoBk;
     
                  TRect HintRect = HintForm->CalcHintRect(Screen->WorkAreaWidth / 2, Application->Hint, NULL);
                  HintForm->ActivateHint(Rect(MenuRect.Left + 4, PM.y, MenuRect.Left + 4 + HintRect.Width(), PM.y + HintRect.Height()), Application->Hint);
                }
              }
            }
          }
        }
      }
    }
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    rbh
    rbh est déconnecté
    Membre confirmé Avatar de rbh
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    384
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2004
    Messages : 384
    Points : 473
    Points
    473
    Par défaut
    Merci ShaiLeTroll pour ta réponse.

    Après validation avec les pouvoirs supérieurs, j'ai supprimé WORDBREAK des Flags pour diminuer les risques.
    Ça va mieux, je n'ai plus de problème de hauteur, mais la largeur me pose toujours des soucis.

    J'ai fait des essais avec TextWidth (et aussi TextExtent avant de supprimer wordbreak), et les résultats sont différents mais toujours pas bon.

    Ce qui me perturbe le plus est le premier appel d'une exécution me renvoie toujours ~ 0 que ce soit avec DrawText(CALCRECT) ou Text[Extent/Width/Height]

    Je continue donc mes recherches en me concentrant sur GetTextExtentPoint32 (appelé par TextExtent) mais sans limiter mes résultats à Delphi.

    Je viendrais ajouter la solution si je me débloque.

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 742
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 742
    Points : 13 295
    Points
    13 295
    Par défaut
    Es-tu sûr que Caption est déjà initialisé avant CalcHintRect ? Si il y a un paramètre AHint ce n'est certainement pas par hasard

  5. #5
    rbh
    rbh est déconnecté
    Membre confirmé Avatar de rbh
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    384
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2004
    Messages : 384
    Points : 473
    Points
    473
    Par défaut
    Oh quel id**t je suis !

    Merci Andnotor !


+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. DrawText
    Par nac dans le forum MFC
    Réponses: 5
    Dernier message: 07/04/2006, 09h38
  2. [MFC] Drawtext vertical
    Par ouquoi dans le forum MFC
    Réponses: 15
    Dernier message: 10/02/2006, 15h01
  3. DrawText()
    Par johspi dans le forum MFC
    Réponses: 1
    Dernier message: 21/03/2005, 11h19
  4. Réponses: 2
    Dernier message: 21/03/2005, 10h17
  5. [THintwindow] Erreur à la compilation
    Par jpc34 dans le forum C++Builder
    Réponses: 1
    Dernier message: 28/10/2004, 12h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo