3DS Max plugin 编程三,utility

*.dlu插件就是一个utility,这个插件通常在rollup栏的utility中加入一个自身选项,我们可以通过双击这个选项,让rollup的栏目上添加上一个我们自己的项目,通常会覆盖掉一个原先的项目。这个项目被点击的时候,能在rollup下面出现utility的相关功能,不同的utility会实现不同的需求。


在SDK中,我们可以编译SceneManager这个utility来看相关的功能。下面是对相关代码的注释,这些点是初学的时候的关键点。


1, dlu后缀名决定了max能知道该插件内部使用的肯定是属于UtilityObj,因此,代码中的SMananger继承这个类。


2,BeginEditParams()是Max调用显示相关界面,在rollup下

void SManager::BeginEditParams(Interface *ip,IUtil *iu)
{
    this->iu = iu;
    this->ip = ip;
    hPanel = ip->AddRollupPage(
        hInstance,
        MAKEINTRESOURCE(IDD_SM_PANEL),       // panel的句柄,在Windows里用resource制作
        SManagerDlgProc,                     // panel的消息处理入口,有max调用
        GetString(IDS_PARAMS),               // string,显示在rollup上,作为这个单位的抬头
        0);
}

3,上面的消息处理入口方法


static INT_PTR CALLBACK SManagerDlgProc(
        HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg) 
    {
        case WM_INITDIALOG:
            MM.Init(hWnd);
            break;

        case WM_DESTROY:
            MM.Destroy(hWnd);
            break;

        case WM_ENABLE:
            if(MM.hMapper!=NULL) EnableWindow(MM.hMapper,(BOOL) wParam);
            break;

        case WM_COMMAND:
        switch (LOWORD(wParam)) 
        {
            case IDC_LAUNCH:                          //这个是LaunchManager这个按键的ID
                if(MM.hMapper==NULL) MM.hMapper =
                    CreateDialog(
                    hInstance,
                    MAKEINTRESOURCE(IDD_SM_FLOATER),  //是一个对话框,在windows中制作好
                    GetCOREInterface()->GetMAXHWnd(), //GetMAXHWnd()得到max的窗口句柄
                    MMDlgProc);                       //Dialog的回调函数入口
                break;
        }
            break;

        default:
            return FALSE;
    }
    return TRUE;
}


4, 按下按键后弹出的对话框的消息处理出口

