Не удается заставить DragAcceptFiles работать при использовании диалогового окна

#delphi #winapi #drag-and-drop #dialog

#delphi #winapi #перетаскивание #диалоговое

Вопрос:

Я использую Delphi для написания кода простого приложения, которое должно принимать добавленные в него имена каталогов. Хотя я использую Delphi, эта программа является прямым Windows API (без VCL, без объектно-ориентированного материала), как и в обычном C.

У меня был некоторый код, который уже работал с использованием обычного окна (созданного CreateWindowEx). Когда я преобразовал этот код для использования диалогового окна, функциональность перетаскивания сломалась, и я не могу понять почему.

Это (часть) кода, который у меня был, который работал нормально:

функция WndProc (Wnd: hWnd; Msg, wParam, lParam : DWORD): DWORD; stdcall;
 { основное приложение / функция обработки окон } 
const
 DROPPED_FILE_COUNT = -1;

var 
 FileCnt: целое число; { количество удаленных файлов}

 Имя файла: упакованный массив[0..MAX_PATH] символа; {буфер имени файла}
 DropInfo: HDROP абсолютный wParam; { wParam указывает на Drop ...}

 I: целое число; { для цикла}

начать
 WndProc := 0;

 { пусть обработчик Windows по умолчанию позаботится обо всем }

 сообщение о случае 
 WM_CREATE:
 начать
 initcommon Controls;

 если создать Windowex(WS_EX_CLIENTEDGE или WS_EX_RIGHTSCROLLBAR, 
'LISTBOX', 
ноль, 
 WS_CHILD или WS_HSCROLL или WS_VSCROLL или 
 WS_CLIPSIBLINGS или WS_CLIPCHILDREN или 
 WS_VISIBLE или LBS_NOINTEGRALHEIGHT, 
0, 
0, 
0, 
0, 
 Wnd,
 IDC_LISTBOX,
 Препятствие, 
 nil) = 0, тогда 
 начать
 MessageBox (Wnd, 
 "Не удалось создать поле списка", "Главное окно", MB_OK);

 WndProc := -1;
 завершение;

 { сообщите Windows, что мы принимаем файлы, перетаскиваемые через наш клиент}
 { область. }

 DragAcceptFiles(Wnd, TRUE);

 { укажите в поле списка использовать красивый шрифт}

 Отправить сообщение (GetDlgItem(Wnd, IDC_LISTBOX), 
 WM_SETFONT, GetStockObject(DEFAULT_GUI_FONT), 0);

 выход;
 end; { WM_CREATE }

 WM_DROPFILES:
 начать
 { один или несколько файлов были сброшены на нас! }

 FileCnt := DragQueryFile(DropInfo, DROPPED_FILE_COUNT, ноль, 0);

 для I:= 0 к FileCnt - 1 выполните 
 начать
 { получите имена удаленных файлов и добавьте их в список }

 DragQueryFile(DropInfo, I, Filename, sizeof(Имя файла));

 ListBox_AddString(GetDlgItem(Wnd, IDC_LISTBOX), Filename);
 завершение;

 { сообщите Windows, что мы закончили захват удаленных файлов}

 Завершение перетаскивания (DropInfo);

 выход;
 end; { WM_DROPFILES }

 ... за этим следует другой материал, который не имеет ничего общего с перетаскиванием... 

Я преобразовал это в это:

процедура ExecWM_INITDIALOG(wnd: hWnd);
начать
 { убедитесь, что поле списка не принимает удаленные файлы }

 DragAcceptFiles(GetDlgItem(Wnd, IDC_DIRECTORIES), FALSE);

 { убедитесь, что главное диалоговое окно принимает удаленные файлы}

 DragAcceptFiles(Wnd, TRUE);

 { загрузить текущие значения в реестр}

 LoadRegistrySettings(RegistryKey, RegistrySettings, RegistrySettingsCount)
завершение;

процедура ExecWM_DROPFILES(Wnd: hWnd; wParam : word; lParam: longint);
const
 DROPPED_FILE_COUNT = -1;

var 
 FileCnt: целое число; { количество удаленных файлов}

 Имя файла: упакованный массив[0..MAX_PATH] символа; {буфер имени файла}
 DropInfo: HDROP абсолютный wParam; { wParam указывает на Drop ...}

 I: целое число; { для цикла} 
начать
 { один или несколько файлов были сброшены на нас! }

 { -->>> Проблема, похоже, проявляется в этом заявлении: }
 { значение DropInfo (wParam) кажется слишком низким (20 долларов США) }
 { при использовании кода, который работает, значение намного больше }

 FileCnt := DragQueryFile(DropInfo, DROPPED_FILE_COUNT, ноль, 0);

 для I:= 0 к FileCnt - 1 выполните 
 начать
 { получите имена удаленных файлов и добавьте их в список }

 DragQueryFile(DropInfo, I, Filename, sizeof(Имя файла));

 ListBox_AddString(GetDlgItem(Wnd, IDC_DIRECTORIES), Filename);
 завершение;

 { сообщите Windows, что мы закончили захват удаленных файлов}

 Завершение перетаскивания (DropInfo);
завершение;

функция BackupConfigProc(wnd: hWnd;
 сообщение: word;
 wParam : word;
 lParam : longint) : bool; stdcall;
начать
 BackupConfigProc:= FALSE; { возвращаемое значение по умолчанию}

 сообщение о случае 
 WM_COMMAND:
 начать
 ExecWM_COMMAND (wnd, wParam, lParam);
 BackupConfigProc := TRUE;
 завершение;

 WM_DROPFILES:
 начать
 ExecWM_DROPFILES(Wnd, wParam, lParam);
 //BackupConfigProc := TRUE; { это был выстрел в темноте}
 завершение;

 WM_INITDIALOG: 
 начать
 ExecWM_INITDIALOG (wnd);
 BackupConfigProc := TRUE;
 завершение;

 WM_CLOSE:
 начать
 EndDialog(wnd, 0); { и возвращает значение FALSE по умолчанию }
 завершение;
 завершение;
завершение;

начать
 Диалоговое окно (помеха, 'BackupConfigDlg', 0, @BackupConfigProc);
завершение.

Похоже, что значение DropInfo (wParam), полученное диалоговым окном, недопустимо (поскольку оно намного ниже по значению, чем значение, полученное не диалоговым кодом, который работает).

Я буду благодарен всем, кто может пролить некоторый свет на то, почему диалоговая версия не работает и что нужно сделать, чтобы она заработала.

Спасибо,

Джон.

Ответ №1:

 procedure ExecWM_DROPFILES(Wnd : hWnd; wParam : word; lParam : longint);
  

Параметр wParam не должен вводиться, word но Windows.WPARAM который на самом деле является длинным значением int (в Win32).

Комментарии:

1. Вы, к моему большому смущению, абсолютно правы! Я только что понял, что часть кода, который я скопировал, была из программы, которую я написал еще во времена Windows 3.1. Это работает просто отлично после соответствующей настройки параметра. Спасибо вам и приношу свои извинения за довольно глупую ошибку.

2. Мелочи: вот почему параметр озаглавлен wParam : потому что изначально это было СЛОВО и en.wikipedia.org/wiki/Hungarian_notation#Examples .