Community
3ds Max Programming
Welcome to Autodesk’s 3ds Max Forums. Share your knowledge, ask questions, and explore popular 3ds Max SDK, Maxscript and Python topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Floating dialog box with C++

15 REPLIES 15
Reply
Message 1 of 16
Anonymous
1592 Views, 15 Replies

Floating dialog box with C++

Hi guys! I'm new to the C++ sdk (worked exclusively with maxscript before this), and I'm wondering how do you create a floating dialog box? I'm using the plugin wizard and created a utility project, but have yet to figure out how to get it out of the command panel. Thanks for all the help!

 

P.S. Trying to create a floating dialog box that loads a material library and displays their pictures and allows 

  users to apply a material to selected objects in the scene.

15 REPLIES 15
Message 2 of 16
istan
in reply to: Anonymous

a) you can also drag out the commandpanel

b) you have to write "some" extra code for connecting the ParamBlocks and Rollups to the Win Dialog

see

\maxsdk\samples\modifiers\uvwunwrap\ToolRenderUVs.cpp
\maxsdk\samples\modifiers\uvwunwrap\uvwunwrap\ToolPelt.cpp

check also

GetIRollup()
CreateRWParamMap2()
Message 3 of 16
omidt_gh
in reply to: Anonymous

You can find a good sample in

\maxsdk\samples\modifiers\UVWunwrap\unwrap\UI

it is a bit confusing with this all menu and windows but that's a good source to look in especially:

 

 

UnwrapCustomToolBar.cpp
and
UnwrapCustomUI.cpp

 

 


the rest is in mods.rc file

Message 4 of 16
omidt_gh
in reply to: Anonymous

in the easy term, first you need to create an interface in .rc format, then add a class for loading it as a float rollout

Message 5 of 16
istan
in reply to: omidt_gh


@omidt_gh wrote:

in the easy term, first you need to create an interface in .rc format, then add a class for loading it as a float rollout


Today, I'd not start with .rc created dialogs but consider using QT instead. I'd also think about the requirement of using paramblks. QT delivers all features for nice scaleable and resizeable dialogs, including easier localization as well.

Although there are still some bugs in the integration of QT in Max, the advantages outweigh imho.

Message 6 of 16
omidt_gh
in reply to: istan

It shouldn't be a big issue, there are a tons of introduction of how to use QT instead of MFC that you can find on web.
Or you can just look in to the 3dsmax Documentation>
If you need a good start i recommended to looking in to ADN sample repository https://github.com/ADN-DevTech/3dsMax-SampleCode/tree/master/DCM_Operand
For a sample QT code

Also, do not forget to check this tutorial :
https://help.autodesk.com/view/MAXDEV/2021/ENU/?guid=__developer_writing_plug_ins_using_qt_with_3ds_...

Message 7 of 16
klvnk
in reply to: omidt_gh

the best example to start from as a tool is the ChannelInfo project (TreeViewUtil.cpp) shows how to throw up a floating tool dialog and tie into max via mxs so it's easy hook into the ui.

Message 8 of 16
klvnk
in reply to: klvnk

it can be reduced something like this

 

#define TEMPLATE_UTIL_OBJ_CLASS_ID			Class_ID(0xe823fa8, 0x21c0384c)
#define TEMPLATE_UTIL_OBJ_FP_INTERFACE_ID	Interface_ID(0x436202d5, 0x70000ea6)

//********************************************************************************************
// TemplateUtilObj Our Tools class definition

class TemplateUtilObj : public UtilityObj 
{
public:

	HWND			hPanel;			// utility rollout panel
	IUtil			*iu;
	Interface		*ip;
	HWND			floaterHWND;	// our floating window
	
// Constructor/Destructor

	TemplateUtilObj();
	~TemplateUtilObj() {}

// stuff for the utility panel

	void BeginEditParams(Interface *ip,IUtil *iu);
	void EndEditParams(Interface *ip,IUtil *iu);

// util panel

	void Init(HWND hWnd)	{}
	void Destroy(HWND hWnd) {}
	void DeleteThis()		{}		

// tool window handling routines