static INT_PTR CALLBACK MMDlgProc(
        HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {

    switch(msg){

        case WM_INITDIALOG:
            MM.RefreshScanner(hWnd);
        break;

        case WM_DESTROY:
            MM.biDB.SetSize(0); MM.mtDB.SetSize(0); MM.txDB.SetSize(0);
            // kill variables
            MM.totalRAM=0; MM.vertcount=0; MM.facecount=0;
            MM.UV1count=MM.UV2count=0;
        break;


        case WM_COMMAND:
        switch (LOWORD(wParam)) {

            case IDC_SAVE:{
                OPENFILENAME ofn;
                TCHAR filename[255] = _T("");

                memset(&ofn, 0, sizeof(ofn));
                ofn.lStructSize = sizeof(OPENFILENAME);  // No OFN_ENABLEHOOK
                ofn.hwndOwner = hWnd;
                ofn.hInstance = hInstance;
                ofn.lpstrFile = filename;
                ofn.nMaxFile = sizeof(filename) / sizeof(TCHAR);
                ofn.lpstrFilter = _T("Text File\0*.txt\0");
                ofn.nFilterIndex = 1;
                ofn.lpstrTitle   = _T("Choose Output");
                ofn.lpstrFileTitle = NULL;
                ofn.nMaxFileTitle = 0;
                ofn.lpstrInitialDir = MM.ip->GetDir(APP_SCENE_DIR);
                ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
                ofn.FlagsEx = OFN_EX_NOPLACESBAR;

                if (GetSaveFileName(&ofn))
                {
                    if(_tcsicmp(filename + _tcslen(filename) - 4, ".txt"))
                        strcat(filename,".txt");

                    FILE *stream;
                    stream = fopen(filename,"wt");
                    HWND outHwnd = GetDlgItem(hWnd,IDC_OUT);
                    if (stream)
                    {
                        for(int x=0; x<(SendMessage(outHwnd,LB_GETCOUNT,0,0));x++)
                        {
                            char q[255];
                            SendMessage(outHwnd,LB_GETTEXT,x,(WPARAM)q);
                            fprintf(stream,"%s\n",q);
                        }
                        fclose(stream);
                    }
                }
            break;}

            case IDC_CLOSE:
                MM.hMapper=NULL;
                EndDialog(hWnd,1);
            break;
            case IDC_CLEAR:
                SendMessage(GetDlgItem(hWnd,IDC_OUT),LB_RESETCONTENT,0,0);
                InvalidateRect(GetDlgItem(hWnd,IDC_OUT),NULL,TRUE);

            break;
            case IDC_GENERATE:
                    
                    // kill variables
                    MM.totalRAM=0; MM.vertcount=0; MM.facecount=0;
                    MM.UV1count=MM.UV2count=0;
                    MM.biDB.SetSize(0); MM.mtDB.SetSize(0); MM.txDB.SetSize(0);

                    MM.SetStatus("");
                    MM.Output("--- START OF REPORT ---");
                    MM.Output("");
                    MM.Output("");
                    if(MM.m1==1) MM.DoObjects();
                    if(MM.m2==1) MM.DoUVW();
                    if(MM.m3==1) MM.DoMaps();
                    if(MM.m4==1) MM.DoDups();
                    if(MM.m5==1) MM.DoLights();
                    MM.Output("");
                    MM.Output("Total Memory Usage: %.2fMB",(float)MM.totalRAM/1024.0f);
                    MM.Output("");MM.Output("--- END OF REPORT ---");MM.Output("");MM.Output("");
                    MM.SetStatus("");
                break;

            case ID_ALL:
                MM.m1=MM.m2=MM.m3=MM.m4=MM.m5=1;MM.RefreshScanner(hWnd);
            break;
            case ID_NONE:
                MM.m1=MM.m2=MM.m3=MM.m4=MM.m5=0;MM.RefreshScanner(hWnd);
            break;

            case ID_1:{
                if(MM.m1==1){MM.m1=0;}
                else {MM.m1=1;}MM.RefreshScanner(hWnd);
            break;}
            case ID_2:{
                if(MM.m2==1){MM.m2=0;}
                else {MM.m2=1;}MM.RefreshScanner(hWnd);
            break;}
            case ID_3:{
                if(MM.m3==1){MM.m3=0;}
                else {MM.m3=1;}MM.RefreshScanner(hWnd);
            break;}
            case ID_4:{
                if(MM.m4==1){MM.m4=0;}
                else {MM.m4=1;}MM.RefreshScanner(hWnd);
            break;}
            case ID_5:{
                if(MM.m5==1){MM.m5=0;}
                else {MM.m5=1;}MM.RefreshScanner(hWnd);
            break;}

        }
        break;

        case WM_SIZE:{
                MoveWindow(GetDlgItem(hWnd,IDC_OUT),
                    0,
                    0,
                    LOWORD(lParam),
                    HIWORD(lParam)-22,TRUE);
                Rect rw;
                GetWindowRect(GetDlgItem(hWnd,IDC_OUT),&rw);
                MoveWindow(GetDlgItem(hWnd,IDC_STATUS),
                    0,
                    rw.h()+1,
                    LOWORD(lParam),
                    20,TRUE);
            break;}

        case WM_CLOSE:
            MM.hMapper=NULL;
            EndDialog(hWnd,1);
            break;
    }

    
    return FALSE;
    }


上面的方法,大多数是Windows编程的代码,MM起头的字样是内部的处理数据的实例。跟max内部数据打交道的地方,会在后续记录。这里只记录入手max plugin的时候的切入点。


你可能感兴趣的:(编程,windows,Stream,null,callback,variables)