Page 1 of 2

Editorgadget: Notification about caretmovement

Posted: Mon Jul 19, 2010 10:12 am
by Kurzer
Hello everyone,

I'm looking for a way to recognize cursormovements within an editorgadet (without polling the cursorpos all the time in a loop).

I want to get a notification message if the cursor jumps from one line to another in the gadget (to do some syntax checks in a single line. the gadget acts as a kind of programming editor for a pseudo programming language).
Is there a way to achive this using a callback for the editorgadget?

In the purebasic message loop I get no message during cursor movement in an editorgadget.

Thank you in advance.
Kind regards, Kurzer

PB 4.50 / Win XP 32

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 11:51 am
by netmaestro
You can subclass the editorgadget and look for #wm_mousemove, also there are dozens of messages you can study on MSDN for the RichEdit control. However, it looks to me like you might be happier with a Scintilla gadget.

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 2:09 pm
by Kurzer
Hello Netmaestro,

Scintilla would be overkill for my requirements I think, but subclassing works great. I found an example for stringgadget which I modified a bit.
Thanks, man.

Code: Select all

EnableExplicit

Global oldStringGadgetProc

Procedure.i EditGadgetProc(hWnd, uMsg, wParam, lParam)
  Protected Result

  Select uMsg
      Case #WM_KEYUP
	      If wParam = #VK_UP
	        Debug "Up"
	      ElseIf wParam = #VK_DOWN
	        Debug "Down"
	      EndIf
    Default
  EndSelect

  ProcedureReturn CallWindowProc_(oldStringGadgetProc, hWnd, uMsg, wParam, lParam)

EndProcedure

