Tout d'abord, vous devrez remplacer la fonction CDocument
qui gère l'ouverture de nouveaux fichiers; c'est probablement l'un des CDocument::OnNewDocument
ou CDocument::OnOpenDocument
. Je l'ai aussi fait dans le passé en ajoutant la carte de message suivant à CMainFrame
, pas sûr que l'un de la méthode correcte est:
ON_COMMAND(ID_FILE_OPEN, &CMainFrame::OnFileOpen)
Ensuite, pour afficher une boîte de dialogue Nouveau fichier personnalisé, utilisez la fonction WINAPI GetOpenFileName
. Notez que vous devez utiliser cette fonction, CFileDialog
du MFC ne fonctionnera pas. Voici un extrait de code de la fonction CMainFrame::OnFileOpen
I énuméré ci-dessus dans la carte du message:
/**
* Hook procedure for OPENFILENAME structure. This function processes messages from the custom
* controls added to the standard "Open File" dialog.
*
* @param [in] hdlg
* handle of the hdlg.
* @param [in] uiMsg
* message describing the user interface.
* @param [in] wParam
* the wParam field of the message.
* @param [in] lParam
* the lParam field of the message.
*
* @return If the return value is zero, the default dialog box procedure processes the message;
* otherwise it ignores the message.
*/
UINT_PTR CALLBACK OpenHexFileHook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
(void)(wParam);
if(!::IsWindow(hdlg)) {
return 0;
}
switch(uiMsg) {
case WM_NOTIFY:
/* Sent when an event occurs or the custom controls require information */
{
LPOFNOTIFY pOfnNotify = (LPOFNOTIFY)lParam;
if(pOfnNotify == NULL) {
return 0;
}
CWinApp *app = AfxGetApp();
switch(pOfnNotify->hdr.code) {
case CDN_INITDONE:
/* Sent when the system has finished arranging the controls in the dialog box */
{
CString rv;
LRESULT idx;
/* Configure the Hex file format ComboBox */
HWND hHexFmt = GetDlgItem(hdlg, IDC_HEX_FILE_FORMAT);
ASSERT(hHexFmt);
/* Clear existing content */
::SendMessage(hHexFmt, CB_RESETCONTENT, 0, 0);
/* Add new items to the list */
::SendMessage(hHexFmt, CB_ADDSTRING, 0, (LPARAM)_T("INTEL 32"));
::SendMessage(hHexFmt, CB_ADDSTRING, 0, (LPARAM)_T("INTEL 16"));
::SendMessage(hHexFmt, CB_ADDSTRING, 0, (LPARAM)_T("INTEL 8"));
/* Read user's last selection from registry */
rv = app->GetProfileString(_T("Settings"), _T("HexFormat"), _T("INTEL 32"));
idx = ::SendMessage(hHexFmt, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)((LPCTSTR)rv));
if(idx == CB_ERR) {
/* On error select the first item */
idx = 0;
}
/* Set current selection to the previously selected item's index */
::SendMessage(hHexFmt, CB_SETCURSEL, idx, 0);
/* Configure the Bytes per address ComboBox */
HWND hBytePerLoc = GetDlgItem(hdlg, IDC_BYTES_PER_ADDR);
ASSERT(hBytePerLoc);
/* Clear existing content */
::SendMessage(hBytePerLoc, CB_RESETCONTENT, 0, 0);
/* Add new items to the list */
::SendMessage(hBytePerLoc, CB_ADDSTRING, 0, (LPARAM)_T("1"));
::SendMessage(hBytePerLoc, CB_ADDSTRING, 0, (LPARAM)_T("2"));
::SendMessage(hBytePerLoc, CB_ADDSTRING, 0, (LPARAM)_T("4"));
/* Read user's last selection from registry */
rv = app->GetProfileString(_T("Settings"), _T("BytesPerAddr"), _T("1"));
idx = ::SendMessage(hBytePerLoc, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)((LPCTSTR)rv));
if(idx == CB_ERR) {
/* On error select the first item */
idx = 0;
}
/* Set current selection to the previously selected item's index */
::SendMessage(hBytePerLoc, CB_SETCURSEL, idx, 0);
break;
}
case CDN_FILEOK:
/* Sent when the user specifies a file name and clicks the OK button */
{
/* Save user selection for the Hex file format ComboBox */
HWND hHexFmt = GetDlgItem(hdlg, IDC_HEX_FILE_FORMAT);
ASSERT(hHexFmt);
/* Get current selection's index */
LRESULT idx = ::SendMessage(hHexFmt, CB_GETCURSEL, 0, 0);
if(idx != CB_ERR) {
/* Get current selection's text length */
LRESULT len1 = ::SendMessage(hHexFmt, CB_GETLBTEXTLEN, idx, 0);
if(len1 != CB_ERR) {
TCHAR *text = new TCHAR[len1 + 1];
/* Get current selection's text */
LRESULT len2 = ::SendMessage(hHexFmt, CB_GETLBTEXT, idx, (LPARAM)text);
if(len1 == len2) {
/* Write string to registry */
app->WriteProfileString(_T("Settings"), _T("HexFormat"), text);
}
delete[] text;
}
}
/* Save user selection for the Bytes per address ComboBox */
HWND hBytePerLoc = GetDlgItem(hdlg, IDC_BYTES_PER_ADDR);
ASSERT(hBytePerLoc);
/* Get current selection's index */
idx = ::SendMessage(hBytePerLoc, CB_GETCURSEL, 0, 0);
if(idx != CB_ERR) {
/* Get current selection's text length */
LRESULT len1 = ::SendMessage(hBytePerLoc, CB_GETLBTEXTLEN, idx, 0);
if(len1 != CB_ERR) {
TCHAR *text = new TCHAR[len1 + 1];
/* Get current selection's text */
LRESULT len2 = ::SendMessage(hBytePerLoc, CB_GETLBTEXT, idx, (LPARAM)text);
if(len1 == len2) {
/* Write string to registry */
app->WriteProfileString(_T("Settings"), _T("BytesPerAddr"), text);
}
delete[] text;
}
}
break;
}
default:
/* Do nothing */
break;
}
break;
}
default:
/* Do nothing */
break;
}
return 0;
}
void CMainFrame::OnFileOpen()
{
std::basic_string<TCHAR> filterSpec;
/* Use *.hex filter */
filterSpec = _T("Hex Files (*.hex)");
filterSpec += (std::basic_string<TCHAR>::value_type)'\0';
filterSpec += _T("*.hex");
filterSpec += (std::basic_string<TCHAR>::value_type)'\0';
OPENFILENAME ofn = { sizeof(ofn) };
TCHAR filePath[MAX_PATH] = { 0 };
TCHAR fileTitle[MAX_PATH] = { 0 };
ofn.hwndOwner = AfxGetMainWnd()->GetSafeHwnd();
ofn.hInstance = AfxGetInstanceHandle();
ofn.lpstrFilter = filterSpec.c_str();
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = filePath;
ofn.nMaxFile = sizeof(filePath)/sizeof(TCHAR);
ofn.lpstrFileTitle = fileTitle;
ofn.nMaxFileTitle = sizeof(fileTitle)/sizeof(TCHAR);
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = _T("Select Intel HEX file");
ofn.Flags = OFN_ENABLETEMPLATE | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST |
OFN_EXPLORER | OFN_ENABLESIZING | OFN_DONTADDTORECENT |
OFN_HIDEREADONLY | OFN_ENABLEHOOK;
ofn.lpstrDefExt = _T("hex");
ofn.lCustData = NULL;
ofn.lpfnHook = OpenHexFileHook;
ofn.lpTemplateName = MAKEINTRESOURCE(IDD_HEX_FILE_OPEN);
ofn.FlagsEx = 0;
if(GetOpenFileName(&ofn) != false) {
AfxGetApp()->m_pDocManager->OpenDocumentFile(ofn.lpstrFile);
SetTitle(ofn.lpstrFileTitle);
}
}
Dans ce projet, j'ai ajouté 2 ComboBoxes à la boîte de dialogue Ouvrir standard. These Les documents MSDN décrivent comment personnaliser les boîtes de dialogue standard. Ceci est le fichier de ressources (.rc2) personnalisation que je:
//
// HexViewer.RC2 - resources Microsoft Visual C++ does not edit directly
//
#ifdef APSTUDIO_INVOKED
#error this file is not editable by Microsoft Visual C++
#endif //APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// Add manually edited resources here...
/////////////////////////////////////////////////////////////////////////////
//
// File Open Dialog Template
//
IDD_HEX_FILE_OPEN DIALOGEX 0, 0, 370, 40
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
LTEXT "&HEX file format:", IDC_HEX_FILE_FORMAT_TEXT, 67, 2, 58, 8, SS_NOTIFY
COMBOBOX IDC_HEX_FILE_FORMAT, 130, 0, 164, 100,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "&Bytes per address:", IDC_BYTES_PER_ADDR_TEXT, 67, 20, 63, 8, SS_NOTIFY
COMBOBOX IDC_BYTES_PER_ADDR, 130, 18, 164, 100,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
END
/////////////////////////////////////////////////////////////////////////////
Notez que cette méthode de personnalisation est recommandé que si vous programmez pour les versions Windows XP et plus. À partir de Vista MS recommande l'utilisation de l'API Common Item Dialog pour la personnalisation, mais je n'ai jamais utilisé cela.