Created attachment 856 [details] В вайне Соответственно при нажатии на кнопку «ОК» происходит переход на уровень выше, т.к. папка с базой не выбрана (нужен стандартный OpenFileDialog без OFN_EXPLORER). См.скрины. При установке программы выбрать «Сетевая с локальным ключом».
Created attachment 857 [details] В винде
Ошибка воспроизвелась. Используется функция GetOpenFileNameA которая вызывает GetFileName31A
шаблон диалога загружается с помощью: hResInfo = FindResourceA(priv->ofnA->hInstance, priv->ofnA->lpTemplateName, (LPSTR)RT_DIALOG); структура priv->ofnA заполняется при инициализации FD32_Init и берётся она из priv->ofnA = (LPOPENFILENAMEA) lParam; инициализация вызывается из функции FD31_AllocPrivate, а в качестве lParam туда передаётся lpofn. Таким образом шаблон должен браться изlpofn->lpTemlateName, Проверил, при вызове диалога этот параметр не NULL Если я правильно понял, то этот диалог берётся из ресурсов самой программы
сообщения диалога обрабатываются в функции FD31_WMCommand При нажатии ОК вызывается FD31_Validate, которая проверяет выбрано ли правильное имя файла. Если да, то закрывает диалог. В данном случае при нажатии ОК диалог никогда не закроется т.к файл не выбран.
Если FD31_Validate не вызывать, то диалог закрывается, но вместе с ним закрывается и сама программа. Возможно, что возвращается ошибка или пустой путь. Надо писать тест.
Имя файла заносится в соответствующую структуру только при выборе файла. Для контрола directoryList обрабатывается событие LBN_DBLCLK, но при этом также результат не отражается на выходной структуре. Дописал в обработку события LBN_DBLCLK добавление выбранного пути. Теперь lfs->ofnW->lpstrFile добавляется полный путь. Проверил, при нажатии на ОК, перед закрытием диалога путь сохраняется, но программа по-прежнему закрывается при нажатии на ОК. Без теста тут не обойтись.
Можно использовать стандартный тест, лежащий в programs/cmdlgtst для отображения диалога в стиле win31 надо чтобы 1 из флагов (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE) был выставлен.
Тест показал, что после закрытия поле, где должно содержаться имя файла - пустое, хотя перед закрытием диалога там содержится (проверял!) имя выбранной директории. Если при нажатии на ОК всё-таки вызывать FD31_Validate, то результат нормально возвращается, но диалог завершается только при выборе директории. Проблема в проверке полученного файла функцией FD31_TestPath(): При выборе директории она возвращает false, затем FD31_Validate возвращает false, и диалог не завершается. В тесте в эту функцию передаётся filename = '*.*'; Можно не возвращать в FD31_Validate false при неправильном завершении FD31_TestPath(), если filename = '*.*' После данного исправления, тест начинает нормально работать: При нажатии на ОК возвращается выбранная директория. Но сама программа не работает. В этом месте filename = ''; Воспроизвести такую ситуацию на тесте при выставлении различных флагов не удаётся
Необходимо проверить как ведёт себя данный диалог в Windows. Для этого необходимо дописать тестовую программу, и скомпиллировать её для запуска под Windows.
Взял тест из programs/cmdlgtst, урезал его так, чтобы остался только тест на диалог открытия файла. Дописал вывод дополнительных параметров. Проверил на win2k3. Выбрать папку не получается! пробовал ставить различные флаги - папка всё-равно не выбирается, только файлы. Необходимо посмотреть с какими флагами вызывает этот диалог Инфо бухгалтер
флаги = 6240 или 0x1860 , что соответствует OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK
Пропробовал выставить такие же флаги (кроме OFN_ENABLETEMPLATE) - ничего не изменилось. Реализовал функцию нотификации в тесте. Теперь туда отправляются все сообщения из диалога открытия. Можно попробовать отлавливать только нужные, например выбор файлов, выбор папок, и нажатие на ОК, а остальные просто игнорировать. Можно также расшифровывать параметры данных сообщений, чтобы получить строки, содержащие название выбранного элемента А затем сравнить данные в wine и в Windows, но думаю это ни к чему не приведёт. При закрытии диалога программа как-то проверяет полученные данные, и найдя ошибку закрывается. Но что конкретно её не нравится определить не получается. Отправил разработчикам просьбу предоставить исходники.
На запрос исходников был получен ответ: >Как я уже описывал в сообшении о найденых ошибках (на всякий случай >посылаю его еще раз), в данном случае используется стандартный >OpenFileDialog без OFN_EXPLORER, если 2 раза щелкнуть на поле, где >должно отображаться дерево папок, выдается сообщение об ошибке 4104 в >функции GetOpenFileName, но база открывается и работать можно (если базы >в папке нет, она создается). Проверил на wine: действительно, по двойному щелчку на пустом месте в дереве папок выбирается именно нужная директория. Проверил на винде: ситуация противоположная: работает выбора бызы по OK и по двойному щелчку по названию папки, но не работает по двойному щелчку по пустому месту. Заметил ещё одну особенность между запуском диалога из инфобухгалтера и запуском в тесте под win2k3: Слева расположен список с файлами в текущей директории, а над списком редактируемое поле, содержащие имя файла. Такое поле есть при тестировании по win2k3, но его нет при вызове диалога из инфо-бухгалтер. (возможно причина в том, что инфобухгалтер использует свой шаблон диалога)
Ещё раз проверил поведение теста с диалогом в windows. Изменением параметров никак не удалось добиться того, чтобы диалог принимал директорию в качестве выбора пользователся. Отсюда вывод: стандартными средствами сделать это нельзя. Единственный способ (как мне кажется) это сделать - это ловить сообщения с помощью функции нотификации. При трейсе по каналу relay, получил довольно интересную активность функции нотификации (которая реализована в инфо-бухгалтере): fixme:commdlg:FD32_CallWindowProc Call hookA 0x3e1a0c (0x40060, 0400, 0000038d, 00000000----------------------) 0032:Call KERNEL32.GetCurrentDirectoryA(00000103,003ed158) ret=003e1a58 0032:Ret KERNEL32.GetCurrentDirectoryA() retval=00000018 ret=003e1a58 0032:Call KERNEL32.FindClose(ffffffff) ret=003e5bac 0032:Ret KERNEL32.FindClose() retval=00000000 ret=003e5bac 0032:Call KERNEL32.FindFirstFileA(0032e068 "C:\\IB\\ORN\\Ibw8NetL\\ARHIV\\ibw.dcf",0032dde0) ret=003e5d4e 0032:Ret KERNEL32.FindFirstFileA() retval=ffffffff ret=003e5d4e 0032:Call KERNEL32.GetLastError() ret=003e721a 0032:Ret KERNEL32.GetLastError() retval=00000002 ret=003e721a 0032:Call KERNEL32.FindResourceExA(003e0000,00000006,00000001,00000400) ret=003e2705 0032:Ret KERNEL32.FindResourceExA() retval=003f4130 ret=003e2705 0032:Call KERNEL32.LoadResource(003e0000,003f4130) ret=003e2715 0032:Ret KERNEL32.LoadResource() retval=003f4670 ret=003e2715 0032:Call KERNEL32.LockResource(003f4670) ret=003e2726 0032:Ret KERNEL32.LockResource() retval=003f4670 ret=003e2726 0032:Call KERNEL32.WideCharToMultiByte(000004e3,00000000,003f4674 L"База данных неопределенаНазвание базы: ",00000018,0032df68,000001ff,00000000,00000000) ret=003e275f 0032:Ret KERNEL32.WideCharToMultiByte() retval=00000018 ret=003e275f 0032:Call KERNEL32.FreeResource(003f4670) ret=003e2787 0032:Ret KERNEL32.FreeResource() retval=00000000 ret=003e2787 0032:Call KERNEL32.FindResourceExA(003e0000,00000006,00000001,00000400) ret=003e2705 0032:Ret KERNEL32.FindResourceExA() retval=003f4130 ret=003e2705 0032:Call KERNEL32.LoadResource(003e0000,003f4130) ret=003e2715 0032:Ret KERNEL32.LoadResource() retval=003f4670 ret=003e2715 0032:Call KERNEL32.LockResource(003f4670) ret=003e2726 0032:Ret KERNEL32.LockResource() retval=003f4670 ret=003e2726 0032:Call KERNEL32.WideCharToMultiByte(000004e3,00000000,003f46a6 L"Название базы: ",0000000f,0032df68,000001ff,00000000,00000000) ret=003e275f 0032:Ret KERNEL32.WideCharToMultiByte() retval=0000000f ret=003e275f 0032:Call KERNEL32.FreeResource(003f4670) ret=003e2787 0032:Ret KERNEL32.FreeResource() retval=00000000 ret=003e2787 0032:Call user32.SetDlgItemTextA(00040060,000007d1,003efd78 "\xcd\xe0\xe7\xe2\xe0\xed\xe8\xe5 \xe1\xe0\xe7\xfb: \xc1\xe0\xe7\xe0 \xe4\xe0\xed\xed\xfb\xf5 \xed\xe5\xee\xef\xf0\xe5\xe4\xe5\xeb\xe5\xed\xe0") ret=003e1afe 0032:Call window proc 0x7ee92190 (hwnd=0x40046,msg=WM_SETTEXT,wp=00000000,lp=003efd78) 0032:Call window proc 0x7ee46ee0 (hwnd=0x40060,msg=WM_CTLCOLORSTATIC,wp=0000030c,lp=00040046) 0032:Call dialog proc 0x7e96125d (hwnd=0x40060,msg=WM_CTLCOLORSTATIC,wp=0000030c,lp=00040046) 0032:Call user32.GetPropA(00040060,7e97a734 "FILEDLG_OFN") ret=7e961289 0032:Ret user32.GetPropA() retval=001916d8 ret=7e961289 fixme:commdlg:FD32_CallWindowProc Call hookA 0x3e1a0c (0x40060, 0138, 0000030c, 00040046----------------------) fixme:commdlg:FD32_CallWindowProc ret hookA 0x3e1a0c (0x40060, 0138, 0000030c, 00040046-----------------------) 0032:Ret dialog proc 0x7e96125d (hwnd=0x40060,msg=WM_CTLCOLORSTATIC,wp=0000030c,lp=00040046) retval=00000000 result=00000000 0032:Ret window proc 0x7ee46ee0 (hwnd=0x40060,msg=WM_CTLCOLORSTATIC,wp=0000030c,lp=00040046) retval=0000010c 0032:Ret window proc 0x7ee92190 (hwnd=0x40046,msg=WM_SETTEXT,wp=00000000,lp=003efd78) retval=00000001 0032:Ret user32.SetDlgItemTextA() retval=00000001 ret=003e1afe fixme:commdlg:FD32_CallWindowProc ret hookA 0x3e1a0c (0x40060, 0400, 0000038d, 00000000-----------------------)
Разобрался, чтобы начала работать клавиша ОК, необходимо при её нажатии посылать дополнительное сообщение в функцию нотификации. При добавлении: if (lfs->hook) { if (FD31_CallWindowProc(lfs, lfs->lbselchstring, lst2, MAKELONG(0,CD_LBSELCHANGE))) return TRUE; } инфо-бухгалтер начинает адекватно реагировать на нажатие ОК.
Патч отослал. Должен появиться в следующей сборке (сейчас сборка 34.1) Прошу протестировать
Протестировано. Патч исправляет проблему. Ждем новую сборку.