Notifications
Clear all

[Closed] Question: On Creating Exporter Dialog

…getting there.

I found the custom controls section in the SDK… which has been helpful to read. One thing I can’t find to do though, is how to setup a case for a right-click on the spinners to reset them to 0… I mean I found the function/method that does the reset… but not how to catch the mouse right-click. :shrug:

The spinners still don’t show up as grayed-out initially (but they are disabled)… in order to gray-out I must toggle the box… oh well. At least all of the export options are now sticky and working properly.

Updated code:

static INT_PTR CALLBACK ROFFexportOptionsDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
 {
 	static ROFFexport *exp = NULL;
 	static ISpinnerControl *toSpin;
 	static ISpinnerControl *fmSpin;
 	Interface *ipCore = GetCOREInterface();	
 	Interval animRange = ipCore->GetAnimRange();
 	int start = animRange.Start() / GetTicksPerFrame();
 	 int end = animRange.End() / GetTicksPerFrame();
 
 	SetSpinDragNotify(TRUE);	// Activates sending the CC_SPINNER_CHANGE message notifications
 								// while the user adjusts spinner with mouse.
 
 	switch(message) 
 	{
 		case WM_INITDIALOG:
 			exp = (ROFFexport *)lParam;
 			CenterWindow(hWnd,GetParent(hWnd));
 
 			//
 			// Set the export options
 			//
 
 			CheckDlgButton(hWnd, IDC_NOTES, g_ExportOptions.bNoteTracks);
 			CheckDlgButton(hWnd, IDC_ASCII, g_ExportOptions.bWriteASCII);
 			CheckDlgButton(hWnd, IDC_SEGMENT, g_ExportOptions.bExportSegment);
 
 			// Setup the spinner control for the segment_FROM frame#
 			fmSpin = SetupIntSpinner(hWnd, IDC_FROM_FRAME_SPIN, IDC_FROM_FRAME, start, end, g_ExportOptions.nSegFrom);
 			g_ExportOptions.bExportSegment ?  fmSpin->Enable() : fmSpin->Disable();
 			ReleaseISpinner(fmSpin);
 
 			// Setup the spinner control for the segment_TO frame#	
 			toSpin = SetupIntSpinner(hWnd, IDC_TO_FRAME_SPIN, IDC_TO_FRAME , start, end, g_ExportOptions.nSegTo);
 			g_ExportOptions.bExportSegment ?  toSpin->Enable() : toSpin->Disable();
 			ReleaseISpinner(toSpin);	
 				
 			break;
 
 		case WM_COMMAND:
 			switch(LOWORD(wParam))
 			{
 				case IDC_SEGMENT:
 				{
 					g_ExportOptions.bExportSegment = IsDlgButtonChecked(hWnd, IDC_SEGMENT);
 
 					 fmSpin = GetISpinner(GetDlgItem(hWnd ,IDC_FROM_FRAME_SPIN));
 					 g_ExportOptions.bExportSegment ? fmSpin->Enable(): fmSpin->Disable();
 					 ReleaseISpinner(fmSpin);
 
 					 toSpin = GetISpinner(GetDlgItem(hWnd ,IDC_TO_FRAME_SPIN));
 					 g_ExportOptions.bExportSegment ? toSpin->Enable(): toSpin->Disable();
 					 ReleaseISpinner(toSpin);
 
 					break;
 				}
 
 				case IDC_NOTES:
 				{
 					g_ExportOptions.bNoteTracks = IsDlgButtonChecked(hWnd, IDC_NOTES);
 
 					// Do something...
 					break;
 				}
 
 				case IDC_WRITE_ASCII:
 				{
 					g_ExportOptions.bWriteASCII = IsDlgButtonChecked(hWnd, IDC_WRITE_ASCII);
 
 					// Do something...
 					break;
 				}
 
 				case IDC_about:
 					DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUT_DLG), hWnd, AboutBoxDlgProc);	
 					break;
 
 				case IDC_BROWSE:
 					//Browse for the output directory...
 					break;
 
 				case IDC_EXPORT:
 					//Do the export...
 					break;
 
 				case IDC_CANCEL:
 					EndDialog(hWnd, 0);
 					break;
 			}
 			break;
 
 		case CC_SPINNER_CHANGE:
 			switch (LOWORD(wParam)) 
 			{ 
 				// Switch on ID
 				case IDC_FROM_FRAME_SPIN:
 					g_ExportOptions.nSegFrom = ((ISpinnerControl *)lParam)->GetIVal();
 					break;
 
 				case IDC_TO_FRAME_SPIN:
 					g_ExportOptions.nSegTo = ((ISpinnerControl *)lParam)->GetIVal();
 					break;
 			}
 			break;
 
 		case WM_CLOSE:
 			EndDialog(hWnd, 0);
 			break;
 
 		default:
 			return FALSE;
 
 	}
 	return TRUE;
 }

