I figured it out and will share what I learned.
If you put a form inside of the dialog, you can access it just like any other Dojo form. But you have to make sure that dialog is not already in another form. That was my problem, it caused the inner form to disappear when the dialog is moved to the end of the body tag.
<div id="my_dialog" dojoType="dojo.dijit.Dialog" style="display:none;" title="My Dialog">
<form id="my_form" dojotType="dijit.form.Form" method="post" action="/path/">
<input type="text" dojoType="dijit.form.TextBox" id="input_1" name="input_1" value="info" />
<button type="submit" dojoType="dijit.form.Button" onclick="return someFunction();">Submit</button>
</form>
</div>
Using the structure above, you have a couple of options to get the form's values: from the dialog, or from the form. That means dijit.byId("my_dialog").attr("value") is the same as dijit.byId("my_form").attr("value"). That was what originally confused me and made me thing the dialog itself could act as a form.
To process or validate the form before it is submitted, add onclick="return someFunction();", and make sure that function returns true only if the form should be submitted.
One additional pitfall is that all inputs in the dialog are moved to the end of the dom. So if you did not have the form inside the dialog, and you expected those inputs in the dialog to be submitted with a parent form, that isn't going to happen. In this case, I create hidden fields inside the parent form, then manually copy the dialog input values into them before submitting.