Common Dialogs
Windows provides a set of built-in dialog boxes (often referred to as "Common Dialogs") that handle frequently used functionality such as opening and saving files, selecting folders, picking colors, etc. These dialogs typically require you to fill out and pass a corresponding structure, which they then use to display a standardized UI and return relevant data. This page will cover some of the dialogs used commonly in gamedev.
Each dialog has its own function, structure, and flags, but they all follow a similar pattern: create and populate the structure, call the function, and handle the user's input (or canceled operation). Let's take a look at these in action.
Open File
The Open File Dialog allows users to select a file to open. Internally, this is implemented using the
GetOpenFileNameA
function from the Windows Common Dialog Box Library. You fill out an
OPENFILENAMEA
structure, specifying filters, default paths, flags (like requiring the file to exist),
and a buffer to store the result.
In the following example, the OPENFILENAMEA
structure stores the user's file choice in the
fileName
buffer. If the user cancels the operation,
GetOpenFileNameA
returns FALSE
.
#include <windows.h> #include <commdlg.h> #include <stdio.h> void main() { char fileName[MAX_PATH] = ""; OPENFILENAMEA ofn = { 0 }; ofn.lStructSize = sizeof(OPENFILENAMEA); ofn.hwndOwner = NULL; ofn.lpstrFilter = "Text Files\0*.txt\0All Files\0*.*\0"; ofn.lpstrFile = fileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; if (GetOpenFileNameA(&ofn)) { printf("Selected file: %s\n", fileName); } else { printf("No file selected.\n"); } }
Save File
The Save File Dialog is similar, but uses GetSaveFileNameA
. This dialog is typically
used to prompt the user for a location and file name where you can save data. You can provide different
flags such as OFN_OVERWRITEPROMPT
to warn users if they're about to overwrite an existing file.
#include <windows.h> #include <commdlg.h> #include <stdio.h> void main() { char fileName[MAX_PATH] = ""; OPENFILENAMEA ofn = { 0 }; ofn.lStructSize = sizeof(OPENFILENAMEA); ofn.hwndOwner = NULL; ofn.lpstrFilter = "Text Files\0*.txt\0All Files\0*.*\0"; ofn.lpstrFile = fileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_OVERWRITEPROMPT; if (GetSaveFileNameA(&ofn)) { printf("File to save: %s\n", fileName); } else { printf("Save operation canceled.\n"); } }
Open Folder
The Open Folder Dialog helps users pick a directory rather than a file. Older code often uses
SHBrowseForFolderA
for this. You fill out the BROWSEINFOA
structure, which describes
the dialog's title and flags.
When the user hits OK, SHBrowseForFolderA
returns an item id list LPITEMIDLIST
that references the chosen folder. That needs to be converted it into a normal file path using SHGetPathFromIDListA
.
#include#include #include void main() { char folderPath[MAX_PATH] = ""; BROWSEINFOA bi = { 0 }; bi.lpszTitle = "Select a folder:"; bi.ulFlags = BIF_RETURNONLYFSDIRS; LPITEMIDLIST pidl = SHBrowseForFolderA(&bi); if (pidl) { SHGetPathFromIDListA(pidl, folderPath); printf("Selected folder: %s\n", folderPath); CoTaskMemFree(pidl); } else { printf("No folder selected.\n"); } }
SHBrowseForFolderA
can feel a bit dated. In newer applications, you might
consider modern shell APIs, but this approach still works in many Win32 tools and games.
Color Picker
For selecting a color, Win32 provides the ChooseColorA
dialog. You prepare a
CHOOSECOLORA
structure, supply an optional array for custom colors, then call
ChooseColorA
. The user can pick a color, or cancel.
#include <windows.h> #include <commdlg.h> #include <stdio.h> void main() { CHOOSECOLORA cc = { 0 }; COLORREF acrCustClr[16] = { 0 }; cc.lStructSize = sizeof(CHOOSECOLORA); cc.hwndOwner = NULL; cc.lpCustColors = acrCustClr; cc.Flags = CC_FULLOPEN | CC_RGBINIT; if (ChooseColorA(&cc)) { printf("Selected color: 0x%06X\n", cc.rgbResult); } else { printf("Color selection canceled.\n"); } }
Here, cc.rgbResult
will hold the RGB color chosen by the user, and
acrCustClr
stores 16 custom colors that the user can adjust in the UI.