April 24, 2024, 03:08:21 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Rich edit control basics

Started by Andy, August 23, 2020, 04:30:48 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

August 23, 2020, 04:30:48 AM Last Edit: August 23, 2020, 04:36:31 AM by Andy
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.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

aurelCB

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...

aurelCB

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 ?

aurelCB

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

aurelCB

..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

Andy

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.

Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

aurelCB

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...

aurelCB

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"
2020-08-27_203535.png

aurelCB

as you can see this one return proper line number 3 which is on line 4
because richedit is zero based.

aurelCB

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..

Andy

August 27, 2020, 10:28:18 PM #10 Last Edit: August 27, 2020, 10:30:41 PM by Andy
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.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

aurelCB

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...

Andy

August 29, 2020, 03:13:27 AM #12 Last Edit: August 29, 2020, 03:19:15 AM by Andy
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.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

aurelCB

thanks Andy 
I see,yes something like that  :)

aurelCB

August 31, 2020, 02:14:32 PM #14 Last Edit: August 31, 2020, 02:16:29 PM by aurelCB
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

Andy

August 31, 2020, 10:15:13 PM #15 Last Edit: August 31, 2020, 10:17:14 PM by Andy
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.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

aurelCB

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

aurelCB

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 !!

aurelCB

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

Andy

Aurel,

Good man! that's a nice work around for you.

And no problem with the help, if I can I always will.

Andy.
 :)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

aurelCB

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.

Andy

September 02, 2020, 09:56:08 PM #21 Last Edit: September 03, 2020, 11:02:52 AM by Andy
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.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

jalih

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.

aurelCB

Hi Andy
 i already add 60 to cbSize and work ok
and yes i understand now how selection work
thanks !