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

Windows Discussion :

[WIN32] Richedits avec style visuel XP ?


Sujet :

Windows

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 5
    Points
    5
    Par défaut [WIN32] Richedits avec style visuel XP ?
    Bonjour à tous,

    J'ai une petite contrariété avec les RichEdits : ils ne prennent pas l'apparence XP, comme les edits normaux. Dixit MSDN : "To use visual styles with these controls, an application must include a manifest and must call InitCommonControls at the beginning of the program."

    Il se trouve que j'intègre effectivement un manifest dans mon exe et que j'appelle bien InitCommonControls au début de mon programme, que j'utilise un RICHEDIT_CLASS correspondant à L"RichEdit20W" (vérifié après passage du préprocesseur), et qu'il n'a pas le style XP à l'exécution. J'ai ensuite essayé avec un MSFTEDIT_CLASS (soit L"RICHEDIT50W"), et le style XP n'est pas pris en compte non plus.

    Quid ?

    PS : j'avais posté précédemment dans le forum "Visual C++", mais ce message est davantage à sa place ici... désolé

  2. #2
    Membre habitué Avatar de ken_le_videur
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 129
    Points : 145
    Points
    145
    Par défaut
    Si je ne m'abuse, InitCommonControls ne charge pas le contrôle richedit car celui ci est dans une dll à part ( riched32.dll il me semble). Essaye de chargerla dll à la main.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Effectivement, il faut bien charger les librairies des richedits manuellement (msftedit.dll pour un MSFTEDIT_CLASS, riched20.dll pour les autres). Mais je l'ai déjà fait, puisque je constate que mon contrôle apparaît sans styles XP (sinon il ne serait pas créé du tout).

  4. #4
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 671
    Points
    10 671
    Billets dans le blog
    3
    Par défaut
    Ca consiste en quoi le style XP sur un richedit ? D'après cet article:
    http://www.codeguru.com/Cpp/controls/richedit/conversions/print.php/c8729__1/
    ca consiste en rien car le richedit n'a pas de style particulier sous XP.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    C'est ce que je pensais aussi mais la MSDN semble dire le contraire... Je vais essayer d'adapter ce code MFC en API, merci pour le lien

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    J'ai adapté le code en C, mais il subsiste un petit bug qui fait qu'une application sans manifest (et donc, non censée utiliser les thèmes XP) dessine malgré tout les richedits avec l'apparence XP, ce qui fait un peu tache au milieu des autres composants...

    D'après la MSDN, je devrais utiliser la fonction IsAppThemed et/ou IsThemeActive. Je les ai donc importées et utilisées lors de la réception du message WM_THEMECHANGED mais elles retournent toujours TRUE, indifféremment avec ou sans manifest.

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/functions/isappthemed.asp
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/functions/isthemeactive.asp

    Y'a t'il autre chose à faire :

  7. #7
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 671
    Points
    10 671
    Billets dans le blog
    3
    Par défaut
    WM_THEMECHANGED normalement tu le reçois quand le theme change. Je ne crios pas que tu le reçois au lancement de ton app.

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Effectivement, mais j'ai "triché" et je me l'envoie lors de WM_NCCREATE (ce qui marche très bien, j'ai d'ailleurs super-classé les richedits avant de les créer au lieu de les sous-classer un par un comme dans le code du lien, je trouve çà plus transparent).

    En gros, la nouvelle procédure des richedits ressemble à ceci :
    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
    static LRESULT CALLBACK WndProcRichXP(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
      /* appel de l'ancienne procédure */
      LRESULT lResult = CallWindowProc(WndProcRichEdit, hWnd, uMsg, wParam, lParam);
      switch (uMsg) {
        /* le thème courant, si NULL on laisse le richedit se dessiner seul (thèmes indisponibles) sinon on le fait nous-même (look XP) */
        static HTHEME hTheme = NULL;
      case WM_NCCREATE:
        /* le richedit s'envoie un WM_THEMECHANGED */
        SendMessage(hWnd, WM_THEMECHANGED, 0, 0);
        return TRUE;
      case WM_NCCALCSIZE:
        /* calcul de la taille de la bordure, ou traitement par défaut (thèmes non chargés) */
        return WVR_REDRAW;
      case WM_NCPAINT:
        /* dessin de la bordure, ou traitement par défaut (thèmes non chargés) */
        return 0;
      case WM_ENABLE:
      case WM_STYLECHANGED:
        /* faut redessiner la bordure */
        RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
        return 0;
      case WM_THEMECHANGED:
        /* on libère l'ancien thème, le cas échéant */
        if (hTheme != NULL) {
          pCloseThemeData(hTheme);
        }
        /* j'ai essayé un appel à IsAppThemed et IsThemeActive ici en plus du test sur pOpenThemeData, mais ils sont sans effet */
        /* on récupère le nouveau thème */
        if (pOpenThemeData != NULL) {
          hTheme = pOpenThemeData(hWnd, L"EDIT");
        } else {
          hTheme = NULL;
        }
        /* et on positionne les bordures du richedit en fonction du thème : si "look XP" on la dessine, sinon on laisse le richedit le faire */
        if (hTheme != NULL) {
          SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE);
        } else {
          SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_CLIENTEDGE);
        }
        return 0;
      default:
        /* autres messages : ne pas interférer */
        return lResult;
      }
    }
    pOpenThemeData et pCloseData sont des pointeurs de fonctions sur les fonctions éponymes d'uxtheme.dll, et sont valides.

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    J'ai essayé d'utiliser la fonction GetThemeAppProperties en plus des autres, ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        if (pIsThemeActive() != 0
         && pIsAppThemed() != 0
         && (pGetThemeAppProperties() & STAP_ALLOW_NONCLIENT) != 0
         && (pGetThemeAppProperties() & STAP_ALLOW_CONTROLS) != 0
        ) {
          /* mode XP */
          hTheme = pOpenThemeData(hWnd, L"EDIT");
        } else {
          /* mode classique */
          hTheme = NULL;
        }
    Mais rien n'y fait, les richedits sont toujours dessinés avec le style XP malgré l'absence d'un manifest... C'est déprimant

  10. #10
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 671
    Points
    10 671
    Billets dans le blog
    3
    Par défaut
    Si IsThemeActive() renvoie FALSE, tu laisses WndProcRichEdit dessiner le bord, sinon tu le dessines toi.
    Toi tu appelles tout le temps WndProcRichEdit, normalement quand on subclass on appelle l'ancienne wndproc pour les messages qu'on a pas trairé => en place l'appel dans default:.
    Et puis au lieu de t'envoyer WM_THEMECHANGED lors de WM_NCCREATE, tu peux combiner les 2 à la suite. On utilise plutot WM_CREATE que WM_NCCREATE amsi bon. Y'a quoi dans WM_NCPAINT ?

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Aurelien.Regat-Barrel
    tu appelles tout le temps WndProcRichEdit, normalement quand on subclass on appelle l'ancienne wndproc pour les messages qu'on a pas traité
    C'est un fait, mais comme je dois également prendre en compte l'absence de thèmes XP (versions antérieures ou thèmes désactivés), je profite de WM_THEMECHANGED pour activer la bordure du richedit (qui sera alors dessinée par la procédure originale) en l'absence de thèmes, sinon je la désactive et la procédure originale ne fera rien, me laissant ainsi le champ libre (voir plus bas pour le code). Je m'occuperais d'affiner cela plus tard, quand le richedit réagira comme il faut

    Citation Envoyé par Aurelien.Regat-Barrel
    au lieu de t'envoyer WM_THEMECHANGED lors de WM_NCCREATE, tu peux combiner les 2 à la suite
    Tiens c'est pas idiot çà, j'y avais pas pensé...

    Citation Envoyé par Aurelien.Regat-Barrel
    on utilise plutot WM_CREATE que WM_NCCREATE
    Je sais, mais WM_CREATE survient après WM_NCCALCSIZE et comme je dois traiter ce message aussi...

    Citation Envoyé par Aurelien.Regat-Barrel
    Y'a quoi dans WM_NCPAINT ?
    Çà :
    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
        if (hTheme != NULL) {
          INT nStatus = (IsWindowEnabled(hWnd) != 0) ? ETS_NORMAL : ETS_DISABLED;
          hDC = GetWindowDC(hWnd);
          GetWindowRect(hWnd, &rPos);
          SetRect(&rPos, 0, 0, rPos.right - rPos.left, rPos.bottom - rPos.top);
          ExcludeClipRect(hDC, rPos.left + rClip.left, rPos.top + rClip.top, rPos.right - rClip.right, rPos.bottom - rClip.bottom);
          if (pIsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, nStatus) != 0) {
            pDrawThemeParentBackground(hWnd, hDC, &rPos);
          }
          pDrawThemeBackground(hTheme, hDC, EP_EDITTEXT, nStatus, &rPos, NULL);
          ReleaseDC(hWnd, hDC);
          return 0;
        } else {
          return lResult;
        }
    Autrement dit, si on a pu charger un thème lors du traitement de WM_THEMECHANGED, alors on le dessine. Sinon, on ne fait rien.

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Bon, j'ai finalement trouvé... Il "suffit" de vérifier la version de comctl32.dll mappée dans notre processus : avec un manifest on a la version 6 ou plus, sans manifest on a la version 5.

    Merci pour votre aide

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

Discussions similaires

  1. pb avec composant visuel créé dynamiquement
    Par richard038 dans le forum Composants VCL
    Réponses: 9
    Dernier message: 12/08/2005, 09h59
  2. (Débutant API) Utilisation de Richedit avec les APIs
    Par LibrairieSI dans le forum Windows
    Réponses: 2
    Dernier message: 10/08/2005, 16h53
  3. Appliquer le style visuel de Windows XP
    Par daladim dans le forum MFC
    Réponses: 1
    Dernier message: 02/06/2005, 21h46
  4. Fonction "CreateElement" avec style sous Firebird
    Par protos69 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 24/11/2004, 17h30
  5. [API WIN32] Pb avec SHGetSpecialFolderLocation
    Par Invité dans le forum MFC
    Réponses: 3
    Dernier message: 27/01/2004, 21h19

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