XP Dialog Box

Hello! I'm learning XP. It's fun, and it may turn out to be a critical tool for me. I could not find the answer to a question anywhere, so I thought I'd ask here.

How can one create a custom dialog window from C++? I can input text or use the common dialogs, but I'd like to collect multiple inputs like some of the internal tools. For instance, a few integers, perhaps a color, etc.

Thank you!

Comments

  • jslaytonjslayton Moderator, ProFantasy Mapmaker

    The short version for FastCAD custom dialogs is:

    • Create a dialog resource in the project's RC file with the controls you want to use
    • Use DefDlg to define a dialog container from the dialog resource
    • Use EDCTL, LSTCTL, BTNCTL, and so on to associate items in the dialog resource with variable and handlers.
    • Use XPDlog to show and execute the dialog. The return code will indicate why the dialog ended.
    • Use RelDlg with the handle returned by DefDlg to clean up the dialog container.

    A short example of a command that uses a dialog:

    static int scaleMode = 0;
    static GLINE2 mapBorder;
    static unsigned int mapWidth  = 0;
    static unsigned int mapHeight = 0;
     
    static int XPCALL SizeChangeW(void)
    {
    	mapHeight = (unsigned)(mapWidth / (mapBorder.p2.x - mapBorder.p1.x)*(mapBorder.p2.y - mapBorder.p1.y));
    	UpdCtl(IDC_EDITH);
    	return 0;
    }
     
    static int XPCALL SizeChangeH(void)
    {
    	mapWidth = (unsigned)(mapHeight / (mapBorder.p2.y - mapBorder.p1.y)*(mapBorder.p2.x - mapBorder.p1.x));
    	UpdCtl(IDC_EDITW);
    	return 0;
    }
     
    static int XPCALL initDialog(void)
    {
    	return 0;
    }
     
    void XPCALL ScaleMapExtCmd(void)
    {
    	// get scaleMode and mapBorder from drawing
    	mapWidth  = (unsigned)(mapBorder.p2.x - mapBorder.p1.x + 0.5f);
    	mapHeight = (unsigned)(mapBorder.p2.y - mapBorder.p1.y + 0.5f);
     
    	auto hDlg = DefDlg("IDD_DLGSCALEMAPEXT", 0, 0, initDialog, NULL, NULL);
    	EDCTL(hDlg, IDC_EDITW, 0, FT_UDec4, 6, &mapWidth, SizeChangeW);
    	EDCTL(hDlg, IDC_EDITH, 0, FT_UDec4, 6, &mapHeight, SizeChangeH);
    	auto rc = XPDlog(hDlg, MyXP.ModHdl, 0);
    	RelDlg(hDlg);
     
    	if (rc == IDOK)
    	{
    		MapScaleW = (float)mapWidth;
    		MapScaleH = (float)mapHeight;
    		// rescaleMap(MapScaleW, MapScaleH);
    		Redraw();
    	}
     
    	CmdEnd();
    }
    

    And here's the corresponding dialog resource:

    IDD_DLGSCALEMAPEXT DIALOGEX 0, 0, 190, 87
    STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "Scale Map"
    FONT 8, "MS Sans Serif", 0, 0, 0x0
    BEGIN
        GROUPBOX        "Dimensions",-1,20,11,152,39
        LTEXT           "Width",-1,28,20,53,8
        EDITTEXT        IDC_EDITW,28,31,52,13,ES_AUTOHSCROLL
        CTEXT           "X",-1,86,31,13,9
        LTEXT           "Height",-1,104,20,50,8
        EDITTEXT        IDC_EDITH,104,31,52,13,ES_AUTOHSCROLL
        PUSHBUTTON      "Finish",IDOK,25,66,50,14
        PUSHBUTTON      "Cancel",IDCANCEL,79,66,50,14
        PUSHBUTTON      "Help",IDHELP,133,66,50,14
    END
    


    MonsenJimPLoopysueMapjunkieGlitch
  • Yay. Thank you. I will try this.

  • OK, I have been working with this for a bit. I hate to come back to the forums for help with something that should be simple, but I can't find anything on Google to help.

    Do you have any documentation on DefDlg?

    When I call it (e.g., your line #31), it returns a handle. It returns the handle even when I pass in a garbage dialog name, as though that first parameter isn't being used correctly. The handle that comes back always causes a return of 1 (IDOK) from XPDlog. It never calls the init function (e.g., initDialog from your example). Any documentation for that DefDlg function might help me.

    I'll admit, it's been a long time since I worked with Win32 dialog code. Please forgive my silly questions. I really appreciate the help! Thank you!

  • jslaytonjslayton Moderator, ProFantasy Mapmaker

    You need to make sure that your dialog resource is named as a string rather than the default enumeration that the Visual Studio rc file editor generates. The FastCAD engine has a feature that strings specified as smallish numbers (resource IDs) get converted internally in its translation lookup table. Unfortunately, enumerations generated by the VS resource editor fall right into that range.

    Short version: delete the #define in resource.h that corresponds to your dialog and it should start working. I tend to be mystified by this regularly, so it's not just you.

  • jslaytonjslayton Moderator, ProFantasy Mapmaker

    Technical note: DefDlg returns the address of a FastCAD dialog record that includes (among other things) the Windows dialog handle. Failure to load the resource isn't well communicated and calling xpdlg with an incompletely initialized dialog record returns immediately with a "I did everything I could so all is well" return value.

Sign In or Register to comment.