Reputation: 41
I have C++ code to show dialog chooser file. I want to the user can only chooser type file specified. My dialog can show type file specified but the user can input other type file in File name like my picture
So, how can I make the user only input File name and search type file specified in lpstrFilter
? OR Can i disable File name box?
This is my code:
const wchar_t* ChooserFile(const char* typeFile)
{
try
{
ZeroMemory( &sfn , sizeof( sfn));
sfn.lStructSize = sizeof ( sfn );
sfn.hwndOwner = NULL ;
wchar_t w_syFile[MAX_PATH];
//mbstowcs(w_syFile, syFile, strlen(syFile)+1);//Plus null
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, w_syFile, MAX_PATH, syFile, _TRUNCATE);
sfn.lpstrFile = w_syFile ;
sfn.lpstrFile[0] = _T('\0');
sfn.nMaxFile = sizeof( syFile );
//TypeFile
sfn.lpstrFilter = TEXT("Microsoft Office Word Documents (*.xlsx)\0*.XLSX\0");
sfn.nFilterIndex =1;
sfn.lpstrFileTitle = NULL ;
sfn.nMaxFileTitle = 0 ;
sfn.lpstrInitialDir=NULL;
//sfn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT|OFN_EXPLORER | OFN_ENABLEHOOK ;
sfn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_NOVALIDATE|OFN_HIDEREADONLY ;
if (GetOpenFileName( &sfn ) != TRUE)
{
wstrPathFile = TEXT("");
return wstrPathFile.c_str();
}
DWORD retval=0;
//BOOL success;
TCHAR buffer[BUFSIZE]=TEXT("");
TCHAR buf[BUFSIZE]=TEXT("");
TCHAR** lppPart={NULL};
wchar_t wstrPath[BUFSIZE];
retval = GetFullPathNameW(sfn.lpstrFile,sfn.nMaxFile,wstrPath,lppPart);
if (retval==0)
{
wstrPathFile = TEXT("");
return wstrPathFile.c_str();
}
std::wstring s(wstrPath);
wstrPathFile = s;
wcout<<wstrPathFile<<endl;
return wstrPathFile.c_str();
}
catch (...)
{
PrintToFile("ChooserFile","Error");
wstrPathFile = TEXT("");
return wstrPathFile.c_str();
}
}
Upvotes: 4
Views: 9984
Reputation: 598031
Your code is commenting out the OFN_EXPLORER
and OFN_ENABLEHOOK
flags, so you must already know about the existence of Explorer-style hooking. As others have told you, you can use that hook to catch the CDN_FILEOK
notification to accept/reject a selected filename. For example:
UINT_PTR CALLBACK MyOFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
if (uiMsg == WM_NOTIFY)
{
LPOFNOTIFY ofn = (LPOFNOTIFY) lParam;
if (ofn->hdr.code == CDN_FILEOK)
{
LPOPENFILENAMEW lpOFN = (LPOPENFILENAMEW) ofn->lpOFN;
LPWSTR lpExt = PathFindExtensionW(lpOFN->lpstrFile);
if (lstrcmpiW(lpExt, L".XLSX") != 0)
{
SetWindowLongPtr(hdlg, DWL_MSGRESULT, 1);
return 1;
}
}
}
return 0;
}
std::wstring ChooserFile(const char* typeFile)
{
OPENFILEAMEW sfn = {0};
wchar_t w_syFile[MAX_PATH+1] = {0};
size_t convertedChars = 0;
sfn.lStructSize = sizeof(sfn);
sfn.hwndOwner = NULL;
mbstowcs_s(&convertedChars, w_syFile, MAX_PATH, syFile, _TRUNCATE);
sfn.lpstrFile = w_syFile;
sfn.nMaxFile = MAX_PATH;
//TypeFile
sfn.lpstrFilter = L"Microsoft Office Word Documents (*.xlsx)\0*.XLSX\0";
sfn.nFilterIndex = 1;
sfn.lpstrFileTitle = NULL;
sfn.nMaxFileTitle = 0;
sfn.lpstrInitialDir = NULL;
sfn.lpfnHook = &MyOFNHookProc;
sfn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOVALIDATE | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK;
if (!GetOpenFileNameW(&sfn))
return L"";
WCHAR szPath[MAX_PATH+1] = {0};
DWORD retval = GetFullPathNameW(sfn.lpstrFile, MAX_PATH, szPath, NULL);
if ((retval == 0) || (retval > MAX_PATH))
return L"";
std::wstring wstrPath(szPath, retval);
std::wcout << wstrPath << endl;
return wstrPath;
}
Upvotes: 0
Reputation: 613461
I want to the user can only chooser type file specified.
You can't stop the user choosing whatever file they like by typing into the file name edit control. So, you should simply let them do that and instead validate that the file name matches your requirements.
You have a couple of options to do that:
lpfnHook
member of the OPENFILENAME
struct. That will get sent a CDN_FILEOK
notification message when the user attempts to accept a file. Perform your validation in response to that message. If the file name does not meet requirements, show a message to that effect and return a non-zero value to force the dialog to remain open.Upvotes: 4