AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

cRichEdit - Standard RichEdit control for AutoHotkey scripts
Goto page 1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
corrupt



Joined: 29 Dec 2004
Posts: 2393

PostPosted: Tue May 22, 2007 5:21 am    Post subject: cRichEdit - Standard RichEdit control for AutoHotkey scripts Reply with quote

With all the exciting new options available for AutoHotkey these days I thought I'd start coding functions for using a RICHEDIT control in an AutoHotkey GUI for fun Smile . The functionality is pretty basic so far but could be useful to someone. If anyone is interested in trying it out and providing feedback I'd appreciate it Smile . This version uses riched20.dll (or riched32.dll when run in Win95) which should already exist in Win98/ME/NT/2000/XP/Vista.

Version 0.09 Beta.
A zip file that contains the necessary files and demo scripts can be downloaded here: Download.




Recent changes:
  • AutoHotkey v1.0.47 or greater required
  • added: WordWrap On/Off
  • modified: fixed a bug in cGUI.ahk for specifying a HWND for the control's parent
  • added: tab_example.ahk example file to show one method of adding the RichEdit control to a tab
  • added: GetLineNum - to retrieve the current line number, the total number of lines or the line number at a specific character index
  • fixed: bug with specifying a colour by name
  • added: Align (Left, Right, Center)
  • added: ReplaceSel - to insert or replace text at the current position
  • added: GetRTF - to retrieve RTF code for the current selection or contents of the RichEdit control
  • added: an option to cGUI to specify the HWND to the parent control (currently untested)
  • modified: removed dependency on Insert/Extract Integer functions (now uses NumPut, NumGet instead)
  • updated: demo scripts (simple, feature)
  • modified: method used for colour names, minor bug fixes/tweaks
  • modified: split the include files into cGUI.ahk and cRichEdit.ahk since cGUI.ahk might be used for other controls in the future.
  • renamed: cGUI_RICHEDIT function to c_RichEdit() instead (easier to remember and less to type)
  • modified: feature_demo.ahk to use a ListView to list/test commands instead of the buttons that were used previously. This method seems to allow more flexibility when adding/modifying/testing new options
  • added: FontName _action to specify a font to use by name
  • added: GetFontSize _action to get the font size of the current selection
  • added: SetFontSize _action to set the font size of the current selection
  • added: FontStyle _action to set/toggle Bold, Italic, UnderLine, Strikethrough for the current selection or current position (optional custom dwMask and dwEffects settings available also)
  • added: FontColor _action to change the colour of selected text or change the colour at the current location (RRGGBB value or by name - same names/values as Object Colors in the AutoHotkey documentation)
  • updated: BackColor _action to support colour names also
  • updated: feature_demo.ahk script to test some of the newer features that have been added
  • Added the following to the cGUI_RICHEDIT() function:
    • EXGETSEL - retrieves the starting and ending character positions of the selection
    • EXSETSEL - set the current selection
    • GETSELTEXT - get the current text that is selected in the control
    • GETTEXTLENGTH - get the number of characters in the control
    • GETTEXT - get the text in the control
    • BackColor - change the background colour of the RichEdit control
    • SETSCROLLPOS - scroll to a specific position in the control
    • GETSCROLLPOS - get the current scroll position in the control
    • AutoURLDetect - automatic detection of URLs
  • fixed hInstance usage [thanks PhiLho]
  • fixed: RICHEDIT was hard coded [thanks PhiLho]
  • added FreeDlls option (_action param) to cGUI() to free all dlls loaded by the cGUI() function
  • updated demo to load RichEdit v2.0
  • modifed global variables used
  • Added simple_demo.ahk and feature_demo.ahk scripts to the zip file available for download
  • modified demo scripts to load a RichEdit1.0 control instead if run under Win95
**Note to Win95 users: Win95 can load a RichEdit 2.0 control but the file riched20.dll is not included in a standard install and would have to be downloaded and installed separately.

Here's the code for a sample script (simple_demo.ahk - screenshot). The code for feature_demo.ahk is available in the zip file.
Code:
; v0.06 beta - updated: June 24, 2007