	void CreateNewWindow();	
	void InitWindow();
	void DestroyWindow();
	void UpdateUI();
	LRESULT NotifyHandler( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

};

// our util global static

static TemplateUtilObj utilObj;

//********************************************************************************************
// the class descriptor

class TemplateUtilObjClassDesc : public ClassDesc2 
{
public:
	int 			IsPublic()					{ return TRUE; }
	void *			Create(BOOL loading=FALSE)	{ return &utilObj; }
	const TCHAR *	ClassName()					{ return GetString(IDS_TEMPLATE_CLASS_NAME); }
	SClass_ID		SuperClassID()				{ return UTILITY_CLASS_ID; }
	Class_ID		ClassID()					{ return TEMPLATE_UTIL_OBJ_CLASS_ID; }
	const TCHAR* 	Category()					{ return GetString(IDS_CATEGORY); }
	const TCHAR*	InternalName()				{ return _T("TemplateUtilObj"); }	
	HINSTANCE		HInstance()					{ return hInstance; }	// returns owning module handle
};

static TemplateUtilObjClassDesc TemplateUtilObjDesc;
ClassDesc2* GetTemplateUtilObjDesc() { return &TemplateUtilObjDesc; }

//********************************************************************************************
// function publishing, make some basic functionality available to mxs mostly so we can call our
// utility from the ui via a macroscript without switching to the utility panel first !

class TemplateUtilObjFnP : public FPStaticInterface 
{
public:
	DECLARE_DESCRIPTOR(TemplateUtilObjFnP);

	enum functionID { kOpenWindow, kCloseWindow, kIsOpen };
	
	BEGIN_FUNCTION_MAP			
		VFN_0(kOpenWindow,  OpenWindow)
		VFN_0(kCloseWindow, CloseWindow)
		FN_0(kIsOpen, TYPE_BOOL, IsOpen)
	END_FUNCTION_MAP
	
	void OpenWindow()	{ utilObj.CreateNewWindow(); }
	void CloseWindow()	{ if(utilObj.floaterHWND)  DestroyWindow(utilObj.floaterHWND); }
	bool IsOpen()		{ return IsWindowOpen(); }

	static bool IsWindowOpen()			{ return windowOpen; }
	static void SetWindowOpen(bool val) { windowOpen = val; GetCUIFrameMgr()->SetMacroButtonStates(false); }

private:

	static bool windowOpen;
};

//********************************************************************************************
// create the global static instance

static TemplateUtilObjFnP theTemplateUtilObjFnP(TEMPLATE_UTIL_OBJ_FP_INTERFACE_ID, _T("utilObj"), 
							IDS_TEMPLATE_CLASS_NAME, NULL, FP_CORE,
							TemplateUtilObjFnP::kOpenWindow, _T("openWindow"), -1, TYPE_VOID, FP_NO_REDRAW, 0,
							TemplateUtilObjFnP::kCloseWindow, _T("closeWindow"), -1, TYPE_VOID, FP_NO_REDRAW, 0,
							TemplateUtilObjFnP::kIsOpen, _T("isOpen"), -1, TYPE_BOOL, FP_NO_REDRAW, 0, p_end);

//********************************************************************************************
// initialize the showing static

bool TemplateUtilObjFnP::windowOpen = false;


static INT_PTR CALLBACK TemplateUtilObjPanelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) 
	{
		case WM_INITDIALOG:

			utilObj.Init(hWnd); // can we delete these ?
			break;

		case WM_DESTROY:

			utilObj.Destroy(hWnd); // can we delete these ?
			break;

		case WM_COMMAND:

			switch (LOWORD(wParam)) 
			{
				case IDC_NEW_FLOATER_BTN:

					utilObj.CreateNewWindow();
					break;

				case IDOK:
				case IDCANCEL:

					DestroyWindow(hWnd);
					break;
			}
			break;

		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_MOUSEMOVE:

			utilObj.ip->RollupMouseMessage(hWnd,msg,wParam,lParam); 
			break;

		default:
			return FALSE;
	}
	return TRUE;
}

//********************************************************************************************
// the main handler callback for our floating tool window

