Page 1 sur 3

Tab pour un alinéa dans EditorGadget

Publié : lun. 06/sept./2004 18:18
par Aranoth
Bonjour !

J'aimerait que dans un EditorGadget, TAB fasse un aliné au lieu de donner le focus a un autre element !

Comme dans PureBASIC par exemple, ou comme le NotePad...

Merci :wink:

Publié : lun. 06/sept./2004 19:24
par Dr. Dri
il me semble qu'on a acces aux sources de l'éditeur PB
d'ailleurs si quelqu'un confirme j'aimerais savoir où :)

Dri

[edit]
ca n'a pas été difficile de trouver les sources...
http://www.purebasic.com/download/examples/Editor.zip

maintenant faut chercher dedans pour trouver comment c'est géré ^^

Dri ;)

Publié : lun. 06/sept./2004 19:34
par Dr. Dri
j'ai trouvé cette procedure, faut que je trouve aussi son appel...

Code : Tout sélectionner

Procedure EditorKeyHandler(VirtualKey)
  Shared VK_ReturnState

  If VirtualKey = #VK_RETURN And VK_ReturnState = 0
  
    PreviousCursorX = CursorPositionX-1
    
    SyntaxHighlighting()
        
    *Line = AllocateMemory(#MEM_KEYHANDLER1, 2000, 0)
    PokeW(*Line, 1000)
    
                    SendMessage_(*RichEditGadget, #EM_GETSEL        , @StartPosition, 0)
    StartPosition = SendMessage_(*RichEditGadget, #EM_EXLINEFROMCHAR, 0             , StartPosition)
                    SendMessage_(*RichEditGadget, #EM_GETLINE       , StartPosition , *Line)   ; Get the current line buffer..
    
    VK_ReturnState = 1 ; Very tricky. This inform the WindowCallback to ignore the following #VK_RETURN return, else it's a dead loop
    
    SendMessage_(*RichEditGadget, #WM_KEYDOWN, #VK_RETURN, 1)
    
    ClearEffects() ; Reset all the font effects for the newline..
    
    *Cursor.Byte = UseMemory(#MEM_KEYHANDLER1)
    While *Cursor\b = ' ' And PreviousCursorX > 0   ; Insert space at the start of the newline (auto-indent)
      SendMessage_(*RichEditGadget, #WM_CHAR, ' ', 1)
      *Cursor+1
      PreviousCursorX-1
    Wend
    
    FreeMemory(#MEM_KEYHANDLER1)
    
  ElseIf VirtualKey = #VK_TAB
  
    If GetKeyState_(#VK_SHIFT) < 0
      ShiftMode = 1
    Else
      ShiftMode = 0
    EndIf
  
                       SendMessage_(*RichEditGadget, #EM_GETSEL        , @StartPosition, @EndPosition)
    FirstLineIndex   = SendMessage_(*RichEditGadget, #EM_EXLINEFROMCHAR, 0             , StartPosition)
    LastLineIndex    = SendMessage_(*RichEditGadget, #EM_EXLINEFROMCHAR, 0             , EndPosition)
    LastLinePosition = SendMessage_(*RichEditGadget, #EM_LINEINDEX     , LastLineIndex , 0)
  
    *Buffer = AllocateMemory(#MEM_KEYHANDLER2, EndPosition-StartPosition, 0)

    If LastLinePosition = EndPosition And LastLineIndex <> FirstLineIndex ; Needed to handle the case where the selection is at the very end of the
      LastLineIndex-1                                                      ; line and then the new line is take in count too.
    EndIf

    If FirstLineIndex <> LastLineIndex  ; Block indent when pressing TAB

      For k=FirstLineIndex To LastLineIndex

        LineIndex  = SendMessage_(*RichEditGadget, #EM_LINEINDEX , k        , 0)
        LineLength = SendMessage_(*RichEditGadget, #EM_LINELENGTH, LineIndex, 0)

        If LineLength > 0 And OldLineIndex+LineLength+1 <> EndPosition

          If ShiftMode
            If TabLength > LineLength
              RealTabLength = LineLength
            Else
              RealTabLength = TabLength
            EndIf

            SendMessage_(*RichEditGadget, #EM_SETSEL    , LineIndex, LineIndex+RealTabLength)
            SendMessage_(*RichEditGadget, #EM_GETSELTEXT, 0        , *Buffer)

            Counter = RealTabLength
            *Cursor = *Buffer
            While (*Cursor\b = 9 Or *Cursor\b = ' ') And Counter
              *Cursor+1
              Counter-1
            Wend
            
            If Counter < RealTabLength
              SendMessage_(*RichEditGadget, #EM_SETSEL, LineIndex, LineIndex+RealTabLength-Counter)
              SendMessage_(*RichEditGadget, #EM_REPLACESEL, 1, "")
            EndIf

            Offset-(RealTabLength-Counter)
          Else
            SendMessage_(*RichEditGadget, #EM_SETSEL, LineIndex, LineIndex) ; Cursor to the beginning of the line
                   
            ClearEffects() ; Reset all the font effects for the newline..

            SendMessage_(*RichEditGadget, #EM_REPLACESEL, 1, Space(TabLength))
            
            Offset+TabLength
          EndIf
        EndIf
      Next

      SendMessage_(*RichEditGadget, #EM_SETSEL, StartPosition, EndPosition+Offset)
    Else
      ClearEffects()  ; Reset all the font effects for start of the newline..

      RealTabLength = TabLength-MOD(CursorPositionX-1, TabLength)  ; Smart indent
      
      SendMessage_(*RichEditGadget, #EM_REPLACESEL, 1, Space(RealTabLength))
    EndIf
 
 Else 
   VK_ReturnState = 0
 EndIf
   
EndProcedure
Dri

Publié : lun. 06/sept./2004 19:48
par nico

Code : Tout sélectionner

  SetWindowLong_(GadgetID(0),#gwl_style,GetWindowLong_(GadgetID(0),#gwl_style)-#ws_tabstop)
Cette ligne permet de supprimer le changement du focus lors de l'appui sur la touche Tab, mais alors après... :?

Publié : lun. 06/sept./2004 20:15
par Aranoth
J'avais jamais tilter que l'IDE de PB était OpenSource^^ merci Dri :wink:

J'ai essayé le code de Nico (merci à toi !) et ca marche bien, après suffit d'ajouter quelques espaces à l'emplacement du curseur.

Mais comment connaitre l'emplacement du curseur ? c'est pas le role de GetGadgetState()...Et j'ai vu aucunes commandes clair pour cette utilisation dans la doc...

Si qq sais

Publié : lun. 06/sept./2004 20:22
par nico
Oui bien sûr, tu peux facilement ajouter des espaces avec ce code par exemple:

Code : Tout sélectionner

      Case 256
        If EventwParam()=9
          For x=1 To 4
           keybd_event_($20, 0, 0, 0) 
           keybd_event_($20, 0, #KEYEVENTF_KEYUP, 0)
          Next c
        EndIf  
Mais le problème, c'est que ça n'as pas le même comportement qu'un vrai Tabstop qui s'arrête toujours au mêmes endroits quelque soit l'emplacement du curseur.(je sais pas si c'est clair mais disons que c'est pas pareil) :?

:)

Publié : lun. 06/sept./2004 20:32
par Aranoth
je vois ce que tu veut dire oui...
L'alinéa est une entitée à part entière

Remarque j'ai vu que Dreamweaver MX proposait le nombre d'espace composant un alinéa, meme les pros bidouillent :lol:

Mais je ne comprend pas ton code :?

Publié : mer. 08/sept./2004 4:11
par ZapMan
Sendmessage_(GadgetID(0),#EM_GETSEL,@StartS, @EndS)
te permet de récupérer dans les variables StartS et EndS la position de départ et de fin de la sélection courante.

Il y a aussi
Sendmessage_(GadgetID(0),#EM_SETSEL,StartS, EndS)
qui te permet de fixer la sélection aux valeurs que tu souhaites.

Pour simuler une vrai tabulation qui permet de se positionner à un endroit fixe quelque soit l'endroit où l'on est au moment de l'appui, il faut :
- travailler avec une police non-proportionnelle (comme celle utilisée dans PureBasic) pour que tous les caractères aient la même largeur
- compter le nombre de caractères qu'il y a entre StartS et le précédent retour-chariot
- insérer le nombre d'espace nécessaire pour se rendre au point désiré

J'espère que je suis clair.

Publié : mer. 08/sept./2004 13:04
par Aranoth
oui super clair !

Je vais pouvoir implementer ca :P

Merci à tous !

Publié : lun. 20/sept./2004 23:24
par Flype
sinon un truc tout bête :

dans un editorgadget si on tape CTRL+TAB ca fait un vrai 'tab' :wink:

Publié : mar. 21/sept./2004 20:29
par nico
Après expérimentation, ça donne ça:

Code : Tout sélectionner

;nico

  OpenWindow(1,200,200,400,400,#PB_Window_SystemMenu,"Fenêtre principale")
  test=1
  If CreateGadgetList(WindowID(1)) 
    EditorGadget (1,10,40,380,300,#PB_Container_Raised)
  EndIf 
  SetWindowLong_(GadgetID(1),#GWL_STYLE,GetWindowLong_(GadgetID(1),#GWL_STYLE)!#WS_TABSTOP)
  Repeat 
    EventID.l=WaitWindowEvent()
    Select EventID 
      Case #WM_KEYDOWN 
        If EventwParam()=9
          If test=1
            keybd_event_($11, 0, 0, 0)
            keybd_event_($9, 0, #KEYEVENTF_KEYUP, 0)
            keybd_event_($9, 0, 0, 0)
            keybd_event_($11, 0, #KEYEVENTF_KEYUP, 0)
            test=0
          EndIf
        EndIf
                    
      Case #WM_KEYUP       
        If EventwParam()=$11 
          test=1 
        EndIf 
          
      Case #PB_EventGadget
        Select EventGadgetID()
 
        EndSelect
        
      Case #WM_CLOSE
        Quit=1
    EndSelect 
  Until Quit=1

Publié : mar. 21/sept./2004 20:51
par Flype
merci nico c super ce code. ca me servira.
par contre c rigolo parceque maintenant CTRL+Tab çà fait 2 'tab'.

Publié : mar. 21/sept./2004 21:00
par nico
J'avais pas vu, c'est trop fort! :lol:

Publié : mer. 22/sept./2004 11:07
par Aranoth
nickel :D

bravo et merci à toi c'est sur que ca servira^^
:wink:

Publié : dim. 23/janv./2005 14:24
par Aranoth
Désolé de remonter ce vieux sujet, mais je me suis remis à bosser sur mon éditeur de texte.


Pour l'alinéa, j'utilise le code de Nico, mais j'ai un petit problème: l'alinéa est trop grand...

Y'a t'il un moyen de réduire sa taille ? :?


Merci