; **** Download the sample .rtf file if necessary ****
If !(FileExist(A_ScriptDir . "\test1.rtf")) {
  SplashTextOn, 300, 30, !, Downloading sample file. Please wait...
  URLDownloadToFile http://www.autohotkey.net/~corr/test1.rtf, %A_ScriptDir%\test1.rtf
  SplashTextOff

 
; **** RichEdit Demo ****

Gui Add, Button, gOpenScript, Open Script
Gui Add, Button, ym gHelloWorld, Hello World!!
Gui Add, Button, ym gtest1, test1.trf
Gui Show, +hide w500 h500, RichEdit demo
If A_OSVersion = WIN_95
  cGUI("Add", REdit1, 10, 40, 480, 450, "RICHEDIT")
Else
  cGUI("Add", REdit1, 10, 40, 480, 450, "RichEdit20A")
cRichEdit(REdit1, "FileOpen", (A_ScriptDir . "\test1.rtf"))
Gui Show
Return

test1:
cRichEdit(REdit1, "FileOpen", (A_ScriptDir . "\test1.rtf"))
Return

OpenScript:
cRichEdit(REdit1, "FileOpen", A_ScriptFullPath)
Return

HelloWorld:
cRichEdit(REdit1, "Text", "Hello World!!")
Return

GuiClose:
If (REdit1)
  cRichEdit(REdit1, "Destroy")
Gui, %A_Gui%:Destroy
cGUI("FreeDlls", NULL)
ExitApp
Return

; comment the following #Include lines if you are using stdlib and have copied the required
; cGUI.ahk and cRichedit.ahk files to your stdlib directory

#Include cGUI.ahk
#Include cRichEdit.ahk

I'll be adding additional functionality to the cRichEdit() function with each release. If you'd like to help out then feel free to add to the function and post your changes so that I can update the code in the first post.

More to come soon... Enjoy Smile


Last edited by corrupt on Sun Apr 20, 2008 6:37 am; edited 19 times in total
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4001
Location: Pittsburgh

PostPosted: Tue May 22, 2007 3:57 pm    Post subject: Reply with quote

Very nice! Thanks for sharing it!

It shows Unicode characters, so we can write a substitute of MsgBox in a few lines of additional code, with nicely formatted, diacritical letters, symbols.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3622
Location: Belgrade

PostPosted: Tue May 22, 2007 4:16 pm    Post subject: Reply with quote

I am waiting for the other functions, most notably those that change fonts and do other rich edit specific functions.

Now that you are doing it, I will put my own RE wrapper on hold.

Thx.
_________________
Back to top
View user's profile Send private message MSN Messenger
SKAN



Joined: 26 Dec 2005
Posts: 5790

PostPosted: Tue May 22, 2007 6:24 pm    Post subject: Reply with quote

Splendid Very Happy Thanks for creating this.

Smile
Back to top
View user's profile Send private message
Elevator_Hazard



Joined: 28 Oct 2006
Posts: 304
Location: US

PostPosted: Tue May 22, 2007 10:38 pm    Post subject: Reply with quote

Looks nice. How about instead of 4 parameters being taken up and sometimes causing a bunch of commands and confusion, you should have the width height x and y in an options parameter so that support could also easily be added to like an associated output variable and a subroutine if that's possible. Also I haven't tried this out yet, but it looks good and I had been waiting for something like that.
_________________
Changed siggy at request of ahklerner Very Happy
Back to top
View user's profile Send private message
Joy2DWorld



Joined: 04 Dec 2006
Posts: 422
Location: Galil, Israel

PostPosted: Wed May 23, 2007 6:06 pm    Post subject: Reply with quote

Quote:

*/
If _action = Text
{
DllCall("SendMessage", "UInt", _ctrlID, "UInt", 0x461, "Str", "", "Str", opt1) ; EM_SETTEXTEX
Return
}
/*


likely there is reason to use DLL call for sendmessage (vs. built in sendmessage)...


curious as to what it is....
_________________
Joyce Jamce
Back to top
View user's profile Send private message
corrupt



Joined: 29 Dec 2004
Posts: 2393

PostPosted: Thu May 24, 2007 4:16 am    Post subject: Reply with quote

Laszlo wrote:
Very nice! Thanks for sharing it!

It shows Unicode characters, so we can write a substitute of MsgBox in a few lines of additional code, with nicely formatted, diacritical letters, symbols.
Thanks Smile . According to MSDN, version 1.0 of the RichEdit control does not support unicode but since riched32.dll on XP seems to be a stub, it's likely not a version 1.0 control that gets loaded. Win9.x systems will not likely have the same results using the same code.
MSDN - About Rich Edit Controls wrote:
ANSI (single-byte character set (SBCS) and multibyte character set (MBCS)) editing However, there is no Unicode editing.
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2393

PostPosted: Thu May 24, 2007 4:19 am    Post subject: Reply with quote

majkinetor wrote:
I am waiting for the other functions, most notably those that change fonts and do other rich edit specific functions.
The next update should contain a few text formatting features Smile .
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2393

PostPosted: Thu May 24, 2007 4:27 am    Post subject: Reply with quote

Skan wrote:
Splendid Very Happy Thanks for creating this.

Smile
Thanks for giving it a try Smile .
Elevator_Hazard wrote:
Looks nice. How about instead of 4 parameters being taken up and sometimes causing a bunch of commands and confusion, you should have the width height x and y in an options parameter so that support could also easily be added to like an associated output variable and a subroutine if that's possible. Also I haven't tried this out yet, but it looks good and I had been waiting for something like that.
Thanks Smile . I had thought about setting the options up similar to the Gui command but didn't mainly for a couple reasons. There are many options available for a RichEdit control and many of them may require additional params. It seemed easier and a bit more flexible to create a separate function for additional settings, actions, etc... instead of parsing through a single line of text to pull out and process all available options. I would have preferred to use VB style and create properties and methods for the control but that's not going to happen with this release... The other reason for the x,y,w,h being separate params is to allow the use of expressions.
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2393

PostPosted: Thu May 24, 2007 4:43 am    Post subject: Reply with quote

Joy2DWorld wrote:
likely there is reason to use DLL call for sendmessage (vs. built in sendmessage)...
The main reason is for easy porting of code (viewing, order of params) from other projects and snippets. There doesn't seem to be a need to use the built-in SendMessage/PostMessage commands since it's not necessary to search for a Window Title, Text, etc... since the control's HWND has already been passed to the function. Unless the built-in SendMessage/PostMessage turns out to be considerably faster (I haven't tested)...
Back to top
View user's profile Send private message Visit poster's website
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Thu May 24, 2007 10:36 am    Post subject: Reply with quote

corrupt wrote:
Unless the built-in SendMessage/PostMessage turns out to be considerably faster (I haven't tested)...
I doubt it, unless the DllCall adds lot of overhead... Which can be reduced by specifying explicitly the DLL and using SendMessageA (avoids some internal tries).
Additional advantage: you probably don't need the DetectHiddenWindows On.
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
Daniel2
Guest





PostPosted: Fri May 25, 2007 8:39 pm    Post subject: Reply with quote

corrupt- This is really awesome! This has been a highly anticipated gui control.. & I'm looking forward to it being fully implemented. I'm new to trying to make dllcalls.. but thanks to PhiLho's help (ApiViewer really helped w/ making it all click! Smile) I managed to wrap up a couple new functions:
Quote:
EM_EXGETSEL - retrieves the starting and ending character positions of the selection in a RE control.
    cGUI_RICHEDIT(ReHwnd, "EM_GETTEXTRANGE")

EM_SETFONTSIZE - The EM_SETFONTSIZE message sets the font size for the selected text.
    cGUI_RICHEDIT(ReHwnd, "EM_SETFONTSIZE", -4) ; (changes font size from current state..)

(requires ExtractInteger & InsertInteger functions to be available as shown in 'Structures and Arrays')

Code:
/*
*****************************************************************************************
Add your own RICHEDIT features to the function below

Please submit additional features if you think that others may find
them useful so that I can update the current version posted

Much more to come soon...
*****************************************************************************************
*/
  Else If _action = YourNewFeature
  {
    ; Do something here
    Return
  } ;-----------------------------
  Else If _action = EM_EXGETSEL
  {
;-- The EM_EXGETSEL message retrieves the starting and ending character positions of the selection
    VarSetCapacity(_tmp1, 8, 0)     , InsertInteger(8, _tmp1, 4)
    DllCall("SendMessage"                       ;// returns LRESULT in lResult
                    , "UInt"        , _ctrlID   ;// handle to destination control
                    , "UInt"        , 0x434     ;// message ID   (EM_EXGETSEL := WM_USER + 52)
                    , "UInt"        , 0         ;// wParam  - Parameter is not used; must be zero.
                    , "Cdecl UInt"  , &_tmp1)   ;// lParam  - Pointer to CHARRANGE structure that receives the selection range
    Return ExtractInteger(_tmp1, 0) . "|" . ExtractInteger(_tmp1, 4)  ;// Return Value: returns CHARRANGE Structure (cpMin & cpMax)
  } ;-----------------------------
  Else If _action = EM_SETFONTSIZE
  {
;-- The EM_SETFONTSIZE message sets the font size for the selected text.--
    DllCall("SendMessage"                       ;// returns LRESULT in lResult
                    , "UInt"        , _ctrlID   ;// handle to destination control
                    , "UInt"        , 0x4df     ;// message ID   (EM_SETFONTSIZE := WM_USER + 223)
                    , "UInt"        , opt1      ;// wParam  - Change in point size of the selected text (–1637 to 1638)
                    , "Cdecl UInt"  , 0)        ;// lParam  - This parameter is not used; it must be zero.
    Return          ;// Return Value:  This message does not return a value.
  } ;-----------------------------
;   Else If _action = EM_GETSELTEXT
;   {
; ;-- The EM_GETSELTEXT message retrieves the starting and ending character positions of the selection in a rich edit control.
;     DllCall("SendMessage"                       ;// returns LRESULT in lResult
;                     , "UInt"        , _ctrlID   ;// handle to destination control
;                     , "UInt"        , 0x43e     ;// message ID   (EM_GETSELTEXT := WM_USER + 62)
;                     , "UInt"        , 0         ;// wParam  - This parameter is not used; it must be zero.
;                     , "Cdecl Str"   , &_tmp1)   ;// lParam  - Pointer to a buffer that receives the selected text. The calling
;                                                 ;             application must ensure that the buffer is large enough to hold
;                                                 ;              the selected text.
;     Return _tmp1  ;// Return Value: Message returns the # of chars copied, not including the terminating null character
;   } ;-----------------------------
;   Else If _action = EM_GETTEXTRANGE
;   {
; ;-- The EM_GETTEXTRANGE message retrieves a specified range of characters from a rich edit control.
;     VarSetCapacity(_tmp1, 512, 0)   , InsertInteger(2, _tmp1, 4)
;     InsertInteger(10, _tmp1, 8)     , InsertInteger(_tmp1, _tmp1, 12)
;     _tmp2 := DllCall("SendMessage"              ;// returns LRESULT in lResult
;                     , "UInt"        , _ctrlID   ;// handle to destination control
;                     , "UInt"        , 0x44b     ;// message ID   (EM_GETTEXTRANGE := WM_USER + 75)
;                     , "UInt"        , 0         ;// wParam  - This parameter is not used; it must be zero.
;                     , "Cdecl Str"   , &_tmp1)   ;// lParam  - Pointer to a TEXTRANGE structure; specifies the range of
;                                                 ;             characters to retrieve and a buffer to copy the characters to.
;     Return ExtractInteger(_tmp1, 0) . "|" . ExtractInteger(_tmp1, 12)  ;// Return Value: returns TEXTRANGE Structure (chrg & lpstrText)
;   } ;-----------------------------
;   Else If _action = EM_SETCHARFORMAT
;   {
; ;-- The EM_SETCHARFORMAT message sets character formatting in a rich edit control.
;     VarSetCapacity(_tmp1, 32, 0)     , InsertInteger(32, _tmp1, 16)
;     DllCall("SendMessage"                       ;// returns LRESULT in lResult
;                     , "UInt"        , _ctrlID   ;// handle to destination control
;                     , "UInt"        , 0x444     ;// message ID   (EM_SETCHARFORMAT := WM_USER + 68)
;                     , "UInt"        , 0         ;// wParam  - Character formatting that applies to the control
;                     , "Cdecl Str"  , &_tmp1)    ;// lParam  - Pointer to a CHARFORMAT structure specifying the character formatting to use
;     Return ExtractInteger(_tmp1, 0) . "|" . ExtractInteger(_tmp1, 4)  ;// Return Value: returns TEXTRANGE Structure (chrg & lpstrText)
;   } ;-----------------------------
;   Else If _action = EM_SETPAGEROTATE
;   {
; ;-- Deprecated. An application sends an EM_SETPAGEROTATE message to set the text layout for a Microsoft RE control
;     _tmp1 := DllCall("SendMessage"              ;// returns DWORD in lResult
;                     , "UInt"        , _ctrlID   ;// handle to destination control
;                     , "UInt"        , 0x45d     ;// message ID   (EM_SETPAGEROTATE := WM_USER + 93)
;                     , "UInt"        , 90        ;// wParam  - Text layout value (EPR_0, EPR_90, EPR_180, EPR_270)
;                     , "UInt"        , 0)        ;// lParam  - Not used; must be zero.
;     Return _tmp1  ;// Return Value:  the new text layout value
;   } ;-----------------------------

I attempted wrapping up a few more.. but now (being a dllcall noob) I'm hitting a brick wall when it comes to effectively using/understanding structures. I managed to get a simple one working.. but I'm not understanding how to create one w/ Int & Str's in it & ones where one of the members is another structure! (Ex. The TEXTRANGE Structure uses a CHARRANGE Structure as one of its members..)
You can strip off all the BS comments (I left them there to make it easier for someone more experienced to double check..) as well as come up w/ a better naming convention; I'm going to continue trying to improve my knowledge & will maybe post new ones as I get them figured out.
Quote:
As you may have guessed, this function isn't designed only for use with a RICHEDIT
control.
This has quite a bit of potential.. & I'm axious to see how it develops Very Happy
Back to top
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Sat May 26, 2007 9:00 am    Post subject: Reply with quote

So preliminary remarks on corrupt's code:
MSDN wrote:
Rich Edit version DLL
1.0 Riched32.dll
2.0 Riched20.dll - Nearly everywhere
3.0 Riched20.dll - in Windows Me, 2000 & XP
4.1 Msftedit.dll - In Windows XP SP1
[...]
To create a rich edit control, call the CreateWindowEx function, specifying the rich edit window class. If you are using Rich Edit 1.0 (Riched32.dll), specify RichEdit for the window class parameter. If you are using Rich Edit 2.0 or later (Riched20.dll), specify RICHEDIT_CLASS for the window class parameter.

I suggest to drop RichEdit 1.0 to go directly to 2.0/3.0, likely to have fewer bugs.

I see you have a _ClassName parameter, but you hard-coded it in the CreateWindowEx.
Also my use of GetWindowLong to get the hInstance is an error (The Old New Thing : What is the HINSTANCE passed to CreateWindow ...), it must be zero for controls residing in User32.dll, and should be the result of LoadLibrary otherwise, even if Windows seems to take the correct registered class if its name is unique.
It can be useful is some other program is running, using another DLL declaring the same class name (another version, another origin, etc.).
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2393

PostPosted: Sat May 26, 2007 3:55 pm    Post subject: Reply with quote

Daniel2 wrote:
corrupt- This is really awesome! This has been a highly anticipated gui control.. & I'm looking forward to it being fully implemented.
Thanks and thanks for contributing Smile . As there are a few structs that are commonly used when modifying RichEdit controls, I'll likely add a function to make using a few of the common ones a bit easier.
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2393

PostPosted: Sat May 26, 2007 4:08 pm    Post subject: Reply with quote

Quote:
If you are using Rich Edit 2.0 or later (Riched20.dll), specify RICHEDIT_CLASS for the window class parameter.
I haven't been able to get this to work on my XP Pro system but I'll do a bit more research. I'm probably missing something simple...
PhiLho wrote:
I suggest to drop RichEdit 1.0 to go directly to 2.0/3.0, likely to have fewer bugs.
I'm not sure about the number of bugs but it might be worth it for the additional features.
PhiLho wrote:
I see you have a _ClassName parameter, but you hard-coded it in the CreateWindowEx.
Thanks. That was unintentionally left in from a test version.
PhiLho wrote:
Also my use of GetWindowLong to get the hInstance is an error (The Old New Thing : What is the HINSTANCE passed to CreateWindow ...), it must be zero for controls residing in User32.dll, and should be the result of LoadLibrary otherwise, even if Windows seems to take the correct registered class if its name is unique.
It can be useful is some other program is running, using another DLL declaring the same class name (another version, another origin, etc.).
Thanks. I wasn't aware of that.
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3, 4, 5, 6  Next
Page 1 of 6

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group