Thought this would be useful to most of you.
It is a help file I have created to help you to work with rich edit controls, as I don't think the help file tells us enough.
Hopefully, this is a step by step guide to the basics of rich edits and how to work with them - and more importantly save you time and hair pulling.
I think you will find this valuable, so keep a copy for later use.
Hope you like it!
Andy.
:)
Thanks
but i have question ..in a old program for CB i don't understand how this
lineStart = CONTROLCMD (w1, 1,char_start, linenum)
work as Sendmessage pandan without message , what is there is just ID of control?
how is that possible ?
any clue ?
thanks...
Andy
your help is good but still some things missing like
@HIDESEL
and you explained different how to set event mask
in Creative Basic example it is :
mask = CONTROLCMD(w1,1,@RTGETEVENTMASK)
CONTROLCMD w1, 1, @RTSETEVENTMASK, mask | @ENMKEYEVENTS |@ENMCHANGE
in your help it is :
SendMessage(rHandle,EM_SETEVENTMASK,TRUE,ENM_CHANGE)
so it is not the same and how to know which way is proper or better ?
i found that @RTSETEVENTMASK don't have original winapi value
than is somehow modified that work with CB.
native way i found in Garry Been snippets:
SendMessage hRich, EM_SETEVENTMASK , 0, ENMCHANGE | ENMKEYEVENTS
..and another find...
it looks that EM_CHARFROMLINE not work properly with richedit control
i changed rich20A to riched32
curLine = SendMessage(hRich, EM_EXLINEFROMCHAR ,char_start , -1
Aurel.
You have some good questions here.
lineStart = CONTROLCMD (w1, 1,char_start, linenum) - I should have made it clearer that the "1" after the w1 (window) is the rich edit in my program.
CONTROLCMD w1,1,@RTSETEVENTMASK,mask|@ENMKEYEVENTS|@ENMCHANGE - Use this, that's what I do all the time in my program - need to amend the help file!
SendMessage hRich,EM_SETEVENTMASK,0,ENMCHANGE|ENMKEYEVENTS - not seen that version with the zero - I will check it out...
EM_CHARFROMLINE - Think you are right here, I use the IWB version @RTLINEFROMCHAR.
Just got home so will check out all these in more details tomorrow and will let you know.
Thanks for replying!
Andy.
Andy
I use different compiler (o2) and using only native win api constants so
i see that some things are very different than in original and by the way i am not sure
how work ..must be some internal workaround...
also choice of control version is important too...
Andy
just to show you this code give proper current line :
curLine = SendMessage(hRich, EM_EXLINEFROMCHAR ,char_start , -1 )
print "LineNum:" + str(curLine)print is just a messageBox
i am trying to translate my old Creative code to o2
and probably same code must work in IWB..(i have EBasic)
to get syntax coloring in richedit control i tried both
"riched32.dll"
"riched20.dll"
as you can see this one return proper line number 3 which is on line 4
because richedit is zero based.
Also
CONTROLCMD w1, 1, @RTSETSELCOLOR, RGB(0, 0, 0)
if you Google you cannot find anything similar to RTSETSELCOLOR
this must be internal Creative function ,i mean cannot be just ordinary constant..
but i will check more..
Aurel,
The most certain way to colour text is to use WinApi 32, which should work across most languages.
You need to include in your program first the CHARFORMAT structure, it's used for formatting characters, here it is:
TYPE CHARFORMAT
UINT cbSize
DWORD dwMask
DWORD dwEffects
LONG yHeight
LONG yOffset
COLORREF crTextColor
BYTE bCharSet
BYTE bPitchAndFamily
CHAR szFaceName[LF_FACESIZE]
ENDTYPE
CHARFORMAT cf
Here I am defining it as "cf".
Now to colour something:
SENDMESSAGE( id, EM_SETSEL, StartPos, EndPos )
cf.dwMask = CFM_COLOR
cf.crTextColor = RGB(0,0,0)
cf.cbSize = SIZEOF(cf)
SENDMESSAGE( id, EM_SETCHARFORMAT, SCF_SELECTION, &cf )
Note: "id" is the rich edit handle.
cf.dwMask is set to CFM_COLOR meaning in this case we want to colour some text.
cf.crTextColor is set to the colour we want.
SENDMESSAGE then performs the colouring.
This is the safest way I found to colour text and the quickest.
Andy.
THanks Andy
I will try that way of course..
and that wwould be great to put this block of code into subroutine
probably should work from there too.
thanks again...
Aurel,
I'm also building a "richeditplus.inc" file with some handy sub routines in it as I am going along.
This one colours the selected text:
SUB RTColorText(WINDOW WinIn,INT ControlIn,INT StartPosIn,INT EndPosIn,UINT ColorIn)
SENDMESSAGE(GETCONTROLHANDLE(WinIn,ControlIn),EM_SETSEL,StartPosIn,EndPosIn+1)
cf.dwMask = CFM_COLOR
cf.crTextColor = ColorIn
cf.cbSize = SIZEOF(cf)
SENDMESSAGE(GETCONTROLHANDLE(WinIn,ControlIn),EM_SETCHARFORMAT,SCF_SELECTION,&cf)
ENDSUB
And it has the CHARFORMAT structure included in it.
Andy.
thanks Andy
I see,yes something like that :)
Andy
I am now totaly confused because nothing work
and i probably made some strange mistakes,
sorry i have old Ebasic and soe commands are not same but still should work
if you have time do you can try this example from old editor example
Quote/*
a simple SDI editor (like notepad). Created by
using a multiline edit control sized to the window
version 1.2 for EBASIC.
Compile with a WINDOWS target
*/
$include "windows.inc"
def win:window
def left,top,width,height,hprinter:int
def startpg,endpg,copies,collate:int
def filename,ln,printer:string
def file1:FILE
def buffer[32766]:ISTRING
run = 0
TYPE CHARFORMAT
UINT cbSize
WORD dwMask
WORD dwEffects
UINT yHeight
UINT yOffset
UINT crTextColor
CHAR bCharSet
CHAR bPitchAndFamily
CHAR szFaceName[LF_FACESIZE]
ENDTYPE
const EM_SETSEL = 0xB1
const CFM_COLOR = 0x40000000
const EM_SETCHARFORMAT = (WM_USER + 68)
const SCF_SELECTION = 0x0001
int hrich
'Open our main window, get its client size and create the control
openwindow win,0,0,640,400,@SIZE|@MINBOX|@MAXBOX|@MAXIMIZED|@NOAUTODRAW,0,"EDITOR V1.2",&mainwindow
getclientsize win,left,top,width,height
hrich = controlex win,"riched20","syntax color",10,10,400,300,0x50B010C4,@EXCLIENTEDGE,1
'CONTROLEX d1,"msctls_progress32","",4,40,236,20,@BORDER,,20
'CONTROLEX(parent, class as STRING,title as STRING,l as INT,t as INT,w as INT,h as INT,style as INT,exStyle as INT,id as UINT)
BEGINMENU win
MENUTITLE "&File"
MENUITEM "&Load File\tCtrl+L",0,1
MENUITEM "&Save\tCtrl+S",0,2
MENUITEM "&Print\tAlt+P",0,4
MENUITEM "&Quit\tCtrl+C",0,3
MENUTITLE "&Options"
MENUITEM "Change Font\tF4",0,5
ENDMENU
'SETCONTROLCOLOR win,1,0,RGB(255,255,255)
CHARFORMAT cf
SENDMESSAGE hrich, EM_SETSEL, 0, 4,1
cf.cbSize = len(CHARFORMAT)
cf.dwMask = CFM_COLOR
cf.crTextColor = RGB(200,0,0)
SENDMESSAGE hrich, EM_SETCHARFORMAT, SCF_SELECTION, &cf ,1
'process messages until somebody closes us
run = 1
waituntil run=0
closewindow win
end
'this is the handler subroutine for the window
'process @IDSIZE to size the edit control
'process the menus
'process @IDCLOSEWINDOW to quit the program
sub mainwindow
select @MESSAGE
case @IDCLOSEWINDOW
run = 0
case @IDSIZE
'size the edit control to match the client size of the window
'we use CONTROLEXISTS to verify the existance of the edit control
'because the first @IDSIZE message is sent while the window is being created
'but before we have a chance to add the edit control.
if CONTROLEXISTS(win,1)
getclientsize win,left,top,width,height
setsize win,left,top,width,height,1
endif
case @IDMENUPICK
select @MENUNUM
case 5
GOSUB changefont
case 4
'dump the edit control to the printer
GOSUB doprint
case 3
'quit the program
run = 0
case 2
'save the file
GOSUB dosave
case 1
'open a file
GOSUB doopen
endselect
endselect
return
endsub
'------------- DOOPEN ----------------
SUB doopen
filename = filerequest("Load File",win,1)
if(len(filename) > 0)
buffer = ""
if( !openfile(file1,filename,"R"))
do
if(read(file1,ln) = 0)
if len(buffer) < (32766-257)
buffer = buffer + ln + chr$(13) + chr$(10)
endif
endif
until eof(file1)
closefile file1
setcontroltext win,1,buffer
endif
endif
RETURN
endsub
'------------- DOSAVE -----------------
SUB dosave
filename = filerequest("Save File",win,0)
if(len(filename) > 0)
if(openfile(file1,filename,"W") = 0)
buffer = getcontroltext(win,1)
write file1,buffer
closefile file1
endif
endif
RETURN
endsub
'------------- DOPRINT ----------------
'prints the contents of the edit control
'using straight text printing.
'This method won't work for GDI only printers
'--------------------------------------
SUB doprint
startpg = 1
endpg = 1
copies = 1
collate = 1
printer = PRTDIALOG(win,startpg,endpg,copies,collate)
hprinter = OPENPRINTER(printer,"Document","TEXT")
if(hprinter)
buffer = getcontroltext(win,1)
WRITEPRINTER hprinter, buffer
CLOSEPRINTER hprinter
endif
RETURN
endsub
'------------- CHANGEFONT -------------
SUB changefont
DEF size,weight,flags,col:int
DEF fontname:string
size = 12
weight = 400
flags = 0
col = 0
fontname = FONTREQUEST(win,size,weight,flags,col)
if(fontname <> "")
SETFONT win,fontname,size,weight,flags,1
endif
SETCONTROLCOLOR win,1,col,RGB(255,255,255)
RETURN
endsub
Aurel,
This is what I've got for you in Ebasic, there were a few changes needed.
You were getting confused with the variable "hrich", it was not set to the rich edit's handle.
Here I'm using "rHandle" instead.
The loading of a file wasn't working either, so I have changed that too.
There is still a problem...
SENDMESSAGE(rHandle,EM_SETCHARFORMAT,SCF_SELECTION,&cf)
returns zero (failed).
I think the problem lies here:
TYPE CHARFORMAT
UINT cbSize
WORD dwMask
WORD dwEffects
UINT yHeight
UINT yOffset
UINT crTextColor
CHAR bCharSet
CHAR bPitchAndFamily
CHAR szFaceName[LF_FACESIZE]
ENDTYPE
In IWB it's like this:
TYPE CHARFORMAT
UINT cbSize
DWORD dwMask
DWORD dwEffects
LONG yHeight
LONG yOffset
COLORREF crTextColor
BYTE bCharSet
BYTE bPitchAndFamily
CHAR szFaceName[LF_FACESIZE]
ENDTYPE
You also have:
cf.cbSize = len(CHARFORMAT)
I have:
cf.cbSize = SIZEOF(cf)
cf.cbSize in yours returns 56, mine returns a size of 60 for the same colour.
So at this stage it looks to me as CHARFORMAT structure is not correct in ebasic.
Attached is what I have got so far for you.
I've got the program to open a console screen so you can see the values of certain fields.
Andy.
Thanks Andy
Yes it looks that is problem in charformat structure...
well Ebasic don't have sizeOf() so i use LEN() ...
which is explained in user guide that do the same ..hmm
but another compiler(o2) i use have sizeOf()
so i will chek it cbsize with it to see if is different
also i have purebasic(old v4.50) to chek how thisgs work there
and finaly i can try it in FreeBaisc too..
oh man to much compilers.... ;D
Hi Andy
I think that i figured what is wrong with my code in o2
and probably same (i will test it) in EBasic too
You have a right about member cf.cbSize which must be 60
then i set it manualy by adding :
cf.cbSize = 60
and then coloring work ...with this piece of code i get all text in red color:
...
cf.cbSize = 60 'SizeOf(CHARFORMAT) 'Length of structure
cf.dwMask = CFM_COLOR
cf.crTextColor = rgb(200,0,0) 'Set the new color value
..................................................................................................
int cfres = SendMessage(hRich, EM_SETCHARFORMAT, SCF_ALL, cf)
cfres become 1
thanks alot with ideas and helping !!
for bold and colored:
cf.cbSize = 60 ' Length of structure *must be set manually sizeOf() not work!
cf.dwMask = CFM_COLOR | CFM_BOLD
cf.crTextColor = rgb(0,0,200) 'Set the new color value
cf.dwEffects = CFM_BOLD
Aurel,
Good man! that's a nice work around for you.
And no problem with the help, if I can I always will.
Andy.
:)
Andy
just to let you know ,in your help you say that selection change colour .
That is ok ,but selection stay visibile ...right?
then i select one more and selction gone and color is there.
Aurel,
Yes, check this out:
SENDMESSAGE(rHandle,EM_SETSEL,0,10) '<----- Highlight rermains for 2 seconds
sleep(2000)
cf.crTextColor = RGB(0,0,0) '<-------- Select colour (Black)
cf.cbSize = SIZEOF(cf)
SENDMESSAGE(rHandle,EM_SETCHARFORMAT,SCF_SELECTION,&cf) '<------ Sets colour to black
sleep(2000)
cf.crTextColor = Red '<-------- Change to Red does not work as selection is now lost !
cf.cbSize = SIZEOF(cf)
SENDMESSAGE(rHandle,EM_SETCHARFORMAT,SCF_SELECTION,&cf)
The text is never coloured Red as after you have formatted the selection, the selection is lost!
Now by adding in the selection again before colouring Red it works:
SENDMESSAGE(rHandle,EM_SETSEL,0,10) '<----- Highlight rermains for 2 seconds
sleep(2000)
cf.crTextColor = RGB(0,0,0) '<-------- Select colour (Black)
cf.cbSize = SIZEOF(cf)
SENDMESSAGE(rHandle,EM_SETCHARFORMAT,SCF_SELECTION,&cf) '<------ Sets colour to black
sleep(2000)
SENDMESSAGE(rHandle,EM_SETSEL,0,10) '<------- Set selection AGAIN! ############################################
cf.crTextColor = Red '<-------- Change to Red now works!
cf.cbSize = SIZEOF(cf)
SENDMESSAGE(rHandle,EM_SETCHARFORMAT,SCF_SELECTION,&cf)
Don't forget Aurel - change SIZEOF(cf) to 60 for EBasic, Red is just a variable set to a red RGB value, and "rHandle" is just the rich edit's control handle.
Another note to remember:
After colouring / formatting the selection, the cursor is moved to the end of your selection + 1.
How I got to understand selections:
I decided very early on to load a small file, say 10 lines of text, and add a button to my window that I could click on to test and play around with selections, getting sel positions, line number, etc.
So by adding in the code to select sels, colouring etc to the button's code it became much easier to test and understand how all this works - just a tip for anyone who wants to learn about rich edits.
A note on loading files:
This is my sub routine for loading a file...
SUB GetLines(),INT
ClipText = ""
OPENFILE(myFile,ProgPath,"R")
DO
READ myfile,dIn
ClipText = ClipText + RTRIM$(dIn) + CHR$(13) + CHR$ (10)
UNTIL EOF(myFile)
CLOSEFILE myFile
RETURN
ENDSUB
ClipText is just a very large ISTRING.
dIn is a small ISTRING (512 in size).
ProgPath contains the full file name + path to the file being loaded.
You must add CHR$(13) + CHR$ (10) to every line.
After doing this sub routine, send the text to the rich edit, like this:
SETCONTROLTEXT(w1,1,ClipText)
w1 is my window.
1 is the rich edit control.
Andy.
:)
Quote from: Andy on September 02, 2020, 09:56:08 PMDon't forget Aurel - change SIZEOF(cf) to 60 for EBasic...
You really should correct the CHARFORMAT structure to get the correct size. I think it's just missing padding for memory alignment.
Hi Andy
i already add 60 to cbSize and work ok
and yes i understand now how selection work
thanks !