I am using Delphi to code a simple app that needs to accept dropped directory names onto it. Though I am using Delphi, this program is straight Windows API (no VCL, no object oriented stuff) just as it would be in plain C.
I had some code that already worked using a normal window (as created by CreateWindowEx). When I converted that code to use a dialog box, the drag and drop functionality broke and I cannot figure out why.
This is (part of) the code I had that worked fine:
function WndProc (Wnd : hWnd; Msg, wParam, lParam : DWORD) : DWORD; stdcall;
{ main application/window handler function }
const
DROPPED_FILE_COUNT = -1;
var
FileCnt : integer; { number of files dropped }
Filename : packed array[0..MAX_PATH] of char; { filename buffer }
DropInfo : HDROP absolute wParam; { wParam points to Drop...}
I : integer; { for loop }
begin
WndProc := 0;
{ let the Windows default handler take care of everything }
case msg of
WM_CREATE:
begin
InitCommonControls;
if CreateWindowEx(WS_EX_CLIENTEDGE or WS_EX_RIGHTSCROLLBAR,
'LISTBOX',
nil,
WS_CHILD or WS_HSCROLL or WS_VSCROLL or
WS_CLIPSIBLINGS or WS_CLIPCHILDREN or
WS_VISIBLE or LBS_NOINTEGRALHEIGHT,
0,
0,
0,
0,
Wnd,
IDC_LISTBOX,
hInstance,
nil) = 0 then
begin
MessageBox(Wnd,
'Couldn''t create the listbox', 'Main Window', MB_OK);
WndProc := -1;
end;
{ let Windows know that we accept files being dragged over our client}
{ area. }
DragAcceptFiles(Wnd, TRUE);
{ tell the listbox to use a nice font }
SendMessage(GetDlgItem(Wnd, IDC_LISTBOX),
WM_SETFONT, GetStockObject(DEFAULT_GUI_FONT), 0);
exit;
end; { WM_CREATE }
WM_DROPFILES:
begin
{ one or more files have been dropped on us! }
FileCnt := DragQueryFile(DropInfo, DROPPED_FILE_COUNT, nil, 0);
for I := 0 to FileCnt - 1 do
begin
{ get the dropped files names and add them to the listbox }
DragQueryFile(DropInfo, I, Filename, sizeof(Filename));
ListBox_AddString(GetDlgItem(Wnd, IDC_LISTBOX), Filename);
end;
{ tell Windows that we are done grabbing the dropped files }
DragFinish(DropInfo);
exit;
end; { WM_DROPFILES }
... followed by other stuff that has nothing to do with drag and drop ...
I converted that to this:
procedure ExecWM_INITDIALOG(wnd : hWnd);
begin
{ ensure that the listbox isn't accepting dropped files }
DragAcceptFiles(GetDlgItem(Wnd, IDC_DIRECTORIES), FALSE);
{ ensure the main dialog window accept dropped files }
DragAcceptFiles(Wnd, TRUE);
{ load the current values in the registry }
LoadRegistrySettings(RegistryKey, RegistrySettings, RegistrySettingsCount)
end;
procedure ExecWM_DROPFILES(Wnd : hWnd; wParam : word; lParam : longint);
const
DROPPED_FILE_COUNT = -1;
var
FileCnt : integer; { number of files dropped }
Filename : packed array[0..MAX_PATH] of char; { filename buffer }
DropInfo : HDROP absolute wParam; { wParam points to Drop...}
I : integer; { for loop }
begin
{ one or more files have been dropped on us! }
{ -->>> The problem seems to show up at this statement: }
{ the DropInfo (wParam) has a value that seems too low ($20) }
{ when using the code that works the value is much larger }
FileCnt := DragQueryFile(DropInfo, DROPPED_FILE_COUNT, nil, 0);
for I := 0 to FileCnt - 1 do
begin
{ get the dropped files names and add them to the listbox }
DragQueryFile(DropInfo, I, Filename, sizeof(Filename));
ListBox_AddString(GetDlgItem(Wnd, IDC_DIRECTORIES), Filename);
end;
{ tell Windows that we are done grabbing the dropped files }
DragFinish(DropInfo);
end;
function BackupConfigProc(wnd : hWnd;
msg : word;
wParam : word;
lParam : longint) : bool; stdcall;
begin
BackupConfigProc := FALSE; { default return value }
case msg of
WM_COMMAND:
begin
ExecWM_COMMAND (wnd, wParam, lParam);
BackupConfigProc := TRUE;
end;
WM_DROPFILES:
begin
ExecWM_DROPFILES(Wnd, wParam, lParam);
//BackupConfigProc := TRUE; { this was a shot in the dark }
end;
WM_INITDIALOG:
begin
ExecWM_INITDIALOG (wnd);
BackupConfigProc := TRUE;
end;
WM_CLOSE:
begin
EndDialog(wnd, 0); { and return the default FALSE }
end;
end;
end;
begin
DialogBox(hInstance, 'BackupConfigDlg', 0, @BackupConfigProc);
end.
It looks like the value of the DropInfo (wParam) received by the dialog box is not valid (as it is much lower in value than the one received by the non dialog code that works).
I will be grateful to all who can shed some light as to why the Dialog version does not work and what needs to be done to make it work.
Thank you,
John.
procedure ExecWM_DROPFILES(Wnd : hWnd; wParam : word; lParam : longint);
wParam should not be typed word but Windows.WPARAM which is actually a long int (on Win32).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With