[Closed] MSX Editor Access
Hi, I try to do some work with MSX Editor.
1)
–find structure by name in opened script –OK
–go to end of struct –OK
–insert new function like > , fn newFuncrion = (“”) –OK
2)
–it will be nice to add a function which will select all word occurences in whole script –TODO
I would like to say thanks to denisT and Serejah, for wery nice examples of Assembly implementation
for now I have some Command ID List
Global mcWinMsg
struct MICRA_WINDOWS_MESSAGES (
WM_NULL = 0x0000,
WM_CREATE = 0x0001,
WM_DESTROY = 0x0002,
WM_MOVE = 0x0003,
WM_SIZE = 0x0005,
WM_ACTIVATE = 0x0006,
WM_SETFOCUS = 0x0007,
WM_KILLFOCUS = 0x0008,
WM_ENABLE = 0x000A,
WM_SETREDRAW = 0x000B,
WM_SETTEXT = 0x000C,
WM_GETTEXT = 0x000D,
WM_GETTEXTLENGTH = 0x000E,
WM_PAINT = 0x000F,
WM_CLOSE = 0x0010,
WM_QUERYENDSESSION = 0x0011,
WM_QUERYOPEN = 0x0013,
WM_ENDSESSION = 0x0016,
WM_QUIT = 0x0012,
WM_ERASEBKGND = 0x0014,
WM_SYSCOLORCHANGE = 0x0015,
WM_SHOWWINDOW = 0x0018,
WM_WININICHANGE = 0x001A,
WM_SETTINGCHANGE = WM_WININICHANGE,
WM_DEVMODECHANGE = 0x001B,
WM_ACTIVATEAPP = 0x001C,
WM_FONTCHANGE = 0x001D,
WM_TIMECHANGE = 0x001E,
WM_CANCELMODE = 0x001F,
WM_SETCURSOR = 0x0020,
WM_MOUSEACTIVATE = 0x0021,
WM_CHILDACTIVATE = 0x0022,
WM_QUEUESYNC = 0x0023,
WM_GETMINMAXINFO = 0x0024,
WM_PAINTICON = 0x0026,
WM_ICONERASEBKGND = 0x0027,
WM_NEXTDLGCTL = 0x0028,
WM_SPOOLERSTATUS = 0x002A,
WM_DRAWITEM = 0x002B,
WM_MEASUREITEM = 0x002C,
WM_DELETEITEM = 0x002D,
WM_VKEYTOITEM = 0x002E,
WM_CHARTOITEM = 0x002F,
WM_SETFONT = 0x0030,
WM_GETFONT = 0x0031,
WM_SETHOTKEY = 0x0032,
WM_GETHOTKEY = 0x0033,
WM_QUERYDRAGICON = 0x0037,
WM_COMPAREITEM = 0x0039,
WM_GETOBJECT = 0x003D,
WM_COMPACTING = 0x0041,
WM_COMMNOTIFY = 0x0044,
WM_WINDOWPOSCHANGING = 0x0046,
WM_WINDOWPOSCHANGED = 0x0047,
WM_POWER = 0x0048,
WM_COPYDATA = 0x004A,
WM_CANCELJOURNAL = 0x004B,
WM_NOTIFY = 0x004E,
WM_INPUTLANGCHANGEREQUEST = 0x0050,
WM_INPUTLANGCHANGE = 0x0051,
WM_TCARD = 0x0052,
WM_HELP = 0x0053,
WM_USERCHANGED = 0x0054,
WM_NOTIFYFORMAT = 0x0055,
WM_CONTEXTMENU = 0x007B,
WM_STYLECHANGING = 0x007C,
WM_STYLECHANGED = 0x007D,
WM_DISPLAYCHANGE = 0x007E,
WM_GETICON = 0x007F,
WM_SETICON = 0x0080,
WM_NCCREATE = 0x0081,
WM_NCDESTROY = 0x0082,
WM_NCCALCSIZE = 0x0083,
WM_NCHITTEST = 0x0084,
WM_NCPAINT = 0x0085,
WM_NCACTIVATE = 0x0086,
WM_GETDLGCODE = 0x0087,
WM_SYNCPAINT = 0x0088,
WM_NCMOUSEMOVE = 0x00A0,
WM_NCLBUTTONDOWN = 0x00A1,
WM_NCLBUTTONUP = 0x00A2,
WM_NCLBUTTONDBLCLK = 0x00A3,
WM_NCRBUTTONDOWN = 0x00A4,
WM_NCRBUTTONUP = 0x00A5,
WM_NCRBUTTONDBLCLK = 0x00A6,
WM_NCMBUTTONDOWN = 0x00A7,
WM_NCMBUTTONUP = 0x00A8,
WM_NCMBUTTONDBLCLK = 0x00A9,
WM_NCXBUTTONDOWN = 0x00AB,
WM_NCXBUTTONUP = 0x00AC,
WM_NCXBUTTONDBLCLK = 0x00AD,
WM_INPUT_DEVICE_CHANGE = 0x00FE,
WM_INPUT = 0x00FF,
WM_KEYFIRST = 0x0100,
WM_KEYDOWN = 0x0100,
WM_KEYUP = 0x0101,
WM_CHAR = 0x0102,
WM_DEADCHAR = 0x0103,
WM_SYSKEYDOWN = 0x0104,
WM_SYSKEYUP = 0x0105,
WM_SYSCHAR = 0x0106,
WM_SYSDEADCHAR = 0x0107,
WM_UNICHAR = 0x0109,
WM_KEYLAST = 0x0109,
WM_IME_STARTCOMPOSITION = 0x010D,
WM_IME_ENDCOMPOSITION = 0x010E,
WM_IME_COMPOSITION = 0x010F,
WM_IME_KEYLAST = 0x010F,
WM_INITDIALOG = 0x0110,
WM_COMMAND = 0x0111,
WM_SYSCOMMAND = 0x0112,
WM_TIMER = 0x0113,
WM_HSCROLL = 0x0114,
WM_VSCROLL = 0x0115,
WM_INITMENU = 0x0116,
WM_INITMENUPOPUP = 0x0117,
WM_MENUSELECT = 0x011F,
WM_MENUCHAR = 0x0120,
WM_ENTERIDLE = 0x0121,
WM_MENURBUTTONUP = 0x0122,
WM_MENUDRAG = 0x0123,
WM_MENUGETOBJECT = 0x0124,
WM_UNINITMENUPOPUP = 0x0125,
WM_MENUCOMMAND = 0x0126,
WM_CHANGEUISTATE = 0x0127,
WM_UPDATEUISTATE = 0x0128,
WM_QUERYUISTATE = 0x0129,
WM_CTLCOLORMSGBOX = 0x0132,
WM_CTLCOLOREDIT = 0x0133,
WM_CTLCOLORLISTBOX = 0x0134,
WM_CTLCOLORBTN = 0x0135,
WM_CTLCOLORDLG = 0x0136,
WM_CTLCOLORSCROLLBAR = 0x0137,
WM_CTLCOLORSTATIC = 0x0138,
MN_GETHMENU = 0x01E1,
WM_MOUSEFIRST = 0x0200,
WM_MOUSEMOVE = 0x0200,
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_LBUTTONDBLCLK = 0x0203,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_RBUTTONDBLCLK = 0x0206,
WM_MBUTTONDOWN = 0x0207,
WM_MBUTTONUP = 0x0208,
WM_MBUTTONDBLCLK = 0x0209,
WM_MOUSEWHEEL = 0x020A,
WM_XBUTTONDOWN = 0x020B,
WM_XBUTTONUP = 0x020C,
WM_XBUTTONDBLCLK = 0x020D,
WM_MOUSEHWHEEL = 0x020E,
WM_PARENTNOTIFY = 0x0210,
WM_ENTERMENULOOP = 0x0211,
WM_EXITMENULOOP = 0x0212,
WM_NEXTMENU = 0x0213,
WM_SIZING = 0x0214,
WM_CAPTURECHANGED = 0x0215,
WM_MOVING = 0x0216,
WM_POWERBROADCAST = 0x0218,
WM_DEVICECHANGE = 0x0219,
WM_MDICREATE = 0x0220,
WM_MDIDESTROY = 0x0221,
WM_MDIACTIVATE = 0x0222,
WM_MDIRESTORE = 0x0223,
WM_MDINEXT = 0x0224,
WM_MDIMAXIMIZE = 0x0225,
WM_MDITILE = 0x0226,
WM_MDICASCADE = 0x0227,
WM_MDIICONARRANGE = 0x0228,
WM_MDIGETACTIVE = 0x0229,
WM_MDISETMENU = 0x0230,
WM_ENTERSIZEMOVE = 0x0231,
WM_EXITSIZEMOVE = 0x0232,
WM_DROPFILES = 0x0233,
WM_MDIREFRESHMENU = 0x0234,
WM_IME_SETCONTEXT = 0x0281,
WM_IME_NOTIFY = 0x0282,
WM_IME_CONTROL = 0x0283,
WM_IME_COMPOSITIONFULL = 0x0284,
WM_IME_SELECT = 0x0285,
WM_IME_CHAR = 0x0286,
WM_IME_REQUEST = 0x0288,
WM_IME_KEYDOWN = 0x0290,
WM_IME_KEYUP = 0x0291,
WM_MOUSEHOVER = 0x02A1,
WM_MOUSELEAVE = 0x02A3,
WM_NCMOUSEHOVER = 0x02A0,
WM_NCMOUSELEAVE = 0x02A2,
WM_WTSSESSION_CHANGE = 0x02B1,
WM_TABLET_FIRST = 0x02c0,
WM_TABLET_LAST = 0x02df,
WM_CUT = 0x0300,
WM_COPY = 0x0301,
WM_PASTE = 0x0302,
WM_CLEAR = 0x0303,
WM_UNDO = 0x0304,
WM_RENDERFORMAT = 0x0305,
WM_RENDERALLFORMATS = 0x0306,
WM_DESTROYCLIPBOARD = 0x0307,
WM_DRAWCLIPBOARD = 0x0308,
WM_PAINTCLIPBOARD = 0x0309,
WM_VSCROLLCLIPBOARD = 0x030A,
WM_SIZECLIPBOARD = 0x030B,
WM_ASKCBFORMATNAME = 0x030C,
WM_CHANGECBCHAIN = 0x030D,
WM_HSCROLLCLIPBOARD = 0x030E,
WM_QUERYNEWPALETTE = 0x030F,
WM_PALETTEISCHANGING = 0x0310,
WM_PALETTECHANGED = 0x0311,
WM_HOTKEY = 0x0312,
WM_PRINT = 0x0317,
WM_PRINTCLIENT = 0x0318,
WM_APPCOMMAND = 0x0319,
WM_THEMECHANGED = 0x031A,
WM_CLIPBOARDUPDATE = 0x031D,
WM_DWMCOMPOSITIONCHANGED = 0x031E,
WM_DWMNCRENDERINGCHANGED = 0x031F,
WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320,
WM_DWMWINDOWMAXIMIZEDCHANGE = 0x0321,
WM_GETTITLEBARINFOEX = 0x033F,
WM_HANDHELDFIRST = 0x0358,
WM_HANDHELDLAST = 0x035F,
WM_AFXFIRST = 0x0360,
WM_AFXLAST = 0x037F,
WM_PENWINFIRST = 0x0380,
WM_PENWINLAST = 0x038F,
WM_APP = 0x8000,
WM_USER = 0x0400,
WM_REFLECT = WM_USER + 0x1C00,
EM_GETSEL = 0x00B0,
EM_SETSEL = 0x00B1, --put the caret to the end of the edit window
EM_REPLACESEL = 0x00C2 --append text at carret pos
)
mcWinMsg = MICRA_WINDOWS_MESSAGES()
denisT win32 assembly
Global mcWin32
Global mcWin32Assembly
fn CreateWin32Assembly forceRecompile:on = (
if forceRecompile or not iskindof ::mcWin32Assembly dotnetobject or (::mcWin32Assembly.GetType()).name != "Assembly" do (
source = "using System;
"
source += "using System.Runtime.InteropServices;
"
source += "using System.Text;
"
source += "class Win32
"
source += "{
"
source += " [DllImport(\"user32\", CharSet = CharSet.Auto, SetLastError = true)]
"
source += " public static extern Int32 SetFocus(Int32 hWnd);
"
source += " [DllImport(\"user32\", CharSet = CharSet.Auto, SetLastError = true)]
"
source += " internal static extern int GetWindowTextLength(Int32 hWnd);
"
source += " [DllImport(\"user32\", CharSet = CharSet.Auto, SetLastError = true)]
"
source += " internal static extern int GetWindowText(Int32 hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
"
source += " public static string GetWindowText(Int32 hWnd)
"
source += " {
"
source += " int length = GetWindowTextLength(hWnd);
"
source += " StringBuilder sb = new StringBuilder(length + 1);
"
source += " GetWindowText(hWnd, sb, sb.Capacity);
"
source += " return sb.ToString();
"
source += " }
"
source += "}
"
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.Add "System.dll"
compilerParams.ReferencedAssemblies.Add "System.Drawing.dll"
compilerParams.GenerateInMemory = true
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
mcWin32Assembly = compilerResults.CompiledAssembly
mcWin32Assembly.CreateInstance "Win32"
)
)
mcWin32 = CreateWin32Assembly()
and main struct with some functions to comunicate with MSX_Scintilla
Global mcMSX
struct MICRA_MSX_EDITOR (
msx_hwnd = (
for c in (windows.getchildrenhwnd 0) where c[4] == "MXS_SciTEWindow" do exit with c[1]
),
tb_hwnd = (
if msx_hwnd == undefined do return undefined
for c in (windows.getchildrenhwnd msx_hwnd) where c[4] == "MXS_Scintilla" do exit with c[1]
),
fn close = (if msx_hwnd == undefined do retrun false; windows.sendmessage msx_hwnd mcWinMsg.WM_CLOSE 0 0), --OK
fn copySel = (if tb_hwnd == undefined do retrun false; windows.sendmessage tb_hwnd mcWinMsg.WM_COPY 0 0), --OK
fn paste = (if tb_hwnd == undefined do retrun false; windows.sendmessage tb_hwnd mcWinMsg.WM_PASTE 0 0), --OK
fn clearAll = (if tb_hwnd == undefined do retrun false; windows.sendmessage tb_hwnd mcWinMsg.WM_CLEAR 0 0), --not works (works like backspace not clear all text)
fn getSel = (if tb_hwnd == undefined do retrun false; windows.sendmessage tb_hwnd mcWinMsg.EM_GETSEL 0 0), --not works
fn findStr str = ( --OK
if tb_hwnd == undefined do retrun false
local current_script_text = mcWin32.GetWindowText tb_hwnd
local str_pos = findString current_script_text str
if str_pos != undefined do (
windows.sendmessage tb_hwnd mcWinMsg.EM_SETSEL (str_pos-1) (str_pos+str.count-1)
mcWin32.SetFocus tb_hwnd
)
str_pos
),
fn insertAt offset_pos str = ( --need fix
if tb_hwnd == undefined do retrun false
local marshal = dotnetclass "System.Runtime.InteropServices.Marshal"
local ptr = marshal.StringToHGlobalUni str
windows.sendmessage tb_hwnd mcWinMsg.EM_REPLACESEL offset_pos ptr
mcWin32.SetFocus tb_hwnd
)
)
mcMSX = MICRA_MSX_EDITOR()
/*
mcMSX.close()
mcMSX.copySel()
mcMSX.paste()
mcMSX.clearAll() --not works (works like backspace not clear all text)
mcMSX.getSel() --return integer not String
insert_pos = mcMSX.findStr "MICRA_MSX_EDITOR"
mcMSX.insertAt insert_pos "here you are :-)" --need fix
*/
any good idea will be appreciated
It seems you go on with you idea of dinamyc structs… nice!
To find the end of the struct, the only way will be counting parenthesis (open – close). But you must be careful with parenthesis that may be inside quotes or double quotes. Regex should do the trick.
Hi aaandreas,
dynamic structures must wait for better perspective
to find last brace from structure is not easy as you say.
Regex will sure make good work… but I’m not good in it
maybe another scintilla commands ?
|IDM_MATCHBRACE|Match Brace|
|IDM_SELECTTOBRACE|Select to Brace|
This one will insert “fn abc a b = a * b” right before the struct end.
btw You can comment whole struct to see how SCI_BRACEMATCH fails
SCI_BRACEMATCH = 2353
struct test
( /* <-- opening_parenthesis_offset */
a = 0,
b = "())",
fn abc = 111,
on create do ()
)
mxse_hwnd = (dotNetClass "Autodesk.Max.GlobalInterface").Instance.TheMxsEditorInterface.EditorGetEditHWND
opening_parenthesis_offset = 36
match = windows.sendMessage mxse_hwnd SCI_BRACEMATCH opening_parenthesis_offset 0
fn InsertInMXSE offset str =
(
local marshal = dotnetclass "System.Runtime.InteropServices.Marshal"
local ptr = marshal.StringToHGlobalUni str
local mxse_hwnd = (dotNetClass "Autodesk.Max.GlobalInterface").Instance.TheMxsEditorInterface.EditorGetEditHWND
local EM_REPLACESEL = 0x00C2
local SCI_GETCURRENTPOS = 2008
local SCI_GOTOPOS = 2025
local EM_SETSEL = 0x00B1
local prev_offset = windows.sendmessage mxse_hwnd SCI_GETCURRENTPOS 0 0
windows.sendMessage mxse_hwnd SCI_GOTOPOS offset 0
windows.sendMessage mxse_hwnd EM_SETSEL offset offset
windows.sendmessage mxse_hwnd EM_REPLACESEL offset ptr
windows.sendMessage mxse_hwnd EM_SETSEL offset offset
if prev_offset > (offset + str.count) then
(
windows.sendMessage mxse_hwnd SCI_GOTOPOS (prev_offset + str.count) 0
)
else
(
windows.sendMessage mxse_hwnd SCI_GOTOPOS prev_offset 0
)
)
function_to_insert = "fn abc a b = a * b"
if match != -1 do
(
codeblock = "\t,\r\n\t" + function_to_insert + "\r\n"
InsertInMXSE (match-1) codeblock
)
Did you have a look at my MXSEditor Plugin which exposes editor stuff to maxscript ?
It allows to call most of the scintilla based commands via a simple function publishing interface
Problem is that the scintilla component used in Max is pretty old and obsolete and lacks many of the newer features existing nowadays
here’s some more detailed documentation
http://www.frogsinspace.at/?p=2918
UPDATE:
Ahh – i found you already commented on my wordpress post already …
http://www.frogsinspace.at/?p=3232
I would be glad if someone could show how to highlight only the matching words.
fn GetWindowText hwnd =
(
local marshal = dotnetclass "System.Runtime.InteropServices.Marshal"
local str = ""
try (
local len = windows.sendmessage hwnd 0xE 0 0
local lParam = marshal.AllocHGlobal (marshal.SystemDefaultCharSize*(len+1))
windows.sendmessage hwnd 0xD (len+1) lParam
ptr = dotnetobject "System.IntPtr" lParam
str = marshal.PtrToStringAuto ptr
marshal.FreeHGlobal ptr
) catch ()
str
)
fn ClearMXSEHighlights =
(
-- local SCI_MARKERDELETEALL = 2045
windows.sendMessage (dotNetClass "Autodesk.Max.GlobalInterface").Instance.TheMxsEditorInterface.EditorGetEditHWND 2045 -1 -1
)
fn HighlightLines word matchcase:false keep:false =
(
if not matchcase do word = toLower word
local mxse_hwnd = (dotNetClass "Autodesk.Max.GlobalInterface").Instance.TheMxsEditorInterface.EditorGetEditHWND
local src = getWindowText mxse_hwnd
local doc = (if matchcase then src else toLower src) as StringStream
local offsets = #()
while (skipToString doc word) != undefined do
(
append offsets (filePos doc)
)
free doc
if keep == false do
(
local SCI_MARKERDELETEALL = 2045
windows.sendMessage mxse_hwnd SCI_MARKERDELETEALL -1 -1
)
if offsets.count > 0 do
(
local SCI_LINEFROMPOSITION = 2166
local SCI_MARKERADDSET = 2466
for offset in offsets do
(
local line_index = windows.sendMessage mxse_hwnd SCI_LINEFROMPOSITION offset 0
windows.sendMessage mxse_hwnd SCI_MARKERADDSET line_index 2
)
)
offsets
)
-- ClearMXSEHighlights()
HighlightLines "sendM"
Hi Serejah,
very nice way to pick msxe_hwnd , how did you find it
After comment whole structure brace match fail as you say ,
Maybe will help other solution. Not to professional, but should be work
Add one line to end of each structure. After use find function to get exact position, like…
struct test
(
a = 0,
b = "())",
fn abc = 111,
on create do ()
/*<struct test ends here. Insert you code under this marker>*/
)
mcMSX.findStr “struct test end”
I’m glad for you script Serejah, it is nice to see how can achieve same thinks with different ways
Another nice piece of code Serejah. Also good idea to mark each line with marker
Do you think will be posible to get result in MXS like this ?
I tried but without any luck. My editor looks like this after code execution