though there’s nothing wrong with what you’ve done but with a modal dialog box you would usually just grab the settings on the OK/Export button press that way you don’t have to remember the initial settings in case of a Cancel (though in a Export case this isn’t an issue).

1 Reply
(@archangel35757)
Joined: 1 year ago

Posts: 0

@Klunk-1 – I thought I needed to do it that way so that the options stay sticky even after a “Cancel” (I don’t want to make the user have to re-input things) but I do plan to grab/update them again in the “IDC_EXPORT” case.

Also… it appears that I don’t need to do anything regarding right-clicking of spinners… seems that it is automatically handled. I tested right-clicking while dragging and it returned to original value; and I tested a right-click on the spinners and it reset them to zero. So all is good there. :hmm:

I’ve added the code to handle the Browse button… and it’s value is now sticky as well.

No matter what I’ve tried… I cannot get the spinner custEdit fields to initialize as grayed-out (however they are disabled!). :shrug:

Updated code:

static INT_PTR CALLBACK ROFFexportOptionsDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
 {
 	static ROFFexport *exp = NULL;
 	static ISpinnerControl *toSpin;
 	static ISpinnerControl *fmSpin;
 	Interface *ipCore = GetCOREInterface();	
 	Interval animRange = ipCore->GetAnimRange();
 	int start = animRange.Start() / GetTicksPerFrame();
 	 int end = animRange.End() / GetTicksPerFrame();
 
 	SetSpinDragNotify(TRUE);	// Activates sending the CC_SPINNER_CHANGE message notifications
 								// while the user adjusts spinner with mouse.
 
 	switch(message) 
 	{
 		case WM_INITDIALOG:
 			exp = (ROFFexport *)lParam;
 			CenterWindow(hWnd,GetParent(hWnd));
 
 			//
 			// Set the export options
 			//
 
 			CheckDlgButton(hWnd, IDC_NOTES, g_ExportOptions.bNoteTracks);
 			CheckDlgButton(hWnd, IDC_WRITE_ASCII, g_ExportOptions.bWriteASCII);
 			CheckDlgButton(hWnd, IDC_SEGMENT, g_ExportOptions.bExportSegment);
 
 			SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
 
 			// Setup the spinner control for the segment_FROM frame#
 			fmSpin = SetupIntSpinner(hWnd, IDC_FROM_FRAME_SPIN, IDC_FROM_FRAME, start, end, g_ExportOptions.nSegFrom);
 			g_ExportOptions.bExportSegment ?  fmSpin->Enable() : fmSpin->Disable();
 			ReleaseISpinner(fmSpin);
 
 			// Setup the spinner control for the segment_TO frame#	
 			toSpin = SetupIntSpinner(hWnd, IDC_TO_FRAME_SPIN, IDC_TO_FRAME , start, end, g_ExportOptions.nSegTo);
 			g_ExportOptions.bExportSegment ?  toSpin->Enable() : toSpin->Disable();
 			ReleaseISpinner(toSpin);
 				
 			break;
 
 		case WM_COMMAND:
 			switch(LOWORD(wParam))
 			{
 				case IDC_SEGMENT:
 				{
 					g_ExportOptions.bExportSegment = IsDlgButtonChecked(hWnd, IDC_SEGMENT);
 
 					 fmSpin = GetISpinner(GetDlgItem(hWnd ,IDC_FROM_FRAME_SPIN));
 					 g_ExportOptions.bExportSegment ? fmSpin->Enable(): fmSpin->Disable();
 					 ReleaseISpinner(fmSpin);
 
 					 toSpin = GetISpinner(GetDlgItem(hWnd ,IDC_TO_FRAME_SPIN));
 					 g_ExportOptions.bExportSegment ? toSpin->Enable(): toSpin->Disable();
 					 ReleaseISpinner(toSpin);
 
 					break;
 				}
 
 				case IDC_NOTES:
 				{
 					g_ExportOptions.bNoteTracks = IsDlgButtonChecked(hWnd, IDC_NOTES);
 
 					// Do something...
 					break;
 				}
 
 				case IDC_WRITE_ASCII:
 				{
 					g_ExportOptions.bWriteASCII = IsDlgButtonChecked(hWnd, IDC_WRITE_ASCII);
 
 					// Do something...
 					break;
 				}
 
 				case IDC_about:
 					DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUT_DLG), hWnd, AboutBoxDlgProc);	
 					break;
 
 				case IDC_BROWSE:
 				{
 					BROWSEINFO bi = { 0 };
 					bi.lpszTitle = _T("Specify the output directory");
 					LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
 					if ( pidl != 0 )
 					{
 						// get the name of the folder
 						TCHAR path[MAX_PATH];
 						if ( SHGetPathFromIDList ( pidl, path ) )
 						{
 							memset ( g_ExportOptions.szOutputDir,0,2048);
 							strcpy ( g_ExportOptions.szOutputDir, path );
 							SendDlgItemMessage ( hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir );
 						}
 
 						// free memory used
 						IMalloc * imalloc = 0;
 						if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
 						{
 							imalloc->Free( pidl );
 							imalloc->Release( );
 						}
 					}
 					break;
 				}
 
 				case IDC_EXPORT:
 					//Do the export...
 					break;
 
 				case IDC_CANCEL:
 					EndDialog(hWnd, 0);
 					break;
 			}
 			break;
 
 		case CC_SPINNER_CHANGE:
 			switch (LOWORD(wParam)) 
 			{ 
 				// Switch on ID
 				case IDC_FROM_FRAME_SPIN:
 					g_ExportOptions.nSegFrom = ((ISpinnerControl *)lParam)->GetIVal();
 					break;
 
 				case IDC_TO_FRAME_SPIN:
 					g_ExportOptions.nSegTo = ((ISpinnerControl *)lParam)->GetIVal();
 					break;
 			}
 			break;
 
 		case WM_CLOSE:
 			EndDialog(hWnd, 0);
 			break;
 
 		default:
 			return FALSE;
 
 	}
 	return TRUE;
 }

