游戏开发论坛

 找回密码
 立即注册
搜索
查看: 6295|回复: 0

3DS Max 插件开发学习心得2(UI部分)

[复制链接]

4

主题

11

帖子

26

积分

注册会员

Rank: 2

积分
26
发表于 2007-10-29 19:07:00 | 显示全部楼层 |阅读模式
这几天研究了一下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 Panel添加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 ProcessMessage(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
虽然功能实现的较简单,但学习的过程却不轻松,还是一句话,请大家多给批评指教。
(另外,怎么在帖子中添加图片啊?谁能教我一下)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-19 15:51

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表