GetOpenFileName() und multiselection - Es haut nicht hin
-
Hi!
Ich bekomm es einfach nicht hin. Die Vergrößerung des buffers scheint sich nie auszuwirken. Es funktioniert nur bis zur initialen Buffergröße. Wenn darüber, steht in openFileName.lpstrFile nur noch ein komisches Zeichen (Wahrscheinlich die neue Größe weil FNERR_BUFFERTOOSMALL, wie MSDN beschreibt).
Aber mit dem DialogHook() sollte doch dynamisch vergrößert werden und dieser FNERR gar nicht mehr auftreten?!Daran hab ich mich gehalten: http://support.microsoft.com/?scid=kb%3Ben-us%3B131462&x=4&y=11
LPTSTR lpsz = 0; lpsz = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 50); OPENFILENAME openFileName = { sizeof(OPENFILENAME) }; openFileName.hwndOwner = dialogHandle; openFileName.Flags = OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_DONTADDTORECENT | OFN_NONETWORKBUTTON | OFN_HIDEREADONLY; openFileName.lpstrFilter = "All Files\0*.*\0\0"; openFileName.lpstrFile = lpsz; openFileName.nMaxFile = 50; // Initialgröße openFileName.lpfnHook = DialogHook; openFileName.lCustData = (LPARAM)&openFileName; int res = GetOpenFileName(&openFileName); if(!res && CommDlgExtendedError() == FNERR_BUFFERTOOSMALL) Beep(200, 100); /* Es Beept bei Pfaden+Namen > 50 Bytes. Dabei sollte doch dynamisch vergrößert werden. Was ist da los? */ /* openFileName.nMaxFile ist hier dann allerdings auch größer als 50. */
unsigned int __stdcall DialogHook(HWND windowHandle, unsigned message, WPARAM wParam, LPARAM lParam) { // Wird alles aufgerufen! Und cbLength scheint zu stimmen! switch(message) { case WM_INITDIALOG: { SetProp(GetParent(windowHandle), "OFN", (void*)lParam); return false; } case WM_NOTIFY: { LPOFNOTIFY lpofn = (LPOFNOTIFY)lParam; if(lpofn->hdr.code == CDN_SELCHANGE) { LPOPENFILENAME lpofn; int cbLength = CommDlg_OpenSave_GetSpec(GetParent(windowHandle), 0, 0); cbLength += _MAX_PATH; lpofn = (LPOPENFILENAME)GetProp(GetParent(windowHandle), "OFN"); if(lpofn->nMaxFile < cbLength) { if(lpsz) HeapFree(GetProcessHeap(), 0, lpsz); lpsz = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbLength); if (lpsz) { lpofn->lpstrFile = lpsz; lpofn->nMaxFile = cbLength; } } } return false; } case WM_DESTROY: { RemoveProp(GetParent(windowHandle), "OFN"); return false; } } return false; }
-
nicht gut:
OPENFILENAME openFileName = { sizeof(OPENFILENAME) };
besser:
OPENFILENAME openFileName; memset(&openFileName, 0, sizeof(OPENFILENAME)); openFileName.lStructSize = sizeof(OPENFILENAME); : : :
-
Ist doch dasselbe.
-
Das ist Faulenzercode. lStructSize wird zwar richtig inizialisiert, aber der Rest nicht auf 0 gesetzt, aber ok jeder so wie ers gelernt hat.
-
...... schrieb:
lStructSize wird zwar richtig inizialisiert, aber der Rest nicht auf 0 gesetzt, aber ok jeder so wie ers gelernt hat.
Genau. Aber jeder sollte auch das, was er gelernt hat, bei Gelegenheit überprüfen.
-
...... schrieb:
Das ist Faulenzercode. lStructSize wird zwar richtig inizialisiert, aber der Rest nicht auf 0 gesetzt, aber ok jeder so wie ers gelernt hat.
Deine Aussage ist falsch!
Ich kann mich dem Rat vom MFK nur anschließen!
-
Du hast das hier vergessen :
WNDPROC* g_lpfnDialogProc =NULL;
-
Martin Richter schrieb:
...... schrieb:
Das ist Faulenzercode. lStructSize wird zwar richtig inizialisiert, aber der Rest nicht auf 0 gesetzt, aber ok jeder so wie ers gelernt hat.
Deine Aussage ist falsch!
Ich kann mich dem Rat vom MFK nur anschließen!Bist Du dir sicher?
Das da:
OPENFILENAME openFileName = { sizeof(OPENFILENAME) };
definiert offensichtlich eine lokale Variable. Ich kann mich nicht daran erinnern, daß der Standard vorschreibt, daß lokale Variablen vom Compiler mit 0 initialisiert werden müssen.
mfg Martin
-
Der Thread ist über ein Jahr alt.
Ich habe ich nur den C++-Standard (n3290) - ein Auszug aus 8.5.1 (7)
If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member
not explicitly initialized shall be initialized from an empty initializer list (8.5.4). [ Example:
struct S { int a; const char* b; int c; };
S ss = { 1, "asdf" };
initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form int(), that
is, 0. —end example ]-> vom Standard gedeckt.
-
Fällt mir gerade erst auf:
Ich habe hier
-> Hier habe ich
-> Ich habe ich
-
Thorgrim schrieb:
Der Thread ist über ein Jahr alt.
Ich habe ich nur den C++-Standard (n3290) - ein Auszug aus 8.5.1 (7)
If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member
not explicitly initialized shall be initialized from an empty initializer list (8.5.4). [ Example:
struct S { int a; const char* b; int c; };
S ss = { 1, "asdf" };
initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form int(), that
is, 0. —end example ]-> vom Standard gedeckt.
Wir sind aber hier im WinAPI-unterforum und von C++ war bisher nicht die Rede.
mfg Martin
-
Naja, im C99-Draft (6.7.8)
21 If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
Und komm' jetzt bitte nicht damit, dass dies C99 ist
(einen C89-Draft habe ich nicht gefunden, habe aber auch nicht sonderlich lange gesucht).