这几天研究了一下UI部分的制作方法,感觉要了解的东西挺多,加上时间不允许,我本着“够用就行”的心态学习了两种向3ds Max添加自己控件的方法。一种是添加RollupPage,一种是添加ToolBar。因为没有深入研究,我只能做到添加简单的控件,实现基本交互功能,这里介绍一下,希望大家指点:(程序截图在附件中) 一. 添加RollupPage的方式: 可以利用ApplicationWizard生成Utility程序,查看工程资源可以看到一个对话框: 1.jpg 该对话框的静态文本部分使用StaticEdit控件,交互部分使用的是VC自带的CustomCtrl控件。需要注意的是:一定要指定CustomCtrl的class,例如,如果控件用作表示文本输入框,则class的类型为:CustEdit。如果为按钮,则类型为:CustButton。几个常用的控件类型如下: Custom Edit control - CustEdit Custom Spinner Control - SpinnerControl Custom Button control - CustButton Custom Toolbar control - CustToolbar Custom Image control - CustImage Custom Status control - CustStatus Color Swatch control - ColorSwatch Custom Rollup Window - RollupWindow Custom DragAndDrop Window control - DragDropWindow Custom TCB Graph – TCBGraph 下面再来看看程序部分: 首先要实现下面这个函数: void RollupPageTest::BeginEditParams(Interface *ip,IUtil *iu) { this->iu = iu; this->ip = ip; hPanel = ip->AddRollupPage( hInstance, MAKEINTRESOURCE(IDD_PANEL), RollupPageTestDlgProc, GetString(IDS_PARAMS), 0); } 这里的RollupPageTest继承于UtilityObj,我们可以使用UtilityObj来创建自己的Utility。 而我们需要实现的虚函数BeginEditParams,当用户选择使用该插件时,系统就会掉用这个函数,在这里该函数用来向command  anel添加RollupPage。代码”hPanel = ip->AddRollupPage(…);”用来实现这样的功能,注意其中的参数RollupPageTestDlgProc,这是一个函数的入口地址,也就是一个函数名,主要用来提供控件的消息回调函数。 另一个需要实现的函数是: void RollupPageTest::EndEditParams(Interface *ip,IUtil *iu) { this->iu = NULL; this->ip = NULL; ip->DeleteRollupPage(hPanel); hPanel = NULL; } 这个函数在用户结束使用控件的时候调用,需要执行一些收尾和释放的工作。 上面这两个函数ApplicationWizard会为你填充好。所以你不用亲自去编写代码。我们只需了解它的原理就行。如果这时候调试插件,可以发现在Utility里面已经多了一个插件,但是没有任何信息交互的功能。 所以现在需要添加消息回调函数: static BOOL CALLBACK RollupPageTestDlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: theRollupPageTest.Init(hWnd); //当控件初始化的时候调用。 break; case WM_DESTROY: theRollupPageTest.Destroy(hWnd); break; case WM_COMMAND: switch (LOWORD(wParam)) { /*表示如果选择了IDC_CUSTOM_BUTTON 该控件为我用custom ctrl创建的按钮控件*/ case IDC_CUSTOM_BUTTON: char buf[20]; /*获取插件中的文本框控件*/ ICustEdit* iEditTest = GetICustEdit( GetDlgItem(hWnd,IDC_EDIT) ); /*获取文本框中的文本信息*/ iEditTest->GetText(buf,20); /*显示文本信息*/ MessageBox(NULL,buf,NULL,MB_OK); ReleaseICustEdit(iEditTest); break; } case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE: theRollupPageTest.ip->RollupMouseMessage(hWnd,msg,wParam,lParam); break; default: return FALSE; } return TRUE; } 该代码的说明见注释,程序结果如图: 2.jpg 添加RollupPage的方式比较简单,而且有向导生成,比较方便。 二. 添加ToolBar的方式:(声明这里使用了OSGExp的代码和资源) 首先还是利用ApplicationWizar来生成一个Utility。然后在BeginEditParams里添加这样的代码: this->iu = iu; this->ip = ip; /* 返回MAX的窗口句柄*/ HWND hParent = ip->GetMAXHWnd(); /*创建一个独立的Frame,其中包含工具条,菜单,命令面板等等*/ HWND hWnd = CreateCUIFrameWindow(hParent, _T("My Export Toolbar"), 0, 0, 100, 100); /*获取所创建的Frame指针 */ ICUIFrame* iFrame = ::GetICUIFrame(hWnd); /*设置frame的内容类型*/ iFrame->SetContentType(CUI_TOOLBAR); /*设置位置类型*/ iFrame->SetPosType(CUI_HORIZ_DOCK | CUI_VERT_DOCK | CUI_FLOATABLE | CUI_SM_HANDLES); /*创建一个ToolBar窗体*/ HWND hToolbar = CreateWindow( CUSTTOOLBARWINDOWCLASS, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 250, 100, hWnd, NULL, hInstance, NULL); /*讲ToolBar控件和窗体连接起来*/ ICustToolbar *iToolBar = GetICustToolbar(hToolbar); /*This method links this toolbar to the CUI frame whose window handle and message handler are passed.*/ iToolBar->LinkToCUIFrame(hWnd, NULL);
/*这两个估计是设置外形的,不深究*/ iToolBar->SetBottomBorder(FALSE); iToolBar->SetTopBorder(FALSE); /* 创建一个新的消息处理器*/ tbMsgHandler = new TBMsgHandler(this); /*装载这个消息处理器*/ iFrame->InstallMsgHandler(tbMsgHandler); /*以下代码向工具栏添加图标和按钮*/ // Get the 0th icon from the CUITest icon file. // Note that the index is 1-based. MaxBmpFileIcon* pIcon = new MaxBmpFileIcon(_T("osgexp_simple"), 1); iToolBar->AddTool(TBITEM(CTB_PUSHBUTTON, pIcon, ID_TB_0)); pIcon = new MaxBmpFileIcon(_T("osgexp_simple"), 2); iToolBar->AddTool(TBITEM(CTB_PUSHBUTTON, pIcon, ID_TB_1)); // Add a separator iToolBar->AddTool(ToolSeparatorItem(8)); pIcon = new MaxBmpFileIcon(_T("osgexp_simple"), 3); iToolBar->AddTool(TBITEM(CTB_PUSHBUTTON, pIcon, ID_TB_2)); pIcon = new MaxBmpFileIcon(_T("osgexp_simple"), 4); iToolBar->AddTool(TBITEM(CTB_PUSHBUTTON, pIcon, ID_TB_3)); // Add a separator iToolBar->AddTool(ToolSeparatorItem(8)); pIcon = new MaxBmpFileIcon(_T("osgexp_simple"), 5); iToolBar->AddTool(TBITEM(CTB_PUSHBUTTON, pIcon, ID_TB_4)); pIcon = new MaxBmpFileIcon(_T("osgexp_simple"), 6); iToolBar->AddTool(TBITEM(CTB_PUSHBUTTON, pIcon, ID_TB_5)); SIZE sz; RECT rect; iToolBar->GetFloatingCUIFrameSize(&sz); rect.top = 100; rect.left = 100; rect.right = rect.left+sz.cx; rect.bottom = rect.top+sz.cy; GetCUIFrameMgr()->FloatCUIWindow(hWnd, &rect); MoveWindow(hWnd, rect.left, rect.right, sz.cx, sz.cy, TRUE); // We are done, release the toolbar and frame handles ReleaseICustToolbar(iToolBar); iToolBar = NULL; ReleaseICUIFrame(iFrame); 工具栏按钮和函数TBITEM的定义: #defineTBITEM(type, pIcon, cmd)ToolButtonItem(type,pIcon,GetCUIFrameMgr()->GetImageSize(),\GetCUIFrameMgr()->GetImageSize(),GetCUIFrameMgr()->GetButtonWidth(),\GetCUIFrameMgr()->GetButtonHeight(),cmd,0)
#define ID_TB_0 10000 #define ID_TB_1 10001 #define ID_TB_2 10002 #define ID_TB_3 10003 #define ID_TB_4 10004 #define ID_TB_5 10005 消息处理器的实现: class TBMsgHandler : public CUIFrameMsgHandler { MyUtilityToolBar *tb; public: TBMsgHandler( MyUtilityToolBar *tb) { this->tb = tb; } int  rocessMessage(UINT message, WPARAM wParam, LPARAM lParam); }; 接着填充消息相应函数: int TBMsgHandler: rocessMessage(UINT message, WPARAM wParam, LPARAM lParam) { BOOL suppressPrompts = TRUE; DWORD MAXOptions = 0; switch(message) { case WM_COMMAND: switch (LOWORD(wParam)) { case ID_TB_0: MessageBox(NULL,"0",NULL,MB_OK); break; case ID_TB_1: MessageBox(NULL,"1",NULL,MB_OK); break; case ID_TB_2: MessageBox(NULL,"2",NULL,MB_OK); break; case ID_TB_3: MessageBox(NULL,"3",NULL,MB_OK); break; case ID_TB_4: MessageBox(NULL,"4",NULL,MB_OK); break; case ID_TB_5: MessageBox(NULL,"5",NULL,MB_OK); return TRUE; default: return FALSE; } } return FALSE; } 这里将消息响应处理做了很大的简化,实现的功能是点击按钮会显示相应的数字。编译调试,可以看到新生成的工具栏: 3.jpg 虽然功能实现的较简单,但学习的过程却不轻松,还是一句话,请大家多给批评指教。 (另外,怎么在帖子中添加图片啊?谁能教我一下)
|