├── License.md ├── README.md └── Sources ├── RichEdit.ahk ├── RichEditDlgs.ahk └── RichEditSample.ahk /License.md: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AHK2 - RichEdit 2 | RichEdit control for AHK v2 3 | -------------------------------------------------------------------------------- /Sources/RichEdit.ahk: -------------------------------------------------------------------------------- 1 | ; ====================================================================================================================== 2 | ; Scriptname: RichEdit.ahk 3 | ; Namespace: RichEdit 4 | ; Author: just me 5 | ; AHK Version: 2.0.2 (Unicode) 6 | ; OS Version: Win 10 Pro (x64) 7 | ; Function: The class provides some wrapper functions for rich edit controls (v4.1 Unicode). 8 | ; Change History: 9 | ; 1.0.00.00 2023-05-23/just me - initial release 10 | ; Credits: 11 | ; corrupt for cRichEdit: 12 | ; http://www.autohotkey.com/board/topic/17869-crichedit-standard-richedit-control-for-autohotkey-scripts/ 13 | ; jballi for HE_Print: 14 | ; http://www.autohotkey.com/board/topic/45513-function-he-print-wysiwyg-print-for-the-hiedit-control/ 15 | ; majkinetor for Dlg: 16 | ; http://www.autohotkey.com/board/topic/15836-module-dlg-501/ 17 | ; ====================================================================================================================== 18 | #Requires AutoHotkey v2.0 19 | #DllLoad "Msftedit.dll" 20 | ; ====================================================================================================================== 21 | Class RichEdit { 22 | ; =================================================================================================================== 23 | ; Class variables - do not change !!! 24 | ; =================================================================================================================== 25 | ; Callback functions for RichEdit 26 | Static GetRTFCB := 0 27 | Static LoadRTFCB := 0 28 | Static SubclassCB := 0 29 | ; Initialize the class on startup 30 | Static __New() { 31 | ; RichEdit.SubclassCB := CallbackCreate(RichEdit_SubclassProc) 32 | RichEdit.GetRTFCB := CallbackCreate(ObjBindMethod(RichEdit, "GetRTFProc"), , 4) 33 | RichEdit.LoadRTFCB := CallbackCreate(ObjBindMethod(RichEdit, "LoadRTFProc"), , 4) 34 | RichEdit.SubclassCB := CallbackCreate(ObjBindMethod(RichEdit, "SubclassProc"), , 6) 35 | } 36 | ; ------------------------------------------------------------------------------------------------------------------- 37 | Static GetRTFProc(dwCookie, pbBuff, cb, pcb) { ; Callback procedure for GetRTF 38 | Static RTF := "" 39 | If (cb > 0) { 40 | RTF .= StrGet(pbBuff, cb, "CP0") 41 | Return 0 42 | } 43 | If (dwCookie = "*GetRTF*") { 44 | Out := RTF 45 | VarSetStrCapacity(&RTF, 0) 46 | RTF := "" 47 | Return Out 48 | } 49 | Return 1 50 | } 51 | ; ------------------------------------------------------------------------------------------------------------------- 52 | Static LoadRTFProc(FileHandle, pbBuff, cb, pcb) { ; Callback procedure for LoadRTF 53 | Return !DllCall("ReadFile", "Ptr", FileHandle, "Ptr", pbBuff, "UInt", cb, "Ptr", pcb, "Ptr", 0) 54 | } 55 | ; ------------------------------------------------------------------------------------------------------------------- 56 | Static SubclassProc(H, M, W, L, I, R) { ; RichEdit subclassproc 57 | ; See -> docs.microsoft.com/en-us/windows/win32/api/commctrl/nc-commctrl-subclassproc 58 | ; WM_GETDLGCODE = 0x87, DLGC_WANTALLKEYS = 4 59 | Return (M = 0x87) ? 4 : DllCall("DefSubclassProc", "Ptr", H, "UInt", M, "Ptr", W, "Ptr", L, "Ptr") 60 | } 61 | ; =================================================================================================================== 62 | ; CONSTRUCTOR 63 | ; =================================================================================================================== 64 | __New(GuiObj, Options, MultiLine := True) { 65 | Static WS_TABSTOP := 0x10000, WS_HSCROLL := 0x100000, WS_VSCROLL := 0x200000, WS_VISIBLE := 0x10000000, 66 | WS_CHILD := 0x40000000, 67 | WS_EX_CLIENTEDGE := 0x200, WS_EX_STATICEDGE := 0x20000, 68 | ES_MULTILINE := 0x0004, ES_AUTOVSCROLL := 0x40, ES_AUTOHSCROLL := 0x80, ES_NOHIDESEL := 0x0100, 69 | ES_WANTRETURN := 0x1000, ES_DISABLENOSCROLL := 0x2000, ES_SUNKEN := 0x4000, ES_SAVESEL := 0x8000, 70 | ES_SELECTIONBAR := 0x1000000 71 | Static MSFTEDIT_CLASS := "RICHEDIT50W" ; RichEdit v4.1+ (Unicode) 72 | ; Specify default styles & exstyles 73 | Styles := WS_TABSTOP | WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL 74 | If (MultiLine) 75 | Styles |= WS_HSCROLL | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN | 76 | ES_DISABLENOSCROLL | ES_SAVESEL ; | ES_SELECTIONBAR ; does not work properly 77 | ExStyles := WS_EX_STATICEDGE 78 | ; Create the control 79 | CtrlOpts := "Class" . MSFTEDIT_CLASS . " " . Options . " +" . Styles . " +E" . ExStyles 80 | This.RE := GuiObj.AddCustom(CtrlOpts) 81 | ; Initialize control 82 | ; EM_SETLANGOPTIONS = 0x0478 (WM_USER + 120) 83 | ; IMF_AUTOKEYBOARD = 0x01, IMF_AUTOFONT = 0x02 84 | ; SendMessage(0x0478, 0, 0x03, This.HWND) ; commented out 85 | ; Subclass the control to get Tab key and prevent Esc from sending a WM_CLOSE message to the parent window. 86 | ; One of majkinetor's splendid discoveries! 87 | DllCall("SetWindowSubclass", "Ptr", This.HWND, "Ptr", RichEdit.SubclassCB, "Ptr", This.HWND, "Ptr", 0) 88 | This.MultiLine := !!MultiLine 89 | This.DefFont := This.GetFont(1) 90 | This.DefFont.Default := 1 91 | This.BackColor := DllCall("GetSysColor", "Int", 5, "UInt") ; COLOR_WINDOW 92 | This.TextColor := This.DefFont.Color 93 | This.TxBkColor := This.DefFont.BkColor 94 | ; Additional settings for multiline controls 95 | If (MultiLine) { 96 | ; Adjust the formatting rectangle 97 | RC := This.GetRect() 98 | This.SetRect(RC.L + 6, RC.T + 2, RC.R, RC.B) 99 | ; Set advanced typographic options 100 | ; EM_SETTYPOGRAPHYOPTIONS = 0x04CA (WM_USER + 202) 101 | ; TO_ADVANCEDTYPOGRAPHY = 1, TO_ADVANCEDLAYOUT = 8 ? not documented 102 | SendMessage(0x04CA, 1, 1, This.HWND) 103 | } 104 | ; Correct AHK font size setting, if necessary 105 | If (Round(This.DefFont.Size) != This.DefFont.Size) { 106 | This.DefFont.Size := Round(This.DefFont.Size) 107 | This.SetDefaultFont() 108 | } 109 | ; Initialize the print margins 110 | This.GetMargins() 111 | ; Initialize the text limit 112 | This.LimitText(2147483647) 113 | } 114 | ; =================================================================================================================== 115 | ; DESTRUCTOR 116 | ; =================================================================================================================== 117 | __Delete() { 118 | If DllCall("IsWindow", "Ptr", This.HWND) && (RichEdit.SubclassCB) { 119 | DllCall("RemoveWindowSubclass", "Ptr", This.HWND, "Ptr", RichEdit.SubclassCB, "Ptr", 0) 120 | } 121 | This.RE := 0 122 | } 123 | ; =================================================================================================================== 124 | ; GUICONTROL PROPERTIES ============================================================================================= 125 | ; =================================================================================================================== 126 | ClassNN => This.RE.ClassNN 127 | Enabled => This.RE.Enabled 128 | Focused => This.RE.Focused 129 | Gui => This.RE.Gui 130 | Hwnd => This.RE.Hwnd 131 | Name { 132 | Get => This.RE.Name 133 | Set => This.RE.Name := Value 134 | } 135 | Visible => This.RE.Visible 136 | ; =================================================================================================================== 137 | ; GUICONTROL METHODS ================================================================================================ 138 | ; =================================================================================================================== 139 | Focus() => This.RE.Focus() 140 | GetPos(&X?, &Y?, &W?, &H?) => This.RE.GetPos(&X?, &Y?, &W?, &H?) 141 | Move(X?, Y?, W?, H?) => This.RE.Move(X?, Y?, W?, H?) 142 | OnCommand(Code, Callback, AddRemove?) => This.RE.OnCommand(Code, Callback, AddRemove?) 143 | OnNotify(Code, Callback, AddRemove?) => This.RE.OnNotify(Code, Callback, AddRemove?) 144 | Opt(Options) => This.RE.Opt(Options) 145 | Redraw() => This.RE.Redraw() 146 | ; =================================================================================================================== 147 | ; PUBLIC METHODS ==================================================================================================== 148 | ; =================================================================================================================== 149 | ; =================================================================================================================== 150 | ; Methods to be used by advanced users only 151 | ; =================================================================================================================== 152 | GetCharFormat() { ; Retrieves the character formatting of the current selection 153 | ; For details see http://msdn.microsoft.com/en-us/library/bb787883(v=vs.85).aspx. 154 | ; Returns a 'CF2' object containing the formatting settings. 155 | ; EM_GETCHARFORMAT = 0x043A 156 | CF2 := RichEdit.CHARFORMAT2() 157 | SendMessage(0x043A, 1, CF2.Ptr, This.HWND) 158 | Return (CF2.Mask ? CF2 : False) 159 | } 160 | ; ------------------------------------------------------------------------------------------------------------------- 161 | SetCharFormat(CF2) { ; Sets character formatting of the current selection 162 | ; For details see http://msdn.microsoft.com/en-us/library/bb787883(v=vs.85).aspx. 163 | ; CF2 : CF2 object like returned by GetCharFormat(). 164 | ; EM_SETCHARFORMAT = 0x0444 165 | Return SendMessage(0x0444, 1, CF2.Ptr, This.HWND) 166 | } 167 | ; ------------------------------------------------------------------------------------------------------------------- 168 | GetParaFormat() { ; Retrieves the paragraph formatting of the current selection 169 | ; For details see http://msdn.microsoft.com/en-us/library/bb787942(v=vs.85).aspx. 170 | ; Returns a 'PF2' object containing the formatting settings. 171 | ; EM_GETPARAFORMAT = 0x043D 172 | PF2 := RichEdit.PARAFORMAT2() 173 | SendMessage(0x043D, 0, PF2.Ptr, This.HWND) 174 | Return (PF2.Mask ? PF2 : False) 175 | } 176 | ; ------------------------------------------------------------------------------------------------------------------- 177 | SetParaFormat(PF2) { ; Sets the paragraph formatting for the current selection 178 | ; For details see http://msdn.microsoft.com/en-us/library/bb787942(v=vs.85).aspx. 179 | ; PF2 : PF2 object like returned by GetParaFormat(). 180 | ; EM_SETPARAFORMAT = 0x0447 181 | Return SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 182 | } 183 | ; =================================================================================================================== 184 | ; Control specific 185 | ; =================================================================================================================== 186 | IsModified() { ; Has the control been modified? 187 | ; EM_GETMODIFY = 0xB8 188 | Return SendMessage(0xB8, 0, 0, This.HWND) 189 | } 190 | ; ------------------------------------------------------------------------------------------------------------------- 191 | SetModified(Modified := False) { ; Sets or clears the modification flag for an edit control 192 | ; EM_SETMODIFY = 0xB9 193 | Return SendMessage(0xB9, !!Modified, 0, This.HWND) 194 | } 195 | ; ------------------------------------------------------------------------------------------------------------------- 196 | SetEventMask(Events?) { ; Set the events which shall send notification codes control's owner 197 | ; Events : Array containing one or more of the keys defined in 'ENM'. 198 | ; For details see http://msdn.microsoft.com/en-us/library/bb774238(v=vs.85).aspx 199 | ; EM_SETEVENTMASK = 0x0445 200 | Static ENM := {NONE: 0x00, CHANGE: 0x01, UPDATE: 0x02, SCROLL: 0x04, SCROLLEVENTS: 0x08, DRAGDROPDONE: 0x10, 201 | PARAGRAPHEXPANDED: 0x20, PAGECHANGE: 0x40, KEYEVENTS: 0x010000, MOUSEEVENTS: 0x020000, 202 | REQUESTRESIZE: 0x040000, SELCHANGE: 0x080000, DROPFILES: 0x100000, PROTECTED: 0x200000, 203 | LINK: 0x04000000} 204 | If !IsSet(Events) || (Type(Events) != "Array") 205 | Events := ["NONE"] 206 | Mask := 0 207 | For Each, Event In Events { 208 | If ENM.HasProp(Event) 209 | Mask |= ENM.%Event% 210 | Else 211 | Return False 212 | } 213 | Return SendMessage(0x0445, 0, Mask, This.HWND) 214 | } 215 | ; =================================================================================================================== 216 | ; Loading and storing RTF format 217 | ; =================================================================================================================== 218 | GetRTF(Selection := False) { ; Gets the whole content of the control as rich text 219 | ; Selection = False : whole contents (default) 220 | ; Selection = True : current selection 221 | ; EM_STREAMOUT = 0x044A 222 | ; SF_TEXT = 0x1, SF_RTF = 0x2, SF_RTFNOOBJS = 0x3, SF_UNICODE = 0x10, SF_USECODEPAGE = 0x0020 223 | ; SFF_PLAINRTF = 0x4000, SFF_SELECTION = 0x8000 224 | ; UTF-8 = 65001, UTF-16 = 1200 225 | ; Static GetRTFCB := CallbackCreate(RichEdit_GetRTFProc) 226 | Flags := 0x4022 | (1200 << 16) | (Selection ? 0x8000 : 0) 227 | ES := Buffer((A_PtrSize * 2) + 4, 0) ; EDITSTREAM structure 228 | NumPut("UPtr", This.HWND, ES) ; dwCookie 229 | NumPut("UPtr", RichEdit.GetRTFCB, ES, A_PtrSize + 4) ; pfnCallback 230 | SendMessage(0x044A, Flags, ES.Ptr, This.HWND) 231 | Return RichEdit.GetRTFProc("*GetRTF*", 0, 0, 0) 232 | } 233 | ; ------------------------------------------------------------------------------------------------------------------- 234 | LoadRTF(FilePath, Selection := False) { ; Loads RTF file into the control 235 | ; FilePath = file path 236 | ; Selection = False : whole contents (default) 237 | ; Selection = True : current selection 238 | ; EM_STREAMIN = 0x0449 239 | ; SF_TEXT = 0x1, SF_RTF = 0x2, SF_RTFNOOBJS = 0x3, SF_UNICODE = 0x10, SF_USECODEPAGE = 0x0020 240 | ; SFF_PLAINRTF = 0x4000, SFF_SELECTION = 0x8000 241 | ; UTF-16 = 1200 242 | ; Static LoadRTFCB := CallbackCreate(RichEdit_LoadRTFProc) 243 | Flags := 0x4002 | (Selection ? 0x8000 : 0) ; | (1200 << 16) 244 | If !(File := FileOpen(FilePath, "r")) 245 | Return False 246 | ES := Buffer((A_PtrSize * 2) + 4, 0) ; EDITSTREAM structure 247 | NumPut("UPtr", File.Handle, ES) ; dwCookie 248 | NumPut("UPtr", RichEdit.LoadRTFCB, ES, A_PtrSize + 4) ; pfnCallback 249 | Result := SendMessage(0x0449, Flags, ES.Ptr, This.HWND) 250 | File.Close() 251 | Return Result 252 | } 253 | ; =================================================================================================================== 254 | ; Scrolling 255 | ; =================================================================================================================== 256 | GetScrollPos() { ; Obtains the current scroll position 257 | ; Returns on object with keys 'X' and 'Y' containing the scroll position. 258 | ; EM_GETSCROLLPOS = 0x04DD 259 | PT := Buffer(8, 0) 260 | SendMessage(0x04DD, 0, PT.Ptr, This.HWND) 261 | Return {X: NumGet(PT, 0, "Int"), Y: NumGet(PT, 4, "Int")} 262 | } 263 | ; ------------------------------------------------------------------------------------------------------------------ 264 | SetScrollPos(X, Y) { ; Scrolls the contents of a rich edit control to the specified point 265 | ; X : x-position to scroll to. 266 | ; Y : y-position to scroll to. 267 | ; EM_SETSCROLLPOS = 0x04DE 268 | PT := Buffer(8, 0) 269 | NumPut("Int", X, "Int", Y, PT) 270 | Return SendMessage(0x04DE, 0, PT.Ptr, This.HWND) 271 | } 272 | ; ------------------------------------------------------------------------------------------------------------------- 273 | ScrollCaret() { ; Scrolls the caret into view 274 | ; EM_SCROLLCARET = 0x00B7 275 | SendMessage(0x00B7, 0, 0, This.HWND) 276 | Return True 277 | } 278 | ; ------------------------------------------------------------------------------------------------------------------- 279 | ShowScrollBar(SB, Mode := True) { ; Shows or hides one of the scroll bars of a rich edit control 280 | ; SB : Identifies which scroll bar to display: horizontal or vertical. 281 | ; This parameter must be 1 (SB_VERT) or 0 (SB_HORZ). 282 | ; Mode : Specify TRUE to show the scroll bar and FALSE to hide it. 283 | ; EM_SHOWSCROLLBAR = 0x0460 (WM_USER + 96) 284 | SendMessage(0x0460, SB, !!Mode, This.HWND) 285 | Return True 286 | } 287 | ; =================================================================================================================== 288 | ; Text and selection 289 | ; =================================================================================================================== 290 | FindText(Find, Mode?) { ; Finds Unicode text within a rich edit control 291 | ; Find : Text to search for. 292 | ; Mode : Optional array containing one or more of the keys specified in 'FR'. 293 | ; For details see http://msdn.microsoft.com/en-us/library/bb788013(v=vs.85).aspx. 294 | ; Returns True if the text was found; otherwise false. 295 | ; EM_FINDTEXTEXW = 0x047C, EM_SCROLLCARET = 0x00B7 296 | Static FR:= {DOWN: 1, WHOLEWORD: 2, MATCHCASE: 4} 297 | Flags := 0 298 | If IsSet(Mode) && (Type(Mode) = "Array") { 299 | For Each, Value In Mode 300 | If FR.HasProp(Value) 301 | Flags |= FR[Value] 302 | } 303 | Sel := This.GetSel() 304 | Min := (Flags & FR.DOWN) ? Sel.E : Sel.S 305 | Max := (Flags & FR.DOWN) ? -1 : 0 306 | FTX := Buffer(16 + A_PtrSize, 0) 307 | NumPut("Int", Min, "Int", Max, "UPtr", StrPtr(Find), FTX) 308 | SendMessage(0x047C, Flags, FTX.Ptr, This.HWND) 309 | S := NumGet(FTX, 8 + A_PtrSize, "Int"), E := NumGet(FTX, 12 + A_PtrSize, "Int") 310 | If (S = -1) && (E = -1) 311 | Return False 312 | This.SetSel(S, E) 313 | This.ScrollCaret() 314 | Return True 315 | } 316 | ; ------------------------------------------------------------------------------------------------------------------- 317 | ; Finds the next word break before or after the specified character position or retrieves information about 318 | ; the character at that position. 319 | FindWordBreak(CharPos, Mode := "Left") { 320 | ; CharPos : Character position. 321 | ; Mode : Can be one of the keys specified in 'WB'. 322 | ; Returns the character index of the word break or other values depending on 'Mode'. 323 | ; For details see http://msdn.microsoft.com/en-us/library/bb788018(v=vs.85).aspx. 324 | ; EM_FINDWORDBREAK = 0x044C (WM_USER + 76) 325 | Static WB := {LEFT: 0, RIGHT: 1, ISDELIMITER: 2, CLASSIFY: 3, MOVEWORDLEFT: 4, MOVEWORDRIGHT: 5, LEFTBREAK: 6 326 | , RIGHTBREAK: 7} 327 | Option := WB.HasProp(Mode) ? WB[Mode] : 0 328 | Return SendMessage(0x044C, Option, CharPos, This.HWND) 329 | } 330 | ; ------------------------------------------------------------------------------------------------------------------- 331 | GetSelText() { ; Retrieves the currently selected text as plain text 332 | ; Returns selected text. 333 | ; EM_GETSELTEXT = 0x043E, EM_EXGETSEL = 0x0434 334 | Txt := "" 335 | CR := This.GetSel() 336 | TxtL := CR.E - CR.S + 1 337 | If (TxtL > 1) { 338 | VarSetStrCapacity(&Txt, TxtL) 339 | SendMessage(0x043E, 0, StrPtr(Txt), This.HWND) 340 | VarSetStrCapacity(&Txt, -1) 341 | } 342 | Return Txt 343 | } 344 | ; ------------------------------------------------------------------------------------------------------------------- 345 | GetSel() { ; Retrieves the starting and ending character positions of the selection in a rich edit control 346 | ; Returns an object containing the keys S (start of selection) and E (end of selection)). 347 | ; EM_EXGETSEL = 0x0434 348 | CR := Buffer(8, 0) 349 | SendMessage(0x0434, 0, CR.Ptr, This.HWND) 350 | Return {S: NumGet(CR, 0, "Int"), E: NumGet(CR, 4, "Int")} 351 | } 352 | ; ------------------------------------------------------------------------------------------------------------------- 353 | GetText() { ; Gets the whole content of the control as plain text 354 | ; EM_GETTEXTEX = 0x045E 355 | Txt := "" 356 | If (TxtL := This.GetTextLen() + 1) { 357 | GTX := Buffer(12 + (A_PtrSize * 2), 0) ; GETTEXTEX structure 358 | NumPut("UInt", TxtL * 2, GTX) ; cb 359 | NumPut("UInt", 1200, GTX, 8) ; codepage = Unicode 360 | VarSetStrCapacity(&Txt, TxtL) 361 | SendMessage(0x045E, GTX.Ptr, StrPtr(Txt), This.HWND) 362 | VarSetStrCapacity(&Txt, -1) 363 | } 364 | Return Txt 365 | } 366 | ; ------------------------------------------------------------------------------------------------------------------- 367 | ; GetTextColors() { ; Gets the text and background colors - not implemented 368 | ; } 369 | ; ------------------------------------------------------------------------------------------------------------------- 370 | GetTextLen() { ; Calculates text length in various ways 371 | ; EM_GETTEXTLENGTHEX = 0x045F 372 | GTL := Buffer(8, 0) ; GETTEXTLENGTHEX structure 373 | NumPut( "UInt", 1200, GTL, 4) ; codepage = Unicode 374 | Return SendMessage(0x045F, GTL.Ptr, 0, This.HWND) 375 | } 376 | ; ------------------------------------------------------------------------------------------------------------------- 377 | ; Retrieves the position of the first occurence of the specified text within the specified range. 378 | GetTextPos(Find, Min := 0, Max := -1, Mode := 1) { 379 | ; Find : Text to search for. 380 | ; Min : Character position index immediately preceding the first character in the range. 381 | ; Integer value to store as cpMin in the CHARRANGE structure. 382 | ; Default: 0 - first character 383 | ; Max : Character position immediately following the last character in the range. 384 | ; Integer value to store as cpMax in the CHARRANGE structure. 385 | ; Default: -1 - last character 386 | ; Mode : Any combination of the following values: 387 | ; 0 : search backward, 1 : search forward, 2 : match whole word only, 4 : case-sensitive 388 | ; Returns an object containing the keys S (start of text) and E (end of text) if found, otherwise False. 389 | ; EM_FINDTEXTEXW = 0x047C 390 | Flags := Mode & 0x07 391 | FTX := Buffer(16 + A_PtrSize, 0) 392 | NumPut("Int", Min, "Int", Max, "UPtr", StrPtr(Find), FTX) 393 | P := SendMessage(0x047C, Flags, FTX.Ptr, This.Hwnd) << 32 >> 32 394 | Return (P = -1) ? False : {S: NumGet(FTX, 8 + A_PtrSize, "Int"), E: NumGet(FTX, 12 + A_PtrSize, "Int")} 395 | } 396 | ; ------------------------------------------------------------------------------------------------------------------- 397 | GetTextRange(Min, Max) { ; Retrieves a specified range of characters from a rich edit control 398 | ; Min : Character position index immediately preceding the first character in the range. 399 | ; Integer value to store as cpMin in the CHARRANGE structure. 400 | ; Max : Character position immediately following the last character in the range. 401 | ; Integer value to store as cpMax in the CHARRANGE structure. 402 | ; CHARRANGE -> http://msdn.microsoft.com/en-us/library/bb787885(v=vs.85).aspx 403 | ; EM_GETTEXTRANGE = 0x044B 404 | If (Max <= Min) 405 | Return "" 406 | Txt := "" 407 | VarSetStrCapacity(&Txt, Max - Min) 408 | TR := Buffer(8 + A_PtrSize, 0) ; TEXTRANGE Struktur 409 | NumPut("UInt", Min, "UInt", Max, "UPtr", StrPtr(Txt), TR) 410 | SendMessage(0x044B, 0, TR.Ptr, This.HWND) 411 | VarSetStrCapacity(&Txt, -1) 412 | Return Txt 413 | } 414 | ; ------------------------------------------------------------------------------------------------------------------- 415 | HideSelection(Mode) { ; Hides or shows the selection 416 | ; Mode : True to hide or False to show the selection. 417 | ; EM_HIDESELECTION = 0x043F (WM_USER + 63) 418 | SendMessage(0x043F, !!Mode, 0, This.HWND) 419 | Return True 420 | } 421 | ; ------------------------------------------------------------------------------------------------------------------- 422 | LimitText(Limit) { ; Sets an upper limit to the amount of text the user can type or paste into a rich edit control 423 | ; Limit : Specifies the maximum amount of text that can be entered. 424 | ; If this parameter is zero, the default maximum is used, which is 64K characters. 425 | ; EM_EXLIMITTEXT = 0x435 (WM_USER + 53) 426 | SendMessage(0x0435, 0, Limit, This.HWND) 427 | Return True 428 | } 429 | ; ------------------------------------------------------------------------------------------------------------------- 430 | ReplaceSel(Text := "") { ; Replaces the selected text with the specified text 431 | ; EM_REPLACESEL = 0xC2 432 | Return SendMessage(0xC2, 1, StrPtr(Text), This.HWND) 433 | } 434 | ; ------------------------------------------------------------------------------------------------------------------- 435 | SetText(Text := "", Mode?) { ; Replaces the selection or the whole content of the control 436 | ; Mode : Array of option flags. It can be any reasonable combination of the keys defined in 'ST'. 437 | ; For details see http://msdn.microsoft.com/en-us/library/bb774284(v=vs.85).aspx. 438 | ; EM_SETTEXTEX = 0x0461, CP_UNICODE = 1200 439 | ; ST_DEFAULT = 0, ST_KEEPUNDO = 1, ST_SELECTION = 2, ST_NEWCHARS = 4 ??? 440 | Static ST := {DEFAULT: 0, KEEPUNDO: 1, SELECTION: 2} 441 | Flags := 0 442 | If IsSet(Mode) && (Type(Mode) = "Array") { 443 | For Value In Mode 444 | If ST.HasProp(Value) 445 | Flags |= ST[Value] 446 | } 447 | CP := 1200 448 | TxtPtr := StrPtr(Text) 449 | ; RTF formatted text has to be passed as ANSI!!! 450 | If (SubStr(Text, 1, 5) = "{\rtf") || (SubStr(Text, 1, 5) = "{urtf") { 451 | Buf := Buffer(StrPut(Text, "CP0"), 0) 452 | StrPut(Text, Buf, "CP0") 453 | TxtPtr := Buf.Ptr 454 | CP := 0 455 | } 456 | STX := Buffer(8, 0) ; SETTEXTEX structure 457 | NumPut("UInt", Flags, "UInt", CP, STX) ; flags, codepage 458 | Return SendMessage(0x0461, STX.Ptr, TxtPtr, This.HWND) 459 | } 460 | ; ------------------------------------------------------------------------------------------------------------------- 461 | SetSel(Start, End) { ; Selects a range of characters 462 | ; Start : zero-based start index 463 | ; End : zero-beased end index (-1 = end of text)) 464 | ; EM_EXSETSEL = 0x0437 465 | CR := Buffer(8, 0) 466 | NumPut("Int", Start, "Int", End, CR) 467 | Return SendMessage(0x0437, 0, CR.Ptr, This.HWND) 468 | } 469 | ; =================================================================================================================== 470 | ; Appearance, styles, and options 471 | ; =================================================================================================================== 472 | AutoURL(Mode := 1) { ; En- or disable AutoURLDetection 473 | ; Mode : one or a combination of the following values: 474 | ; Disable 0 475 | ; AURL_ENABLEURL 1 476 | ; AURL_ENABLEEMAILADDR 2 ; Win 8+ 477 | ; AURL_ENABLETELNO 4 ; Win 8+ 478 | ; AURL_ENABLEEAURLS 8 ; Win 8+ 479 | ; AURL_ENABLEDRIVELETTERS 16 ; WIn 8+ 480 | ; EM_AUTOURLDETECT = 0x45B 481 | RetVal := SendMessage(0x045B, Mode & 0x1F, 0, This.HWND) 482 | WinRedraw(This.HWND) 483 | Return RetVal 484 | } 485 | ; ------------------------------------------------------------------------------------------------------------------- 486 | GetRect(&RC := "") { ; Retrieves the rich edit control's formatting rectangle 487 | ; Returns an object with keys L (eft), T (op), R (ight), and B (ottom). 488 | ; If a variable is passed in the Rect parameter, the complete RECT structure will be stored in it. 489 | RC := Buffer(16, 0) 490 | If !This.MultiLine 491 | Return False 492 | SendMessage(0x00B2, 0, RC.Ptr, This.HWND) 493 | Return {L: NumGet(RC, 0, "Int"), T: NumGet(RC, 4, "Int"), R: NumGet(RC, 8, "Int"), B: NumGet(RC, 12, "Int")} 494 | } 495 | ; ------------------------------------------------------------------------------------------------------------------- 496 | GetOptions(&Options := "") { ; Retrieves the rich edit control`s options 497 | ; Returns an array of currently set options as the keys defined in 'ECO'. 498 | ; If a variable is passed in the Option parameter, the combined numeric value of the options will be stored in it. 499 | ; For details see http://msdn.microsoft.com/en-us/library/bb774178(v=vs.85).aspx. 500 | ; EM_GETOPTIONS = 0x044E 501 | Static ECO := {AUTOWORDSELECTION: 0x01, AUTOVSCROLL: 0x40, AUTOHSCROLL: 0x80, NOHIDESEL: 0x100, 502 | READONLY: 0x800, WANTRETURN: 0x1000, SAVESEL: 0x8000, SELECTIONBAR: 0x01000000, 503 | VERTICAL: 0x400000} 504 | Options := SendMessage(0x044E, 0, 0, This.HWND) 505 | O := [] 506 | For Key, Value In ECO.OwnProps() 507 | If (Options & Value) 508 | O.Push(Key) 509 | Return O 510 | } 511 | ; -------------------------------------------------------------------------------------------------------------------. 512 | GetStyles(&Styles := "") { ; Retrieves the current edit style flags 513 | ; Returns an object containing keys as defined in 'SES'. 514 | ; If a variable is passed in the Styles parameter, the combined numeric value of the styles will be stored in it. 515 | ; For details see http://msdn.microsoft.com/en-us/library/bb788031(v=vs.85).aspx. 516 | ; EM_GETEDITSTYLE = 0x04CD (WM_USER + 205) 517 | Static SES := {1: "EMULATESYSEDIT", 1: "BEEPONMAXTEXT", 4: "EXTENDBACKCOLOR", 32: "NOXLTSYMBOLRANGE", 518 | 64: "USEAIMM", 128: "NOIME", 256: "ALLOWBEEPS", 512: "UPPERCASE", 1024: "LOWERCASE", 519 | 2048: "NOINPUTSEQUENCECHK", 4096: "BIDI", 8192: "SCROLLONKILLFOCUS", 16384: "XLTCRCRLFTOCR", 520 | 32768: "DRAFTMODE", 0x0010000: "USECTF", 0x0020000: "HIDEGRIDLINES", 0x0040000: "USEATFONT", 521 | 0x0080000: "CUSTOMLOOK",0x0100000: "LBSCROLLNOTIFY", 0x0200000: "CTFALLOWEMBED", 522 | 0x0400000: "CTFALLOWSMARTTAG", 0x0800000: "CTFALLOWPROOFING"} 523 | Styles := SendMessage(0x04CD, 0, 0, This.HWND) 524 | S := [] 525 | For Key, Value In SES.OwnProps() 526 | If (Styles & Key) 527 | S.Push(Value) 528 | Return S 529 | } 530 | ; ------------------------------------------------------------------------------------------------------------------- 531 | GetZoom() { ; Gets the current zoom ratio 532 | ; Returns the zoom ratio in percent. 533 | ; EM_GETZOOM = 0x04E0 534 | N := Buffer(4, 0), D := Buffer(4, 0) 535 | SendMessage(0x04CD, N.Ptr, D.Ptr, This.HWND) 536 | N := NumGet(N, 0, "Int"), D := NumGet(D, 0, "Int") 537 | Return (N = 0) && (D = 0) ? 100 : Round(N / D * 100) 538 | } 539 | ; ------------------------------------------------------------------------------------------------------------------- 540 | SetBkgndColor(Color) { ; Sets the background color 541 | ; Color : RGB integer value or HTML color name or 542 | ; "Auto" to reset to system default color. 543 | ; Returns the prior background color. 544 | ; EM_SETBKGNDCOLOR = 0x0443 545 | If (Color = "Auto") 546 | System := True, Color := 0 547 | Else 548 | System := False, Color := This.GetBGR(Color) 549 | Result := SendMessage(0x0443, System, Color, This.HWND) 550 | Return This.GetRGB(Result) 551 | } 552 | ; ------------------------------------------------------------------------------------------------------------------- 553 | SetOptions(Options, Mode := "SET") { ; Sets the options for a rich edit control 554 | ; Options : Array of options as the keys defined in 'ECO'. 555 | ; Mode : Settings mode: SET, OR, AND, XOR 556 | ; For details see http://msdn.microsoft.com/en-us/library/bb774254(v=vs.85).aspx. 557 | ; EM_SETOPTIONS = 0x044D 558 | Static ECO := {AUTOWORDSELECTION: 0x01, AUTOVSCROLL: 0x40, AUTOHSCROLL: 0x80, NOHIDESEL: 0x100, READONLY: 0x800 559 | , WANTRETURN: 0x1000, SAVESEL: 0x8000, SELECTIONBAR: 0x01000000, VERTICAL: 0x400000} 560 | , ECOOP := {SET: 0x01, OR: 0x02, AND: 0x03, XOR: 0x04} 561 | If (Type(Options) != "Array") || !ECOOP.HasProp(Mode) 562 | Return False 563 | O := 0 564 | For Each, Option In Options { 565 | If ECO.HasProp(Option) 566 | O |= ECO.%Option% 567 | Else 568 | Return False 569 | } 570 | Return SendMessage(0x044D, ECOOP.%Mode%, O, This.HWND) 571 | } 572 | ; ------------------------------------------------------------------------------------------------------------------- 573 | SetRect(L, T, R, B) { ; Sets the formatting rectangle of a multiline edit control 574 | ; L (eft), T (op), R (ight), B (ottom) 575 | ; Set all parameters to zero to set it to its default values. 576 | ; Returns True for multiline controls. 577 | If !This.MultiLine 578 | Return False 579 | If (L + T + R + B) = 0 580 | RC := {Ptr: 0} 581 | Else { 582 | RC := Buffer(16, 0) 583 | NumPut("Int", L, "Int", T, "Int", R, "Int", B, RC) 584 | } 585 | SendMessage(0xB3, 0, RC.Ptr, This.HWND) 586 | Return True 587 | } 588 | ; ------------------------------------------------------------------------------------------------------------------- 589 | SetStyles(Styles) { ; Sets the current edit style flags for a rich edit control. 590 | ; Styles : Object containing on or more of the keys defined in 'SES'. 591 | ; If the value is 0 the style will be removed, otherwise it will be added. 592 | ; For details see http://msdn.microsoft.com/en-us/library/bb774236(v=vs.85).aspx. 593 | ; EM_SETEDITSTYLE = 0x04CC (WM_USER + 204) 594 | Static SES := {EMULATESYSEDIT: 1, BEEPONMAXTEXT: 2, EXTENDBACKCOLOR: 4, NOXLTSYMBOLRANGE: 32, USEAIMM: 64, 595 | NOIME: 128, ALLOWBEEPS: 256, UPPERCASE: 512, LOWERCASE: 1024, NOINPUTSEQUENCECHK: 2048, 596 | BIDI: 4096, SCROLLONKILLFOCUS: 8192, XLTCRCRLFTOCR: 16384, DRAFTMODE: 32768, 597 | USECTF: 0x0010000, HIDEGRIDLINES: 0x0020000, USEATFONT: 0x0040000, CUSTOMLOOK: 0x0080000, 598 | LBSCROLLNOTIFY: 0x0100000, CTFALLOWEMBED: 0x0200000, CTFALLOWSMARTTAG: 0x0400000, 599 | CTFALLOWPROOFING: 0x0800000} 600 | If (Type(Styles) != "Object") 601 | Return False 602 | Flags := Mask := 0 603 | For Style, Value In Styles.OwnProps() { 604 | If SES.HasProp(Style) { 605 | Mask |= SES.%Style% 606 | If (Value != 0) 607 | Flags |= SES.%Style% 608 | } 609 | } 610 | Return Mask ? SendMessage(0x04CC, Flags, Mask, This.HWND) : False 611 | } 612 | ; ------------------------------------------------------------------------------------------------------------------- 613 | SetZoom(Ratio := "") { ; Sets the zoom ratio of a rich edit control. 614 | ; Ratio : Float value between 100/64 and 6400; a ratio of 0 turns zooming off. 615 | ; EM_SETZOOM = 0x4E1 616 | Return SendMessage(0x04E1, (Ratio > 0 ? Ratio : 100), 100, This.HWND) 617 | } 618 | ; =================================================================================================================== 619 | ; Copy, paste, etc. 620 | ; =================================================================================================================== 621 | CanRedo() { ; Determines whether there are any actions in the control redo queue. 622 | ; EM_CANREDO = 0x0455 (WM_USER + 85) 623 | Return SendMessage(0x0455, 0, 0, This.HWND) 624 | } 625 | ; ------------------------------------------------------------------------------------------------------------------- 626 | CanUndo() { ; Determines whether there are any actions in an edit control's undo queue. 627 | ; EM_CANUNDO = 0x00C6 628 | Return SendMessage(0x00C6, 0, 0, This.HWND) 629 | } 630 | ; ------------------------------------------------------------------------------------------------------------------- 631 | Clear() { 632 | ; WM_CLEAR = 0x303 633 | Return SendMessage(0x0303, 0, 0, This.HWND) 634 | } 635 | ; ------------------------------------------------------------------------------------------------------------------- 636 | Copy() { 637 | ; WM_COPY = 0x301 638 | Return SendMessage(0x0301, 0, 0, This.HWND) 639 | } 640 | ; ------------------------------------------------------------------------------------------------------------------- 641 | Cut() { 642 | ; WM_CUT = 0x300 643 | Return SendMessage(0x0300, 0, 0, This.HWND) 644 | } 645 | ; ------------------------------------------------------------------------------------------------------------------- 646 | Paste() { 647 | ; WM_PASTE = 0x302 648 | Return SendMessage(0x0302, 0, 0, This.HWND) 649 | } 650 | ; ------------------------------------------------------------------------------------------------------------------- 651 | Redo() { 652 | ; EM_REDO := 0x454 653 | Return SendMessage(0x0454, 0, 0, This.HWND) 654 | } 655 | ; ------------------------------------------------------------------------------------------------------------------- 656 | Undo() { 657 | ; EM_UNDO = 0xC7 658 | Return SendMessage(0x00C7, 0, 0, This.HWND) 659 | } 660 | ; ------------------------------------------------------------------------------------------------------------------- 661 | SelAll() { 662 | ; Select all 663 | Return This.SetSel(0, -1) 664 | } 665 | ; ------------------------------------------------------------------------------------------------------------------- 666 | Deselect() { 667 | ; Deselect all 668 | Sel := This.GetSel() 669 | Return This.SetSel(Sel.S, Sel.S) 670 | } 671 | ; =================================================================================================================== 672 | ; Font & colors 673 | ; =================================================================================================================== 674 | ChangeFontSize(Diff) { ; Change font size 675 | ; Diff : any positive or negative integer, positive values are treated as +1, negative as -1. 676 | ; Returns new size. 677 | ; EM_SETFONTSIZE = 0x04DF 678 | ; Font size changes by 1 in the range 4 - 11 pt, by 2 for 12 - 28 pt, afterward to 36 pt, 48 pt, 72 pt, 80 pt, 679 | ; and by 10 for > 80 pt. The maximum value is 160 pt, the minimum is 4 pt 680 | Font := This.GetFont() 681 | If (Diff > 0 && Font.Size < 160) || (Diff < 0 && Font.Size > 4) 682 | SendMessage(0x04DF, (Diff > 0 ? 1 : -1), 0, This.HWND) 683 | Else 684 | Return False 685 | Font := This.GetFont() 686 | Return Font.Size 687 | } 688 | ; ------------------------------------------------------------------------------------------------------------------- 689 | GetFont(Default := False) { ; Get current font 690 | ; Set Default to True to get the default font. 691 | ; Returns an object containing current options (see SetFont()) 692 | ; EM_GETCHARFORMAT = 0x043A 693 | ; BOLD_FONTTYPE = 0x0100, ITALIC_FONTTYPE = 0x0200 694 | ; CFM_BOLD = 1, CFM_ITALIC = 2, CFM_UNDERLINE = 4, CFM_STRIKEOUT = 8, CFM_PROTECTED = 16, CFM_SUBSCRIPT = 0x30000 695 | ; CFM_BACKCOLOR = 0x04000000, CFM_CHARSET := 0x08000000, CFM_FACE = 0x20000000, CFM_COLOR = 0x40000000 696 | ; CFM_SIZE = 0x80000000 697 | ; CFE_SUBSCRIPT = 0x10000, CFE_SUPERSCRIPT = 0x20000, CFE_AUTOBACKCOLOR = 0x04000000, CFE_AUTOCOLOR = 0x40000000 698 | ; SCF_SELECTION = 1 699 | Static Mask := 0xEC03001F 700 | Static Effects := 0xEC000000 701 | CF2 := RichEdit.CHARFORMAT2() 702 | CF2.Mask := Mask 703 | CF2.Effects := Effects 704 | SendMessage(0x043A, (Default ? 0 : 1), CF2.Ptr, This.HWND) 705 | Font := {} 706 | Font.Name := CF2.FaceName 707 | Font.Size := CF2.Height / 20 708 | CFS := CF2.Effects 709 | Style := (CFS & 1 ? "B" : "") . (CFS & 2 ? "I" : "") . (CFS & 4 ? "U" : "") . (CFS & 8 ? "S" : "") 710 | . (CFS & 0x10000 ? "L" : "") . (CFS & 0x20000 ? "H" : "") . (CFS & 16 ? "P" : "") 711 | Font.Style := Style = "" ? "N" : Style 712 | Font.Color := This.GetRGB(CF2.TextColor) 713 | If (CF2.Effects & 0x40000000) ; CFE_AUTOCOLOR 714 | Font.Color := "Auto" 715 | Else 716 | Font.Color := This.GetRGB(CF2.TextColor) 717 | If (CF2.Effects & 0x04000000) ; CFE_AUTOBACKCOLOR 718 | Font.BkColor := "Auto" 719 | Else 720 | Font.BkColor := This.GetRGB(CF2.BackColor) 721 | Font.CharSet := CF2.CharSet 722 | Return Font 723 | } 724 | ; ------------------------------------------------------------------------------------------------------------------- 725 | SetDefaultFont(Font := "") { ; Set default font 726 | ; Font : Optional object - see SetFont(). 727 | If IsObject(Font) { 728 | For Key, Value In Font.OwnProps() 729 | If This.DefFont.HasProp(Key) 730 | This.DefFont.%Key% := Value 731 | } 732 | Return This.SetFont(This.DefFont) 733 | } 734 | ; ------------------------------------------------------------------------------------------------------------------- 735 | SetFont(Font) { ; Set current/default font 736 | ; Font : Object containing the following keys 737 | ; Name : optional font name 738 | ; Size : optional font size in points 739 | ; Style : optional string of one or more of the following styles 740 | ; B = bold, I = italic, U = underline, S = strikeout, L = subscript 741 | ; H = superschript, P = protected, N = normal 742 | ; Color : optional text color as RGB integer value or HTML color name 743 | ; "Auto" for "automatic" (system's default) color 744 | ; BkColor : optional text background color (see Color) 745 | ; "Auto" for "automatic" (system's default) background color 746 | ; CharSet : optional font character set 747 | ; 1 = DEFAULT_CHARSET, 2 = SYMBOL_CHARSET 748 | ; Empty parameters preserve the corresponding properties 749 | ; EM_SETCHARFORMAT = 0x0444 750 | ; SCF_DEFAULT = 0, SCF_SELECTION = 1 751 | If (Type(Font) != "Object") 752 | Return False 753 | CF2 := RichEdit.CHARFORMAT2() 754 | Mask := Effects := 0 755 | If Font.HasProp("Name") && (Font.Name != "") { 756 | Mask |= 0x20000000, Effects |= 0x20000000 ; CFM_FACE, CFE_FACE 757 | CF2.FaceName := Font.Name 758 | } 759 | If Font.HasProp("Size") && (Font.Size != "") { 760 | Size := Font.Size 761 | If (Size < 161) 762 | Size *= 20 763 | Mask |= 0x80000000, Effects |= 0x80000000 ; CFM_SIZE, CFE_SIZE 764 | CF2.Height := Size 765 | } 766 | If Font.HasProp("Style") && (Font.Style != "") { 767 | Mask |= 0x3001F ; all font styles 768 | If InStr(Font.Style, "B") 769 | Effects |= 1 ; CFE_BOLD 770 | If InStr(Font.Style, "I") 771 | Effects |= 2 ; CFE_ITALIC 772 | If InStr(Font.Style, "U") 773 | Effects |= 4 ; CFE_UNDERLINE 774 | If InStr(Font.Style, "S") 775 | Effects |= 8 ; CFE_STRIKEOUT 776 | If InStr(Font.Style, "P") 777 | Effects |= 16 ; CFE_PROTECTED 778 | If InStr(Font.Style, "L") 779 | Effects |= 0x10000 ; CFE_SUBSCRIPT 780 | If InStr(Font.Style, "H") 781 | Effects |= 0x20000 ; CFE_SUPERSCRIPT 782 | } 783 | If Font.HasProp("Color") && (Font.Color != "") { 784 | Mask |= 0x40000000 ; CFM_COLOR 785 | If (Font.Color = "Auto") 786 | Effects |= 0x40000000 ; CFE_AUTOCOLOR 787 | Else 788 | CF2.TextColor := This.GetBGR(Font.Color) 789 | } 790 | If Font.HasProp("BkColor") && (Font.BkColor != "") { 791 | Mask |= 0x04000000 ; CFM_BACKCOLOR 792 | If (Font.BkColor = "Auto") 793 | Effects |= 0x04000000 ; CFE_AUTOBACKCOLOR 794 | Else 795 | CF2.BackColor := This.GetBGR(Font.BkColor) 796 | } 797 | If Font.HasProp("CharSet") && (Font.CharSet != "") { 798 | Mask |= 0x08000000, Effects |= 0x08000000 ; CFM_CHARSET, CFE_CHARSET 799 | CF2.CharSet := Font.CharSet = 2 ? 2 : 1 ; SYMBOL|DEFAULT 800 | } 801 | If (Mask != 0) { 802 | Mode := Font.HasProp("Default") ? 0 : 1 803 | CF2.Mask := Mask 804 | CF2.Effects := Effects 805 | Return SendMessage(0x0444, Mode, CF2.Ptr, This.HWND) 806 | } 807 | Return False 808 | } 809 | ; ------------------------------------------------------------------------------------------------------------------- 810 | SetFontStyles(Styles, Default := False) { ; Set the font styles for the current selection or the default font 811 | ; Styles : a string containing one or more of the following styles 812 | ; B = bold, I = italic, U = underline, S = strikeout, L = subscript, H = superschript, P = protected, 813 | ; N = normal (reset all other styles) 814 | ; EM_GETCHARFORMAT = 0x043A, EM_SETCHARFORMAT = 0x0444 815 | ; CFM_BOLD = 1, CFM_ITALIC = 2, CFM_UNDERLINE = 4, CFM_STRIKEOUT = 8, CFM_PROTECTED = 16, CFM_SUxSCRIPT = 0x30000 816 | ; CFE_SUBSCRIPT = 0x10000, CFE_SUPERSCRIPT = 0x20000, SCF_SELECTION = 1 817 | Static FontStyles := {N: 0, B: 1, I: 2, U: 4, S: 8, P: 16, L: 0x010000, H: 0x020000} 818 | CF2 := RichEdit.CHARFORMAT2() 819 | CF2.Mask := 0x3001F ; FontStyles 820 | If InStr(Styles, "N") 821 | CF2.Effects := 0 822 | Else 823 | For Style In StrSplit(Styles) 824 | CF2.Effects |= FontStyles.HasProp(Style) ? FontStyles.%Style% : 0 825 | Return SendMessage(0x0444, !Default, CF2.Ptr, This.HWND) 826 | } 827 | ; ------------------------------------------------------------------------------------------------------------------- 828 | ToggleFontStyle(Style) { ; Toggle single font style 829 | ; Style : one of the following styles 830 | ; B = bold, I = italic, U = underline, S = strikeout, L = subscript, H = superschript, P = protected, 831 | ; N = normal (reset all other styles) 832 | ; EM_GETCHARFORMAT = 0x043A, EM_SETCHARFORMAT = 0x0444 833 | ; CFM_BOLD = 1, CFM_ITALIC = 2, CFM_UNDERLINE = 4, CFM_STRIKEOUT = 8, CFM_PROTECTED = 16, CFM_SUBSCRIPT = 0x30000 834 | ; CFE_SUBSCRIPT = 0x10000, CFE_SUPERSCRIPT = 0x20000, SCF_SELECTION = 1 835 | Static FontStyles := {N: 0, B: 1, I: 2, U: 4, S: 8, P: 16, L: 0x010000, H: 0x020000} 836 | If !FontStyles.HasProp(Style) 837 | Return False 838 | CF2 := This.GetCharFormat() 839 | CF2.Mask := 0x3001F ; FontStyles 840 | If (Style = "N") 841 | CF2.Effects := 0 842 | Else 843 | CF2.Effects ^= FontStyles.%Style% 844 | Return SendMessage(0x0444, 1, CF2.Ptr, This.HWND) 845 | } 846 | ; =================================================================================================================== 847 | ; Paragraph formatting 848 | ; =================================================================================================================== 849 | AlignText(Align := 1) { ; Set paragraph's alignment 850 | ; Note: Values greater 3 doesn't seem to work though they should as documented 851 | ; Align: may contain one of the following numbers: 852 | ; PFA_LEFT 1 853 | ; PFA_RIGHT 2 854 | ; PFA_CENTER 3 855 | ; PFA_JUSTIFY 4 // New paragraph-alignment option 2.0 (*) 856 | ; PFA_FULL_INTERWORD 4 // These are supported in 3.0 with advanced 857 | ; PFA_FULL_INTERLETTER 5 // typography enabled 858 | ; PFA_FULL_SCALED 6 859 | ; PFA_FULL_GLYPHS 7 860 | ; PFA_SNAP_GRID 8 861 | ; EM_SETPARAFORMAT = 0x0447, PFM_ALIGNMENT = 0x08 862 | Static PFA := {LEFT: 1, RIGHT: 2, CENTER: 3, JUSTIFY: 4} 863 | If PFA.HasProp(Align) 864 | Align := PFA.%Align% 865 | If (Align >= 1) && (ALign <= 8) { 866 | PF2 := RichEdit.PARAFORMAT2() ; PARAFORMAT2 struct 867 | PF2.Mask := 0x08 ; dwMask 868 | PF2.Alignment := Align ; wAlignment 869 | SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 870 | Return True 871 | } 872 | Return False 873 | } 874 | ; ------------------------------------------------------------------------------------------------------------------- 875 | SetBorder(Widths, Styles) { ; Set paragraph's borders 876 | ; Borders are not displayed in RichEdit, so the call of this function has no visible result. 877 | ; Even WordPad distributed with Win7 does not show them, but e.g. Word 2007 does. 878 | ; Widths : Array of the 4 border widths in the range of 1 - 15 in order left, top, right, bottom; zero = no border 879 | ; Styles : Array of the 4 border styles in the range of 0 - 7 in order left, top, right, bottom (see remarks) 880 | ; Note: 881 | ; The description on MSDN at http://msdn.microsoft.com/en-us/library/bb787942(v=vs.85).aspx is wrong! 882 | ; To set borders you have to put the border width into the related nibble (4 Bits) of wBorderWidth 883 | ; (in order: left (0 - 3), top (4 - 7), right (8 - 11), and bottom (12 - 15). The values are interpreted as 884 | ; half points (i.e. 10 twips). Border styles are set in the related nibbles of wBorders. 885 | ; Valid styles seem to be: 886 | ; 0 : \brdrdash (dashes) 887 | ; 1 : \brdrdashsm (small dashes) 888 | ; 2 : \brdrdb (double line) 889 | ; 3 : \brdrdot (dotted line) 890 | ; 4 : \brdrhair (single/hair line) 891 | ; 5 : \brdrs ? looks like 3 892 | ; 6 : \brdrth ? looks like 3 893 | ; 7 : \brdrtriple (triple line) 894 | ; EM_SETPARAFORMAT = 0x0447, PFM_BORDER = 0x800 895 | If (Type(Widths) != "Array") || (Type(Styles) != "Array") || (Widths.Length != 4) || (Styles.Length != 4) 896 | Return False 897 | W := S := 0 898 | For I, V In Widths { 899 | If (V) 900 | W |= V << ((A_Index - 1) * 4) 901 | If Styles[I] 902 | S |= Styles[I] << ((A_Index - 1) * 4) 903 | } 904 | PF2 := RichEdit.PARAFORMAT2() 905 | PF2.Mask := 0x800 906 | PF2.BorderWidth := W 907 | PF2.Borders := S 908 | Return SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 909 | } 910 | ; ------------------------------------------------------------------------------------------------------------------- 911 | SetLineSpacing(Lines) { ; Sets paragraph's line spacing. 912 | ; Lines : number of lines as integer or float. 913 | ; SpacingRule = 5: 914 | ; The value of dyLineSpacing / 20 is the spacing, in lines, from one line to the next. Thus, setting 915 | ; dyLineSpacing to 20 produces single-spaced text, 40 is double spaced, 60 is triple spaced, and so on. 916 | ; EM_SETPARAFORMAT = 0x0447, PFM_LINESPACING = 0x100 917 | PF2 := RichEdit.PARAFORMAT2() 918 | PF2.Mask := 0x100 919 | PF2.LineSpacing := Abs(Lines) * 20 920 | PF2.LineSpacingRule := 5 921 | Return SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 922 | } 923 | ; ------------------------------------------------------------------------------------------------------------------- 924 | SetParaIndent(Indent := "Reset") { ; Sets space left/right of the paragraph. 925 | ; Indent : Object containing up to three keys: 926 | ; - Start : Optional - Absolute indentation of the paragraph's first line. 927 | ; - Right : Optional - Indentation of the right side of the paragraph, relative to the right margin. 928 | ; - Offset : Optional - Indentation of the second and subsequent lines, relative to the indentation 929 | ; of the first line. 930 | ; Values are interpreted as centimeters/inches depending on the user's locale measurement settings. 931 | ; Call without passing a parameter to reset indentation. 932 | ; EM_SETPARAFORMAT = 0x0447 933 | ; PFM_STARTINDENT = 0x0001 934 | ; PFM_RIGHTINDENT = 0x0002 935 | ; PFM_OFFSET = 0x0004 936 | Static PFM := {STARTINDENT: 0x01, RIGHTINDENT: 0x02, OFFSET: 0x04} 937 | Measurement := This.GetMeasurement() 938 | PF2 := RichEdit.PARAFORMAT2() 939 | If (Indent = "Reset") 940 | PF2.Mask := 0x07 ; reset indentation 941 | Else If !IsObject(Indent) 942 | Return False 943 | Else { 944 | PF2.Mask := 0 945 | If (Indent.HasProp("Start")) { 946 | PF2.Mask |= PFM.STARTINDENT 947 | PF2.StartIndent := Round((Indent.Start / Measurement) * 1440) 948 | } 949 | If (Indent.HasProp("Offset")) { 950 | PF2.Mask |= PFM.OFFSET 951 | PF2.Offset := Round((Indent.Offset / Measurement) * 1440) 952 | } 953 | If (Indent.HasProp("Right")) { 954 | PF2.Mask |= PFM.RIGHTINDENT 955 | PF2.RightIndent := Round((Indent.Right / Measurement) * 1440) 956 | } 957 | } 958 | If (PF2.Mask) 959 | Return SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 960 | Return False 961 | } 962 | ; ------------------------------------------------------------------------------------------------------------------- 963 | SetParaNumbering(Numbering := "Reset") { 964 | ; Numbering : Object containing up to four keys: 965 | ; - Type : Options used for bulleted or numbered paragraphs. 966 | ; - Style : Optional - Numbering style used with numbered paragraphs. 967 | ; - Tab : Optional - Minimum space between a paragraph number and the paragraph text. 968 | ; - Start : Optional - Sequence number used for numbered paragraphs (e.g. 3 for C or III) 969 | ; Tab is interpreted as centimeters/inches depending on the user's locale measurement settings. 970 | ; Call without passing a parameter to reset numbering. 971 | ; EM_SETPARAFORMAT = 0x0447 972 | ; PARAFORMAT numbering options 973 | ; PFN_BULLET 1 ; tomListBullet 974 | ; PFN_ARABIC 2 ; tomListNumberAsArabic: 0, 1, 2, ... 975 | ; PFN_LCLETTER 3 ; tomListNumberAsLCLetter: a, b, c, ... 976 | ; PFN_UCLETTER 4 ; tomListNumberAsUCLetter: A, B, C, ... 977 | ; PFN_LCROMAN 5 ; tomListNumberAsLCRoman: i, ii, iii, ... 978 | ; PFN_UCROMAN 6 ; tomListNumberAsUCRoman: I, II, III, ... 979 | ; PARAFORMAT2 wNumberingStyle options 980 | ; PFNS_PAREN 0x0000 ; default, e.g., 1) 981 | ; PFNS_PARENS 0x0100 ; tomListParentheses/256, e.g., (1) 982 | ; PFNS_PERIOD 0x0200 ; tomListPeriod/256, e.g., 1. 983 | ; PFNS_PLAIN 0x0300 ; tomListPlain/256, e.g., 1 984 | ; PFNS_NONUMBER 0x0400 ; used for continuation w/o number 985 | ; PFNS_NEWNUMBER 0x8000 ; start new number with wNumberingStart 986 | ; PFM_NUMBERING 0x0020 987 | ; PFM_NUMBERINGSTYLE 0x2000 988 | ; PFM_NUMBERINGTAB 0x4000 989 | ; PFM_NUMBERINGSTART 0x8000 990 | Static PFM := {Type: 0x0020, Style: 0x2000, Tab: 0x4000, Start: 0x8000} 991 | Static PFN := {Bullet: 1, Arabic: 2, LCLetter: 3, UCLetter: 4, LCRoman: 5, UCRoman: 6} 992 | Static PFNS := {Paren: 0x0000, Parens: 0x0100, Period: 0x0200, Plain: 0x0300, None: 0x0400, New: 0x8000} 993 | PF2 := RichEdit.PARAFORMAT2() 994 | If (Numbering = "Reset") 995 | PF2.Mask := 0xE020 996 | Else If !IsObject(Numbering) 997 | Return False 998 | Else { 999 | If (Numbering.HasProp("Type")) { 1000 | PF2.Mask |= PFM.Type 1001 | PF2.Numbering := PFN.%Numbering.Type% 1002 | } 1003 | If (Numbering.HasProp("Style")) { 1004 | PF2.Mask |= PFM.Style 1005 | PF2.NumberingStyle := PFNS.%Numbering.Style% 1006 | } 1007 | If (Numbering.HasProp("Tab")) { 1008 | PF2.Mask |= PFM.Tab 1009 | PF2.NumberingTab := Round((Numbering.Tab / This.GetMeasurement()) * 1440) 1010 | } 1011 | If (Numbering.HasProp("Start")) { 1012 | PF2.Mask |= PFM.Start 1013 | PF2.NumberingStart := Numbering.Start 1014 | } 1015 | } 1016 | If (PF2.Mask) 1017 | Return SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 1018 | Return False 1019 | } 1020 | ; ------------------------------------------------------------------------------------------------------------------- 1021 | SetParaSpacing(Spacing := "Reset") { ; Set space before / after the paragraph 1022 | ; Spacing : Object containing one or two keys: 1023 | ; - Before : additional space before the paragraph in points 1024 | ; - After : additional space after the paragraph in points 1025 | ; Call without passing a parameter to reset spacing to zero. 1026 | ; EM_SETPARAFORMAT = 0x0447 1027 | ; PFM_SPACEBEFORE = 0x0040 1028 | ; PFM_SPACEAFTER = 0x0080 1029 | Static PFM := {Before: 0x40, After: 0x80} 1030 | PF2 := RichEdit.PARAFORMAT2() 1031 | If (Spacing = "Reset") 1032 | PF2.Mask := 0xC0 ; reset spacing 1033 | Else If !IsObject(Spacing) 1034 | Return False 1035 | Else { 1036 | If Spacing.HasProp("Before") && (Spacing.Before >= 0) { 1037 | PF2.Mask |= PFM.Before 1038 | PF2.SpaceBefore := Round(Spacing.Before * 20) 1039 | } 1040 | If Spacing.HasProp("After") && (Spacing.After >= 0) { 1041 | PF2.Mask |= PFM.After 1042 | PF2.SpaceAfter := Round(Spacing.After * 20) 1043 | } 1044 | } 1045 | If (PF2.Mask) 1046 | Return SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 1047 | Return False 1048 | } 1049 | ; ------------------------------------------------------------------------------------------------------------------- 1050 | SetDefaultTabs(Distance) { ; Set default tabstops 1051 | ; Distance will be interpreted as inches or centimeters depending on the current user's locale. 1052 | ; EM_SETTABSTOPS = 0xCB 1053 | Static DUI := 64 ; dialog units per inch 1054 | , MinTab := 0.20 ; minimal tab distance 1055 | , MaxTab := 3.00 ; maximal tab distance 1056 | IM := This.GetMeasurement() 1057 | Distance := StrReplace(Distance, ",", ".") 1058 | Distance := Round(Distance / IM, 2) 1059 | If (Distance < MinTab) 1060 | Distance := MinTab 1061 | Else If (Distance > MaxTab) 1062 | Distance := MaxTab 1063 | TabStops := Buffer(4, 0) 1064 | NumPut("Int", Round(DUI * Distance), TabStops) 1065 | Result := SendMessage(0x00CB, 1, TabStops.Ptr, This.HWND) 1066 | DllCall("UpdateWindow", "Ptr", This.HWND) 1067 | Return Result 1068 | } 1069 | ; ------------------------------------------------------------------------------------------------------------------- 1070 | SetTabStops(TabStops := "Reset") { ; Set paragraph's tabstobs 1071 | ; TabStops is an object containing the integer position as hundredth of inches/centimeters as keys 1072 | ; and the alignment ("L", "C", "R", or "D") as values. 1073 | ; The position will be interpreted as hundredth of inches or centimeters depending on the current user's locale. 1074 | ; Call without passing a parameter to reset to default tabs. 1075 | ; EM_SETPARAFORMAT = 0x0447, PFM_TABSTOPS = 0x10 1076 | Static MinT := 30 ; minimal tabstop in hundredth of inches 1077 | Static MaxT := 830 ; maximal tabstop in hundredth of inches 1078 | Static Align := {L: 0x00000000 ; left aligned (default) 1079 | , C: 0x01000000 ; centered 1080 | , R: 0x02000000 ; right aligned 1081 | , D: 0x03000000} ; decimal tabstop 1082 | Static MAX_TAB_STOPS := 32 1083 | IC := This.GetMeasurement() 1084 | PF2 := RichEdit.PARAFORMAT2() 1085 | PF2.Mask := 0x10 1086 | If (TabStops = "Reset") 1087 | Return !!SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 1088 | If !IsObject(TabStops) 1089 | Return False 1090 | Tabs := [] 1091 | For Position, Alignment In TabStops.OwnProps() { 1092 | Position /= IC 1093 | If (Position < MinT) Or (Position > MaxT) || 1094 | !Align.HasProp(Alignment) Or (A_Index > MAX_TAB_STOPS) 1095 | Return False 1096 | Tabs.Push(Align.%Alignment% | Round((Position / 100) * 1440)) 1097 | } 1098 | If (Tabs.Length) { 1099 | PF2.Tabs := Tabs 1100 | Return SendMessage(0x0447, 0, PF2.Ptr, This.HWND) 1101 | } 1102 | Return False 1103 | } 1104 | ; =================================================================================================================== 1105 | ; Line handling 1106 | ; =================================================================================================================== 1107 | GetCaretLine() { ; Get the line containing the caret 1108 | ; EM_LINEINDEX = 0xBB, EM_EXLINEFROMCHAR = 0x0436 1109 | Result := SendMessage(0x00BB, -1, 0, This.HWND) 1110 | Return SendMessage(0x0436, 0, Result, This.HWND) + 1 1111 | } 1112 | ; ------------------------------------------------------------------------------------------------------------------- 1113 | GetLineCount() { ; Get the total number of lines 1114 | ; EM_GETLINECOUNT = 0xBA 1115 | Return SendMessage(0x00BA, 0, 0, This.HWND) 1116 | } 1117 | ; ------------------------------------------------------------------------------------------------------------------- 1118 | GetLineIndex(LineNumber) { ; Get the index of the first character of the specified line. 1119 | ; EM_LINEINDEX := 0x00BB 1120 | ; LineNumber - zero-based line number 1121 | Return SendMessage(0x00BB, LineNumber, 0, This.HWND) 1122 | } 1123 | ; =================================================================================================================== 1124 | ; Statistics 1125 | ; =================================================================================================================== 1126 | GetStatistics() { ; Get some statistic values 1127 | ; Get the line containing the caret, it's position in this line, the total amount of lines, the absulute caret 1128 | ; position and the total amount of characters. 1129 | ; EM_GETSEL = 0xB0, EM_LINEFROMCHAR = 0xC9, EM_LINEINDEX = 0xBB, EM_GETLINECOUNT = 0xBA 1130 | Stats := {} 1131 | SB := Buffer(A_PtrSize, 0) 1132 | SendMessage(0x00B0, SB.Ptr, 0, This.Hwnd) 1133 | LI := This.GetLineIndex(-1) 1134 | Stats.LinePos := NumGet(SB, "Ptr") - LI + 1 1135 | Stats.Line := SendMessage(0x00C9, -1, 0, This.HWND) + 1 1136 | Stats.LineCount := This.GetLineCount() 1137 | Stats.CharCount := This.GetTextLen() 1138 | Return Stats 1139 | } 1140 | ; =================================================================================================================== 1141 | ; Layout 1142 | ; =================================================================================================================== 1143 | WordWrap(On) { ; Turn wordwrapping on/off 1144 | ; EM_SCROLLCARET = 0xB7 1145 | Sel := This.GetSel() 1146 | SendMessage(0x0448, 0, On ? 0 : -1, This.HWND) 1147 | This.SetSel(Sel.S, Sel.E) 1148 | SendMessage(0x00B7, 0, 0, This.HWND) 1149 | Return On 1150 | } 1151 | ; ------------------------------------------------------------------------------------------------------------------- 1152 | WYSIWYG(On) { ; Show control as printed (WYSIWYG) 1153 | ; Text measuring is based on the default printer's capacities, thus changing the printer may produce different 1154 | ; results. See remarks/comments in Print() also. 1155 | ; EM_SCROLLCARET = 0xB7, EM_SETTARGETDEVICE = 0x0448 1156 | ; PD_RETURNDC = 0x0100, PD_RETURNDEFAULT = 0x0400 1157 | Static PDC := 0 1158 | Static PD_Size := (A_PtrSize = 4 ? 66 : 120) 1159 | Static OffFlags := A_PtrSize * 5 1160 | Sel := This.GetSel() 1161 | If !(On) { 1162 | DllCall("LockWindowUpdate", "Ptr", This.HWND) 1163 | DllCall("DeleteDC", "Ptr", PDC) 1164 | SendMessage(0x0448, 0, -1, This.HWND) 1165 | This.SetSel(Sel.S, Sel.E) 1166 | SendMessage(0x00B7, 0, 0, This.HWND) 1167 | DllCall("LockWindowUpdate", "Ptr", 0) 1168 | Return True 1169 | } 1170 | PD := Buffer(PD_Size, 0) 1171 | Numput("UInt", PD_Size, PD) 1172 | NumPut("UInt", 0x0100 | 0x0400, PD, A_PtrSize * 5) ; PD_RETURNDC | PD_RETURNDEFAULT 1173 | If !DllCall("Comdlg32.dll\PrintDlg", "Ptr", PD.Ptr, "Int") 1174 | Return 1175 | DllCall("GlobalFree", "Ptr", NumGet(PD, A_PtrSize * 2, "UPtr")) 1176 | DllCall("GlobalFree", "Ptr", NumGet(PD, A_PtrSize * 3, "UPtr")) 1177 | PDC := NumGet(PD, A_PtrSize * 4, "UPtr") 1178 | DllCall("LockWindowUpdate", "Ptr", This.HWND) 1179 | Caps := This.GetPrinterCaps(PDC) 1180 | ; Set up page size and margins in pixel 1181 | UML := This.Margins.LT ; user margin left 1182 | UMR := This.Margins.RT ; user margin right 1183 | PML := Caps.POFX ; physical margin left 1184 | PMR := Caps.PHYW - Caps.HRES - Caps.POFX ; physical margin right 1185 | LPW := Caps.HRES ; logical page width 1186 | ; Adjust margins 1187 | UML := UML > PML ? (UML - PML) : 0 1188 | UMR := UMR > PMR ? (UMR - PMR) : 0 1189 | LineLen := LPW - UML - UMR 1190 | SendMessage(0x0448, PDC, LineLen, This.HWND) 1191 | This.SetSel(Sel.S, Sel.E) 1192 | SendMessage(0x00B7, 0, 0, This.HWND) 1193 | DllCall("LockWindowUpdate", "Ptr", 0) 1194 | Return True 1195 | } 1196 | ; =================================================================================================================== 1197 | ; File handling 1198 | ; =================================================================================================================== 1199 | LoadFile(File, Mode := "Open") { ; Load file 1200 | ; File : file name 1201 | ; Mode : Open / Add / Insert 1202 | ; Open : Replace control's content 1203 | ; Append : Append to conrol's content 1204 | ; Insert : Insert at / replace current selection 1205 | If !FileExist(File) 1206 | Return False 1207 | Ext := "" 1208 | SplitPath(File, , , &Ext) 1209 | If (Ext = "rtf") { 1210 | Switch Mode { 1211 | Case "Open": 1212 | Selection := False 1213 | Case "Insert": 1214 | Selection := True 1215 | Case "Append": 1216 | This.SetSel(-1, -2) 1217 | Selection := True 1218 | } 1219 | This.LoadRTF(File, Selection) 1220 | } 1221 | Else { 1222 | Text := FileRead(File) 1223 | Switch Mode { 1224 | Case "Open": 1225 | This.SetText(Text) 1226 | Case "Insert": 1227 | This.ReplaceSel(Text) 1228 | Case "Append": 1229 | This.SetSel(-1, -2) 1230 | This.ReplaceSel(Text) 1231 | } 1232 | } 1233 | Return True 1234 | } 1235 | ; ------------------------------------------------------------------------------------------------------------------- 1236 | SaveFile(File) { ; Save file 1237 | ; File : file name 1238 | ; Returns True on success, otherwise False. 1239 | This.Gui.Opt("+OwnDialogs") 1240 | Ext := "" 1241 | SplitPath(File, , , &Ext) 1242 | Text := Ext = "rtf" ? This.GetRTF() : This.GetText() 1243 | Try { 1244 | FileObj := FileOpen(File, "w") 1245 | FileObj.Write(Text) 1246 | FileObj.Close() 1247 | Return True 1248 | } 1249 | Catch As Err { 1250 | MsgBox 16, A_ThisFunc, "Couldn't save '" . File . "'!`n`n" . Type(Err) ": " Err.Message 1251 | Return False 1252 | } 1253 | } 1254 | ; =================================================================================================================== 1255 | ; Printing 1256 | ; THX jballi -> http://www.autohotkey.com/board/topic/45513-function-he-print-wysiwyg-print-for-the-hiedit-control/ 1257 | ; =================================================================================================================== 1258 | Print() { 1259 | ; EM_FORMATRANGE = 0x0439, EM_SETTARGETDEVICE = 0x0448 1260 | ; ---------------------------------------------------------------------------------------------------------------- 1261 | ; Static variables 1262 | Static PD_ALLPAGES := 0x00, PD_SELECTION := 0x01, PD_PAGENUMS := 0x02, PD_NOSELECTION := 0x04 1263 | , PD_RETURNDC := 0x0100, PD_USEDEVMODECOPIES := 0x040000, PD_HIDEPRINTTOFILE := 0x100000 1264 | , PD_NONETWORKBUTTON := 0x200000, PD_NOCURRENTPAGE := 0x800000 1265 | , MM_TEXT := 0x1 1266 | , DocName := "AHKRichEdit" 1267 | , PD_Size := (A_PtrSize = 8 ? (13 * A_PtrSize) + 16 : 66) 1268 | ErrorMsg := "" 1269 | ; ---------------------------------------------------------------------------------------------------------------- 1270 | ; Prepare to call PrintDlg 1271 | ; Define/Populate the PRINTDLG structure 1272 | PD := Buffer(PD_Size, 0) 1273 | Numput("UInt", PD_Size, PD) ; lStructSize 1274 | Numput("UPtr", This.Gui.Hwnd, PD, A_PtrSize) ; hwndOwner 1275 | ; Collect Start/End select positions 1276 | Sel := This.GetSel() 1277 | ; Determine/Set Flags 1278 | Flags := PD_ALLPAGES | PD_RETURNDC | PD_USEDEVMODECOPIES | PD_HIDEPRINTTOFILE | PD_NONETWORKBUTTON 1279 | | PD_NOCURRENTPAGE 1280 | If (Sel.S = Sel.E) 1281 | Flags |= PD_NOSELECTION 1282 | Else 1283 | Flags |= PD_SELECTION 1284 | Offset := A_PtrSize * 5 1285 | ; Flags, pages, and copies 1286 | NumPut("UInt", Flags, "UShort", 1, "UShort", 1, "UShort", 1, "UShort", -1, "UShort", 1, PD, Offset) 1287 | ; Note: Use -1 to specify the maximum page number (65535). 1288 | ; Programming note: The values that are loaded to these fields are critical. The Print dialog will not 1289 | ; display (returns an error) if unexpected values are loaded to one or more of these fields. 1290 | ; ---------------------------------------------------------------------------------------------------------------- 1291 | ; Print dialog box 1292 | ; Open the Print dialog. Bounce If the user cancels. 1293 | If !DllCall("Comdlg32.dll\PrintDlg", "Ptr", PD, "UInt") 1294 | Throw Error("Function: " . A_ThisFunc . " - DLLCall of 'PrintDlg' failed.", -1) 1295 | ; Get the printer device context. Bounce If not defined. 1296 | If !(PDC := NumGet(PD, A_PtrSize * 4, "UPtr")) ; hDC 1297 | Throw Error("Function: " . A_ThisFunc . " - Couldn't get a printer's device context.", -1) 1298 | ; Free global structures created by PrintDlg 1299 | DllCall("GlobalFree", "Ptr", NumGet(PD, A_PtrSize * 2, "UPtr")) 1300 | DllCall("GlobalFree", "Ptr", NumGet(PD, A_PtrSize * 3, "UPtr")) 1301 | ; ---------------------------------------------------------------------------------------------------------------- 1302 | ; Prepare to print 1303 | ; Collect Flags 1304 | Offset := A_PtrSize * 5 1305 | Flags := NumGet(PD, OffSet, "UInt") ; Flags 1306 | ; Determine From/To Page 1307 | If (Flags & PD_PAGENUMS) { 1308 | PageF := NumGet(PD, Offset += 4, "UShort") ; nFromPage (first page) 1309 | PageL := NumGet(PD, Offset += 2, "UShort") ; nToPage (last page) 1310 | } 1311 | Else 1312 | PageF := 1, PageL := 65535 1313 | ; Collect printer capacities 1314 | Caps := This.GetPrinterCaps(PDC) 1315 | ; Set up page size and margins in Twips (1/20 point or 1/1440 of an inch) 1316 | UML := This.Margins.LT ; user margin left 1317 | UMT := This.Margins.TT ; user margin top 1318 | UMR := This.Margins.RT ; user margin right 1319 | UMB := This.Margins.BT ; user margin bottom 1320 | PML := Caps.POFX ; physical margin left 1321 | PMT := Caps.POFY ; physical margin top 1322 | PMR := Caps.PHYW - Caps.HRES - Caps.POFX ; physical margin right 1323 | PMB := Caps.PHYH - Caps.VRES - Caps.POFY ; physical margin bottom 1324 | LPW := Caps.HRES ; logical page width 1325 | LPH := Caps.VRES ; logical page height 1326 | ; Adjust margins 1327 | UML := UML > PML ? (UML - PML) : 0 1328 | UMT := UMT > PMT ? (UMT - PMT) : 0 1329 | UMR := UMR > PMR ? (UMR - PMR) : 0 1330 | UMB := UMB > PMB ? (UMB - PMB) : 0 1331 | ; Define/Populate the FORMATRANGE structure 1332 | FR := Buffer((A_PtrSize * 2) + (4 * 10), 0) 1333 | NumPut("UPtr", PDC, "UPtr", PDC, FR) ; hdc , hdcTarget 1334 | ; Define FORMATRANGE.rc 1335 | ; rc is the area to render to (rcPage - margins), measured in twips (1/20 point or 1/1440 of an inch). 1336 | ; If the user-defined margins are smaller than the printer's margins (the unprintable areas at the edges 1337 | ; of each page), the user margins are set to the printer's margins. In addition, the user-defined margins 1338 | ; must be adjusted to account for the printer's margins. 1339 | ; For example: If the user requests a 3/4 inch (19.05 mm) left margin but the printer's left margin is 1340 | ; 1/4 inch (6.35 mm), rc.Left is set to 720 twips (1/2 inch or 12.7 mm). 1341 | Offset := A_PtrSize * 2 1342 | NumPut("Int", UML, "Int", UMT, "Int", LPW - UMR, "Int", LPH - UMB, FR, Offset) 1343 | ; Define FORMATRANGE.rcPage 1344 | ; rcPage is the entire area of a page on the rendering device, measured in twips (1/20 point or 1/1440 of an inch) 1345 | ; Note: rc defines the maximum printable area which does not include the printer's margins (the unprintable areas 1346 | ; at the edges of the page). The unprintable areas are represented by PHYSICALOFFSETX and PHYSICALOFFSETY. 1347 | Offset += 16 1348 | NumPut("Int", 0, "Int", 0, "Int", LPW, "Int", LPH, FR, Offset) 1349 | ; Determine print range. 1350 | ; If "Selection" option is chosen, use selected text, otherwise use the entire document. 1351 | If (Flags & PD_SELECTION) 1352 | PrintS := Sel.S, PrintE := Sel.E 1353 | Else 1354 | PrintS := 0, PrintE := -1 ; (-1 = Select All) 1355 | Offset += 16 1356 | Numput("Int", PrintS, "Int", PrintE, FR, OffSet) ; cr.cpMin , cr.cpMax 1357 | ; Define/Populate the DOCINFO structure 1358 | DI := Buffer(A_PtrSize * 5, 0) 1359 | NumPut("UPtr", A_PtrSize * 5, "UPtr", StrPtr(DocName), "UPtr", 0, DI) ; lpszDocName, lpszOutput 1360 | ; Programming note: All other DOCINFO fields intentionally left as null. 1361 | ; Determine MaxPrintIndex 1362 | If (Flags & PD_SELECTION) 1363 | PrintM := Sel.E 1364 | Else 1365 | PrintM := This.GetTextLen() 1366 | ; Be sure that the printer device context is in text mode 1367 | DllCall("SetMapMode", "Ptr", PDC, "Int", MM_TEXT) 1368 | ; ---------------------------------------------------------------------------------------------------------------- 1369 | ; Print it! 1370 | ; Start a print job. Bounce If there is a problem. 1371 | PrintJob := DllCall("StartDoc", "Ptr", PDC, "Ptr", DI.Ptr, "Int") 1372 | If (PrintJob <= 0) 1373 | Throw Error("Function: " . A_ThisFunc . " - DLLCall of 'StartDoc' failed.", -1) 1374 | ; Print page loop 1375 | PageC := 0 ; current page 1376 | PrintC := 0 ; current print index 1377 | While (PrintC < PrintM) { 1378 | PageC++ 1379 | ; Are we done yet? 1380 | If (PageC > PageL) 1381 | Break 1382 | If (PageC >= PageF) && (PageC <= PageL) { 1383 | ; StartPage function. Break If there is a problem. 1384 | If (DllCall("StartPage", "Ptr", PDC, "Int") <= 0) { 1385 | ErrorMsg := "Function: " . A_ThisFunc . " - DLLCall of 'StartPage' failed." 1386 | Break 1387 | } 1388 | } 1389 | ; Format or measure page 1390 | If (PageC >= PageF) && (PageC <= PageL) 1391 | Render := True 1392 | Else 1393 | Render := False 1394 | PrintC := SendMessage(0x0439, Render, FR.Ptr, This.HWND) 1395 | If (PageC >= PageF) && (PageC <= PageL) { 1396 | ; EndPage function. Break If there is a problem. 1397 | If (DllCall("EndPage", "Ptr", PDC, "Int") <= 0) { 1398 | ErrorMsg := "Function: " . A_ThisFunc . " - DLLCall of 'EndPage' failed." 1399 | Break 1400 | } 1401 | } 1402 | ; Update FR for the next page 1403 | Offset := (A_PtrSize * 2) + (4 * 8) 1404 | Numput("Int", PrintC, "Int", PrintE, FR, Offset) ; cr.cpMin, cr.cpMax 1405 | } 1406 | ; ---------------------------------------------------------------------------------------------------------------- 1407 | ; End the print job 1408 | DllCall("EndDoc", "Ptr", PDC) 1409 | ; Delete the printer device context 1410 | DllCall("DeleteDC", "Ptr", PDC) 1411 | ; Reset control (free cached information) 1412 | SendMessage(0x0439, 0, 0, This.HWND) 1413 | ; Return to sender 1414 | If (ErrorMsg) 1415 | Throw Error(ErrorMsg, -1) 1416 | Return True 1417 | } 1418 | ; ------------------------------------------------------------------------------------------------------------------- 1419 | GetMargins() { ; Get the default print margins 1420 | Static PSD_RETURNDEFAULT := 0x00000400, PSD_INTHOUSANDTHSOFINCHES := 0x00000004 1421 | , I := 1000 ; thousandth of inches 1422 | , M := 2540 ; hundredth of millimeters 1423 | , PSD_Size := (4 * 10) + (A_PtrSize * 11) 1424 | , PD_Size := (A_PtrSize = 8 ? (13 * A_PtrSize) + 16 : 66) 1425 | , OffFlags := 4 * A_PtrSize 1426 | , OffMargins := OffFlags + (4 * 7) 1427 | If !This.HasOwnProp("Margins") { 1428 | PSD := Buffer(PSD_Size, 0) ; PAGESETUPDLG structure 1429 | NumPut("UInt", PSD_Size, PSD) 1430 | NumPut("UInt", PSD_RETURNDEFAULT, PSD, OffFlags) 1431 | If !DllCall("Comdlg32.dll\PageSetupDlg", "Ptr", PSD, "UInt") 1432 | Return false 1433 | DllCall("GlobalFree", "UInt", NumGet(PSD, 2 * A_PtrSize, "UPtr")) 1434 | DllCall("GlobalFree", "UInt", NumGet(PSD, 3 * A_PtrSize, "UPtr")) 1435 | Flags := NumGet(PSD, OffFlags, "UInt") 1436 | Metrics := (Flags & PSD_INTHOUSANDTHSOFINCHES) ? I : M 1437 | Offset := OffMargins 1438 | This.Margins := {} 1439 | This.Margins.L := NumGet(PSD, Offset += 0, "Int") ; Left 1440 | This.Margins.T := NumGet(PSD, Offset += 4, "Int") ; Top 1441 | This.Margins.R := NumGet(PSD, Offset += 4, "Int") ; Right 1442 | This.Margins.B := NumGet(PSD, Offset += 4, "Int") ; Bottom 1443 | This.Margins.LT := Round((This.Margins.L / Metrics) * 1440) ; Left in twips 1444 | This.Margins.TT := Round((This.Margins.T / Metrics) * 1440) ; Top in twips 1445 | This.Margins.RT := Round((This.Margins.R / Metrics) * 1440) ; Right in twips 1446 | This.Margins.BT := Round((This.Margins.B / Metrics) * 1440) ; Bottom in twips 1447 | } 1448 | Return True 1449 | } 1450 | ; ------------------------------------------------------------------------------------------------------------------- 1451 | GetPrinterCaps(DC) { ; Get printer's capacities 1452 | Static HORZRES := 0x08, VERTRES := 0x0A 1453 | , LOGPIXELSX := 0x58, LOGPIXELSY := 0x5A 1454 | , PHYSICALWIDTH := 0x6E, PHYSICALHEIGHT := 0x6F 1455 | , PHYSICALOFFSETX := 0x70, PHYSICALOFFSETY := 0x71 1456 | Caps := {} 1457 | ; Number of pixels per logical inch along the page width and height 1458 | LPXX := DllCall("GetDeviceCaps", "Ptr", DC, "Int", LOGPIXELSX, "Int") 1459 | LPXY := DllCall("GetDeviceCaps", "Ptr", DC, "Int", LOGPIXELSY, "Int") 1460 | ; The width and height of the physical page, in twips. 1461 | Caps.PHYW := Round((DllCall("GetDeviceCaps", "Ptr", DC, "Int", PHYSICALWIDTH, "Int") / LPXX) * 1440) 1462 | Caps.PHYH := Round((DllCall("GetDeviceCaps", "Ptr", DC, "Int", PHYSICALHEIGHT, "Int") / LPXY) * 1440) 1463 | ; The distance from the left/right edge (PHYSICALOFFSETX) and the top/bottom edge (PHYSICALOFFSETY) of the 1464 | ; physical page to the edge of the printable area, in twips. 1465 | Caps.POFX := Round((DllCall("GetDeviceCaps", "Ptr", DC, "Int", PHYSICALOFFSETX, "Int") / LPXX) * 1440) 1466 | Caps.POFY := Round((DllCall("GetDeviceCaps", "Ptr", DC, "Int", PHYSICALOFFSETY, "Int") / LPXY) * 1440) 1467 | ; Width and height of the printable area of the page, in twips. 1468 | Caps.HRES := Round((DllCall("GetDeviceCaps", "Ptr", DC, "Int", HORZRES, "Int") / LPXX) * 1440) 1469 | Caps.VRES := Round((DllCall("GetDeviceCaps", "Ptr", DC, "Int", VERTRES, "Int") / LPXY) * 1440) 1470 | Return Caps 1471 | } 1472 | ; =================================================================================================================== 1473 | ; Internally used classes * 1474 | ; =================================================================================================================== 1475 | ; CHARFORMAT2 structure -> docs.microsoft.com/en-us/windows/win32/api/richedit/ns-richedit-charformat2w_1 1476 | Class CHARFORMAT2 Extends Buffer { 1477 | Size { 1478 | Get => NumGet(This, 0, "UInt") 1479 | Set => NumPut("UInt", Value, This, 0) 1480 | } 1481 | Mask { 1482 | Get => NumGet(This, 4, "UInt") 1483 | Set => NumPut("UInt", Value, This, 4) 1484 | } 1485 | Effects { 1486 | Get => NumGet(This, 8, "UInt") 1487 | Set => NumPut("UInt", Value, This, 8) 1488 | } 1489 | Height { 1490 | Get => NumGet(This, 12, "Int") 1491 | Set => NumPut("Int", Value, This, 12) 1492 | } 1493 | Offset { 1494 | Get => NumGet(This, 16, "Int") 1495 | Set => NumPut("Int", Value, This, 16) 1496 | } 1497 | TextColor { 1498 | Get => NumGet(This, 20, "UInt") 1499 | Set => NumPut("UInt", Value, This, 20) 1500 | } 1501 | CharSet { 1502 | Get => NumGet(This, 24, "UChar") 1503 | Set => NumPut("UChar", Value, This, 24) 1504 | } 1505 | PitchAndFamily { 1506 | Get => NumGet(This, 25, "UChar") 1507 | Set => NumPut("UChar", Value, This, 25) 1508 | } 1509 | FaceName { 1510 | Get => StrGet(This.Ptr + 26, 32) 1511 | Set => StrPut(Value, This.Ptr + 26, 32) 1512 | } 1513 | Weight { 1514 | Get => NumGet(This, 90, "UShort") 1515 | Set => NumPut("UShort", Value, This, 90) 1516 | } 1517 | Spacing { 1518 | Get => NumGet(This, 92, "Short") 1519 | Set => NumPut("Short", Value, This, 92) 1520 | } 1521 | BackColor { 1522 | Get => NumGet(This, 96, "UInt") 1523 | Set => NumPut("UInt", Value, This, 96) 1524 | } 1525 | LCID { 1526 | Get => NumGet(This, 100, "UInt") 1527 | Set => NumPut("UInt", Value, This, 100) 1528 | } 1529 | Cookie { 1530 | Get => NumGet(This, 104, "UInt") 1531 | Set => NumPut("UInt", Value, This, 104) 1532 | } 1533 | Style { 1534 | Get => NumGet(This, 108, "Short") 1535 | Set => NumPut("Short", Value, This, 108) 1536 | } 1537 | Kerning { 1538 | Get => NumGet(This, 110, "UShort") 1539 | Set => NumPut("UShort", Value, This, 110) 1540 | } 1541 | UnderlineType { 1542 | Get => NumGet(This, 112, "UChar") 1543 | Set => NumPut("UChar", Value, This, 112) 1544 | } 1545 | Animation { 1546 | Get => NumGet(This, 113, "UChar") 1547 | Set => NumPut("UChar", Value, This, 113) 1548 | } 1549 | RevAuthor { 1550 | Get => NumGet(This, 114, "UChar") 1551 | Set => NumPut("UChar", Value, This, 114) 1552 | } 1553 | UnderlineColor { 1554 | Get => NumGet(This, 115, "UChar") 1555 | Set => NumPut("UChar", Value, This, 115) 1556 | } 1557 | ; ---------------------------------------------------------------------------------------------------------------- 1558 | __New() { 1559 | Static CF2_Size := 116 1560 | Super.__New(CF2_Size, 0) 1561 | This.Size := CF2_Size 1562 | } 1563 | } 1564 | ; ------------------------------------------------------------------------------------------------------------------- 1565 | ; PARAFORMAT2 structure -> docs.microsoft.com/en-us/windows/win32/api/richedit/ns-richedit-paraformat2_1 1566 | Class PARAFORMAT2 Extends Buffer { 1567 | Size { 1568 | Get => NumGet(This, 0, "UInt") 1569 | Set => NumPut("UInt", Value, This, 0) 1570 | } 1571 | Mask { 1572 | Get => NumGet(This, 4, "UInt") 1573 | Set => NumPut("UInt", Value, This, 4) 1574 | } 1575 | Numbering { 1576 | Get => NumGet(This, 8, "UShort") 1577 | Set => NumPut("UShort", Value, This, 8) 1578 | } 1579 | StartIndent { 1580 | Get => NumGet(This, 12, "Int") 1581 | Set => (NumPut("Int", Value, This, 12), Value) 1582 | } 1583 | RightIndent { 1584 | Get => NumGet(This, 16, "Int") 1585 | Set => NumPut("Int", Value, This, 16) 1586 | } 1587 | Offset { 1588 | Get => NumGet(This, 20, "Int") 1589 | Set => NumPut("Int", Value, This, 20) 1590 | } 1591 | Alignment { 1592 | Get => NumGet(This, 24, "UShort") 1593 | Set => NumPut("UShort", Value, This, 24) 1594 | } 1595 | TabCount => NumGet(This, 26, "UShort") 1596 | Tabs { 1597 | Get { 1598 | TabCount := This.TabCount 1599 | Addr := This.Ptr + 28 - 4 1600 | Tabs := Array() 1601 | Tabs.Length := TabCount 1602 | Loop TabCount 1603 | Tabs[A_Index] := NumGet(Addr += 4, "UInt") 1604 | Return Tabs 1605 | } 1606 | Set { 1607 | Static ErrMsg := "Requires a value of type Array but got type " 1608 | If (Type(Value) != "Array") 1609 | Throw TypeError(ErrMsg . Type(Value) . "!", -1) 1610 | DllCall("RtlZeroMemory", "Ptr", This.Ptr + 28, "Ptr", 128) 1611 | TabCount := Value.Length 1612 | Addr := This.Ptr + 28 1613 | For I, Tab In Value 1614 | Addr := NumPut("UInt", Tab, Addr) 1615 | NumPut("UShort", TabCount, This, 26) 1616 | Return Value 1617 | } 1618 | } 1619 | SpaceBefore { 1620 | Get => NumGet(This, 156, "Int") 1621 | Set => NumPut("Int", Value, This, 156) 1622 | } 1623 | SpaceAfter { 1624 | Get => NumGet(This, 160, "Int") 1625 | Set => NumPut("Int", Value, This, 160) 1626 | } 1627 | LineSpacing { 1628 | Get => NumGet(This, 164, "Int") 1629 | Set => NumPut("Int", Value, This, 164) 1630 | } 1631 | Style { 1632 | Get => NumGet(This, 168, "Short") 1633 | Set => NumPut("Short", Value, This, 168) 1634 | } 1635 | LineSpacingRule { 1636 | Get => NumGet(This, 170, "UChar") 1637 | Set => NumPut("UChar", Value, This, 170) 1638 | } 1639 | OutlineLevel { 1640 | Get => NumGet(This, 171, "UChar") 1641 | Set => NumPut("UChar", Value, This, 171) 1642 | } 1643 | ShadingWeight { 1644 | Get => NumGet(This, 172, "UShort") 1645 | Set => NumPut("UShort", Value, This, 172) 1646 | } 1647 | ShadingStyle { 1648 | Get => NumGet(This, 174, "UShort") 1649 | Set => NumPut("UShort", Value, This, 174) 1650 | } 1651 | NumberingStart { 1652 | Get => NumGet(This, 176, "UShort") 1653 | Set => NumPut("UShort", Value, This, 176) 1654 | } 1655 | NumberingStyle { 1656 | Get => NumGet(This, 178, "UShort") 1657 | Set => NumPut("UShort", Value, This, 178) 1658 | } 1659 | NumberingTab { 1660 | Get => NumGet(This, 180, "UShort") 1661 | Set => NumPut("UShort", Value, This, 180) 1662 | } 1663 | BorderSpace { 1664 | Get => NumGet(This, 182, "UShort") 1665 | Set => NumPut("UShort", Value, This, 182) 1666 | } 1667 | BorderWidth { 1668 | Get => NumGet(This, 184, "UShort") 1669 | Set => NumPut("UShort", Value, This, 184) 1670 | } 1671 | Borders { 1672 | Get => NumGet(This, 186, "UShort") 1673 | Set => NumPut("UShort", Value, This, 186) 1674 | } 1675 | ; ---------------------------------------------------------------------------------------------------------------- 1676 | __New() { 1677 | Static PF2_Size := 188 1678 | Super.__New(PF2_Size, 0) 1679 | This.Size := PF2_Size 1680 | } 1681 | } 1682 | ; =================================================================================================================== 1683 | ; Internally called methods * 1684 | ; =================================================================================================================== 1685 | GetBGR(RGB) { ; Get numeric BGR value from numeric RGB value or HTML color name 1686 | Static HTML := {BLACK: 0x000000, SILVER: 0xC0C0C0, GRAY: 0x808080, WHITE: 0xFFFFFF 1687 | , MAROON: 0x000080, RED: 0x0000FF, PURPLE: 0x800080, FUCHSIA: 0xFF00FF 1688 | , GREEN: 0x008000, LIME: 0x00FF00, OLIVE: 0x008080, YELLOW: 0x00FFFF 1689 | , NAVY: 0x800000, BLUE: 0xFF0000, TEAL: 0x808000, AQUA: 0xFFFF00} 1690 | If HTML.HasProp(RGB) 1691 | Return HTML.%RGB% 1692 | Return ((RGB & 0xFF0000) >> 16) + (RGB & 0x00FF00) + ((RGB & 0x0000FF) << 16) 1693 | } 1694 | ; ------------------------------------------------------------------------------------------------------------------- 1695 | GetRGB(BGR) { ; Get numeric RGB value from numeric BGR-Value 1696 | Return ((BGR & 0xFF0000) >> 16) + (BGR & 0x00FF00) + ((BGR & 0x0000FF) << 16) 1697 | } 1698 | ; ------------------------------------------------------------------------------------------------------------------- 1699 | GetMeasurement() { ; Get locale measurement (metric / inch) 1700 | ; LOCALE_USER_DEFAULT = 0x0400, LOCALE_IMEASURE = 0x0D, LOCALE_RETURN_NUMBER = 0x20000000 1701 | Static Metric := 2.54 ; centimeters 1702 | , Inches := 1.00 ; inches 1703 | , Measurement := "" 1704 | If (Measurement = "") { 1705 | LCD := Buffer(4, 0) 1706 | DllCall("GetLocaleInfo", "UInt", 0x400, "UInt", 0x2000000D, "Ptr", LCD, "Int", 2) 1707 | Measurement := NumGet(LCD, 0, "UInt") ? Inches : Metric 1708 | } 1709 | Return Measurement 1710 | } 1711 | } 1712 | -------------------------------------------------------------------------------- /Sources/RichEditDlgs.ahk: -------------------------------------------------------------------------------- 1 | #DllLoad "Comdlg32.dll" 2 | Class RichEditDlgs { 3 | Static Call(*) => False 4 | ; =================================================================================================================== 5 | ; =================================================================================================================== 6 | ; RICHEDIT COMMON DIALOGS =========================================================================================== 7 | ; =================================================================================================================== 8 | Static FindReplMsg := DllCall("RegisterWindowMessage", "Str", "commdlg_FindReplace", "UInt") ; FINDMSGSTRING 9 | ; =================================================================================================================== 10 | ; Most of the following methods are based on DLG 5.01 by majkinetor 11 | ; http://www.autohotkey.com/board/topic/15836-module-dlg-501/ 12 | ; =================================================================================================================== 13 | Static ChooseColor(RE, Color := "") { ; Choose color dialog box 14 | ; =================================================================================================================== 15 | ; RE : RichEdit object 16 | Static CC_Size := A_PtrSize * 9, CCU := Buffer(64, 0) 17 | GuiHwnd := RE.Gui.Hwnd 18 | If (Color != "") 19 | Color := RE.GetBGR(Color) 20 | Else 21 | Color := 0x000000 22 | CC := Buffer(CC_Size, 0) ; CHOOSECOLOR structure 23 | NumPut("UInt", CC_Size, CC, 0) ; lStructSize 24 | NumPut("UPtr", GuiHwnd, CC, A_PtrSize) ; hwndOwner makes dialog modal 25 | NumPut("UInt", Color, CC, A_PtrSize * 3) ; rgbResult 26 | NumPut("UPtr", CCU.Ptr, CC, A_PtrSize * 4) ; COLORREF *lpCustColors (16) 27 | NumPut("UInt", 0x0101, CC, A_PtrSize * 5) ; Flags: CC_ANYCOLOR | CC_RGBINIT | ; CC_FULLOPEN 28 | R := DllCall("Comdlg32.dll\ChooseColor", "Ptr", CC.Ptr, "UInt") 29 | Return (R = 0) ? "" : RE.GetRGB(NumGet(CC, A_PtrSize * 3, "UInt")) 30 | } 31 | ; =================================================================================================================== 32 | Static ChooseFont(RE) { ; Choose font dialog box 33 | ; =================================================================================================================== 34 | ; RE : RichEdit object 35 | DC := DllCall("GetDC", "Ptr", RE.Gui.Hwnd, "Ptr") 36 | LP := DllCall("GetDeviceCaps", "Ptr", DC, "UInt", 90, "Int") ; LOGPIXELSY 37 | DllCall("ReleaseDC", "Ptr", RE.Gui.Hwnd, "Ptr", DC) 38 | ; Get current font 39 | Font := RE.GetFont() 40 | ; LF_FACENAME = 32 41 | LF := Buffer(92, 0) ; LOGFONT structure 42 | Size := -(Font.Size * LP / 72) 43 | NumPut("Int", Size, LF, 0) ; lfHeight 44 | If InStr(Font.Style, "B") 45 | NumPut("Int", 700, LF, 16) ; lfWeight 46 | If InStr(Font.Style, "I") 47 | NumPut("UChar", 1, LF, 20) ; lfItalic 48 | If InStr(Font.Style, "U") 49 | NumPut("UChar", 1, LF, 21) ; lfUnderline 50 | If InStr(Font.Style, "S") 51 | NumPut("UChar", 1, LF, 22) ; lfStrikeOut 52 | NumPut("UChar", Font.CharSet, LF, 23) ; lfCharSet 53 | StrPut(Font.Name, LF.Ptr + 28, 32) 54 | ; CF_BOTH = 3, CF_INITTOLOGFONTSTRUCT = 0x40, CF_EFFECTS = 0x100, CF_SCRIPTSONLY = 0x400 55 | ; CF_NOVECTORFONTS = 0x800, CF_NOSIMULATIONS = 0x1000, CF_LIMITSIZE = 0x2000, CF_WYSIWYG = 0x8000 56 | ; CF_TTONLY = 0x40000, CF_FORCEFONTEXIST =0x10000, CF_SELECTSCRIPT = 0x400000 57 | ; CF_NOVERTFONTS =0x01000000 58 | Flags := 0x00002141 ; 0x01013940 59 | If (Font.Color = "Auto") 60 | Color := DllCall("GetSysColor", "Int", 8, "UInt") ; COLOR_WINDOWTEXT = 8 61 | Else 62 | Color := RE.GetBGR(Font.Color) 63 | CF_Size := (A_PtrSize = 8 ? (A_PtrSize * 10) + (4 * 4) + A_PtrSize : (A_PtrSize * 14) + 4) 64 | CF := Buffer(CF_Size, 0) ; CHOOSEFONT structure 65 | NumPut("UInt", CF_Size, CF) ; lStructSize 66 | NumPut("UPtr", RE.Gui.Hwnd, CF, A_PtrSize) ; hwndOwner (makes dialog modal) 67 | NumPut("UPtr", LF.Ptr, CF, A_PtrSize * 3) ; lpLogFont 68 | NumPut("UInt", Flags, CF, (A_PtrSize * 4) + 4) ; Flags 69 | NumPut("UInt", Color, CF, (A_PtrSize * 4) + 8) ; rgbColors 70 | OffSet := (A_PtrSize = 8 ? (A_PtrSize * 11) + 4 : (A_PtrSize * 12) + 4) 71 | NumPut("Int", 4, CF, Offset) ; nSizeMin 72 | NumPut("Int", 160, CF, OffSet + 4) ; nSizeMax 73 | ; Call ChooseFont Dialog 74 | If !DllCall("Comdlg32.dll\ChooseFont", "Ptr", CF.Ptr, "UInt") 75 | Return false 76 | ; Get name 77 | Font.Name := StrGet(LF.Ptr + 28, 32) 78 | ; Get size 79 | Font.Size := NumGet(CF, A_PtrSize * 4, "Int") / 10 80 | ; Get styles 81 | Font.Style := "" 82 | If NumGet(LF, 16, "Int") >= 700 83 | Font.Style .= "B" 84 | If NumGet(LF, 20, "UChar") 85 | Font.Style .= "I" 86 | If NumGet(LF, 21, "UChar") 87 | Font.Style .= "U" 88 | If NumGet(LF, 22, "UChar") 89 | Font.Style .= "S" 90 | OffSet := A_PtrSize * (A_PtrSize = 8 ? 11 : 12) 91 | FontType := NumGet(CF, Offset, "UShort") 92 | If (FontType & 0x0100) && !InStr(Font.Style, "B") ; BOLD_FONTTYPE 93 | Font.Style .= "B" 94 | If (FontType & 0x0200) && !InStr(Font.Style, "I") ; ITALIC_FONTTYPE 95 | Font.Style .= "I" 96 | If (Font.Style = "") 97 | Font.Style := "N" 98 | ; Get character set 99 | Font.CharSet := NumGet(LF, 23, "UChar") 100 | ; We don't use the limited colors of the font dialog 101 | ; Return selected values 102 | Return RE.SetFont(Font) 103 | } 104 | ; =================================================================================================================== 105 | Static FileDlg(RE, Mode, File := "") { ; Open and save as dialog box 106 | ; =================================================================================================================== 107 | ; RE : RichEdit object 108 | ; Mode : O = Open, S = Save 109 | ; File : optional file name 110 | Static OFN_ALLOWMULTISELECT := 0x200, OFN_EXTENSIONDIFFERENT := 0x400, OFN_CREATEPROMPT := 0x2000, 111 | OFN_DONTADDTORECENT := 0x2000000, OFN_FILEMUSTEXIST := 0x1000, OFN_FORCESHOWHIDDEN := 0x10000000, 112 | OFN_HIDEREADONLY := 0x4, OFN_NOCHANGEDIR := 0x8, OFN_NODEREFERENCELINKS := 0x100000, 113 | OFN_NOVALIDATE := 0x100, OFN_OVERWRITEPROMPT := 0x2, OFN_PATHMUSTEXIST := 0x800, 114 | OFN_READONLY := 0x1, OFN_SHOWHELP := 0x10, OFN_NOREADONLYRETURN := 0x8000, 115 | OFN_NOTESTFILECREATE := 0x10000, OFN_ENABLEXPLORER := 0x80000 116 | OFN_Size := (4 * 5) + (2 * 2) + (A_PtrSize * 16) 117 | Static FilterN1 := "RichText", FilterP1 := "*.rtf", 118 | FilterN2 := "Text", FilterP2 := "*.txt", 119 | FilterN3 := "AutoHotkey", FilterP3 := "*.ahk", 120 | DefExt := "rtf", 121 | DefFilter := 1 122 | SplitPath(File, &Name := "", &Dir := "") 123 | Flags := OFN_ENABLEXPLORER 124 | Flags |= Mode = "O" ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY 125 | : OFN_OVERWRITEPROMPT 126 | VarSetStrCapacity(&FileName, 512) 127 | FileName := Name 128 | LenN1 := (StrLen(FilterN1) + 1) * 2, LenP1 := (StrLen(FilterP1) + 1) * 2 129 | LenN2 := (StrLen(FilterN2) + 1) * 2, LenP2 := (StrLen(FilterP2) + 1) * 2 130 | LenN3 := (StrLen(FilterN3) + 1) * 2, LenP3 := (StrLen(FilterP3) + 1) * 2 131 | Filter := Buffer(LenN1 + LenP1 + LenN2 + LenP2 + LenN3 + LenP3 + 4, 0) 132 | Adr := Filter.Ptr 133 | StrPut(FilterN1, Adr) 134 | StrPut(FilterP1, Adr += LenN1) 135 | StrPut(FilterN2, Adr += LenP1) 136 | StrPut(FilterP2, Adr += LenN2) 137 | StrPut(FilterN3, Adr += LenP2) 138 | StrPut(FilterP3, Adr += LenN3) 139 | OFN := Buffer(OFN_Size, 0) ; OPENFILENAME Structure 140 | NumPut("UInt", OFN_Size, OFN, 0) 141 | Offset := A_PtrSize 142 | NumPut("Ptr", RE.Gui.Hwnd, OFN, Offset) ; HWND owner 143 | Offset += A_PtrSize * 2 144 | NumPut("Ptr", Filter.Ptr, OFN, OffSet) ; Pointer to FilterStruc 145 | OffSet += (A_PtrSize * 2) + 4 146 | OffFilter := Offset 147 | NumPut("UInt", DefFilter, OFN, Offset) ; DefaultFilter Pair 148 | OffSet += 4 149 | NumPut("Ptr", StrPtr(FileName), OFN, OffSet) ; lpstrFile / InitialisationFileName 150 | Offset += A_PtrSize 151 | NumPut("UInt", 512, OFN, Offset) ; MaxFile / lpstrFile length 152 | OffSet += A_PtrSize * 3 153 | NumPut("Ptr", StrPtr(Dir), OFN, Offset) ; StartDir 154 | Offset += A_PtrSize * 2 155 | NumPut("UInt", Flags, OFN, Offset) ; Flags 156 | Offset += 8 157 | NumPut("Ptr", StrPtr(DefExt), OFN, Offset) ; DefaultExt 158 | R := Mode = "S" ? DllCall("Comdlg32.dll\GetSaveFileNameW", "Ptr", OFN.Ptr, "UInt") 159 | : DllCall("Comdlg32.dll\GetOpenFileNameW", "Ptr", OFN.Ptr, "UInt") 160 | If !(R) 161 | Return "" 162 | DefFilter := NumGet(OFN, OffFilter, "UInt") 163 | Return StrGet(StrPtr(FileName)) 164 | } 165 | ; =================================================================================================================== 166 | Static FindText(RE) { ; Find dialog box 167 | ; =================================================================================================================== 168 | ; RE : RichEdit object 169 | Static FR_DOWN := 1, FR_MATCHCASE := 4, FR_WHOLEWORD := 2, 170 | Buf := "", BufLen := 256, FR := "", FR_Size := A_PtrSize * 10 171 | Text := RE.GetSelText() 172 | Buf := "" 173 | VarSetStrCapacity(&Buf, BufLen) 174 | If (Text != "") && !RegExMatch(Text, "\W") 175 | Buf := Text 176 | FR := Buffer(FR_Size, 0) 177 | NumPut("UInt", FR_Size, FR) 178 | Offset := A_PtrSize 179 | NumPut("UPtr", RE.Gui.Hwnd, FR, Offset) ; hwndOwner 180 | OffSet += A_PtrSize * 2 181 | NumPut("UInt", FR_DOWN, FR, Offset) ; Flags 182 | OffSet += A_PtrSize 183 | NumPut("UPtr", StrPtr(Buf), FR, Offset) ; lpstrFindWhat 184 | OffSet += A_PtrSize * 2 185 | NumPut("Short", BufLen, FR, Offset) ; wFindWhatLen 186 | This.FindTextProc("Init", RE.HWND, "") 187 | OnMessage(RichEditDlgs.FindReplMsg, RichEditDlgs.FindTextProc) 188 | Return DllCall("Comdlg32.dll\FindTextW", "Ptr", FR.Ptr, "UPtr") 189 | } 190 | ; ------------------------------------------------------------------------------------------------------------------- 191 | Static FindTextProc(L, M, H) { ; skipped wParam, can be found in "This" when called by system 192 | ; Find dialog callback procedure 193 | ; EM_FINDTEXTEXW = 0x047C, EM_EXGETSEL = 0x0434, EM_EXSETSEL = 0x0437, EM_SCROLLCARET = 0x00B7 194 | ; FR_DOWN = 1, FR_WHOLEWORD = 2, FR_MATCHCASE = 4, 195 | Static FR_DOWN := 1, FR_MATCHCASE := 4, FR_WHOLEWORD := 2 , FR_FINDNEXT := 0x8, FR_DIALOGTERM := 0x40, 196 | HWND := 0 197 | If (L = "Init") { 198 | HWND := M 199 | Return True 200 | } 201 | Flags := NumGet(L, A_PtrSize * 3, "UInt") 202 | If (Flags & FR_DIALOGTERM) { 203 | OnMessage(RichEditDlgs.FindReplMsg, RichEditDlgs.FindTextProc, 0) 204 | If (RE := GuiCtrlFromHwnd(HWND)) 205 | RE.Focus() 206 | HWND := 0 207 | Return 208 | } 209 | CR := Buffer(8, 0) 210 | SendMessage(0x0434, 0, CR.Ptr, HWND) 211 | Min := (Flags & FR_DOWN) ? NumGet(CR, 4, "Int") : NumGet(CR, 0, "Int") 212 | Max := (Flags & FR_DOWN) ? -1 : 0 213 | OffSet := A_PtrSize * 4 214 | Find := StrGet(NumGet(L, Offset, "UPtr")) 215 | FTX := Buffer(16 + A_PtrSize, 0) 216 | NumPut("Int", Min, "Int", Max, "UPtr", StrPtr(Find), FTX) 217 | SendMessage(0x047C, Flags, FTX.Ptr, HWND) 218 | S := NumGet(FTX, 8 + A_PtrSize, "Int"), E := NumGet(FTX, 12 + A_PtrSize, "Int") 219 | If (S = -1) && (E = -1) 220 | MsgBox("No (further) occurence found!", "Find", 262208) 221 | Else { 222 | SendMessage(0x0437, 0, FTX.Ptr + 8 + A_PtrSize, HWND) 223 | SendMessage(0x00B7, 0, 0, HWND) 224 | } 225 | } 226 | ; =================================================================================================================== 227 | Static PageSetup(RE) { ; Page setup dialog box 228 | ; =================================================================================================================== 229 | ; RE : RichEdit object 230 | ; http://msdn.microsoft.com/en-us/library/ms646842(v=vs.85).aspx 231 | Static PSD_DEFAULTMINMARGINS := 0x00000000, ; default (printer's) 232 | PSD_INWININIINTLMEASURE := 0x00000000, ; 1st of 4 possible 233 | PSD_MINMARGINS := 0x00000001, ; use caller's 234 | PSD_MARGINS := 0x00000002, ; use caller's 235 | PSD_INTHOUSANDTHSOFINCHES := 0x00000004, ; 2nd of 4 possible 236 | PSD_INHUNDREDTHSOFMILLIMETERS := 0x00000008, ; 3rd of 4 possible 237 | PSD_DISABLEMARGINS := 0x00000010, 238 | PSD_DISABLEPRINTER := 0x00000020, 239 | PSD_NOWARNING := 0x00000080, ; must be same as PD_* 240 | PSD_DISABLEORIENTATION := 0x00000100, 241 | PSD_RETURNDEFAULT := 0x00000400, ; must be same as PD_* 242 | PSD_DISABLEPAPER := 0x00000200, 243 | PSD_SHOWHELP := 0x00000800, ; must be same as PD_* 244 | PSD_ENABLEPAGESETUPHOOK := 0x00002000, ; must be same as PD_* 245 | PSD_ENABLEPAGESETUPTEMPLATE := 0x00008000, ; must be same as PD_* 246 | PSD_ENABLEPAGESETUPTEMPLATEHANDLE := 0x00020000, ; must be same as PD_* 247 | PSD_ENABLEPAGEPAINTHOOK := 0x00040000, 248 | PSD_DISABLEPAGEPAINTING := 0x00080000, 249 | PSD_NONETWORKBUTTON := 0x00200000, ; must be same as PD_* 250 | I := 1000, ; thousandth of inches 251 | M := 2540, ; hundredth of millimeters 252 | Margins := {}, 253 | Metrics := "", 254 | PSD_Size := (4 * 10) + (A_PtrSize * 11), 255 | PD_Size := (A_PtrSize = 8 ? (13 * A_PtrSize) + 16 : 66), 256 | OffFlags := 4 * A_PtrSize, 257 | OffMargins := OffFlags + (4 * 7) 258 | PSD := Buffer(PSD_Size, 0) ; PAGESETUPDLG structure 259 | NumPut("UInt", PSD_Size, PSD) 260 | NumPut("UPtr", RE.Gui.Hwnd, PSD, A_PtrSize) ; hwndOwner 261 | Flags := PSD_MARGINS | PSD_DISABLEPRINTER | PSD_DISABLEORIENTATION | PSD_DISABLEPAPER 262 | NumPut("Int", Flags, PSD, OffFlags) ; Flags 263 | Offset := OffMargins 264 | NumPut("Int", RE.Margins.L, PSD, Offset += 0) ; rtMargin left 265 | NumPut("Int", RE.Margins.T, PSD, Offset += 4) ; rtMargin top 266 | NumPut("Int", RE.Margins.R, PSD, Offset += 4) ; rtMargin right 267 | NumPut("Int", RE.Margins.B, PSD, Offset += 4) ; rtMargin bottom 268 | If !DllCall("Comdlg32.dll\PageSetupDlg", "Ptr", PSD.Ptr, "UInt") 269 | Return False 270 | DllCall("Kernel32.dll\GlobalFree", "Ptr", NumGet(PSD, 2 * A_PtrSize, "UPtr")) 271 | DllCall("Kernel32.dll\GlobalFree", "Ptr", NumGet(PSD, 3 * A_PtrSize, "UPtr")) 272 | Flags := NumGet(PSD, OffFlags, "UInt") 273 | Metrics := (Flags & PSD_INTHOUSANDTHSOFINCHES) ? I : M 274 | Offset := OffMargins 275 | RE.Margins.L := NumGet(PSD, Offset += 0, "Int") 276 | RE.Margins.T := NumGet(PSD, Offset += 4, "Int") 277 | RE.Margins.R := NumGet(PSD, Offset += 4, "Int") 278 | RE.Margins.B := NumGet(PSD, Offset += 4, "Int") 279 | RE.Margins.LT := Round((RE.Margins.L / Metrics) * 1440) ; Left as twips 280 | RE.Margins.TT := Round((RE.Margins.T / Metrics) * 1440) ; Top as twips 281 | RE.Margins.RT := Round((RE.Margins.R / Metrics) * 1440) ; Right as twips 282 | RE.Margins.BT := Round((RE.Margins.B / Metrics) * 1440) ; Bottom as twips 283 | Return True 284 | } 285 | ; =================================================================================================================== 286 | Static ReplaceText(RE) { ; Replace dialog box 287 | ; =================================================================================================================== 288 | ; RE : RichEdit object 289 | Static FR_DOWN := 1, FR_MATCHCASE := 4, FR_WHOLEWORD := 2, 290 | FBuf := "", RBuf := "", BufLen := 256, FR := "", FR_Size := A_PtrSize * 10 291 | Text := RE.GetSelText() 292 | FBuf := RBuf := "" 293 | VarSetStrCapacity(&FBuf, BufLen) 294 | If (Text != "") && !RegExMatch(Text, "\W") 295 | FBuf := Text 296 | VarSetStrCapacity(&RBuf, BufLen) 297 | FR := Buffer(FR_Size, 0) 298 | NumPut("UInt", FR_Size, FR) 299 | Offset := A_PtrSize 300 | NumPut("UPtr", RE.Gui.Hwnd, FR, Offset) ; hwndOwner 301 | OffSet += A_PtrSize * 2 302 | NumPut("UInt", FR_DOWN, FR, Offset) ; Flags 303 | OffSet += A_PtrSize 304 | NumPut("UPtr", StrPtr(FBuf), FR, Offset) ; lpstrFindWhat 305 | OffSet += A_PtrSize 306 | NumPut("UPtr", StrPtr(RBuf), FR, Offset) ; lpstrReplaceWith 307 | OffSet += A_PtrSize 308 | NumPut("Short", BufLen, "Short", BufLen, FR, Offset) ; wFindWhatLen, wReplaceWithLen 309 | This.ReplaceTextProc("Init", RE.HWND, "") 310 | OnMessage(RichEditDlgs.FindReplMsg, RichEditDlgs.ReplaceTextProc) 311 | Return DllCall("Comdlg32.dll\ReplaceText", "Ptr", FR.Ptr, "UPtr") 312 | } 313 | ; ------------------------------------------------------------------------------------------------------------------- 314 | Static ReplaceTextProc(L, M, H) { ; skipped wParam, can be found in "This" when called by system 315 | ; Replace dialog callback procedure 316 | ; EM_FINDTEXTEXW = 0x047C, EM_EXGETSEL = 0x0434, EM_EXSETSEL = 0x0437 317 | ; EM_REPLACESEL = 0xC2, EM_SCROLLCARET = 0x00B7 318 | ; FR_DOWN = 1, FR_WHOLEWORD = 2, FR_MATCHCASE = 4, 319 | Static FR_DOWN := 1, FR_MATCHCASE := 4, FR_WHOLEWORD := 2, FR_FINDNEXT := 0x8, 320 | FR_REPLACE := 0x10, FR_REPLACEALL := 0x20, FR_DIALOGTERM := 0x40, 321 | HWND := 0, Min := "", Max := "", FS := "", FE := "", 322 | OffFind := A_PtrSize * 4, OffRepl := A_PtrSize * 5 323 | If (L = "Init") { 324 | HWND := M, FS := "", FE := "" 325 | Return True 326 | } 327 | Flags := NumGet(L, A_PtrSize * 3, "UInt") 328 | If (Flags & FR_DIALOGTERM) { 329 | OnMessage(RichEditDlgs.FindReplMsg, RichEditDlgs.ReplaceTextProc, 0) 330 | If (RE := GuiCtrlFromHwnd(HWND)) 331 | RE.Focus() 332 | HWND := 0 333 | Return 334 | } 335 | If (Flags & FR_REPLACE) { 336 | IF (FS >= 0) && (FE >= 0) { 337 | SendMessage(0xC2, 1, NumGet(L, OffRepl, "UPtr"), HWND) 338 | Flags |= FR_FINDNEXT 339 | } 340 | Else 341 | Return 342 | } 343 | If (Flags & FR_FINDNEXT) { 344 | CR := Buffer(8, 0) 345 | SendMessage(0x0434, 0, CR.Ptr, HWND) 346 | Min := NumGet(CR, 4) 347 | FS := FE := "" 348 | Find := NumGet(L, OffFind, "UPtr") 349 | FTX := Buffer(16 + A_PtrSize, 0) 350 | NumPut("Int", Min, "Int", -1, "Ptr", Find, FTX) 351 | SendMessage(0x047C, Flags, FTX.Ptr, HWND) 352 | S := NumGet(FTX, 8 + A_PtrSize, "Int"), E := NumGet(FTX, 12 + A_PtrSize, "Int") 353 | If (S = -1) && (E = -1) 354 | MsgBox("No (further) occurence found!", "Replace", 262208) 355 | Else { 356 | SendMessage(0x0437, 0, FTX.Ptr + 8 + A_PtrSize, HWND) 357 | SendMessage(0x00B7, 0, 0, HWND) 358 | FS := S, FE := E 359 | } 360 | Return 361 | } 362 | If (Flags & FR_REPLACEALL) { 363 | CR := Buffer(8, 0) 364 | SendMessage(0x0434, 0, CR.Ptr, HWND) 365 | If (FS = "") 366 | FS := FE := 0 367 | DllCall("User32.dll\LockWindowUpdate", "Ptr", HWND) 368 | Find := NumGet(L, OffFind, "UPtr") 369 | FTX := Buffer(16 + A_PtrSize, 0) 370 | NumPut("Int", FS, "Int", -1, "Ptr",, Find, FTX) 371 | While (FS >= 0) && (FE >= 0) { 372 | SendMessage(0x044F, Flags, FTX.Ptr, HWND) 373 | FS := NumGet(FTX, A_PtrSize + 8, "Int"), FE := NumGet(FTX, A_PtrSize + 12, "Int") 374 | If (FS >= 0) && (FE >= 0) { 375 | SendMessage(0x0437, 0, FTX.Ptr + 8 + A_PtrSize, HWND) 376 | SendMessage(0xC2, 1, NumGet(L + 0, OffRepl, "UPtr" ), HWND) 377 | NumPut("Int", FE, FTX) 378 | } 379 | } 380 | SendMessage(0x0437, 0, CR.Ptr, HWND) 381 | DllCall("User32.dll\LockWindowUpdate", "Ptr", 0) 382 | Return 383 | } 384 | } 385 | } 386 | -------------------------------------------------------------------------------- /Sources/RichEditSample.ahk: -------------------------------------------------------------------------------- 1 | ; ====================================================================================================================== 2 | ; RichEdit Demo 3 | ; ====================================================================================================================== 4 | #Include RichEdit.ahk 5 | #Include RichEditDlgs.ahk 6 | ; ====================================================================================================================== 7 | SetWinDelay -1 8 | SetControlDelay -1 9 | ; ====================================================================================================================== 10 | ; Create a Gui with RichEdit controls 11 | ; ====================================================================================================================== 12 | ; Initial values ------------------------------------------------------------------------------------------------------- 13 | EditW := 800 14 | EditH := 400 15 | GuiW := 0 16 | GuiH := 0 17 | REW := 0 18 | REH := 0 19 | MarginX := 10 20 | MarginY := 10 21 | GuiTitle := "Poor Man's Rich Edit" 22 | ; BackColor := "Auto" 23 | ; FontName := "Arial" 24 | ; FontSize := "10" 25 | ; FontStyle := "N" 26 | ; FontCharSet := 1 27 | ; TextColor := "Auto" 28 | ; TextBkColor := "Auto" 29 | WordWrap := False 30 | AutoURL := False 31 | Zoom := "100 %" 32 | ShowWysiwyg := False 33 | CurrentLine := 0 34 | CurrentLineCount := 0 35 | HasFocus := False 36 | ; ---------------------------------------------------------------------------------------------------------------------- 37 | ; Menus 38 | ; ---------------------------------------------------------------------------------------------------------------------- 39 | ; FileMenu-------------------------------------------------------------------------------------------------------------- 40 | FileMenu := Menu() 41 | FileMenu.Add("&Open", FileLoadFN.Bind("Open")) 42 | FileMenu.Add("&Append", FileLoadFN.Bind("Append")) 43 | FileMenu.Add("&Insert", FileLoadFN.Bind("Insert")) 44 | FileMenu.Add("&Close", FileCloseFN) 45 | FileMenu.Add("&Save", FileSaveFN) 46 | FileMenu.Add("Save &as", FileSaveAsFN) 47 | FileMenu.Add() 48 | FileMenu.Add("Page &Margins", PageSetupFN) 49 | FileMenu.Add("&Print", PrintFN) 50 | FileMenu.Add() 51 | FileMenu.Add("&Exit", MainGuiClose) 52 | ; EditMenu-------------------------------------------------------------------------------------------------------------- 53 | EditMenu := Menu() 54 | EditMenu.Add("&Undo`tCtrl+Z", UndoFN) 55 | EditMenu.Add("&Redo`tCtrl+Y", RedoFN) 56 | EditMenu.Add() 57 | EditMenu.Add("C&ut`tCtrl+X", CutFN) 58 | EditMenu.Add("&Copy`tCtrl+C", CopyFN) 59 | EditMenu.Add("&Paste`tCtrl+V", PasteFN) 60 | EditMenu.Add("C&lear`tDel", ClearFN) 61 | EditMenu.Add() 62 | EditMenu.Add("Select &all `tCtrl+A", SelAllFN) 63 | EditMenu.Add("&Deselect all", DeselectFN) 64 | ; SearchMenu------------------------------------------------------------------------------------------------------------ 65 | SearchMenu := Menu() 66 | SearchMenu.Add("&Find", FindFN) 67 | SearchMenu.Add("&Replace", ReplaceFN) 68 | ; FormatMenu------------------------------------------------------------------------------------------------------------ 69 | ; Paragraph 70 | AlignMenu := Menu() 71 | AlignMenu.Add("Align &left`tCtrl+L", AlignFN.Bind("Left")) 72 | AlignMenu.Add("Align ¢er`tCtrl+E", AlignFN.Bind("Center")) 73 | AlignMenu.Add("Align &right`tCtrl+R", AlignFN.Bind("Right")) 74 | AlignMenu.Add("Align &justified", AlignFN.Bind("Justify")) 75 | IndentMenu := Menu() 76 | IndentMenu.Add("&Set", IndentationFN.Bind("Set")) 77 | IndentMenu.Add("&Reset", IndentationFN.Bind("Reset")) 78 | LineSpacingMenu := Menu() 79 | LineSpacingMenu.Add("1 line`tCtrl+1", SpacingFN.Bind(1.0)) 80 | LineSpacingMenu.Add("1.5 lines`tCtrl+5", SpacingFN.Bind(1.5)) 81 | LineSpacingMenu.Add("2 lines`tCtrl+2", SpacingFN.Bind(2.0)) 82 | NumberingMenu := Menu() 83 | NumberingMenu.Add("&Set", NumberingFN.Bind("Set")) 84 | NumberingMenu.Add("&Reset", NumberingFN.Bind("Reset")) 85 | TabstopsMenu := Menu() 86 | TabstopsMenu.Add("&Set Tabstops", SetTabstopsFN.Bind("Set")) 87 | TabstopsMenu.Add("&Reset to Default", SetTabstopsFN.Bind("Reset")) 88 | TabstopsMenu.Add() 89 | TabstopsMenu.Add("Set &Default Tabs", SetTabstopsFN.Bind("Default")) 90 | ParaSpacingMenu := Menu() 91 | ParaSpacingMenu.Add("&Set", ParaSpacingFN.Bind("Set")) 92 | ParaSpacingMenu.Add("&Reset", ParaSpacingFN.Bind("Reset")) 93 | ParagraphMenu := Menu() 94 | ParagraphMenu.Add("&Alignment", AlignMenu) 95 | ParagraphMenu.Add("&Indentation", IndentMenu) 96 | ParagraphMenu.Add("&Numbering", NumberingMenu) 97 | ParagraphMenu.Add("&Linespacing", LineSpacingMenu) 98 | ParagraphMenu.Add("&Space before/after", ParaSpacingMenu) 99 | ParagraphMenu.Add("&Tabstops", TabstopsMenu) 100 | ; Character 101 | TxColorMenu := Menu() 102 | TxColorMenu.Add("&Choose", TextColorFN.Bind("Choose")) 103 | TxColorMenu.Add("&Auto", TextColorFN.Bind("Auto")) 104 | BkColorMenu := Menu() 105 | BkColorMenu.Add("&Choose", TextBkColorFN.Bind("Choose")) 106 | BkColorMenu.Add("&Auto", TextBkColorFN.Bind("Auto")) 107 | CharacterMenu := Menu() 108 | CharacterMenu.Add("&Font", ChooseFontFN) 109 | CharacterMenu.Add("&Text color", TxColorMenu) 110 | CharacterMenu.Add("Text &Backcolor", BkColorMenu) 111 | ; Format 112 | FormatMenu := Menu() 113 | FormatMenu.Add("&Character", CharacterMenu) 114 | FormatMenu.Add("&Paragraph", ParagraphMenu) 115 | ; ViewMenu-------------------------------------------------------------------------------------------------------------- 116 | ; Background 117 | BackgroundMenu := Menu() 118 | BackgroundMenu.Add("&Choose", BackGroundColorFN.Bind("Choose")) 119 | BackgroundMenu.Add("&Auto", BackgroundColorFN.Bind("Auto")) 120 | ; Zoom 121 | ZoomMenu := Menu() 122 | ZoomMenu.Add("200 %", ZoomFN.Bind(200)) 123 | ZoomMenu.Add("150 %", ZoomFN.Bind(150)) 124 | ZoomMenu.Add("125 %", ZoomFN.Bind(125)) 125 | ZoomMenu.Add("100 %", Zoom100FN) 126 | ZoomMenu.Check("100 %") 127 | ZoomMenu.Add("75 %", ZoomFN.Bind(75)) 128 | ZoomMenu.Add("50 %", ZoomFN.Bind(50)) 129 | ; View 130 | ViewMenu := Menu() 131 | MenuWordWrap := "&Word-wrap" 132 | ViewMenu.Add(MenuWordWrap, WordWrapFN) 133 | MenuWysiwyg := "Wrap as &printed" 134 | ViewMenu.Add(MenuWysiwyg, WysiWygFN) 135 | ViewMenu.Add("&Zoom", ZoomMenu) 136 | ViewMenu.Add() 137 | ViewMenu.Add("&Background Color", BackgroundMenu) 138 | ViewMenu.Add("&URL Detection", AutoURLDetectionFN) 139 | ; ContextMenu ---------------------------------------------------------------------------------------------------------- 140 | ContextMenu := Menu() 141 | ContextMenu.Add("&File", FileMenu) 142 | ContextMenu.Add("&Edit", EditMenu) 143 | ContextMenu.Add("&Search", SearchMenu) 144 | ContextMenu.Add("F&ormat", FormatMenu) 145 | ContextMenu.Add("&View", ViewMenu) 146 | ; MainMenuBar ---------------------------------------------------------------------------------------------------------- 147 | MainMenuBar := MenuBar() 148 | MainMenuBar.Add("&File", FileMenu) 149 | MainMenuBar.Add("&Edit", EditMenu) 150 | MainMenuBar.Add("&Search", SearchMenu) 151 | MainMenuBar.Add("F&ormat", FormatMenu) 152 | MainMenuBar.Add("&View", ViewMenu) 153 | ; Main Gui ============================================================================================================= 154 | GuiNum := 1 155 | MainGui := Gui("+ReSize +MinSize", GuiTitle) 156 | MainGui.OnEvent("Size", MainGuiSize) 157 | MainGui.OnEvent("Close", MainGuiClose) 158 | MainGui.OnEvent("ContextMenu", MainContextMenu) 159 | MainGui.MenuBar := MainMenuBar 160 | MainGui.MarginX := MarginX 161 | MainGui.MarginY := MarginY 162 | ; Style buttons -------------------------------------------------------------------------------------------------------- 163 | MainGui.SetFont("Bold", "Arial") 164 | MainBNSB := MainGui.AddButton("xm y3 w20 h20", "&B") 165 | MainBNSB.OnEvent("Click", SetFontStyleFN.Bind("B")) 166 | GuiCtrlSetTip(MainBNSB, "Bold (Alt+B)") 167 | MainGui.SetFont("Norm Italic") 168 | MainBNSI := MainGui.AddButton("x+0 yp wp hp", "&I") 169 | MainBNSI.OnEvent("Click", SetFontStyleFN.Bind("I")) 170 | GuiCtrlSetTip(MainBNSI, "Italic (Alt+I)") 171 | MainGui.SetFont("Norm Underline") 172 | MainBNSU := MainGui.AddButton("x+0 yp wp hp", "&U") 173 | MainBNSU.OnEvent("Click", SetFontStyleFN.Bind("U")) 174 | GuiCtrlSetTip(MainBNSU, "Underline (Alt+U)") 175 | MainGui.SetFont("Norm Strike") 176 | MainBNSS := MainGui.AddButton("x+0 yp wp hp", "&S") 177 | MainBNSS.OnEvent("Click", SetFontStyleFN.Bind("S")) 178 | GuiCtrlSetTip(MainBNSS, "Strikeout (Alt+S)") 179 | MainGui.SetFont("Norm", "Arial") 180 | MainBNSH := MainGui.AddButton("x+0 yp wp hp", "¯") 181 | MainBNSH.OnEvent("Click", SetFontStyleFN.Bind("H")) 182 | GuiCtrlSetTip(MainBNSH, "Superscript (Ctrl+Shift+'+')") 183 | MainBNSL := MainGui.AddButton("x+0 yp wp hp", "_") 184 | MainBNSL.OnEvent("Click", SetFontStyleFN.Bind("L")) 185 | GuiCtrlSetTip(MainBNSL, "Subscript (Ctrl+'+')") 186 | MainBNSN := MainGui.AddButton("x+0 yp wp hp", "&N") 187 | MainBNSN.OnEvent("Click", SetFontStyleFN.Bind("N")) 188 | GuiCtrlSetTip(MainBNSN, "Normal (Alt+N)") 189 | MainBNTC := MainGui.AddButton("x+10 yp wp hp", "&T") 190 | MainBNTC.OnEvent("Click", TextColorFN.Bind("Choose")) 191 | GuiCtrlSetTip(MainBNTC, "Text color (Alt+T)") 192 | MainColors := MainGui.AddProgress("x+0 yp wp hp BackgroundYellow cNavy Border", 50) 193 | MainBNBC := MainGui.AddButton("x+0 yp wp hp", "B") 194 | MainBNBC.OnEvent("Click", TextBkColorFN.Bind("Choose")) 195 | GuiCtrlSetTip(MainBNBC, "Text backcolor") 196 | MainFNAME := MainGui.AddEdit("x+10 yp w150 hp ReadOnly", "") 197 | MainBNCF := MainGui.AddButton("x+0 yp w20 hp", "...") 198 | MainBNCF.OnEvent("Click", ChooseFontFN) 199 | GuiCtrlSetTip(MainBNCF, "Choose font") 200 | MainBNFP := MainGui.AddButton("x+5 yp wp hp", "&+") 201 | MainBNFP.OnEvent("Click", ChangeSize.Bind(1)) 202 | GuiCtrlSetTip(MainBNFP, "Increase size (Alt+'+')") 203 | MainFSIZE := MainGui.AddEdit("x+0 yp w30 hp ReadOnly", "") 204 | MainBNFM := MainGui.AddButton("x+5 yp wp hp", "&-") 205 | MainBNFM.OnEvent("Click", ChangeSize.Bind(-1)) 206 | GuiCtrlSetTip(MainBNFM, "Decrease size (Alt+'-')") 207 | ; RichEdit #1 ---------------------------------------------------------------------------------------------------------- 208 | MainGui.SetFont("Bold Italic", "Arial") 209 | MainT1 := MainGui.AddText("x+10 yp hp", "WWWWWWWW") 210 | MainT1.GetPos(&TX := 0, &TY := 0, &TW := 0, &TH := 0) 211 | TX := EditW - TW + MarginX 212 | MainT1.Move(TX) 213 | MainGui.SetFont("Norm", "Arial") 214 | Options := "x" . TX . " y" . TY . " w" . TW . " h" . TH 215 | If !IsObject(RE1 := RichEdit(MainGui, Options, False)) 216 | Throw("Could not create the RE1 RichEdit control!", -1) 217 | RE1.ReplaceSel("AaBbYyZz") 218 | RE1.AlignText("CENTER") 219 | RE1.SetOptions(["READONLY"], "SET") 220 | RE1.SetParaSpacing({Before: 2}) 221 | ; Alignment & line spacing --------------------------------------------------------------------------------------------- 222 | MainGui.SetFont("Norm", "Arial") 223 | MainGui.AddText("0x1000 xm y+2 h2 w" . EditW) 224 | MainBNAL := MainGui.AddButton("x10 y+1 w30 h20", "|<") 225 | MainBNAL.OnEvent("Click", AlignFN.Bind("Left")) 226 | GuiCtrlSetTip(MainBNAL, "Align left (Ctrl+L)") 227 | MainBNAC := MainGui.AddButton("x+0 yp wp hp", "><") 228 | MainBNAC.OnEvent("Click", AlignFN.Bind("Center")) 229 | GuiCtrlSetTip(MainBNAC, "Align center (Ctrl+E)") 230 | MainBNAR := MainGui.AddButton("x+0 yp wp hp", ">|") 231 | MainBNAR.OnEvent("Click", AlignFN.Bind("Right")) 232 | GuiCtrlSetTip(MainBNAR, "Align right (Ctrl+R)") 233 | MainBNAJ := MainGui.AddButton("x+0 yp wp hp", "|<>|") 234 | MainBNAJ.OnEvent("Click", AlignFN.Bind("Justify")) 235 | GuiCtrlSetTip(MainBNAJ, "Align justified") 236 | MainBN10 := MainGui.AddButton("x+10 yp wp hp", "1") 237 | MainBN10.OnEvent("Click", SpacingFN.Bind(1.0)) 238 | GuiCtrlSetTip(MainBN10, "Linespacing 1 line (Ctrl+1)") 239 | MainBN15 := MainGui.AddButton("x+0 yp wp hp", "1½") 240 | MainBN15.OnEvent("Click", SpacingFN.Bind(1.5)) 241 | GuiCtrlSetTip(MainBN15, "Linespacing 1,5 lines (Ctrl+5)") 242 | MainBN20 := MainGui.AddButton("x+0 yp wp hp", "2") 243 | MainBN20.OnEvent("Click", SpacingFN.Bind(2.0)) 244 | GuiCtrlSetTip(MainBN20, "Linespacing 2 lines (Ctrl+2)") 245 | ; RichEdit #2 ---------------------------------------------------------------------------------------------------------- 246 | MainFNAME.Text := "Arial" 247 | MainFSIZE.Text := "10" 248 | MainGui.SetFont("s10", "Arial") 249 | Options := "xm y+5 w" . EditW . " r20" 250 | If !IsObject(RE2 := RichEdit(MainGui, Options)) 251 | Throw("Could not create the RE2 RichEdit control!", -1) 252 | ; RE2.SetOptions(["SELECTIONBAR"]) 253 | RE2.AutoURL(True) 254 | RE2.SetEventMask(["SELCHANGE", "LINK"]) 255 | RE2.OnNotify(0x0702, RE2_SelChange) 256 | RE2.OnNotify(0x070B, RE2_Link) 257 | RE2.GetPos( , , &REW, &REH) 258 | MainGui.SetFont() 259 | ; The rest 260 | MainSB := MainGui.AddStatusbar() 261 | MainSB.SetParts(10, 200) 262 | MainGui.Show() 263 | RE2.Focus() 264 | UpdateGui() 265 | Return 266 | ; ====================================================================================================================== 267 | ; End of auto-execute section 268 | ; ====================================================================================================================== 269 | ; Testing >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 270 | ^+1:: { 271 | RC := Buffer(16, 0) 272 | DllCall("SendMessage", "Ptr", RE2.HWND, "UInt", 0x00B2, "Ptr", 0, "Ptr", RC.Ptr) ; EM_GETRECT 273 | CharIndex := DllCall("SendMessage", "Ptr", RE2.HWND, "UInt", 0x00D7, "Ptr", 0, "Ptr", RC.Ptr, "Ptr") ; EM_CHARFROMPOS 274 | LineIndex := DllCall("SendMessage", "Ptr", RE2.HWND, "UInt", 0x0436, "Ptr", 0, "Ptr", Charindex, "Ptr") ; EM_EXLINEFROMCHAR 275 | MsgBox("First visible line = " . LineIndex) 276 | } 277 | ^+f:: { 278 | CS := RE2.GetSel() 279 | SP := RE2.GetScrollPos() 280 | RE2.Opt("-Redraw") 281 | CF2 := RichEdit.CHARFORMAT2() 282 | ; CF2 := RE2.GetCharFormat() ; retrieve a CHARFORMAT2 object for the current selection 283 | CF2.Mask := 0x40000001 ; CFM_COLOR = 0x40000000, CFM_BOLD = 0x00000001 284 | CF2.TextColor := 0xFF0000 ; colors are BGR 285 | CF2.Effects := 0x01 ; CFE_BOLD := 0x00000001 286 | RE2.SetSel(0, 0) ; start searching at the begin of the text 287 | While (RE2.FindText("Lorem", ["Down"]) != 0) ; find the specific phrase 288 | RE2.SetCharFormat(CF2) ; apply the new settings 289 | CF2 := "" 290 | RE2.SetScrollPos(SP.X, SP.Y) 291 | RE2.SetSel(CS.X, CS.Y) 292 | RE2.Opt("+Redraw") 293 | } 294 | ^+l:: { 295 | Sel := DllCall("SendMessage", "Ptr", RE2.HWND, "UInt", 0x00BB, "Ptr", 18, "Ptr", 0, "Ptr") 296 | RE2.SetSel(Sel, Sel) 297 | RE2.ScrollCaret() 298 | } 299 | ^+b:: { 300 | RE2.SetBorder([10], [2]) 301 | } 302 | ; ---------------------------------------------------------------------------------------------------------------------- 303 | #HotIf RE2.Focused 304 | ; FontStyles 305 | ^!b:: ; bold 306 | ^!h:: ; superscript 307 | ^!i:: ; italic 308 | ^!l:: ; subscript 309 | ^!n:: ; normal 310 | ^!p:: ; protected 311 | ^!s:: ; strikeout 312 | ^!u:: ; underline 313 | { 314 | RE2.ToggleFontStyle(SubStr(A_ThisHotkey, 3)) 315 | UpdateGui() 316 | } 317 | #HotIf 318 | ; ====================================================================================================================== 319 | ; Testing <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 320 | ; ---------------------------------------------------------------------------------------------------------------------- 321 | RE2_SelChange(RE, L) { 322 | SetTimer UpdateGui, -10 323 | } 324 | RE2_Link(RE, L) { 325 | If (NumGet(L, A_PtrSize * 3, "Int") = 0x0202) { ; WM_LBUTTONUP 326 | wParam := NumGet(L, (A_PtrSize * 3) + 4, "UPtr") 327 | lParam := NumGet(L, (A_PtrSize * 4) + 4, "UPtr") 328 | cpMin := NumGet(L, (A_PtrSize * 5) + 4, "Int") 329 | cpMax := NumGet(L, (A_PtrSize * 5) + 8, "Int") 330 | URLtoOpen := RE2.GetTextRange(cpMin, cpMax) 331 | ToolTip "0x0202 - " wParam " - " lParam " - " cpMin " - " cpMax " - " URLtoOpen 332 | Run '"' URLtoOpen '"' 333 | } 334 | } 335 | ; ---------------------------------------------------------------------------------------------------------------------- 336 | ; UpdateGui: 337 | UpdateGui(*) { 338 | Static FontName := "", FontCharset := 0, FontStyle := 0, FontSize := 0, TextColor := 0, TxBkColor := 0 339 | Local Font := RE2.GetFont() 340 | If (FontName != Font.Name || FontCharset != Font.CharSet || FontStyle != Font.Style || FontSize != Font.Size || 341 | TextColor != Font.Color || TxBkColor != Font.BkColor) { 342 | FontStyle := Font.Style 343 | TextColor := Font.Color 344 | TxBkColor := Font.BkColor 345 | FontCharSet := Font.CharSet 346 | If (FontName != Font.Name) { 347 | FontName := Font.Name 348 | MainFNAME.Text := FontName 349 | } 350 | If (FontSize != Font.Size) { 351 | FontSize := Round(Font.Size) 352 | MainFSIZE.Text := FontSize 353 | } 354 | Font.Size := 8 355 | RE1.SetSel(0, -1) ; select all 356 | RE1.SetFont(Font) 357 | RE1.SetSel(0, 0) ; deselect all 358 | } 359 | Local Stats := RE2.GetStatistics() 360 | MainSB.SetText(Stats.Line . " : " . Stats.LinePos . " (" . Stats.LineCount . ") [" . Stats.CharCount . "]", 2) 361 | } 362 | ; ====================================================================================================================== 363 | ; Gui related 364 | ; ====================================================================================================================== 365 | ; GuiClose: 366 | MainGuiClose(*) { 367 | Global RE1, RE2 368 | If IsObject(RE1) 369 | RE1 := "" 370 | If IsObject(RE2) 371 | RE2 := "" 372 | MainGui.Destroy() 373 | ExitApp 374 | } 375 | ; ---------------------------------------------------------------------------------------------------------------------- 376 | ; GuiSize: 377 | MainGuiSize(GuiObj, MinMax, Width, Height) { 378 | Global GuiW, GuiH, REW, REH 379 | Critical 380 | If (MinMax = 1) 381 | Return 382 | If (GuiW = 0) { 383 | GuiW := Width 384 | GuiH := Height 385 | Return 386 | } 387 | If (Width != GuiW || Height != GuiH) { 388 | REW += Width - GuiW 389 | REH += Height - GuiH 390 | RE2.Move( , , REW, REH) 391 | GuiW := Width 392 | GuiH := Height 393 | } 394 | } 395 | ; ---------------------------------------------------------------------------------------------------------------------- 396 | ; GuiContextMenu 397 | MainContextMenu(GuiObj, GuiCtrlObj, *) { 398 | If (GuiCtrlObj = RE2) 399 | ContextMenu.Show() 400 | } 401 | ; ====================================================================================================================== 402 | ; Text operations 403 | ; ====================================================================================================================== 404 | ; SetFontStyle 405 | SetFontStyleFN(Style, GuiCtrl, *) { 406 | RE2.ToggleFontStyle(Style) 407 | UpdateGui() 408 | RE2.Focus() 409 | } 410 | ; ---------------------------------------------------------------------------------------------------------------------- 411 | ; ChangeSize 412 | ChangeSize(IncDec, GuiCtrl, *) { 413 | Global FontSize := RE2.ChangeFontSize(IncDec) 414 | MainFSIZE.Text := Round(FontSize) 415 | RE2.Focus() 416 | } 417 | ; ====================================================================================================================== 418 | ; Menu File 419 | ; ====================================================================================================================== 420 | ; FileAppend 421 | ; FileOpen 422 | ; FileInsert 423 | FileLoadFN(Mode, *) { 424 | Global Open_File 425 | If (File := RichEditDlgs.FileDlg(RE2, "O")) { 426 | RE2.LoadFile(File, Mode) 427 | If (Mode = "O") { 428 | MainGui.Opt("+LastFound") 429 | Title := WinGetTitle() 430 | Title := StrSplit(Title, "-", " ") 431 | WinSetTitle(Title[1] . " - " . File) 432 | Open_File := File 433 | } 434 | UpdateGui() 435 | } 436 | RE2.SetModified() 437 | RE2.Focus() 438 | } 439 | ; ---------------------------------------------------------------------------------------------------------------------- 440 | ; FileClose 441 | FileCloseFN(*) { 442 | Global Open_File 443 | If (Open_File) { 444 | If RE2.IsModified() { 445 | MainGui.Opt("+OwnDialogs") 446 | Switch MsgBox(35, "Close File", "Content has been modified!`nDo you want to save changes?") { 447 | Case "Cancel": 448 | RE2.Focus() 449 | Return 450 | Case "Yes": 451 | FileSaveFN() 452 | } 453 | } 454 | If RE2.SetText() { 455 | MainGui.Opt("+LastFound") 456 | Title := WinGetTitle() 457 | Title := StrSplit(Title, "-", " ") 458 | WinSetTitle(Title[1]) 459 | Open_File := "" 460 | } 461 | UpdateGui() 462 | } 463 | RE2.SetModified() 464 | RE2.Focus() 465 | } 466 | ; ---------------------------------------------------------------------------------------------------------------------- 467 | ; FileSave 468 | FileSaveFN(*) { 469 | If !(Open_File) 470 | Return FileSaveAsFN() 471 | RE2.SaveFile(Open_File) 472 | RE2.SetModified() 473 | RE2.Focus() 474 | } 475 | ; ---------------------------------------------------------------------------------------------------------------------- 476 | ; FileSaveAs: 477 | FileSaveAsFN(*) { 478 | If (File := RichEditDlgs.FileDlg(RE2, "S")) { 479 | RE2.SaveFile(File) 480 | MainGui.Opt("+LastFound") 481 | Title := WinGetTitle() 482 | Title := StrSplit(Title, "-", " ") 483 | WinSetTitle(Title[1] . " - " . File) 484 | Global Open_File := File 485 | } 486 | RE2.Focus() 487 | } 488 | ; ---------------------------------------------------------------------------------------------------------------------- 489 | ; PageSetup 490 | PageSetupFN(*) { 491 | RichEditDlgs.PageSetup(RE2) 492 | RE2.Focus() 493 | } 494 | ; ---------------------------------------------------------------------------------------------------------------------- 495 | ; Print 496 | PrintFN(*) { 497 | RE2.Print() 498 | RE2.Focus() 499 | } 500 | ; ====================================================================================================================== 501 | ; Menu Edit 502 | ; ====================================================================================================================== 503 | ; Undo 504 | UndoFN(*) { 505 | RE2.Undo() 506 | RE2.Focus() 507 | } 508 | ; ---------------------------------------------------------------------------------------------------------------------- 509 | ; Redo 510 | RedoFN(*) { 511 | RE2.Redo() 512 | RE2.Focus() 513 | } 514 | ; ---------------------------------------------------------------------------------------------------------------------- 515 | ; Cut 516 | CutFN(*) { 517 | RE2.Cut() 518 | RE2.Focus() 519 | } 520 | ; ---------------------------------------------------------------------------------------------------------------------- 521 | ; Copy 522 | CopyFN(*) { 523 | RE2.Copy() 524 | RE2.Focus() 525 | } 526 | ; ---------------------------------------------------------------------------------------------------------------------- 527 | ; Paste: 528 | PasteFN(*) { 529 | RE2.Paste() 530 | RE2.Focus() 531 | } 532 | ; ---------------------------------------------------------------------------------------------------------------------- 533 | ; Clear 534 | ClearFN(*) { 535 | RE2.Clear() 536 | RE2.Focus() 537 | } 538 | ; ---------------------------------------------------------------------------------------------------------------------- 539 | ; SelAll 540 | SelAllFN(*) { 541 | RE2.SelAll() 542 | RE2.Focus() 543 | } 544 | ; ---------------------------------------------------------------------------------------------------------------------- 545 | ; Deselect 546 | DeselectFN(*) { 547 | RE2.Deselect() 548 | RE2.Focus() 549 | } 550 | ; ====================================================================================================================== 551 | ; Menu View 552 | ; ====================================================================================================================== 553 | ; WordWrap 554 | WordWrapFN(Item, *) { 555 | Global WordWrap ^= True 556 | RE2.WordWrap(WordWrap) 557 | ViewMenu.ToggleCheck(Item) 558 | If (WordWrap) 559 | ViewMenu.Disable(MenuWysiwyg) 560 | Else 561 | ViewMenu.Enable(MenuWysiwyg) 562 | RE2.Focus() 563 | } 564 | ; ---------------------------------------------------------------------------------------------------------------------- 565 | ; Zoom 566 | Zoom100FN(*) => ZoomFN(100, "100 %") 567 | ZoomFN(Ratio, Item, *) { 568 | Global Zoom 569 | ZoomMenu.UnCheck(Zoom) 570 | Zoom := Item 571 | ZoomMenu.Check(Zoom) 572 | RE2.SetZoom(Ratio) 573 | RE2.Focus() 574 | } 575 | ; ---------------------------------------------------------------------------------------------------------------------- 576 | ; WYSIWYG 577 | WYSIWYGFN(Item, *) { 578 | Global ShowWysiwyg ^= True 579 | If (ShowWysiwyg) 580 | Zoom100FN() 581 | RE2.WYSIWYG(ShowWysiwyg) 582 | ViewMenu.ToggleCheck(Item) 583 | If (ShowWysiwyg) 584 | ViewMenu.Disable(MenuWordWrap) 585 | Else 586 | ViewMenu.Enable(MenuWordWrap) 587 | RE2.Focus() 588 | } 589 | ; ---------------------------------------------------------------------------------------------------------------------- 590 | ; BackgroundColor 591 | BackgroundColorFN(Mode, *) { 592 | Global BackColor 593 | Switch Mode { 594 | Case "Auto": 595 | RE2.SetBkgndColor("Auto") 596 | RE2.BackColor := "Auto" 597 | Case "Choose": 598 | If RE2.BackColor != "Auto" 599 | Color := RE2.BackColor 600 | Else 601 | Color := RE2.GetRGB(DllCall("GetSysColor", "Int", 5, "UInt")) ; COLOR_WINDOW 602 | NC := RichEditDlgs.ChooseColor(RE2, Color) 603 | If (NC != "") { 604 | RE2.SetBkgndColor(NC) 605 | RE2.BackColor := NC 606 | } 607 | } 608 | RE2.Focus() 609 | } 610 | ; ---------------------------------------------------------------------------------------------------------------------- 611 | ; AutoURLDetection 612 | AutoURLDetectionFN(ItemName, ItemPos, MenuObj) { 613 | RE2.AutoURL(AutoURL ^= True) 614 | MenuObj.ToggleCheck(ItemName) 615 | RE2.Focus() 616 | } 617 | ; ====================================================================================================================== 618 | ; Menu Character 619 | ; ====================================================================================================================== 620 | ; ChooseFont 621 | ChooseFontFN(*) { 622 | Global FontName, FontSize 623 | RichEditDlgs.ChooseFont(RE2) 624 | Font := RE2.GetFont() 625 | FontName := Font.Name 626 | FontSize := Font.Size 627 | MainFNAME.Text := FontName 628 | MainFSIZE.Text := Round(FontSize) 629 | RE2.Focus() 630 | } 631 | ; ---------------------------------------------------------------------------------------------------------------------- 632 | ; MTextColor ; menu label 633 | ; BTextColor ; button label 634 | TextColorFN(Mode, *) { 635 | Global TextColor 636 | Switch Mode { 637 | Case "Auto": 638 | RE2.SetFont({Color: "Auto"}) 639 | RE2.TextColor := "Auto" 640 | Case "Choose": 641 | If RE2.TextColor != "Auto" 642 | Color := RE2.TextColor 643 | Else 644 | Color := RE2.GetRGB(DllCall("GetSysColor", "Int", 8, "UInt")) ; COLOR_WINDOWTEXT 645 | NC := RichEditDlgs.ChooseColor(RE2, Color) 646 | If (NC != "") { 647 | RE2.SetFont({Color: NC}) 648 | RE2.TextColor := NC 649 | } 650 | } 651 | UpdateGui() 652 | RE2.Focus() 653 | } 654 | ; ---------------------------------------------------------------------------------------------------------------------- 655 | ; MTextBkColor ; menu label 656 | ; BTextBkColor ; button label 657 | TextBkColorFN(Mode, *) { 658 | Global TextBkColor 659 | Switch Mode { 660 | Case "Auto": 661 | RE2.SetFont({BkColor: "Auto"}) 662 | Case "Choose": 663 | If RE2.TxBkColor != "Auto" 664 | Color := RE2.TxBkColor 665 | Else 666 | Color := RE2.GetRGB(DllCall("GetSysColor", "Int", 5, "UInt")) ; COLOR_WINDOW 667 | NC := RichEditDlgs.ChooseColor(RE2, Color) 668 | If (NC != "") { 669 | RE2.SetFont({BkColor: NC}) 670 | RE2.TxBkColor := NC 671 | } 672 | } 673 | UpdateGui() 674 | RE2.Focus() 675 | } 676 | ; ====================================================================================================================== 677 | ; Menu Paragraph 678 | ; ====================================================================================================================== 679 | ; AlignLeft 680 | ; AlignCenter 681 | ; AlignRight: 682 | ; AlignJustify 683 | AlignFN(Alignment, *) { 684 | Static Align := {Left: 1, Right: 2, Center: 3, Justify: 4} 685 | If Align.HasProp(Alignment) 686 | RE2.AlignText(Align.%Alignment%) 687 | RE2.Focus() 688 | } 689 | ; ---------------------------------------------------------------------------------------------------------------------- 690 | IndentationFN(Mode, *) { 691 | Switch Mode { 692 | Case "Set": ParaIndentGui(RE2) 693 | Case "Reset": RE2.SetParaIndent() 694 | } 695 | RE2.Focus() 696 | } 697 | ; ---------------------------------------------------------------------------------------------------------------------- 698 | ; Numbering 699 | NumberingFN(Mode, *) { 700 | Switch Mode { 701 | Case "Set": ParaNumberingGui(RE2) 702 | Case "Reset": RE2.SetParaNumbering() 703 | } 704 | RE2.Focus() 705 | } 706 | ; ---------------------------------------------------------------------------------------------------------------------- 707 | ; ParaSpacing 708 | ; ResetParaSpacing 709 | ParaSpacingFN(Mode, *) { 710 | Switch Mode { 711 | Case "Set": ParaSpacingGui(RE2) 712 | Case "Reset": RE2.SetParaSpacing() 713 | } 714 | RE2.Focus() 715 | } 716 | ; ---------------------------------------------------------------------------------------------------------------------- 717 | ; Spacing10 718 | ; Spacing15 719 | ; Spacing20 720 | SpacingFN(Val, *) { 721 | RE2.SetLineSpacing(Val) 722 | RE2.Focus() 723 | } 724 | ; ---------------------------------------------------------------------------------------------------------------------- 725 | ; SetTabStops 726 | ; ResetTabStops 727 | ; SetDefTabs 728 | SetTabStopsFN(Mode, *) { 729 | Switch Mode { 730 | Case "Set": SetTabStopsGui(RE2) 731 | Case "Reset": RE2.SetTabStops() 732 | Case "Default": RE2.SetDefaultTabs(1) 733 | } 734 | RE2.Focus() 735 | } 736 | ; ====================================================================================================================== 737 | ; Menu Search 738 | ; ====================================================================================================================== 739 | FindFN(*) { 740 | RichEditDlgs.FindText(RE2) 741 | } 742 | ; ---------------------------------------------------------------------------------------------------------------------- 743 | ReplaceFN(*) { 744 | RichEditDlgs.ReplaceText(RE2) 745 | } 746 | ; ====================================================================================================================== 747 | ; ParaIndentation GUI 748 | ; ====================================================================================================================== 749 | ParaIndentGui(RE) { 750 | Static Owner := "", 751 | Success := False 752 | Metrics := RE.GetMeasurement() 753 | PF2 := RE.GetParaFormat() 754 | Owner := RE.Gui.Hwnd 755 | ParaIndentGui := Gui("+Owner" . Owner . " +ToolWindow +LastFound", "Paragraph Indentation") 756 | ParaIndentGui.OnEvent("Close", ParaIndentGuiClose) 757 | ParaIndentGui.MarginX := 20 758 | ParaIndentGui.MarginY := 10 759 | ParaIndentGui.AddText("Section h20 0x200", "First line left indent (absolute):") 760 | ParaIndentGui.AddText("xs hp 0x200", "Other lines left indent (relative):") 761 | ParaIndentGui.AddText("xs hp 0x200", "All lines right indent (absolute):") 762 | EDLeft1 := ParaIndentGui.AddEdit("ys hp Limit5") 763 | EDLeft2 := ParaIndentGui.AddEdit("hp Limit6") 764 | EDRight := ParaIndentGui.AddEdit("hp Limit5") 765 | CBStart := ParaIndentGui.AddCheckBox("ys x+5 hp", "Apply") 766 | CBOffset := ParaIndentGui.AddCheckBox("hp", "Apply") 767 | CBRight := ParaIndentGui.AddCheckBox("hp", "Apply") 768 | Left1 := Round((PF2.StartIndent / 1440) * Metrics, 2) 769 | If (Metrics = 2.54) 770 | Left1 := RegExReplace(Left1, "\.", ",") 771 | EDLeft1.Text := Left1 772 | Left2 := Round((PF2.Offset / 1440) * Metrics, 2) 773 | If (Metrics = 2.54) 774 | Left2 := RegExReplace(Left2, "\.", ",") 775 | EDLeft2.Text := Left2 776 | Right := Round((PF2.RightIndent / 1440) * Metrics, 2) 777 | If (Metrics = 2.54) 778 | Right := RegExReplace(Right, "\.", ",") 779 | EDRight.Text := Right 780 | BN1 := ParaIndentGui.AddButton("xs", "Apply") 781 | BN1.OnEvent("Click", ParaIndentGuiApply) 782 | BN2 := ParaIndentGui.AddButton("x+10 yp", "Cancel") 783 | BN2.OnEvent("Click", ParaIndentGuiClose) 784 | BN2.GetPos( , , &BW := 0) 785 | BN1.Move( , , BW) 786 | CBRight.GetPos(&CX := 0, , &CW := 0) 787 | BN2.Move(CX + CW - BW) 788 | RE.Gui.Opt("+Disabled") 789 | ParaIndentGui.Show() 790 | WinWaitActive 791 | WinWaitClose 792 | Return Success 793 | ; ------------------------------------------------------------------------------------------------------------------- 794 | ParaIndentGuiClose(*) { 795 | Success := False 796 | RE.Gui.Opt("-Disabled") 797 | ParaIndentGui.Destroy() 798 | } 799 | ; ------------------------------------------------------------------------------------------------------------------- 800 | ParaIndentGuiApply(*) { 801 | ApplyStart := CBStart.Value 802 | ApplyOffset := CBOffset.Value 803 | ApplyRight := CBRight.Value 804 | Indent := {} 805 | If ApplyStart { 806 | Start := EDLeft1.Text 807 | If (Start = "") 808 | Start := 0 809 | If !RegExMatch(Start, "^\d{1,2}((\.|,)\d{1,2})?$") { 810 | EDLeft1.Text := "" 811 | EDLeft1.Focus() 812 | Return 813 | } 814 | Indent.Start := StrReplace(Start, ",", ".") 815 | } 816 | If (ApplyOffset) { 817 | Offset := EDLeft2.Text 818 | If (Offset = "") 819 | Offset := 0 820 | If !RegExMatch(Offset, "^(-)?\d{1,2}((\.|,)\d{1,2})?$") { 821 | EDLeft2.Text := "" 822 | EDLeft2.Focus() 823 | Return 824 | } 825 | Indent.Offset := StrReplace(Offset, ",", ".") 826 | } 827 | If (ApplyRight) { 828 | Right := EDRight.Text 829 | If (Right = "") 830 | Right := 0 831 | If !RegExMatch(Right, "^\d{1,2}((\.|,)\d{1,2})?$") { 832 | EDRight.Text := "" 833 | EDRight.Focus() 834 | Return 835 | } 836 | Indent.Right := StrReplace(Right, ",", ".") 837 | } 838 | Success := RE.SetParaIndent(Indent) 839 | RE.Gui.Opt("-Disabled") 840 | ParaIndentGui.Destroy() 841 | } 842 | } 843 | ; ====================================================================================================================== 844 | ; ParaNumbering GUI 845 | ; ====================================================================================================================== 846 | ParaNumberingGui(RE) { 847 | Static Owner := "", 848 | Bullet := "•", 849 | StyleArr := ["1)", "(1)", "1.", "1", "w/o"], 850 | TypeArr := [Bullet, "0, 1, 2", "a, b, c", "A, B, C", "i, ii, iii", "I, I, III"], 851 | PFN := ["Bullet", "Arabic", "LCLetter", "UCLetter", "LCRoman", "UCRoman"], 852 | PFNS := ["Paren", "Parens", "Period", "Plain", "None"], 853 | Success := False 854 | Metrics := RE.GetMeasurement() 855 | PF2 := RE.GetParaFormat() 856 | Owner := RE.Gui.Hwnd 857 | ParaNumberingGui := Gui("+Owner" . Owner . " +ToolWindow +LastFound", "Paragraph Numbering") 858 | ParaNumberingGui.OnEvent("Close", ParaNumberingGuiClose) 859 | ParaNumberingGui.MarginX := 20 860 | ParaNumberingGui.MarginY := 10 861 | ParaNumberingGui.AddText("Section h20 w100 0x200", "Type:") 862 | DDLType := ParaNumberingGui.AddDDL("xp y+0 wp AltSubmit", TypeArr) 863 | If (PF2.Numbering) 864 | DDLType.Choose(PF2.Numbering) 865 | ParaNumberingGui.AddText("xs h20 w100 0x200", "Start with:") 866 | EDStart := ParaNumberingGui.AddEdit("y+0 wp hp Limit5", PF2.NumberingStart) 867 | ParaNumberingGui.AddText("ys h20 w100 0x200", "Style:") 868 | DDLStyle := ParaNumberingGui.AddDDL("y+0 wp AltSubmit Choose1", StyleArr) 869 | If (PF2.NumberingStyle) 870 | DDLStyle.Choose((PF2.NumberingStyle // 0x0100) + 1) 871 | ParaNumberingGui.AddText("h20 w100 0x200", "Distance: (" . (Metrics = 1.00 ? "in." : "cm") . ")") 872 | EDDist := ParaNumberingGui.AddEdit("y+0 wp hp Limit5") 873 | Tab := Round((PF2.NumberingTab / 1440) * Metrics, 2) 874 | If (Metrics = 2.54) 875 | Tab := RegExReplace(Tab, "\.", ",") 876 | EDDist.Text := Tab 877 | BN1 := ParaNumberingGui.AddButton("xs", "Apply") ; gParaNumberingGuiApply hwndhBtn1, Apply 878 | BN1.OnEvent("Click", ParaNumberingGuiApply) 879 | BN2 := ParaNumberingGui.AddButton("x+10 yp", "Cancel") ; gParaNumberingGuiClose hwndhBtn2, Cancel 880 | BN2.OnEvent("Click", ParaNumberingGuiClose) 881 | BN2.GetPos( , , &BW := 0) 882 | BN1.Move( , , BW) 883 | DDLStyle.GetPos(&DX := 0, , &DW := 0) 884 | BN2.Move(DX + DW - BW) 885 | RE.Gui.Opt("+Disabled") 886 | ParaNumberingGui.Show() 887 | WinWaitActive 888 | WinWaitClose 889 | Return Success 890 | ; ------------------------------------------------------------------------------------------------------------------- 891 | ParaNumberingGuiClose(*) { 892 | Success := False 893 | RE.Gui.Opt("-Disabled") 894 | ParaNumberingGui.Destroy() 895 | } 896 | ; ------------------------------------------------------------------------------------------------------------------- 897 | ParaNumberingGuiApply(*) { 898 | Type := DDLType.Value 899 | Style := DDLStyle.Value 900 | Start := EDStart.Text 901 | Tab := EDDist.Text 902 | If !RegExMatch(Tab, "^\d{1,2}((\.|,)\d{1,2})?$") { 903 | EDDist.Text := "" 904 | EDDist.Focus() 905 | Return 906 | } 907 | Numbering := {Type: PFN[Type], Style: PFNS[Style]} 908 | Numbering.Tab := RegExReplace(Tab, ",", ".") 909 | Numbering.Start := Start 910 | Success := RE.SetParaNumbering(Numbering) 911 | RE.Gui.Opt("-Disabled") 912 | ParaNumberingGui.Destroy() 913 | } 914 | } 915 | ; ====================================================================================================================== 916 | ; ParaSpacing GUI 917 | ; ====================================================================================================================== 918 | ParaSpacingGui(RE) { 919 | Static Owner := "", 920 | Success := False 921 | PF2 := RE.GetParaFormat() 922 | Owner := RE.Gui.Hwnd 923 | ParaSpacingGui := Gui("+Owner" . Owner . " +ToolWindow +LastFound", "Paragraph Spacing") ; +LabelParaSpacingGui 924 | ParaSpacingGui.OnEvent("Close", ParaSpacingGuiClose) 925 | ParaSpacingGui.MarginX := 20 926 | ParaSpacingGui.MarginY := 10 927 | ParaSpacingGui.AddText("Section h20 0x200", "Space before in points:") 928 | ParaSpacingGui.AddText("xs y+10 hp 0x200", "Space after in points:") 929 | EDBefore := ParaSpacingGui.AddEdit("ys hp Number Limit2 Right", "00") 930 | EDBefore.Text := PF2.SpaceBefore // 20 931 | EDAfter := ParaSpacingGui.AddEdit("xp y+10 hp Number Limit2 Right", "00") 932 | EDAfter.Text := PF2.SpaceAfter // 20 933 | BN1 := ParaSpacingGui.AddButton("xs", "Apply") 934 | BN1.OnEvent("Click", ParaSpacingGuiApply) 935 | BN2 := ParaSpacingGui.AddButton("x+10 yp", "Cancel") 936 | BN2.OnEvent("Click", ParaSpacingGuiClose) 937 | BN2.GetPos( , ,&BW := 0) 938 | BN1.Move( , ,BW) 939 | EDAfter.GetPos(&EX := 0, , &EW := 0) 940 | X := EX + EW - BW 941 | BN2.Move(X) 942 | RE.Gui.Opt("+Disabled") 943 | ParaSpacingGui.Show() 944 | WinWaitActive 945 | WinWaitClose 946 | Return Success 947 | ; ------------------------------------------------------------------------------------------------------------------- 948 | ParaSpacingGuiClose(*) { 949 | Success := False 950 | RE.Gui.Opt("-Disabled") 951 | ParaSpacingGui.Destroy() 952 | } 953 | ; ------------------------------------------------------------------------------------------------------------------- 954 | ParaSpacingGuiApply(*) { 955 | Before := EDBefore.Text 956 | After := EDAfter.Text 957 | Success := RE.SetParaSpacing({Before: Before, After: After}) 958 | RE.Gui.Opt("-Disabled") 959 | ParaSpacingGui.Destroy() 960 | } 961 | } 962 | ; ====================================================================================================================== 963 | ; SetTabStops GUI 964 | ; ====================================================================================================================== 965 | SetTabStopsGui(RE) { 966 | ; Set paragraph's tabstobs 967 | ; Call with parameter mode = "Reset" to reset to default tabs 968 | ; EM_GETPARAFORMAT = 0x43D, EM_SETPARAFORMAT = 0x447 969 | ; PFM_TABSTOPS = 0x10 970 | Static Owner := "", 971 | Metrics := 0, 972 | MinTab := 0.30, ; minimal tabstop in inches 973 | MaxTab := 8.30, ; maximal tabstop in inches 974 | AL := 0x00000000, ; left aligned (default) 975 | AC := 0x01000000, ; centered 976 | AR := 0x02000000, ; right aligned 977 | AD := 0x03000000, ; decimal tabstop 978 | Align := {0x00000000: "L", 0x01000000: "C", 0x02000000: "R", 0x03000000: "D"}, 979 | TabCount := 0, ; tab count 980 | MAX_TAB_STOPS := 32, 981 | Success := False ; return value 982 | Metrics := RE.GetMeasurement() 983 | PF2 := RE.GetParaFormat() 984 | TabCount := PF2.TabCount 985 | Tabs := [] 986 | Tabs.Length := PF2.Tabs.Length 987 | For I, V In PF2.Tabs 988 | Tabs[I] := [Format("{:.2f}", Round(((V & 0x00FFFFFF) * Metrics) / 1440, 2)), V & 0xFF000000] 989 | Owner := RE.Gui.Hwnd 990 | SetTabStopsGui := Gui("+Owner" . Owner . " +ToolWindow +LastFound", "Set Tabstops") 991 | SetTabStopsGui.OnEvent("Close", SetTabStopsGuiClose) 992 | SetTabStopsGui.MarginX := 10 993 | SetTabStopsGui.MarginY := 10 994 | SetTabStopsGui.AddText("Section", "Position: (" . (Metrics = 1.00 ? "in." : "cm") . ")") 995 | CBBTabs := SetTabStopsGui.AddComboBox("xs y+2 w120 r6 Simple +0x800 AltSubmit") 996 | CBBTabs.OnEvent("Change", SetTabStopsGuiSelChanged) 997 | If (TabCount) { 998 | For T In Tabs { 999 | I := SendMessage(0x0143, 0, StrPtr(T[1]), CBBTabs.Hwnd) ; CB_ADDSTRING 1000 | SendMessage(0x0151, I, T[2], CBBTabs.Hwnd) ; CB_SETITEMDATA 1001 | } 1002 | } 1003 | SetTabStopsGui.AddText("ys Section", "Alignment:") 1004 | RBL := SetTabStopsGui.AddRadio("xs w60 Section y+2 Checked Group", "Left") 1005 | RBC := SetTabStopsGui.AddRadio("wp", "Center") 1006 | RBR := SetTabStopsGui.AddRadio("ys wp", "Right") 1007 | RBD := SetTabStopsGui.AddRadio("wp", "Decimal") 1008 | BNAdd := SetTabStopsGui.AddButton("xs Section w60 Disabled", "&Add") 1009 | BNAdd.OnEvent("Click", SetTabStopsGuiAdd) 1010 | BNRem := SetTabStopsGui.AddButton("ys w60 Disabled", "&Remove") 1011 | BNRem.OnEvent("Click", SetTabStopsGuiRemove) 1012 | BNAdd.GetPos(&X1 := 0) 1013 | BNRem.GetPos(&X2 := 0, , &W2 := 0) 1014 | W := X2 + W2 - X1 1015 | BNClr := SetTabStopsGui.AddButton("xs w" . W, "&Clear all") 1016 | BNClr.OnEvent("Click", SetTabStopsGuiRemoveAll) 1017 | SetTabStopsGui.AddText("xm h5") 1018 | BNApply := SetTabStopsGui.AddButton("xm y+0 w60", "&Apply") 1019 | BNApply.OnEvent("Click", SetTabStopsGuiApply) 1020 | X := X2 + W2 - 60 1021 | BNCancel := SetTabStopsGui.AddButton("x" . X . " yp wp", "&Cancel") 1022 | BNCancel.OnEvent("Click", SetTabStopsGuiClose) 1023 | RE.Gui.Opt("+Disabled") 1024 | SetTabStopsGui.Show() 1025 | WinWaitActive 1026 | WinWaitClose 1027 | Return Success 1028 | ; ------------------------------------------------------------------------------------------------------------------- 1029 | SetTabStopsGuiClose(*) { 1030 | Success := False 1031 | RE.Gui.Opt("-Disabled") 1032 | SetTabStopsGui.Destroy() 1033 | } 1034 | ; ------------------------------------------------------------------------------------------------------------------- 1035 | SetTabStopsGuiSelChanged(*) { 1036 | If (TabCount < MAX_TAB_STOPS) 1037 | BNAdd.Enabled := !!RegExMatch(CBBTabs.Text, "^\d*[.,]?\d+$") 1038 | If !(I := CBBTabs.Value) { 1039 | BNRem.Enabled := False 1040 | Return 1041 | } 1042 | BNRem.Enabled := True 1043 | A := SendMessage(0x0150, I - 1, 0, CBBTabs.Hwnd) ; CB_GETITEMDATA 1044 | C := A = AC ? RBC : A = AR ? RBR : A = AD ? RBD : RBl 1045 | C.Value := 1 1046 | } 1047 | ; ------------------------------------------------------------------------------------------------------------------- 1048 | SetTabStopsGuiAdd(*) { 1049 | T := CBBTabs.Text 1050 | If !RegExMatch(T, "^\d*[.,]?\d+$") { 1051 | CBBTabs.Focus() 1052 | Return 1053 | } 1054 | T := Round(StrReplace(T, ",", "."), 2) 1055 | RT := Round(T / Metrics, 2) 1056 | If (RT < MinTab) || (RT > MaxTab){ 1057 | CBBTabs.Focus() 1058 | Return 1059 | } 1060 | A := RBC.Value ? AC : RBR.Value ? AR : RBD.Value ? AD : AL 1061 | TabArr := ControlGetItems(CBBTabs.Hwnd) 1062 | P := -1 1063 | T := Format("{:.2f}", T) 1064 | For I, V In TabArr { 1065 | If (T < V) { 1066 | P := I - 1 1067 | Break 1068 | } 1069 | IF (T = V) { 1070 | P := I - 1 1071 | CBBTabs.Delete(I) 1072 | Break 1073 | } 1074 | } 1075 | I := SendMessage(0x014A, P, StrPtr(T), CBBTabs.Hwnd) ; CB_INSERTSTRING 1076 | SendMessage(0x0151, I, A, CBBTabs.Hwnd) ; CB_SETITEMDATA 1077 | TabCount++ 1078 | If !(TabCount < MAX_TAB_STOPS) 1079 | BNAdd.Enabled := False 1080 | CBBTabs.Text := "" 1081 | CBBTabs.Focus() 1082 | } 1083 | ; ------------------------------------------------------------------------------------------------------------------- 1084 | SetTabStopsGuiRemove(*) { 1085 | If (I := CBBTabs.Value) { 1086 | CBBTabs.Delete(I) 1087 | CBBTabs.Text := "" 1088 | TabCount-- 1089 | RBL.Value := 1 1090 | } 1091 | CBBTabs.Focus() 1092 | } 1093 | ; ------------------------------------------------------------------------------------------------------------------- 1094 | SetTabStopsGuiRemoveAll(*) { 1095 | CBBTabs.Text := "" 1096 | CBBTabs.Delete() 1097 | RBL.Value := 1 1098 | CBBTabs.Focus() 1099 | } 1100 | ; ------------------------------------------------------------------------------------------------------------------- 1101 | SetTabStopsGuiApply(*) { 1102 | TabCount := SendMessage(0x0146, 0, 0, CBBTabs.Hwnd) << 32 >> 32 ; CB_GETCOUNT 1103 | If (TabCount < 1) 1104 | Return 1105 | TabArr := ControlGetItems(CBBTabs.HWND) 1106 | TabStops := {} 1107 | For I, T In TabArr { 1108 | Alignment := Format("0x{:08X}", SendMessage(0x0150, I - 1, 0, CBBTabs.HWND)) ; CB_GETITEMDATA 1109 | TabPos := Format("{:i}", T * 100) 1110 | TabStops.%TabPos% := Align.%Alignment% 1111 | } 1112 | Success := RE.SetTabStops(TabStops) 1113 | RE.Gui.Opt("-Disabled") 1114 | SetTabStopsGui.Destroy() 1115 | } 1116 | } 1117 | ; ====================================================================================================================== 1118 | ; Sets multi-line tooltips for any Gui control. 1119 | ; Parameters: 1120 | ; GuiCtrl - A Gui.Control object 1121 | ; TipText - The text for the tooltip. If you pass an empty string for a formerly added control, 1122 | ; its tooltip will be removed. 1123 | ; UseAhkStyle - If set to true, the tooltips will be shown using the visual styles of AHK ToolTips. 1124 | ; Otherwise, the current theme settings will be used. 1125 | ; Default: True 1126 | ; CenterTip - If set to true, the tooltip will be shown centered below/above the control. 1127 | ; Default: False 1128 | ; Return values: 1129 | ; True on success, otherwise False. 1130 | ; Remarks: 1131 | ; Text and Picture controls require the SS_NOTIFY (+0x0100) style. 1132 | ; MSDN: 1133 | ; https://learn.microsoft.com/en-us/windows/win32/controls/tooltip-control-reference 1134 | ; ====================================================================================================================== 1135 | GuiCtrlSetTip(GuiCtrl, TipText, UseAhkStyle := True, CenterTip := False) { 1136 | Static SizeOfTI := 24 + (A_PtrSize * 6) 1137 | Static Tooltips := Map() 1138 | Local Flags, HGUI, HCTL, HTT, TI 1139 | ; Check the passed GuiCtrl 1140 | If !(GuiCtrl Is Gui.Control) 1141 | Return False 1142 | HGUI := GuiCtrl.Gui.Hwnd 1143 | ; Create the TOOLINFO structure -> msdn.microsoft.com/en-us/library/bb760256(v=vs.85).aspx 1144 | Flags := 0x11 | (CenterTip ? 0x02 : 0x00) ; TTF_SUBCLASS | TTF_IDISHWND [| TTF_CENTERTIP] 1145 | TI := Buffer(SizeOfTI, 0) 1146 | NumPut("UInt", SizeOfTI, "UInt", Flags, "UPtr", HGUI, "UPtr", HGUI, TI) ; cbSize, uFlags, hwnd, uID 1147 | ; Create a tooltip control for this Gui, if needed 1148 | If !ToolTips.Has(HGUI) { 1149 | If !(HTT := DllCall("CreateWindowEx", "UInt", 0, "Str", "tooltips_class32", "Ptr", 0, "UInt", 0x80000003 1150 | , "Int", 0x80000000, "Int", 0x80000000, "Int", 0x80000000, "Int", 0x80000000 1151 | , "Ptr", HGUI, "Ptr", 0, "Ptr", 0, "Ptr", 0, "UPtr")) 1152 | Return False 1153 | If (UseAhkStyle) 1154 | DllCall("Uxtheme.dll\SetWindowTheme", "Ptr", HTT, "Ptr", 0, "Ptr", 0) 1155 | SendMessage(0x0432, 0, TI.Ptr, HTT) ; TTM_ADDTOOLW 1156 | Tooltips[HGUI] := {HTT: HTT, Ctrls: Map()} 1157 | } 1158 | HTT := Tooltips[HGUI].HTT 1159 | HCTL := GuiCtrl.HWND 1160 | ; Add / remove a tool for this control 1161 | NumPut("UPtr", HCTL, TI, 8 + A_PtrSize) ; uID 1162 | NumPut("UPtr", HCTL, TI, 24 + (A_PtrSize * 4)) ; uID 1163 | If !Tooltips[HGUI].Ctrls.Has(HCTL) { ; add the control 1164 | If (TipText = "") 1165 | Return False 1166 | SendMessage(0x0432, 0, TI.Ptr, HTT) ; TTM_ADDTOOLW 1167 | SendMessage(0x0418, 0, -1, HTT) ; TTM_SETMAXTIPWIDTH 1168 | Tooltips[HGUI].Ctrls[HCTL] := True 1169 | } 1170 | Else If (TipText = "") { ; remove the control 1171 | SendMessage(0x0433, 0, TI.Ptr, HTT) ; TTM_DELTOOLW 1172 | Tooltips[HGUI].Ctrls.Delete(HCTL) 1173 | Return True 1174 | } 1175 | ; Set / Update the tool's text. 1176 | NumPut("UPtr", StrPtr(TipText), TI, 24 + (A_PtrSize * 3)) ; lpszText 1177 | SendMessage(0x0439, 0, TI.Ptr, HTT) ; TTM_UPDATETIPTEXTW 1178 | Return True 1179 | } 1180 | --------------------------------------------------------------------------------