@Klunk-1 – Thanks for all of your help!

Here is the current code for the Export Dialog Process:


static INT_PTR CALLBACK ROFFexportOptionsDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{
    static ROFFexport *exp = NULL;
     static ISpinnerControl *toSpin;
     static ISpinnerControl *fmSpin;
     Interface *ipCore = GetCOREInterface();    
     Interval animRange = ipCore->GetAnimRange();
     int start = animRange.Start() / GetTicksPerFrame();
     int end = animRange.End() / GetTicksPerFrame();
 
     SetSpinDragNotify(TRUE); // Activates sending CC_SPINNER_CHANGE messages
 
     switch(message) 
     {
    case WM_INITDIALOG:
        exp = (ROFFexport *)lParam;
        CenterWindow(hWnd,GetParent(hWnd));
 
        //
        // Initialize dialog export options
        //
 
        CheckDlgButton(hWnd, IDC_NOTES, g_ExportOptions.bNoteTracks);
        CheckDlgButton(hWnd, IDC_WRITE_ASCII, g_ExportOptions.bWriteASCII);
        CheckDlgButton(hWnd, IDC_SEGMENT, g_ExportOptions.bExportSegment);
 
        SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
 
        // Setup the spinner control for the segment_FROM frame#
        fmSpin = SetupIntSpinner(hWnd, IDC_FROM_FRAME_SPIN, IDC_FROM_FRAME, start, end, g_ExportOptions.nSegFrom);
        g_ExportOptions.bExportSegment ?  fmSpin->Enable() : fmSpin->Disable();
        ReleaseISpinner(fmSpin);
 
        // Setup the spinner control for the segment_TO frame#    
        toSpin = SetupIntSpinner(hWnd, IDC_TO_FRAME_SPIN, IDC_TO_FRAME , start, end, g_ExportOptions.nSegTo);
        g_ExportOptions.bExportSegment ?  toSpin->Enable() : toSpin->Disable();
        ReleaseISpinner(toSpin);
 
        break;
 
    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case IDC_SEGMENT:
            g_ExportOptions.bExportSegment = IsDlgButtonChecked(hWnd, IDC_SEGMENT);
 
            fmSpin = GetISpinner(GetDlgItem(hWnd ,IDC_FROM_FRAME_SPIN));
            g_ExportOptions.bExportSegment ? fmSpin->Enable(): fmSpin->Disable();
            ReleaseISpinner(fmSpin);
 
            toSpin = GetISpinner(GetDlgItem(hWnd ,IDC_TO_FRAME_SPIN));
            g_ExportOptions.bExportSegment ? toSpin->Enable(): toSpin->Disable();
            ReleaseISpinner(toSpin);
 
            break;
 
        case IDC_NOTES:
            g_ExportOptions.bNoteTracks = IsDlgButtonChecked(hWnd, IDC_NOTES);
 
            // Do something...
            break;
 
        case IDC_WRITE_ASCII:
            g_ExportOptions.bWriteASCII = IsDlgButtonChecked(hWnd, IDC_WRITE_ASCII);
 
            // Do something...
            break;
 
        case IDC_about:    
            exp->ShowAbout(hWnd);
            break;
 
        case IDC_BROWSE:
        {
            BROWSEINFO bi = { 0 };
            bi.lpszTitle = _T("Specify the output directory");
            LPITEMIDLIST pidl = SHBrowseForFolder (&bi);
            if (pidl != 0)
            {
                // get the name of the folder
                TCHAR path[MAX_PATH];
                if (SHGetPathFromIDList(pidl, path))
                {
                    memset (g_ExportOptions.szOutputDir,0,2048);
                    strcpy (g_ExportOptions.szOutputDir, path);
                    SendDlgItemMessage (hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
                }
 
                // free memory used
                IMalloc * imalloc = 0;
                if (SUCCEEDED(SHGetMalloc(&imalloc)))
                {
                    imalloc->Free(pidl);
                    imalloc->Release();
                }
            }
            break;
        }
 
        case IDC_EXPORT:
            //
            // Update export options
            //
            g_ExportOptions.bExportSegment = IsDlgButtonChecked(hWnd, IDC_SEGMENT);
            if ( g_ExportOptions.bExportSegment )
            {
                fmSpin = GetISpinner(GetDlgItem(hWnd ,IDC_FROM_FRAME_SPIN));
                g_ExportOptions.nSegFrom = fmSpin->GetIVal();
                ReleaseISpinner(fmSpin);
 
                toSpin = GetISpinner(GetDlgItem(hWnd ,IDC_TO_FRAME_SPIN));
                g_ExportOptions.nSegTo = toSpin->GetIVal();
                ReleaseISpinner(toSpin);
            }
            else
            {
                g_ExportOptions.nSegFrom = start; // animation range starting value
                g_ExportOptions.nSegTo = end; // animation range ending value
            }
 
            g_ExportOptions.bNoteTracks = IsDlgButtonChecked(hWnd, IDC_NOTES);
            g_ExportOptions.bWriteASCII = IsDlgButtonChecked(hWnd, IDC_WRITE_ASCII);
 
            // Check output directory is not blank
            if ( strlen ( g_ExportOptions.szOutputDir ) == 0 )
            {
                MessageBox ( NULL, "Output directory not specified. Aborting export...", "Error", MB_OK | MB_ICONEXCLAMATION );
                return 0;
            }
 
            EndDialog(hWnd, 1); 
            break;
 
        case IDC_CANCEL:
            EndDialog(hWnd, 0);
            break;
        }
        break;
 
    case CC_SPINNER_CHANGE:
        switch (LOWORD(wParam)) 
        { 
        case IDC_FROM_FRAME_SPIN:
            g_ExportOptions.nSegFrom = ((ISpinnerControl *)lParam)->GetIVal();
            break;
 
        case IDC_TO_FRAME_SPIN:
            g_ExportOptions.nSegTo = ((ISpinnerControl *)lParam)->GetIVal();
            break;
        }
        break;
 
    case WM_CLOSE:
        EndDialog(hWnd, 0);
        break;
 
    default:
        return FALSE;
 
     }
     return TRUE;
}

