MaxScript 防止你的UI被循环阻塞或卡死

1 windows.processPostedMessages()

貌似在max2012增加了一个函数 windows.processPostedMessages() ,可以防止循环时max变得未响应

-- 你可以这样使用他
try DestroyDialog roll catch()
    
rollout roll "--"
(
    button btn1 "0000"
    on btn1 pressed do
    (
        for i = 1 to 500 do
        (
            windows.processPostedMessages() --将此函数加在此处可防止UI冻结
            btn1.text = i as string
            sleep 0.01
        )
    )
)

CreateDialog roll

2 DoEvents

但是要在低版本使用怎么办?你可以将windows.processPostedMessages()替换为.net的函数

-- 你可以这样使用他
try DestroyDialog roll catch()
    
rollout roll "--"
(
    button btn1 "0000"
    on btn1 pressed do
    (
        for i = 1 to 500 do
        (
            (dotnetclass"System.Windows.Forms.Application").DoEvents() --将此函数加在此处可防止UI冻结
            btn1.text = i as string
            sleep 0.01
        )
    )
)

CreateDialog roll

3 最佳方案

但是上面2种方法存在一个问题,假设你循环对100个物体进行转换多边形操作,由于此时UI是不被冻结的,你可以轻松选择场景中的物体,然后删除他们,这时候物体不存在,代码则会报告异常

SDK内提供一个更为精妙的设计,可以让你仅解冻需要更新的UI句柄,在代码执行时你将只能操作被预先添加的界面,其他界面将被冻结无法操作

-- 在实际使用时你可能需要将他封装的更好
iGlobal = (dotnetClass "Autodesk.Max.GlobalInterface").Instance
maxSDK = iGlobal.MaxSDK
messageFilter = maxSDK.WindowsMessageFilter.Create()

fn checkMessages = 
(       
    messageFilter.RunNonBlockingMessageLoop()
    not messageFilter.Aborted
)


try DestroyDialog roll catch()  
rollout roll "--"
(
    button btn1 "0000"
    on btn1 pressed do
    (
        hwnd = roll.hwnd --windows.getMAXHWND()
        messageFilter.AddUnfilteredWindow (dotnetObject "System.IntPtr" hwnd)
        
        for i = 1 to 500 do
        (
            checkMessages()
            btn1.text = i as string
            sleep 0.01
        )
        messageFilter.ClearUnfilteredWindowList()
    )
)

CreateDialog roll

猜你喜欢

转载自www.cnblogs.com/trykle/p/11839001.html