How do I get Row and Column Positions within a Editor Gadget

Just starting out? Need help? Post your questions and find answers here.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

You're quite welcome. Here's a small implementation:

Code: Select all

OpenWindow(0,0,0,320,240,"",$CF0001)
CreateGadgetList(WindowID(0))
EditorGadget(0,0,0,320,220)
CreateStatusBar(0, WindowID(0))
AddStatusBarField(320)

Restore text
For i=1 To 5
  Read a$
  AddGadgetItem(0,-1, a$)
Next

Repeat
  EventID = WaitWindowEvent()
  If EventID = #WM_LBUTTONUP
      charposinalltext.l 
      SendMessage_(GadgetID(0),#EM_GETSEL,@charposinalltext,0) ; get cursor position in all text 
      currentline=SendMessage_(GadgetID(0),#EM_LINEFROMCHAR,-1,0) ; get the current (0-based) line# 
      currentcolumn = charposinalltext - SendMessage_(GadgetID(0),#EM_LINEINDEX,-1,0) ;get the current charpos on it
      StatusBarText(0,0,"Current Line: "+Str(currentline)+"  Col: "+Str(currentcolumn)) 
  EndIf
Until EventID = #WM_CLOSE
   
DataSection
  text:
  Data.s "There was an old man from Nantucket"
  Data.s "Who kept all his cash in a bucket"
  Data.s "His daughter named Nan"
  Data.s "Ran away with a man"
  Data.s "And as for the bucket, Nantucket"
EndDataSection
Skiller
User
User
Posts: 12
Joined: Sun Oct 08, 2006 8:37 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Skiller »

Hi experts,

Unfortunately I have no experience with "SendMessage_" / API stuff.
But you might be able to help me with this question.

How can I count the lines within the loop "on the fly" without having to click in the editor gadget first?

Code: Select all

;Autor: srod
;http://www.purebasic.fr/english/viewtopic.php?p=173872#p173872

EnableExplicit


Define evMask, i

Procedure Callback(hWnd, uMsg, wParam, lParam)
  Protected result
  Protected *msgf.MSGFILTER
  Protected POINT.POINT
  Protected char
  Protected lineindex
  Protected colindex
  Protected col
  Protected row
  
  Result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_NOTIFY
      *msgf=lParam
      Select *msgf\NMHDR\code
        Case #EN_MSGFILTER   
          Select *msgf\msg
            Case #WM_LBUTTONUP, #WM_KEYUP
              GetCaretPos_(@POINT)
              char = SendMessage_(GadgetID(1), #EM_CHARFROMPOS, 0, @POINT)
              lineindex = SendMessage_(GadgetID(1), #EM_LINEFROMCHAR, char, 0)
              colindex = SendMessage_(GadgetID(1), #EM_LINEINDEX, lineindex, 0)
              col = char-colindex
              row = lineindex + 1
              Debug "(" + Str(col) + ", " + Str(row) + ")"
          EndSelect
      EndSelect
  EndSelect
  ProcedureReturn Result
EndProcedure


If OpenWindow(0, 0, 0, 250, 200, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  EditorGadget(1, 10, 10, WindowWidth(0)-20, WindowHeight(0)-20, #PB_Editor_WordWrap)
  SetActiveGadget(1) ;Focus auf den Editor
  
  evMask = SendMessage_(GadgetID(1), #EM_GETEVENTMASK, 0, 0)
  SendMessage_(GadgetID(1), #EM_SETEVENTMASK, 0, evMask | #ENM_KEYEVENTS | #ENM_MOUSEEVENTS )
  SetWindowCallback(@Callback())
  
 ;---------------------------------------------------- 
 ;How can I count the lines within the loop on the fly
 ;----------------------------------------------------  
  For i = 0 To 40
    SetGadgetText(1,GetGadgetText(1)+Str(i))    
  Next
 ;----------------------------------------------------  
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf


Thx !!!!
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Axolotl »

hi skiller,
counting lines is actually one of the few things you can do in an editor gadget without an api.
Anyway, I add both ways to your code. See below.

Code: Select all

;Autor: srod
;http://www.purebasic.fr/english/viewtopic.php?p=173872#p173872

EnableExplicit

Define evMask, i

Procedure Callback(hWnd, uMsg, wParam, lParam)
  Protected result
  Protected *msgf.MSGFILTER
  Protected POINT.POINT
  Protected char
  Protected lineindex
  Protected colindex
  Protected col
  Protected row
  
  Result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_NOTIFY
      *msgf=lParam
      Select *msgf\NMHDR\code
        Case #EN_MSGFILTER   
          Select *msgf\msg
            Case #WM_LBUTTONUP, #WM_KEYUP
              GetCaretPos_(@POINT)
              char = SendMessage_(GadgetID(1), #EM_CHARFROMPOS, 0, @POINT)
              lineindex = SendMessage_(GadgetID(1), #EM_LINEFROMCHAR, char, 0)
              colindex = SendMessage_(GadgetID(1), #EM_LINEINDEX, lineindex, 0)
              col = char-colindex
              row = lineindex + 1 
              
              Debug "(" + Str(col) + ", " + Str(row) + ")"
              Debug "PB  Count == " + CountGadgetItems(1) ; <------------------------------------------ solution 1 
              Debug "API Count == " + SendMessage_(*msgf\nmhdr\hwndFrom, #EM_GETLINECOUNT, 0, 0) ; <--- solution 2 

Debug "Compare: " + GadgetID(1) + "  " + *msgf\nmhdr\hwndFrom + " ; <-- same window handle !!"

              
          EndSelect
      EndSelect
  EndSelect
  ProcedureReturn Result
EndProcedure


If OpenWindow(0, 0, 0, 250, 200, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  EditorGadget(1, 10, 10, WindowWidth(0)-20, WindowHeight(0)-20, #PB_Editor_WordWrap)
  SetActiveGadget(1) ;Focus auf den Editor
  
  evMask = SendMessage_(GadgetID(1), #EM_GETEVENTMASK, 0, 0)
  SendMessage_(GadgetID(1), #EM_SETEVENTMASK, 0, evMask | #ENM_KEYEVENTS | #ENM_MOUSEEVENTS )
  SetWindowCallback(@Callback())
  
 ;---------------------------------------------------- 
 ;How can I count the lines within the loop on the fly
 ;----------------------------------------------------  
  For i = 0 To 40
    SetGadgetText(1,GetGadgetText(1)+Str(i))    
  Next
 ;----------------------------------------------------  
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Shardik »

About 10 years ago I already posted this cross-platform example on how to get the number of lines in an EditorGadget.
Skiller
User
User
Posts: 12
Joined: Sun Oct 08, 2006 8:37 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Skiller »

Hi Axolotl,

thanks for your reply. But sorry, that´s not quite what i meant.
Everything works fine. Also the Callback works perfektly, but the only way to get a result is
either to click with the mouse in the editor gadget or to type text into it.
But I would like to achieve the same in the loop, letter by letter. One letter -> one result and so on.
Automated, so to speak, without using the mouse or keyboard.

For i = 0 To 40 (... or whatever)
SetGadgetText(1,GetGadgetText(1)+Str(i))
(here should be the output of the lines step by step like: i=0, out = (1,1) i=1, out = (2,1) .... )
Next

If you know of any solutions, I would be very grateful.
Skiller
User
User
Posts: 12
Joined: Sun Oct 08, 2006 8:37 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Skiller »

... only with CountGadgetItems, the number of lines within the loop is shown but the entries
remain invisible until the end. But I need both!! results within the loop, like Keyboard input ...

Code: Select all

EnableExplicit


Define evMask, i


Procedure Callback(hWnd, uMsg, wParam, lParam)
  Protected result
  Protected *msgf.MSGFILTER
  Protected POINT.POINT
  Protected char
  Protected lineindex
  Protected colindex
  Protected col
  Protected row
  
  Result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_NOTIFY
      *msgf=lParam
      Select *msgf\NMHDR\code
        Case #EN_MSGFILTER   
          Select *msgf\msg
            Case #WM_LBUTTONUP, #WM_KEYUP
              GetCaretPos_(@POINT)
              char = SendMessage_(GadgetID(1), #EM_CHARFROMPOS, 0, @POINT)
              lineindex = SendMessage_(GadgetID(1), #EM_LINEFROMCHAR, char, 0)
              colindex = SendMessage_(GadgetID(1), #EM_LINEINDEX, lineindex, 0)
              col = char-colindex
              row = lineindex + 1
              Debug "(" + Str(col) + ", " + Str(row) + ")"
          EndSelect
      EndSelect
  EndSelect
  ProcedureReturn Result
EndProcedure


If OpenWindow(0, 0, 0, 250, 200, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  EditorGadget(1, 10, 10, WindowWidth(0)-20, WindowHeight(0)-20, #PB_Editor_WordWrap)
  SetActiveGadget(1) ;Focus auf den Editor
  
;   evMask = SendMessage_(GadgetID(1), #EM_GETEVENTMASK, 0, 0)
;   SendMessage_(GadgetID(1), #EM_SETEVENTMASK, 0, evMask | #ENM_KEYEVENTS | #ENM_MOUSEEVENTS )
;   SetWindowCallback(@Callback())
  
 ;----------------------------------------------------  
  For i = 0 To 40
    SetGadgetText(1,GetGadgetText(1)+Str(i))    
    Debug CountGadgetItems(1)  
    Delay(100)
  Next
 ;----------------------------------------------------  
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Axolotl »

Sorry,
but what is wrong with CountGadgetItems() like below?

BTW Your code example needs some NEWLINE (#CR$, #CRLF$, #LF$) to add new textlines.
See the difference between SetGadgetText() and AddGadgetItem()

IMHO you will figure it out by yourself. Dont forget. Coding is trail and error......
And you learn the most of it if you do the errors yourself.

Code: Select all

For i = 0 To 40 ; (... or whatever)
  SetGadgetText(1,GetGadgetText(1)+Str(i))
; (here should be the output of the lines step by step like: i=0, out = (1,1) i=1, out = (2,1) .... )
  Debug "Lines: " + CountGadgetItems(1) 
Next
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: How do I get Row and Column Positions within a Editor Gadget

Post by RASHAD »

Code: Select all

If OpenWindow(0, 0, 0, 250, 200, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  EditorGadget(1, 10, 10, WindowWidth(0)-20, WindowHeight(0)-20, #PB_Editor_WordWrap)
  SetActiveGadget(1)
  p.POINT
  For i = 0 To 40 ; (... or whatever)
    SetGadgetText(1,GetGadgetText(1)+Str(i))
    SendMessage_(GadgetID(1), #EM_SETSEL, -1,-1)  
    GetCaretPos_(@p)
    char = SendMessage_(GadgetID(1), #EM_CHARFROMPOS, 0, @p)
    lineindex = SendMessage_(GadgetID(1), #EM_LINEFROMCHAR, char, 0)
    colindex = SendMessage_(GadgetID(1), #EM_LINEINDEX, lineindex, 0)
    col = char-colindex - Len(Str(i))
    row = lineindex + 1
    Debug Str(i)+" at  (" +Str(row) + ", " + Str(col) +")"
    Debug "Lines: " + CountGadgetItems(1) 
  Next   
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
Egypt my love
Skiller
User
User
Posts: 12
Joined: Sun Oct 08, 2006 8:37 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Skiller »

Hi experts,
I don't want to expand on this now and we can end this thread if you want. Just this much: if you put a delay
in the loop you can see that the content in the editor is only displayed when the sendmessage in the background
is finished. Sorry, I forgot to add the delay. Maybe there is still the option to display both at the same time; if not,

thanks!!! guys
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Axolotl »

Hey Skiller,

I didn't mean any offense. I find that people are often too quick to ask questions instead of looking for the causes themselves.....
I am happy to help with my modest knowledge.
I haven't quite understood your problem yet.
Maybe you can try PostMessage instead becaue there is a difference between these two:

Code: Select all

SendMessage_()
PostMessage_()
The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.
The PostMessage function places (posts) a message in the message queue and returns without waiting for the thread to process the message.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Skiller
User
User
Posts: 12
Joined: Sun Oct 08, 2006 8:37 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Skiller »

No problem Axolotl, thanks for your patience.
I haven't quite understood your problem yet.
Ok, I refer again to the first part of the program. If you click in the editbox
and enter text, the Debug output of each letter and line count appears immediately. This means: One letter = one output.
Which means there is output in both Windows at the same time.

Code: Select all

;Autor: srod
;http://www.purebasic.fr/english/viewtopic.php?p=173872#p173872

EnableExplicit


Define evMask, i

Procedure Callback(hWnd, uMsg, wParam, lParam)
  Protected result
  Protected *msgf.MSGFILTER
  Protected POINT.POINT
  Protected char
  Protected lineindex
  Protected colindex
  Protected col
  Protected row
  
  Result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_NOTIFY
      *msgf=lParam
      Select *msgf\NMHDR\code
        Case #EN_MSGFILTER   
          Select *msgf\msg
            Case #WM_LBUTTONUP, #WM_KEYUP
              GetCaretPos_(@POINT)
              char = SendMessage_(GadgetID(1), #EM_CHARFROMPOS, 0, @POINT)
              lineindex = SendMessage_(GadgetID(1), #EM_LINEFROMCHAR, char, 0)
              colindex = SendMessage_(GadgetID(1), #EM_LINEINDEX, lineindex, 0)
              col = char-colindex
              row = lineindex + 1
              Debug "(" + Str(col) + ", " + Str(row) + ")"
          EndSelect
      EndSelect
  EndSelect
  ProcedureReturn Result
EndProcedure


If OpenWindow(0, 0, 0, 250, 200, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  EditorGadget(1, 10, 10, WindowWidth(0)-20, WindowHeight(0)-20, #PB_Editor_WordWrap)
  SetActiveGadget(1) ;Focus auf den Editor
  
  evMask = SendMessage_(GadgetID(1), #EM_GETEVENTMASK, 0, 0)
  SendMessage_(GadgetID(1), #EM_SETEVENTMASK, 0, evMask | #ENM_KEYEVENTS | #ENM_MOUSEEVENTS )
  SetWindowCallback(@Callback())
  
;  ;---------------------------------------------------------
;  ;How can I count and see!! the Letters and lines by each i
;  ;---------------------------------------------------------
;   For i = 0 To 40
;     SetGadgetText(1,GetGadgetText(1)+Str(i)+",")    
;     Debug CountGadgetItems(1)
;     Delay(100)  
;   Next
;  ;--------------------------------------------------------  
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf

If the loop comments are removed, the Loop should act like a simulation of a Keyboard input, but
SetGadgetText(1,GetGadgetText(1)+Str(i)+",") remain invisible until the end of the loop.
I need both!! Each letter within the loop and the output of the Numbers of Letters and lines in the same time.

... same like Keyboard input, that´s all actually.


Best regards Skiller
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Axolotl »

Aahhh I understand now.
Try this.
Look at the line

Code: Select all

CompilerIf 0  ; <<<<<---- 0 for the bad solution or 1 for second (better) solution 
and look at both solutions.
Explanation: the gadget needs the repaint (message loop) which is not called inside any loops.
There is a third solution by doing this by Thread. I skipped that one for now.

Code: Select all

;Autor: srod
;http://www.purebasic.fr/english/viewtopic.php?p=173872#p173872

EnableExplicit

Define evMask, i

Procedure Callback(hWnd, uMsg, wParam, lParam)
  Protected result
  Protected *msgf.MSGFILTER
  Protected POINT.POINT
  Protected char
  Protected lineindex
  Protected colindex
  Protected col
  Protected row
  
  Result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_NOTIFY
      *msgf=lParam
      Select *msgf\NMHDR\code
        Case #EN_MSGFILTER   
          Select *msgf\msg
            Case #WM_LBUTTONUP, #WM_KEYUP
              GetCaretPos_(@POINT)
              char = SendMessage_(GadgetID(1), #EM_CHARFROMPOS, 0, @POINT)
              lineindex = SendMessage_(GadgetID(1), #EM_LINEFROMCHAR, char, 0)
              colindex = SendMessage_(GadgetID(1), #EM_LINEINDEX, lineindex, 0)
              col = char-colindex
              row = lineindex + 1
              Debug "(" + Str(col) + ", " + Str(row) + ")"
          EndSelect
      EndSelect
  EndSelect
  ProcedureReturn Result
EndProcedure



If OpenWindow(0, 0, 0, 250, 200, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  EditorGadget(1, 10, 10, WindowWidth(0)-20, WindowHeight(0)-20, #PB_Editor_WordWrap)
  SetActiveGadget(1) ;Focus auf den Editor
  
  evMask = SendMessage_(GadgetID(1), #EM_GETEVENTMASK, 0, 0)
  SendMessage_(GadgetID(1), #EM_SETEVENTMASK, 0, evMask | #ENM_KEYEVENTS | #ENM_MOUSEEVENTS )
  SetWindowCallback(@Callback())
  
CompilerIf 0  ; <<<<<---- 0 for the bad solution or 1 for second (better) solution 

;  ;---------------------------------------------------------
;  ;How can I count and see!! the Letters and lines by each i
;  ;---------------------------------------------------------
    For i = 0 To 40
      SetGadgetText(1,GetGadgetText(1)+Str(i)+",")    
      Debug CountGadgetItems(1) 

      ; first solution  --> bad idea, but works 
      ; 
      While WindowEvent() : Wend  
      
      Delay(100)  
    Next
;  ;--------------------------------------------------------  

  Repeat 
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver

CompilerElse ; Second solution use a Timer 

  AddWindowTimer(0, 1, 100)     ; Second solution 
  
  Repeat 
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
      Case #PB_Event_Timer  
        If EventTimer() = 1 
          If i < 40 
            SetGadgetText(1,GetGadgetText(1)+Str(i)+",")    
            Debug CountGadgetItems(1) 
            i + 1 
          Else 
            RemoveWindowTimer(0, 1) 
          EndIf 
        EndIf 

    EndSelect
  ForEver
  RemoveWindowTimer(0, 1) 
CompilerEndIf 

EndIf

Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Skiller
User
User
Posts: 12
Joined: Sun Oct 08, 2006 8:37 pm

Re: How do I get Row and Column Positions within a Editor Gadget

Post by Skiller »

Wow, Wow, ...

; first solution --> bad idea, but works
While WindowEvent() : Wend

... it may not be the best idea, but for me it's the greatest idea. Thanks a lot Axolotl.

And so easy :oops:

So in both cases I didn't need the callback at all. Ok, got it
Post Reply