If OpenWindow(0, 100, 200, 300, 100, "Notify line jumps in editgadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  EditorGadget(0, 10, 10, 280, 80)
  oldStringGadgetProc = SetWindowLong_(GadgetID(0), #GWL_WNDPROC, @EditGadgetProc())

  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 2:21 pm
by RASHAD
Hi

Code: Select all

OpenWindow(0,0,0,300,230,"EditorGadget",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  EditorGadget(1,5,5,290,190)
  RemoveGadgetItem(1,0)               ;Fix cursor dir with Bidirection system in XP theme enabled

  For a=0 To 5 
    AddGadgetItem(1,a,"Line "+Str(a)) 
  Next
  OldPos = SendMessage_(GadgetID(1), #EM_LINEINDEX,-1,0)
Repeat  
  CurPos = SendMessage_(GadgetID(1), #EM_LINEINDEX,-1,0)
  If CurPos <> OldPos
     MessageRequester("TEST","Cursor Moved to Another Line",#MB_ICONWARNING)
     OldPos = CurPos
  EndIf
  
  Select WaitWindowEvent() 
    Case #PB_Event_CloseWindow: End 
    Case #PB_Event_Gadget 
      Select EventGadget()
        Case 1
      
      EndSelect 
  EndSelect 
ForEver


Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 2:33 pm
by Kurzer
Yes RASHAD, but this is polling the cursor position all the time, which want to avoid (see my first post) ;-)
Nevertheless, thank you for your suggestion.

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 2:38 pm
by srod
Look out for the #EN_CHANGE notification perhaps?

A long time ago, when I wrote a syntax styling routine based on an editor gadget, then it was the #EN_CHANGE notification which was the all important message.

As netty suggests though... it is a damn site easier using a Scintilla control! :wink: Well, actually, considering just how much of a pain in the arse a Scintilla control can be... :)

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 3:02 pm
by RASHAD
@kurzer Hi
Keyboard intercept solution will not be that easy
You have to consider RETURN ,Right Arrow,Left Arrow too,and all these keys in NumPad too
because if you moved Right Arrow (for example) continuously, at the end of the line the cursor will move to the next line ( Tedious Job for sure )


Good luck mate
and have a good day

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 3:39 pm
by Kurzer
Yes RASHAD, you're right. There are some pitfalls, I have to take care about.
I'm at work at the moment, so not much time to test and think about it.

Thank you for all your sugestions. This will surely not be the final solution, but I'm happy that I found an approach to carry on with.
Later at home I will fine tune this Callback and see which message will fit at best
[sorry no time for better translation] :wink:

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 3:47 pm
by RASHAD
@kurzer Hi again
BTW I am not polling the cursor position,Microsoft do that all the time
I am just asking the OS where I am at the moment

If MS can do the job ,let MS do it
If PB can do the job,let PB do it
If these guys did not consider your case,You have to do it by yourself

Sorry mate I wish you the best with no much effort
Have a good day sir

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 7:22 pm
by Kurzer
Srod, thanks for your statement regarding notification messages to the parent window, but my code is apparently not accurate.
I'll get no debug output while entering text into the gadget.

Please, can someone tell me whats wrong with the code?

Code: Select all

EnableExplicit

Procedure WinCallback(hWnd, uMsg, wParam, lParam) 
  
  If uMsg = #WM_COMMAND
  	; Was it sent from the editorgadget?
  	If wParam & $FFFF = 0
    	Select (wParam >> 16) & $FFFF
        Case #EN_CHANGE
          Debug "Changed"
      EndSelect 
  	EndIf  
  EndIf 

  ProcedureReturn #PB_ProcessPureBasicEvents
  
EndProcedure 


If OpenWindow(0, 100, 200, 300, 100, "Notify line jumps in editgadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  EditorGadget(0, 10, 10, 280, 80)
  SetWindowCallback(@WinCallback(), 0)

  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 7:26 pm
by srod

Code: Select all

hWnd = EditorGadget(0, 10, 10, 280, 80)
SendMessage_(hWnd, #EM_SETEVENTMASK, 0, SendMessage_(hWnd, #EM_GETEVENTMASK, 0,0)|#ENM_CHANGE)

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 7:53 pm
by Kurzer
Ah, the gadget does not send EN_CHANGE by default. :idea:
Phew... the big wide world of Windows API :)

[wait... kurzer is doing some tests...]

Ahhrg, no! There is no notification during cursor movement, even if I try all other #EM_SETEVENTMASK flags.
It seems I have to fallback to the first attempt. :shock:

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 8:42 pm
by Kurzer
Okay this is it.

Come on folks, now tell me this is the most stupid attempt you have ever seen.

Code: Select all

EnableExplicit

Global oldStringGadgetProc
Global Event
#CURSORCHANGE = #WM_USER + 1

Procedure.i EditGadgetProc(hWnd, uMsg, wParam, lParam)
	Protected Result
	Protected hParentWindow.i = GetParent_(hWnd)
	
	Select uMsg
		Case #WM_KEYFIRST
			If wParam = #VK_UP
       	PostMessage_(hParentWindow, #CURSORCHANGE, 0, 0)
			ElseIf wParam = #VK_DOWN
       	PostMessage_(hParentWindow, #CURSORCHANGE, 0, 0)
			ElseIf wParam = #VK_RETURN
       	PostMessage_(hParentWindow, #CURSORCHANGE, 0, 0)
			EndIf
		Case #WM_LBUTTONUP
     	PostMessage_(hParentWindow, #CURSORCHANGE, 0, 0)
		Default
	EndSelect
	
	ProcedureReturn CallWindowProc_(oldStringGadgetProc, hWnd, uMsg, wParam, lParam)
	
EndProcedure

If OpenWindow(0, 100, 200, 300, 100, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	EditorGadget(0, 10, 10, 280, 80)
	oldStringGadgetProc = SetWindowLong_(GadgetID(0), #GWL_WNDPROC, @EditGadgetProc())
	
	Repeat 
		Event = WaitWindowEvent()
		If Event = #CURSORCHANGE
			SetWindowTitle(0, "Caret in Line: " + Str(SendMessage_(GadgetID(0), #EM_LINEFROMCHAR, SendMessage_(GadgetID(0), #EM_LINEINDEX,-1,0), 0)))
		EndIf
		
	Until Event = #PB_Event_CloseWindow
EndIf
Btw: Is it a good idea to use PostMessage_() within a windowcallback?

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 8:53 pm
by srod
PostMessage_() should be fine.

A strange way of structuring the program for sure. Rather than post a message I would just call a separate function in your code.

btw : I've never seen #WM_KEYFIRST used in that way before! I thought it was for use with GetMessage_() or PeekMessage_() etc.

Re: Editorgadget: Notification about cursormovement

Posted: Mon Jul 19, 2010 8:59 pm
by netmaestro
btw : I've never seen #WM_KEYFIRST used in that way before
hehe. It's incorrect but it works fine because WM_KEYDOWN is the first key message and therefore has the same value (256) as WM_KEYFIRST.