The error trapping on the “blank” output directory is pathetic… maybe I should try to figure out how to check if the string value actually represents a valid directory (if they type something into the field… rather than using the Browse button) :shrug:

Everything seems to be working ok with the export dialog… I still need to write the actual exporting code and progress bar dialog process. :argh:

I think this completes the Export Dialog Process code…

    I'm posting it here for other newbies that may need to do this kind of thing in 
    the future... it may not rise to the level of professional coding... but it 
    seems to work OK (...but I've not tested the new directory error trapping yet).
     
    I've attempted to add error-trapping to catch if a user 
    types garbage into the output directory field.  For that, I added a new BOOL 
    method to class ROFFExportOptions to check if the directory exists.
     
    I'm hoping one of you experts will take a look at it-- 
    espcially the output directory error-trapping code... and give me feedback.
static INT_PTR CALLBACK ROFFexportOptionsDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
    {
    	static ROFFexport *exp = NULL;
    	static ISpinnerControl *toSpin;
    	static ISpinnerControl *fmSpin;
    	Interface *ipCore = GetCOREInterface();	
    	Interval animRange = ipCore->GetAnimRange();
    	int start = animRange.Start() / GetTicksPerFrame();
    	int end = animRange.End() / GetTicksPerFrame();
     
    	SetSpinDragNotify(TRUE); // Activates sending CC_SPINNER_CHANGE messages.
     
    	switch(message) 
    	{
    	case WM_INITDIALOG:
    		exp = (ROFFexport *)lParam;
    		CenterWindow(hWnd,GetParent(hWnd));
    
    		//
    		// Initialize dialog export options
    		//
    
    		CheckDlgButton(hWnd, IDC_NOTES, g_ExportOptions.bNoteTracks);
    		CheckDlgButton(hWnd, IDC_WRITE_ASCII, g_ExportOptions.bWriteASCII);
    		CheckDlgButton(hWnd, IDC_SEGMENT, g_ExportOptions.bExportSegment);
    
    		SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
    
    		// Setup the spinner control for the segment_FROM frame#
    		fmSpin = SetupIntSpinner(hWnd, IDC_FROM_FRAME_SPIN, IDC_FROM_FRAME, start, end, g_ExportOptions.nSegFrom);
    		g_ExportOptions.bExportSegment ?  fmSpin->Enable() : fmSpin->Disable();
    		ReleaseISpinner(fmSpin);
    
    		// Setup the spinner control for the segment_TO frame#	
    		toSpin = SetupIntSpinner(hWnd, IDC_TO_FRAME_SPIN, IDC_TO_FRAME , start, end, g_ExportOptions.nSegTo);
    		g_ExportOptions.bExportSegment ?  toSpin->Enable() : toSpin->Disable();
    		ReleaseISpinner(toSpin);
    			
    		break;
     
    	case WM_COMMAND:
    		switch(LOWORD(wParam))
    		{
    		case IDC_SEGMENT:
    			g_ExportOptions.bExportSegment = IsDlgButtonChecked(hWnd, IDC_SEGMENT);
    
    			fmSpin = GetISpinner(GetDlgItem(hWnd ,IDC_FROM_FRAME_SPIN));
    			g_ExportOptions.bExportSegment ? fmSpin->Enable(): fmSpin->Disable();
    			ReleaseISpinner(fmSpin);
    
    			toSpin = GetISpinner(GetDlgItem(hWnd ,IDC_TO_FRAME_SPIN));
    			g_ExportOptions.bExportSegment ? toSpin->Enable(): toSpin->Disable();
    			ReleaseISpinner(toSpin);
    
    			break;
    
    		case IDC_NOTES:
    			g_ExportOptions.bNoteTracks = IsDlgButtonChecked(hWnd, IDC_NOTES);
    
    			// Do something...
    			break;
    
    		case IDC_WRITE_ASCII:
    			g_ExportOptions.bWriteASCII = IsDlgButtonChecked(hWnd, IDC_WRITE_ASCII);
    
    			// Do something...
    			break;
    
    		case IDC_about:	
    			exp->ShowAbout(hWnd);
    			break;
    
    		case IDC_BROWSE:
    		{
    			BROWSEINFO bi = { 0 };
    			bi.lpszTitle = _T("Specify the output directory");
    			LPITEMIDLIST pidl = SHBrowseForFolder (&bi);
    			if (pidl != 0)
    			{
    				// get the name of the folder
    				TCHAR path[MAX_PATH];
    				if (SHGetPathFromIDList(pidl, path))
    				{
    					memset (g_ExportOptions.szOutputDir,0,2048);
    					strcpy (g_ExportOptions.szOutputDir, path);
    					SendDlgItemMessage (hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
    				}
    
    				// free memory used
    				IMalloc * imalloc = 0;
    				if (SUCCEEDED(SHGetMalloc(&imalloc)))
    				{
    					imalloc->Free(pidl);
    					imalloc->Release();
    				}
    			}
    			break;
    		}
    
    		case WM_CUSTEDIT_ENTER:
    			switch (LOWORD(wParam))
    			{
    			case IDC_OUTPUT_DIR:
    			{
    				TCHAR *tempPath = NULL;
    				((ICustEdit *)lParam)->GetText( tempPath, MAX_PATH );
    				strcpy( g_ExportOptions.szOutputDir, tempPath );
    
    				// Check if directory exists
    				switch ( g_ExportOptions.DirExists(tempPath) )
    				{
    				case TRUE: // Valid output directory
    					break;
    
    				case FALSE: // Something is wrong with output directory
    					DWORD dwLastError = GetLastError();
    					switch ( dwLastError )
    					{
    					case ERROR_PATH_NOT_FOUND:
    					{
    						MessageBox( NULL, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION );
    						
    						if (MessageBox( NULL, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION ) == IDYES )
    						{
    							// Create the directory
    							CreateDirectory((LPCTSTR)tempPath, NULL);
    						}
    						
    						if (MessageBox ( NULL, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION ) == IDNO )
    						{
    							// Reset g_ExportOptions.szOutputDir and dialog field to NULL
    							strcpy (g_ExportOptions.szOutputDir, _T("\0"));
    							SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
    							
    							return 0;
    						}
    						
    						break;
    					}
    					default:
    						MessageBox ( NULL, "Invalid output directory.", "Error", MB_OK | MB_ICONEXCLAMATION );
    						// Reset g_ExportOptions.szOutputDir and dialog field to NULL
    						strcpy (g_ExportOptions.szOutputDir, _T("\0"));
    						SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
    						
    						return 0;
    
    					} // end switch
    
    					ExitProcess(dwLastError); 
    
    					break;
    
    				} // end switch
    
    				break;
    			} 
    
    			default:
    				break;
    
    			} // end switch
    			break;
    
    		case IDC_EXPORT:
    			//
    			// Update export options
    			//
    			g_ExportOptions.bExportSegment = IsDlgButtonChecked(hWnd, IDC_SEGMENT);
    			if ( g_ExportOptions.bExportSegment )
    			{
    				fmSpin = GetISpinner(GetDlgItem(hWnd ,IDC_FROM_FRAME_SPIN));
    				g_ExportOptions.nSegFrom = fmSpin->GetIVal();
    				ReleaseISpinner(fmSpin);
    
    				toSpin = GetISpinner(GetDlgItem(hWnd ,IDC_TO_FRAME_SPIN));
    				g_ExportOptions.nSegTo = toSpin->GetIVal();
    				ReleaseISpinner(toSpin);
    			}
    			else
    			{
    				g_ExportOptions.nSegFrom = start; // animation range starting value
    				g_ExportOptions.nSegTo = end; // animation range ending value
    			}
    
    			g_ExportOptions.bNoteTracks = IsDlgButtonChecked(hWnd, IDC_NOTES);
    			g_ExportOptions.bWriteASCII = IsDlgButtonChecked(hWnd, IDC_WRITE_ASCII);
    
    			// Check output directory is not blank
    			if ( strlen ( g_ExportOptions.szOutputDir ) == 0 )
    			{
    				MessageBox ( NULL, "Output directory not specified. Aborting export...", "Error", MB_OK | MB_ICONEXCLAMATION );
    				return 0;
    			}
    
    			EndDialog(hWnd, 1); 
    			break;
    
    		case IDC_CANCEL:
    			EndDialog(hWnd, 0);
    			break;
    		}
    		break;
     
    	case CC_SPINNER_CHANGE:
    		switch (LOWORD(wParam)) 
    		{ 
    		case IDC_FROM_FRAME_SPIN:
    			g_ExportOptions.nSegFrom = ((ISpinnerControl *)lParam)->GetIVal();
    			break;
    
    		case IDC_TO_FRAME_SPIN:
    			g_ExportOptions.nSegTo = ((ISpinnerControl *)lParam)->GetIVal();
    			break;
    		}
    		break;
    
    	case WM_CLOSE:
    		EndDialog(hWnd, 0);
    		break;
    
    	default:
    		return FALSE;
     
    	 }
    	 return TRUE;
    }
    I HATE THIS CODE EDITOR!!!  How do I make this thing respect the tabs in my code when I paste into this editor???? :banghead:

Edit: Must be Internet Explorer… because FireFox seems to respect my tabs…

So… the case “WM_CUSTEDIT_ENTER” for the ICustEdit Control isn’t working at all when I manually enter text in the field and press a return.

  Could someone take a look and see what I'm doing wrong? :blush:    Thanks!

Edit:  So to try and troubleshoot this case... I simple commented out everything and added a messageBox just to check if it registers a return press...  so it looks like:
case WM_CUSTEDIT_ENTER:
   	  MessageBox ( hWnd, "You pressed Enter Key!", "Success", MB_OK );
    	return 0;
...typing and pressing a return key (either keyboard control return or Numpad Enter) does nothing! :eek:

Ok… so I commented out the entire “case WM_CUSTEDIT_ENTER” and replaced it with the following code highlighted in [color=Yellow]Yellow[/color]:

static INT_PTR CALLBACK ROFFexportOptionsDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
        {
        	static ROFFexport *exp = NULL;
        	static ISpinnerControl *toSpin;
        	static ISpinnerControl *fmSpin;
        	static ICustEdit *pCustEdtCtrl;
        	Interface *ipCore = GetCOREInterface();	
        	Interval animRange = ipCore->GetAnimRange();
        	int start = animRange.Start() / GetTicksPerFrame();
        	int end = animRange.End() / GetTicksPerFrame();
        	TCHAR *pPath = NULL;
        
        	SetSpinDragNotify(TRUE); // Activates sending CC_SPINNER_CHANGE messages.
        	pCustEdtCtrl->WantReturn(TRUE); // For handling return key presses in custEdit box.
        	
        	switch(message) 
        	{
        	case WM_INITDIALOG:
        		exp = (ROFFexport *)lParam;
        		CenterWindow(hWnd,GetParent(hWnd));
        
        		//
        		// Initialize dialog export options
        		//
        
        //****************************************
        	.
        	. < truncated code for clarity >
        	.
        //****************************************
      
      	case WM_COMMAND:
      		switch(LOWORD(wParam))
      		{
      		case IDC_SEGMENT:
      			g_ExportOptions.bExportSegment = IsDlgButtonChecked(hWnd, IDC_SEGMENT);
      
      			fmSpin = GetISpinner(GetDlgItem(hWnd ,IDC_FROM_FRAME_SPIN));
      			g_ExportOptions.bExportSegment ? fmSpin->Enable(): fmSpin->Disable();
      			ReleaseISpinner(fmSpin);
      
      			toSpin = GetISpinner(GetDlgItem(hWnd ,IDC_TO_FRAME_SPIN));
      			g_ExportOptions.bExportSegment ? toSpin->Enable(): toSpin->Disable();
      			ReleaseISpinner(toSpin);
      
      			break;
      
      		case IDC_NOTES:
      			g_ExportOptions.bNoteTracks = IsDlgButtonChecked(hWnd, IDC_NOTES);
      
      			// Do something...
      			break;
      
      		case IDC_WRITE_ASCII:
      			g_ExportOptions.bWriteASCII = IsDlgButtonChecked(hWnd, IDC_WRITE_ASCII);
      
      			// Do something...
      			break;
      
      		case IDC_about:	
      			exp->ShowAbout(hWnd);
      			break;
      
      		case IDC_BROWSE:
      		{
      			BROWSEINFO bi = { 0 };
      			bi.lpszTitle = _T("Specify the output directory");
      			LPITEMIDLIST pidl = SHBrowseForFolder (&bi);
      			if (pidl != 0)
      			{
      				// get the name of the folder
      				TCHAR path[MAX_PATH];
      				if (SHGetPathFromIDList(pidl, path))
      				{
      					memset (g_ExportOptions.szOutputDir,0,2048);
      					strcpy (g_ExportOptions.szOutputDir, path);
      					SendDlgItemMessage (hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
      				}
      
      				// free memory used
      				IMalloc * imalloc = 0;
      				if (SUCCEEDED(SHGetMalloc(&imalloc)))
      				{
      					imalloc->Free(pidl);
      					imalloc->Release();
      				}
      			}
      			break;
      		}
       
        		case IDC_OUTPUT_DIR:			
        			if ( HIWORD(wParam) == EN_CHANGE)
        			{
        				pCustEdtCtrl = GetICustEdit(GetDlgItem(hWnd, IDC_OUTPUT_DIR));
        				pCustEdtCtrl->GetText(pPath, MAX_PATH);
        				if( pCustEdtCtrl->GotReturn() )
        				{
        					SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_GETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
        				}
        				ReleaseICustEdit(pCustEdtCtrl);
        			
        				// Check if directory exists
        				switch ( g_ExportOptions.DirExists(pPath) )
        				{
        				case TRUE: // Valid output directory
        					break;
        
        				case FALSE: // Something is wrong with output directory
        					DWORD dwLastError = GetLastError();
        					switch ( dwLastError )
        					{
        					case ERROR_PATH_NOT_FOUND:
        					{
        						MessageBox( NULL, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION );
        						
        						if (MessageBox( NULL, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION ) == IDYES )
        						{
        							// Create the directory
        							CreateDirectory((LPCTSTR)pPath, NULL);
        						}
        						
        						if (MessageBox ( NULL, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION ) == IDNO )
        						{
        							// Reset g_ExportOptions.szOutputDir and dialog field to NULL
        							strcpy (g_ExportOptions.szOutputDir, _T("\0"));
        							SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
        							
        							return 0;
        						}
        						
        						break;
        					}
        					default:
        						MessageBox ( NULL, "Invalid output directory.", "Error", MB_OK | MB_ICONEXCLAMATION );
        						// Reset g_ExportOptions.szOutputDir and dialog field to NULL
        						strcpy (g_ExportOptions.szOutputDir, _T("\0"));
        						SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
        						
        						return 0;
        
        					} // end switch
        
        					ExitProcess(dwLastError); 
        
        					break;
        
        				} // end switch
        
        			}
        			break;
        
        // truncated remaining code...
   The above code for "case IDC_OUTPUT_DIR" compiles successfully but causes a 3dsMax application error and crash right after I dismiss the File Export and File Save dialog.
   
   Would someone help me find where my code is in error? :blush: 
   
   Thanks! 

Edit: Tried various changes… some attempts I at least got the export dialog to show… but as soon as I typed anything into the output directory field I’d get a crash; or if I used the browse button it would input the selected directory but then it would crash (so the two conflict). So no point in posting those code changes… the errors are isolated to my attempt of doing this manual input into IDC_OUTPUT_DIR field and error checking on the text. :banghead:

why are you trying to check for a valid directory on every keystroke ? It’s a modal dialog box the user cannot do anything else in max while it’s up until they press OK/Export or cancel. Put the test for a valid directory on the OK/Export button press, if invalid display the error message box and do not close the dialog.

alternatively use a read only win32 edit field as in the resource collector in conjunction with your browse button, the source code is in maxsdk\samples\utilities\collector. One of the places I’ve worked would “autocreate” the export directory based on art asset “input” directory and the output platform. Obviously there needs to be a rigid discipline on the art side on how the asset directories are arranged but it worked well.

another alternative is if you want the process to work in a non modal way is to use mxs…

exportfile exportfname #noPrompt using:myExporterClass

you can write to the export plugin settings before hand if needed, check the export directory. You could even add mxs callable functions in exporter to set stuff up that way.

@Klunk-1 – yes, I realized my folly and moved it to the case IDC_EXPORT so that snippet now reads:

		case IDC_EXPORT:
  			//
  			// Update export options
  			//
  			g_ExportOptions.bExportSegment = IsDlgButtonChecked(hWnd, IDC_SEGMENT);
  			if ( g_ExportOptions.bExportSegment )
  			{
  				fmSpin = GetISpinner(GetDlgItem(hWnd ,IDC_FROM_FRAME_SPIN));
  				g_ExportOptions.nSegFrom = fmSpin->GetIVal();
  				ReleaseISpinner(fmSpin);
  
  				toSpin = GetISpinner(GetDlgItem(hWnd ,IDC_TO_FRAME_SPIN));
  				g_ExportOptions.nSegTo = toSpin->GetIVal();
  				ReleaseISpinner(toSpin);
  			}
  			else
  			{
  				g_ExportOptions.nSegFrom = start; // animation range starting value
  				g_ExportOptions.nSegTo = end; // animation range ending value
  			}
  
  			g_ExportOptions.bNoteTracks = IsDlgButtonChecked(hWnd, IDC_NOTES);
  			g_ExportOptions.bWriteASCII = IsDlgButtonChecked(hWnd, IDC_WRITE_ASCII);
  
  			// Check output directory is not blank
  			if ( strlen ( g_ExportOptions.szOutputDir ) == 0 )
  			{
  				MessageBox ( NULL, "Output directory not specified. Aborting export...", "Error", MB_OK | MB_ICONEXCLAMATION );
  				return 0;
  			}
  			else
  			{
  				// Check if directory exists
  				strcpy( pPath, g_ExportOptions.szOutputDir );
  				switch ( g_ExportOptions.DirExists(pPath) )
  				{
  				case TRUE: // Valid output directory
  					break;
  
  				case FALSE: // Something is wrong with output directory
  					DWORD dwLastError = GetLastError();
  					switch ( dwLastError )
  					{
  					case ERROR_PATH_NOT_FOUND:
  					{
  						MessageBox( hWnd, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION );
  						
  						if (MessageBox( hWnd, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION ) == IDYES )
  						{
  							// Create the directory
  							CreateDirectory((LPCTSTR)pPath, NULL);
  						}
  						
  						if (MessageBox ( hWnd, "Specified directory does not exist. Would you like to create it?", "Warning", MB_YESNO | MB_ICONEXCLAMATION ) == IDNO )
  						{
  							// Reset g_ExportOptions.szOutputDir and dialog field to NULL
  							strcpy (g_ExportOptions.szOutputDir, _T("\0"));
  							SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
  							
  							return 0;
  						}
  						
  						break;
  					}
  					default:
  						MessageBox ( hWnd, "Invalid output directory.", "Error", MB_OK | MB_ICONEXCLAMATION );
  						// Reset g_ExportOptions.szOutputDir and dialog field to NULL
  						strcpy (g_ExportOptions.szOutputDir, _T("\0"));
  						SendDlgItemMessage(hWnd, IDC_OUTPUT_DIR, WM_SETTEXT, 0, (LPARAM)g_ExportOptions.szOutputDir);
  						
  						return 0;
  
  					} // end switch
  
  					ExitProcess(dwLastError); 
  
  					break;
  
  				} // end switch 
  			}
  
  			EndDialog(hWnd, 1); 
  			break;

My problem now is that it never registers the typed-in text so it always seems that the string is zero and never gets down into the switch case for directory error trapping. Maybe I need to use the SetText method under the Custom Edit Control?

If I use the Browse button to populate the output directory then it gets past the string length == 0 check but then gives me an application error and crashes.

why are you asking for the output directory twice ? if you’re throwing up the settings dialog then you’ve already been through the select export filename dialog. and you already know the filename & path from name function argument in .

DoExport(const TCHAR* name,ExpInterface* ei,Interface* i, BOOL suppressPrompts, DWORD options)
1 Reply
(@archangel35757)
Joined: 1 year ago

Posts: 0

@Klunk-1 – I don’t understand…

I thought the const TCHAR* name parameter in the DoExport function only captured the file name field the user chooses to save the file exported as– not its location… no? But then I guess you’re talking about the drop-down file path menu at the top of that dialog? That’s a good point… …which parameter captures that directory? So I guess I could delete that export option entirely…

Also, this exporter will export all objects (also supports Export Selected…) that have a specific game shader applied to them in the diffuse channel of a standard material as individual files. Therefore the filename the user enters in the initial File Export dialog will only be the prefix of the actual final files (both binary and optional ascii) that get written out for each object (where each file gets the object’s name appended to the filename to make them unique).

I thought the const TCHAR* name parameter in the DoExport function only captured the file name field the user chooses to save the file exported as– not its location… no?

no it’s the full path and filename. It would be tricky otherwise as you are responsible for opening and closing the file !

Also, this exporter will export all objects (also supports Export Selected…) that have a specific game shader applied to them in the diffuse channel of a standard material as individual files. Therefore the filename the user enters in the initial File Export dialog will only be the prefix of the actual final files (both binary and optional ascii) that get written out for each object (where each file gets the object’s name appended to the filename to make them unique).

which still should be derived from the name arg in doExport

Page 2 / 3