![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Newbie
Join Date: Mar 2006
Posts: 7
Rep Power: 0
![]() |
Problem with GetOpenFileName buffer too small.
I have written a DLL for a Delphi application I am making and decided to have the Open/Save dialog
functionality within an external DLL instead of inside the application. The problem is I have to hard code the buffer which makes the DLL much larger then it should be. I have read on MSDN about this problem but it really does not help as I am not too proficient with C++ in general as I only use it when I need it. I have found plenty of article about this issue but they only explain how to solve it using MFC with VS. I am however using Dev-CPP enviroment. Here is the function source: std::string OpenSaveDialog(int Open, char* InitDir)
{
OPENFILENAME ofn;
char szFileName[21000] = "";
string FData("");
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = 21000;
switch(Open)
{
case 0: break;
case 1:
ofn.lpstrFilter = "All Supported Files\0*.mp3;*.mp2;*.wav;*.wma;*.mid;*.ogg\0";
ofn.lpstrInitialDir = InitDir;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT;
if (GetOpenFileName(&ofn))
{
int len = strlen(ofn.lpstrFile);
if( ofn.lpstrFile[len + 1] == 0) { return ofn.lpstrFile; } // If single file was selected.
else {
// This is the directory.
FData = ofn.lpstrFile;
ofn.lpstrFile += len + 1;
while(ofn.lpstrFile[0]) {
// This will contain the current file name from multiple selection.
FData = FData + "|" + ofn.lpstrFile;
// Find next name
len = strlen(ofn.lpstrFile);
ofn.lpstrFile += len + 1;
}
return FData;
}
}
else { return "CANCEL"; }
break;
case 2:
ofn.lpstrFilter = "All Supported Files\0*.sm3l;*.sm3;*.m3u;*.pls\0";
ofn.lpstrInitialDir = InitDir;
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "sm3l";
if (GetOpenFileName(&ofn)) { return ofn.lpstrFile; }
else { return "CANCEL"; }
break;
case 3:
ofn.lpstrFilter = "SM3 format\0*.sm3\0M3U Format\0*.m3u\0PLS Format\0*.pls\0";
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
ofn.lpstrDefExt = "sm3l";
if (GetSaveFileName(&ofn)) { return ofn.lpstrFile; }
else { return "CANCEL"; }
}
}Does anyone know how to solve this issue? From what I read on MSDN I need some sort of callback function to resize the buffer if necessary and read something about calling it twice..... |
|
|
|
|
|
#2 | |
|
Programming Guru
![]() Join Date: Jun 2005
Location: elemental plane
Posts: 1,429
Rep Power: 5
![]() |
Quote:
Or why not increase the size of the buffer (using the keyword new) while the GetOpenFileName function returns FALSE. You will have to check what error returns, you can do so with the CommDlgExtendedError function, you are looking for the FNERR_BUFFERTOOSMALL error code.
__________________
"Employ your time in improving yourself by other men's writings, so that you shall gain easily what others have labored hard for." -- Socrates |
|
|
|
|
|
|
#3 |
|
Newbie
Join Date: Mar 2006
Posts: 7
Rep Power: 0
![]() |
Why 21000? because it's just long enough for 100 files each with a character length of 100 plus the length of the directory and any additional spacing or added characters by me for easier parsing.
I already know I get the buffer to small error, It doesn't need any checking. |
|
|
|
|
|
#4 |
|
Programming Guru
![]() Join Date: Jun 2005
Location: elemental plane
Posts: 1,429
Rep Power: 5
![]() |
Sorry, I missed the multiple files part. Just increase the size of the buffer by catching the CDN_SELCHANGE Notification, which is received by your OFNHookProc hook procedure. Easy as Dell.
__________________
"Employ your time in improving yourself by other men's writings, so that you shall gain easily what others have labored hard for." -- Socrates |
|
|
|
|
|
#5 |
|
Newbie
Join Date: Mar 2006
Posts: 7
Rep Power: 0
![]() |
Sorry to be bothersome but if you have the time to make up an example for me it would be greatly appreciated. I'm used to handling all this stuff in Delphi and there's still quite a bit I haven't picked up yet.
|
|
|
|
|
|
#6 |
|
Programming Guru
![]() Join Date: Jun 2005
Location: elemental plane
Posts: 1,429
Rep Power: 5
![]() |
Well I don't know if this works as I haven't tested fed it to the compiler and never done it before, but here goes anyway:
std::string OpenSaveDialog(int Open, char* InitDir)
{
OPENFILENAME ofn;
char * szFileName = NULL;
string FData("");
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = 21000;
ofn.lpfnHook = OFNHookProc;
switch(Open)
{
case 0:
break;
case 1:
ofn.lpstrFilter = "All Supported Files\0*.mp3;*.mp2;*.wav;*.wma;*.mid;*.ogg\0";
ofn.lpstrInitialDir = InitDir;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT;
if (GetOpenFileName(&ofn))
{
int len = strlen(ofn.lpstrFile);
if( ofn.lpstrFile[len + 1] == 0)
{
return ofn.lpstrFile;
} // If single file was selected.
else
{
// This is the directory.
FData = ofn.lpstrFile;
ofn.lpstrFile += len + 1;
while(ofn.lpstrFile[0])
{
// This will contain the current file name from multiple selection.
FData = FData + "|" + ofn.lpstrFile;
// Find next name
len = strlen(ofn.lpstrFile);
ofn.lpstrFile += len + 1;
}
return FData;
}
}
else
{
return "CANCEL";
}
break;
case 2:
ofn.lpstrFilter = "All Supported Files\0*.sm3l;*.sm3;*.m3u;*.pls\0";
ofn.lpstrInitialDir = InitDir;
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "sm3l";
if(GetOpenFileName(&ofn))
{
return ofn.lpstrFile;
}
else
{
return "CANCEL";
}
break;
case 3:
ofn.lpstrFilter = "SM3 format\0*.sm3\0M3U Format\0*.m3u\0PLS Format\0*.pls\0";
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
ofn.lpstrDefExt = "sm3l";
if (GetSaveFileName(&ofn)) { return ofn.lpstrFile; }
else
{
return "CANCEL";
}
break;
}
}
UINT CALLBACK OFNHookProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
UINT neededSize;
switch(message)
{
case WM_INITDIALOG:
if(!SetProp(GetParent(hDlg), "OFN", (void *)lParam))
{
MessageBox(NULL, "SET PRop Failed", "ERROR", MB_OK);
}
break;
case WM_NOTIFY:
OFNOTIFY* lpof = (OFNOTIFY*)lParam;
if(lpof->hdr.code == CDN_SELCHANGE)
{
neededSize = CommDlg_OpenSave_GetSpec(GetParent(hDlg), NULL, 0);
neededSize += MAX_PATH;
pOfn = (LPOPENFILENAME)GetProp(GetParent(hDlg), "OFN");
if(pOfn->nMaxFile < neededSize)
{
if(pOfn->lpstrFile == NULL)
{
pOfn->lpstrFile = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, neededSize);
}
else
{
pOfn->lpstrFile = (LPTSTR)HeapReAlloc(GetProcessHeap(), 0, pOfn->lpstrFile, neededSize);
}
if(pOfn->lpstrFile != NULL)
{
pOfn->lpstrFile[0] = '\0';
pOfn->nMaxFile = neededSize;
}
}
}
break;
case WM_DESTROY:
RemoveProp(GetParent(hDlg), "OFN");
break;
}
}
return 0;
}
__________________
"Employ your time in improving yourself by other men's writings, so that you shall gain easily what others have labored hard for." -- Socrates |
|
|
|
|
|
#7 |
|
Newbie
Join Date: Mar 2006
Posts: 7
Rep Power: 0
![]() |
Dev-CPP is giving me quite a few compile errors.....
OFNHookProc Undeclared(first use this function) `pOfn` undeclared(first use this function) jump to case label crosses initalization of `OFNOTIFY*lpof` Err yeah there's more but Iv'e never had alot of these errors so i'm clueless. EDIT: Putting the OFNHookProc above my function gets rid of a couple of errors but most remain. |
|
|
|
|
|
#8 | |||
|
Hobbyist
Join Date: Sep 2005
Posts: 259
Rep Power: 3
![]() |
Quote:
Quote:
LPOPENFILENAME pOfn = (LPOPENFILENAME)GetProp(GetParent(hDlg), "OFN"); Quote:
|
|||
|
|
|
|
|
#9 |
|
Newbie
Join Date: Mar 2006
Posts: 7
Rep Power: 0
![]() |
I still can't seem to get it to compile without complaining about alot of stuff.
This is a DLL not a normal Win32 application, there's no windows or anything like that created so the DLL doesn't really have a handle I suppose.... The two functions in this DLL aren't defined at the top of the file or anything, there just in my .h file for exporting. And i'm just going to say this again but the only experience I have with C++ is writing extremely basic DLL's and a base Win32 GUI. Everything else iv'e done in either Visual Basic or for the last year and a half Borland Delphi. |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|