Well this one surprised me.
When I added in the command to set the tabs on loading a file into a rich edit control everything looked nice and neat.
SENDMESSAGE(rHandle,EM_SETSEL,0,0+1)
CONTROLCMD w1,1,@RTGETSELTEXT,ClipText
CONTROLCMD w1,1,@RTREPLACESEL,CLipText
SENDMESSAGE(rHandle,EM_SETTABSTOPS,1,&Tabss) '<-- Tabss is set to 3
But there are problems with that...
It is only a visual effect, it does not change the character positions.
Let me explain, here is the code I use to find out what position I am on in the rich edit:
ppos = GETCARETPOSITION w1,AcrossX,DownY
AcrossX --
AcrossX = AcrossX / 8
AcrossX ++
EditPos = CONTROLCMD(w1,1,@RTCHARFROMLINE,cLine-1)
EditPos = (EditPos + AcrossX) - 1
W1 is my window.
1 is the rich edit control.
cLine is the current line number.
EditPos is the position where I am, i.e. position
Now if we take one simple line (with tabs in it)
<TAB><TAB>IF<TAB>ENDIF
And we set the tab spacing to 3...
On screen when we move across the line the EditPos variable returns this:
<TAB> no 1 (position zero - 0 to 2)
<TAB> no 2 (position three - 3 to 5)
IF (The "I" is shown as position 6)
However, when I use the GETLINE function to get the line text, it gives me what's really there:
<TAB><TAB>IF<TAB>ENDIF
10 characters (let's ignore the CHR$(13) and CHR$(10) at the end of the line).
The problem:
On screen the EditPos variable says the "I" in the word "IF" starts at 6, the GETLINE function says it starts at 3.
The GETLINE function:
CONTROLCMD(w1,1,@RTGETLINE,cLine-1,line$,512) '<-- line$ contains the line
So how can I calculate the position difference?
And here's the punch line!
You would think the <TAB> between the words IF and ENDIF would space 3 on screen, but visually it does not, it only places 1 space between them, even worse, depending on how you have typed the line and what's on it you can even end up with a tab creating two spaces.
So I believe it has something to do with multiples of 3? (as tabs in this case are set to 3).
Try typing the above line in your IWB editor and it does exactly as my program does.
By the way, I'm using
SETFONT w1, "Courier New",10,400,0,1
for my rich edit control.
This is a serious problem for me, it means:
1. I can't use Clint's fast load code to load a file as tabs are not replaced.
2. I can't auto complete key words when typing as the edit position is wrong.
I need a way of translating the EditPos value to the actual position in the line of text.
I need a smart person on this please!
Thanks,
Andy.
Solved.
Well I knew an adjustment of some sort was needed to the edit position on screen, but how?
Here is the code:
ppos = GETCARETPOSITION w1,AcrossX,DownY
AcrossX --
AcrossX = AcrossX / 8
AcrossX ++
EditPos = CONTROLCMD(w1,1,@RTCHARFROMLINE,cLine-1)
EditPos = (EditPos + AcrossX) - 1
IF PrevEditPos <> EditPos
IF cLine = StoreLine
INT varStart2,varEnd2
CONTROLCMD w1,1,@RTGETSELECTION,varStart2,varEnd2
IF varStart2 <> Offset
AdjustPos = EditPos - varStart2
ELSE
AdjustPos = 0
ENDIF
EditPos = EditPos - AdjustPos
ENDIF
IF cLine <> StoreLine and varStart2 = Offset
EditPos = Offset
ENDIF
PrevEditPos = EditPos
ENDIF
Code explained:
This code is in my fast timer.
cLine is the current line you are on now.
StoreLine was the previous line you were on.
PrevEditPos was the position you were on.
If you have changed position but still on the same line as before, get the caret position (where the cursor is).
CONTROLCMD w1,1,@RTGETSELECTION,varStart2,varEnd2
If the caret position is not the first character on the line (Offset) and different to the visual edit position (EditPos) then we have to adjust EditPos.
IF varStart2 <> Offset
AdjustPos = EditPos - varStart2
ELSE
AdjustPos = 0
ENDIF
EditPos = EditPos - AdjustPos '<---- Adjust EditPos
If you've moved to another line and on it's first character:
IF cLine <> StoreLine and varStart2 = Offset
EditPos = Offset
ENDIF
And that's it, even got my auto complete working again.
The above code fixes the actual edit position rather than giving the visual position which is wrong for what I need here, and I won't forget this one for a while!
8)
Andy.
Andy
Dont get me wrong ,and maybe i have no right about that.,
You need some sort of tokenizer to skip chars like empty ,whitespace(blank),tab,cret.lfeed
so skip chr(9) -> tab and never select this chars...
so..do i have right or i am just guesing ? :)
Aurel,
What you say sounds logical to me and common sense, however it's not what I found.
When we add in the command to set tabs, the rich edit control decides on the visual appearance and sets it based on the tab size we have told it.
This then plays havoc with the edit position values, or rather it adjusts the edit position to reflect what a human would expect.
Example:
Tabs set to 3.
<TAB>IF
<TAB> --- sel 0
IF --- sels 1 & 2
To me and you, the "I" in the word "IF" would be sel 1, however, because of setting tabs the position of "I" is moved on (here it is 3, but could be 2 or even 1).
As we don't have control of how many "spaces" a tab might be then we cannot calculate what "I" should be.
The sub routine below re-calculates the "visual position" and tells us the "actual position" in the line.
SUB GetSelPos()
'Get X / Y coordinates of the caret on screen.
ppos = GETCARETPOSITION w1,AcrossX,DownY
'Based on watching the value of AcrossX as I moved cursor position
'This formula might different for a different font / size?
'I'm using "Courier New", size 10.
AcrossX --
AcrossX = AcrossX / 8
AcrossX ++
'Get the first character position in the current line (Offset)
EditPos = CONTROLCMD(w1,1,@RTCHARFROMLINE,cLine-1)
'Now adjust EditPos with the value of AcrossX
EditPos = (EditPos + AcrossX) - 1
'Have we changed position ?
IF PrevEditPos <> EditPos '<---- Yes, where we were is not where we are now.
INT varStart2,varEnd2
'Where we think we are now...
CONTROLCMD w1,1,@RTGETSELECTION,varStart2,varEnd2
'As long as we are not on the first character of the line we need to adjust EditPos.
IF varStart2 <> Offset
AdjustPos = EditPos - varStart2 '<--- Find the difference.
ELSE
AdjustPos = 0
ENDIF
'Adjust EditPos
EditPos = EditPos - AdjustPos
'Has line changed? and are we on it's first character?
IF cLine <> StoreLine and varStart2 = Offset '<--- Yes
EditPos = Offset '<--- Just reset EditPos to the line offset position.
ENDIF
'Update the Previous edit position.
PrevEditPos = EditPos
'Update screen coordinate display information if wanted by you.
SETCONTROLTEXT(w1,PosEdit,ltrim$(str$(EditPos))) 'Rich edit pos (zero based)
CONTROLCMD(w1,1,@RTGETLINE,cLine-1,line$,512)
Offset = SendMessage(rHandle,EM_LINEINDEX,cLine-1,0)
WordNumber = GetAllWordsOnLine(rHandle,cLine-1,line$,Offset)
ENDIF
CharPos = (EditPos - Offset) + 1 'Human position on line ( 1 based)
IF PrevCharPos <> CharPos
PrevCharPos = CharPos
SETCONTROLTEXT(w1,CharPosEdit,ltrim$(str$(CharPos)))
ENDIF
IF PrevWordNumber <> WordNumber 'Human word number ( 1 based)
PrevWordNumber = WordNumber
SETCONTROLTEXT(w1,WordNumberEdit,ltrim$(str$(WordNumber)))
ENDIF
RETURN
ENDSUB
I call this sub from a fast timer, which ensures I always know where I am in the rich edit control.
And I use EditPos for my auto complete of key words function as it has to replace the correct characters with a selected key word at the right position.
And that really is the best I can explain it, all I can say is it works - at least in my program.
Andy.
:)
Wow Andy
i must say that all this looks to complex to me and i am nothing else
than more confused with all this things.
I don't know did i tell you i recently found one code in pureBasic and when i translated it to
EBasic then not work...why i cannot exaplain to myself..also not work¸in oxygen compiler too
it looks crazy..
also there is very big difference in messages
like
EM_SETSEL
and
EM_EXSETSEL
the second cousing crush on my win7 32bit...
ufff
Aurel,
I don't use EM_EXSETSEL at all so I can't say why it crashes your program.
Regarding the visual position, if you think about it, we are getting the x / y coordinates of the cursor on screen.
Now that the rich edit has moved text across due to tabbing we move the mouse / cursor to the position we see the text at, and that's why we get the visual position and not the actual position of that text in the line itself.
Andy.
:)
Andy
sorry but i don't get it this thing with visual x.y
maybe i am too stupid for that things
at moment i have this :
Andy
may i ask you ,is there a way to disable vertical scroll when i scan and hilite line by line ?
Aurel,
Visual X / Y positions - NO you are not stupid at all! It took a good while for my two brain cells to work it out for me too. The X / Y positions we get are the actual positions on screen, not the position in the rich edit control.
To me and you on screen they would appear to be the same, they simply are not.
Disable vertical scrolling:
This works, create a global variable
INT Scanning = 0
Set it to 1 when scanning, then when finished set it back to zero.
I'm presuming you have sub classed your rich edit control? if so, then all you need to add in it is this -
SUB Rich_Edit_Handler(hwnd:int,uMsg:int,wParam:int,lParam:pointer),int
SELECT uMsg
case WM_VSCROLL
IF Scanning = 1
'Here we stop the rich edit scolling by returning zero
return 0
ELSE
'Here we let the rich edit do what it was programmed to so - scroll.
RETURN CallWindowProcA(GetPropA(hwnd,"edit_handler"),hwnd,uMsg,wParam,lParam)
ENDIF
Or this -
SUB Rich_Edit_Handler(hwnd:int,uMsg:int,wParam:int,lParam:pointer),int
SELECT uMsg
case WM_VSCROLL
IF Scanning = 1
'Here we stop the rich edit scolling by returning zero
return 0
ENDIF
The rest I can look into for you if you can clarify what you are doing / meaning.
Andy.
QuoteDisable vertical scrolling:
This works, create a global variable
INT Scanning = 0
Set it to 1 when scanning, then when finished set it back to zero.
I'm presuming you have sub classed your rich edit control? if so, then all you need to add in it is this -
CodeSelect
SUB Rich_Edit_Handler(hwnd:int,uMsg:int,wParam:int,lParam:pointer),int
SELECT uMsg
case WM_VSCROLL
IF Scanning = 1
'Here we stop the rich edit scolling by returning zero
return 0
ELSE
'Here we let the rich edit do what it was programmed to so - scroll.
RETURN CallWindowProcA(GetPropA(hwnd,"edit_handler"),hwnd,uMsg,wParam,lParam)
ENDIF
WOW ..thank you Andy ...i will hard time to figure this ...
and looks really simple... :)
Yes Richedit is subclassed ,image show o2 compiled program which original version is from one Purebasic
example ,,,,so i think that must work in Ebasic or IWB.
I know how to translate o2 to IWB/EB but i am in same time busy with interpreter
but i will make EB version and post it here ..i hope that should work !
Andy
I tried with wm_vscroll and not work, also scrolling still work.
But then i found one example from garrybeane - from powerbasic examples
(yes i have powerbasic10 too..)
and found that
QuoteSendMessage(hRich, WM_SETREDRAW, 0, 0) ' disable control redraw and disable vscroll too
IF LineCount > 0
For Ln = 0 to LineCount
HighlightLine(Ln)
Next Ln
END IF
SendMessage(hRich, WM_SETREDRAW, -1, 0) 'enable redraw (-1) is true
and voila it works great...
and small update
after operation with redraw we need to invalidate rect to unblock control
like this :
QuoteSendMessage(hRich, WM_SETREDRAW, 0, 0)
IF LineCount > 0
For Ln = 0 to LineCount
HighlightLine(Ln)
Next Ln
END IF
SendMessage(hRich, WM_SETREDRAW, -1, 0)
InvalidateRect(hRich, 0, 0) : UpdateWindow hRich
Aurel,
Good man! well worked out.
I'm already doing this in a sub routine I call QuietMode (in my editor program release I miss spelt it as QuiteMode!)
Here it is:
SUB QuietMode(int Switch)
IF Switch
eventMask = SENDMESSAGE(rHandle,EM_SETEVENTMASK,0,mask)
SENDMESSAGE(rHandle,WM_SETREDRAW,false,0)
ENDIf
IF !Switch
SENDMESSAGE(rHandle,WM_SETREDRAW,TRUE,0)
InvalidateRect(rHandle,0,true)
SENDMESSAGE(rHandle,EM_SETEVENTMASK,TRUE,eventMask|ENM_CHANGE)
ENDIF
ENDSUB
I use it mainly for when I am colouring text or setting sel selections to get say the line's text.
I use it like this:
QuietMode(1) '<---- On
Do something like colour some text....
QuietMode(0) '<---- Off
And if you really want to speed things up even more try using Fletchie's conDraw functions like this:
conDrawOff(w1,1) '<---- Turns control updating off
QuietMode(1) '<---- On
Do something like colour some text....
QuietMode(0) '<---- Off
conDrawOn(w1,1) '<---- Turns control updating back on again - important!
w1 is my window, 1 is the rich edit control.
Like I said Aurel, good man, well worked out!
Andy.
:)
well i don't tested it yet in EB but in o2 compiler this operation is really fast
Aurel,
Yes it is, very fast.
In EBasic, you should also be able to use the conDrawOn / conDrawOff function that Fletchie wrote.
If you add in conDraw as well as WM_SETREDRAW then you are completely turning off all messages and notifications from the rich edit to the parent window.
It's these messages and notifications that slow you right down - turn them off and then WOW!
Andy.
:)