#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 .