static INT_PTR CALLBACK TemplateUtilObjWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) 
	{
		case WM_INITDIALOG: 
		{
			utilObj.floaterHWND = hWnd;
			utilObj.InitWindow();
			utilObj.ip->RegisterDlgWnd(hWnd);
			utilObj.UpdateUI();
			TemplateUtilObjFnP::SetWindowOpen(true);
			break;
		}

		case WM_DESTROY: 
		{
			utilObj.DestroyWindow();
			utilObj.ip->UnRegisterDlgWnd(hWnd);
			TemplateUtilObjFnP::SetWindowOpen(false);
			break;
		}

		case WM_RBUTTONDOWN:
		{
			break;
		}
		
		case WM_NOTIFY:

			return utilObj.NotifyHandler(hWnd, msg, wParam, lParam);
			break;


// handle custom max controls handled here spinners etc here e.g.

//		case CC_SPINNER_CHANGE: 
//		case CC_COLOR_SEL:
//		case CC_COLOR_CHANGE:
//		case CC_COLOR_CLOSE:

		case WM_COMMAND:

			switch (LOWORD(wParam)) 
			{
// all other win32 dialog handled here		

				case IDOK:
				case IDCANCEL:

					DestroyWindow(hWnd);
					break;
			}
			break;

		default:
			return FALSE;
	}
	return TRUE;
}

//********************************************************************************************
// TemplateUtilObj, code for our utility starts here

TemplateUtilObj::TemplateUtilObj()
{
	iu = NULL;
	ip = NULL;	
	hPanel = NULL;
	floaterHWND = NULL;
}

//********************************************************************************************

void TemplateUtilObj::BeginEditParams(Interface *ip,IUtil *iu) 
{
	this->iu = iu;
	this->ip = ip;
	hPanel = ip->AddRollupPage(hInstance, MAKEINTRESOURCE(IDD_TEMPLATE_WINDOW_PANEL), 
		TemplateUtilObjPanelProc, GetString(IDS_PARAMS), 0);
}
	
//********************************************************************************************

void TemplateUtilObj::EndEditParams(Interface *ip,IUtil *iu) 
{
	this->iu = NULL;
	ip->DeleteRollupPage(hPanel);
	hPanel = NULL;
}

//********************************************************************************************

void TemplateUtilObj::CreateNewWindow()
{
	ip = GetCOREInterface();	// catches any script calls
	if(floaterHWND == NULL)
		CreateDialog(hInstance, MAKEINTRESOURCE(IDD_TEMPLATE_WINDOW), ip->GetMAXHWnd(), TemplateUtilObjWindowProc);
}

//********************************************************************************************

LRESULT TemplateUtilObj::NotifyHandler( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return 0L;
}

//********************************************************************************************
// Initialize the tool window

void TemplateUtilObj::InitWindow()  
{
}

//********************************************************************************************
// destroy the tool window

void TemplateUtilObj::DestroyWindow()
{
	floaterHWND = NULL;
}

//********************************************************************************************

void TemplateUtilObj::UpdateUI() {}
Message 9 of 16
omidt_gh
in reply to: klvnk

Are you sure it is a floating rollout?

I think this is a utility plugin that will work in the utility panel.

Message 10 of 16
klvnk
in reply to: klvnk

yes it's a floating window. you need a base plugin to hang it off

 

floater2.gif

 

then the mcr would look like....

 

 

 

macroScript template_util
			category: 	"My Utils"
			buttontext:	"util"
			Icon:		#("myicons",1)
			tooltip:	"template util"
(
	on isChecked do utilObj.isOpen();
	on execute do
	(
		if utilObj.isOpen() then 
			utilObj.closeWindow();
		else
			utilObj.openWindow();
	)	
)	

 

 

Message 11 of 16
klvnk
in reply to: klvnk

the same code used as the basis for our node export prop editor.....

floater3.gif

Message 12 of 16
omidt_gh
in reply to: klvnk

How about a node base plugin, do you have any idea?
something like material node.

Message 13 of 16
klvnk
in reply to: omidt_gh

you can use one of the typical win32 create window/dialog routines and register it with max using

 

 

RegisterDlgWnd(hWnd);

 

 

just about anytime. then when it's closed unregister it. What you do with it or what you display in it is upto you. 

Message 14 of 16
omidt_gh
in reply to: klvnk

Channel info tree was a great suggestion, about the node base view I meant something like the image below.
image-asset.jpegimage-asset.gif
Do you have any suggestions?

Message 15 of 16
omidt_gh
in reply to: Anonymous

You did not get the question, i asked do you have any idea of how to create node base view in 3dsmax, like the image i send?

Message 16 of 16
klvnk
in reply to: Anonymous

dunno ? open a schematic view I guess.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report