Session #5
This session I added some features to the editor that were brought up during last session. The two big ones are using the right mouse button to paint in the empty (background) color and to open a data file by allowing the user to drag and drop from Windows Explorer. I also showed how to add another form (an About box in the Help menu) to the application. I showed some other things as well, like using .ini files to persist values between invocations. However, I'm not going to put that here. I need to re-architect the application slightly in light of this enhancement. It will all be in the next session.
Painting with the right mouse button. There are really only two small places in the code that needed to be added/modified to support this. The first one is the addition of an OnMouseDown event handler. The second is a slight modification to the OnMouseMove event handler. You can compare last session's code to this one to see the changes. Look at the online help to see what information is stored in the TMouseButton and TShiftState parameters.
/*
Handler for the OnMouseDown event. The Shift parameter contains
additional information such as the state of the control/alt/shift keys.
*/
void __fastcall TfrmMain::gridWorldMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
// If the right mouse button is pressed down
if (Button == mbRight)
{
// Convert the x/y pixel location to a row and column in the grid
TGridCoord coord = gridWorld->MouseCoord(X, Y);
// Update current row/column
FCurrRow = coord.Y;
FCurrColumn = coord.X;
// Set this cell as empty (background color)
FDataMap[FCurrRow][FCurrColumn] = ctEMPTY;
// Paint the cell
HighlightCell(true);
}
}
Supporting drag and drop from Windows Explorer. Handling files that are dropped onto the main window is straight-forward. After setting up some message-handling code, you simply need to implement the functionality you want to achieve. In this case, when a data file (collision file) is dropped onto the window, we want to load it into the editor. The behavior is exactly the same as if the user browsed for the file with the File Open dialog and selected a file from there. Drag and drop is much more natural (eventually!) than navigating the file system. These are the steps to remember:
void __fastcall WMDropFiles(TWMDropFiles &Message);
BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFiles) END_MESSAGE_MAP(TForm)
// Register this window with the OS as a drop target. DragAcceptFiles(this->Handle, true);
// Unregister this window with the OS as a drop target. DragAcceptFiles(this->Handle, false);
/*
Handler for the WM_DROPFILES message from Windows.
*/
void __fastcall TfrmMain::WMDropFiles(TWMDropFiles &Message)
{
int num_files, filename_length;
char file_name[MAX_PATH + 1];
// Refer to the Win SDK documentation about the details
// of DragQueryFile and the HDROP structure
// Get the number of files that are being dropped on the window
num_files = DragQueryFile((HDROP)Message.Drop, -1, NULL, 0);
// Unlikely to happen
if (num_files < 1)
return;
// Retrieve each filename that was dropped
for(int i = 0; i < num_files; i++)
{
// Get the length of the i'th filename
filename_length = DragQueryFile((HDROP)Message.Drop, i, NULL, 0);
// Retrieve the filename from the HDROP structure
DragQueryFile((HDROP)Message.Drop, i, file_name, filename_length + 1);
// Reset the grid
Init();
// Read in the data
ImportMapData(file_name);
// Update the UI
short r = FRows;
short c = FColumns;
spnRows->Position = r;
spnColumns->Position = c;
// We can only deal with one at this point so bail out.
// If we could handle multiple files, we would loop through all of them.
return;
}
}
You can put this code anywhere. The obvious place is to make a Help menu that has an "About..." choice. When the user selects it, the dialog should be displayed. (See the project for details.) Also, if you want the dialog box to be non-modal, call the Show() method instead of ShowModal().AboutBox->ShowModal();
Exercises