[Tuto] Programme multilingue sous windows

Informations pour bien débuter en PureBasic
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

[Tuto] Programme multilingue sous windows

Message par Dr. Dri »

Voila mon premier vrai tuto pour la comunauté! Ca s'adresse à ceux à l'aise avec l'api win32 pour la plupart des explications à venir mais comme je donne du code tout fait n'importe qui peut venir piocher ici.

Pour commencer, je vais énumérer quelques solutions et voir les avantages de chacune:
  • Directement dans le code
    directement intégré à l'exécutable (limite les risques de perte)
    pas évident de s'y retrouver
    code source lourd
    modifier nécessite de recompiler le tout
  • Dans des fichiers ini/pref
    facile de modifier/ajouter une langue
    il faut que tous les fichiers soit synchronisés/maintenus
  • Dans des ressources
    directement intégré à l'exécutable
    langue par défaut gérée automatiquement

    uniquement disponible sous windows
    modifier nécessite de recompiler le tout (même pas vrai =)
    et d'autres que je ne citerais pas ici
  • Dans des ressources externes (fichiers dll)
    facile de modifier/ajouter une langue
    uniquement disponible sous windows
    il faut que tous les fichiers soit synchronisés/maintenus
Je n'aime pas les solutions avec des fichiers externes parce que ça peut vite devenir un bordel pas possible. Imaginez que vous avez un programme distribué en 15 langues et qu'il fonctionne avec des plugins optionnels eux-même déclinés en une quinzaine de langues.

L'inconvénient de tout intégrer à l'exécutable est que celui-ci pèse plus lourd mais le double avatange des ressources et de prendre moins de place que du code+datasection et que windows ne mappe les ressources en mémoire que si celles-ci sont utilisées.

Maintenant le dernier problème (en fait y'en a encore d'autres =) qui se pose à nous est que puisqu'on utilise l'api win32 on va obtenir des identifiants systèmes et pas des objets utilisables avec les fonctions natives de purebasic. Comme chui un mec sympa j'ai fait deux fonctions pour obtenir une Image PB à partir d'une ressource icon/cursor/bitmap et un Menu/PopupMenu PB à partir d'une ressource menu.

Code : Tout sélectionner

Structure PB_MenuStructure
  MenuID.l
  WindowID.l
EndStructure

Procedure.l HackImage(Image.l, ImageID.l)
  Protected *ImageID.Long, Index.l
  Protected ic.IconInfo, bm.Bitmap
  
  If ImageID And Not GetIconInfo_(ImageID, ic)
    ic\hbmColor = ImageID
  EndIf
    
  If GetObject_(ic\hbmColor, SizeOf(Bitmap), bm)
    Index = CreateImage(Image, bm\bmWidth, bm\bmHeight, bm\bmBitsPixel)
    If Image <> #PB_Any : Index = Image : EndIf
    
    *ImageID = IsImage(Index)
  EndIf
  
  If *ImageID
    
    DeleteObject_(*ImageID\l)
    *ImageID\l = ImageID
    If Image = #PB_Any
      ImageID = Index
    EndIf
    
  Else
    
    If GetIconInfo_(ImageID, ic)
      If ic\fIcon
        DestroyIcon_(ImageID)
      Else
        DestroyCursor_(ImageID)
      EndIf
    Else
      DeleteObject_(ImageID)
    EndIf
    ImageID = #Null
    
  EndIf
  
  ProcedureReturn ImageID
EndProcedure

Procedure.l HackMenu(Menu.l, MenuID.l, WindowID.l = #Null)
  Protected Index.l, *Menu.PB_MenuStructure
  
  If MenuID
    Index = CreatePopupMenu(Menu)
    If Menu <> #PB_Any : Index = Menu : EndIf
    *Menu = IsMenu(Menu)
  EndIf
  
  If *Menu
    SetMenu_(WindowID, MenuID)
    DestroyMenu_(*Menu\MenuID)
    *Menu\MenuID = MenuID
    *Menu\WindowID = WindowID
    If Menu = #PB_Any
      MenuID = Index
    EndIf
  Else
    DestroyMenu_(MenuID)
    MenuID = #Null
  EndIf
  
  ProcedureReturn MenuID
EndProcedure
Puisqu'on prépare le terrain autant le faire jusqu'au bout : le but de ce tuto est de proposer une solution pour programme multilingue, mais cette solution doit inclure la possibilité de changer de langue. J'ai opté pour gérer les langues de façon automatique, et j'ai volontairement décidé de ne pas gérer les sous-langues. Comme les langues sont gérées de façon automatique, voila de quoi changer la langue du programme.

Code : Tout sélectionner

Global ProgramLocale.l = #LANG_NEUTRAL

ProcedureDLL.l GetProgramLocale()
  ProcedureReturn ProgramLocale
EndProcedure

ProcedureDLL.l SetProgramLocale(Locale.l)
  Swap ProgramLocale, Locale
  ProcedureReturn Locale
EndProcedure
Les plus attentifs auront remarqué une constante, la fameuse langue par défaut. Comme toutes les langues ne sont pas définies dans PB voila une petite liste :

Code : Tout sélectionner

Enumeration
  #LANG_NEUTRAL
  #LANG_ARABIC
  #LANG_BULGARIAN
  #LANG_CATALAN
  #LANG_CHINESE
  #LANG_CZECH
  #LANG_DANISH
  #LANG_GERMAN
  #LANG_GREEK
  #LANG_ENGLISH
  #LANG_SPANISH
  #LANG_FINNISH
  #LANG_FRENCH
  #LANG_HEBREW
  #LANG_HUNGARIAN
  #LANG_ICELANDIC
  #LANG_ITALIAN
  #LANG_JAPANESE
  #LANG_KOREAN
  #LANG_DUTCH
  #LANG_NORWEGIAN
  #LANG_POLISH
  #LANG_PORTUGUESE
  #LANG_ROMANIAN   = 24
  #LANG_RUSSIAN
  #LANG_CROATIAN
  #LANG_SERBIAN    = 26
  #LANG_SLOVAK
  #LANG_ALBANIAN
  #LANG_SWEDISH
  #LANG_THAI
  #LANG_TURKISH
  #LANG_URDU
  #LANG_INDONESIAN
  #LANG_UKRAINIAN
  #LANG_BELARUSIAN
  #LANG_SLOVENIAN
  #LANG_ESTONIAN
  #LANG_LATVIAN
  #LANG_LITHUANIAN
  #LANG_FARSI      = 41
  #LANG_VIETNAMESE
  #LANG_ARMENIAN
  #LANG_AZERI
  #LANG_BASQUE
  #LANG_MACEDONIAN = 47
  #LANG_AFRIKAANS  = 54
  #LANG_GEORGIAN
  #LANG_FAEROESE
  #LANG_HINDI
  #LANG_MALAY      = 62
  #LANG_KAZAK
  #LANG_SWAHILI    = 65
  #LANG_UZBEK      = 67
  #LANG_TATAR
  #LANG_BENGALI
  #LANG_PUNJABI
  #LANG_GUJARATI
  #LANG_ORIYA
  #LANG_TAMIL
  #LANG_TELUGU
  #LANG_KANNADA
  #LANG_MALAYALAM
  #LANG_ASSAMESE
  #LANG_MARATHI
  #LANG_SANSKRIT
  #LANG_KONKANI    = 87
  #LANG_MANIPURI
  #LANG_SINDHI
  #LANG_KASHMIRI
  #LANG_NEPALI
EndEnumeration
A suivre : les ressources, on fait comment ? ^_^

Dri