Notifications
Clear all

[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

17 Replies

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

Use SDK reference or c++ sources to look for that type of things

Page 1 / 2