Невозможно заставить DragAcceptFiles работать при использовании диалогового окна - PullRequest
3 голосов
/ 26 апреля 2011

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

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

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


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

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


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.

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

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

Спасибо,

Джон.

1 Ответ

5 голосов
/ 26 апреля 2011
procedure ExecWM_DROPFILES(Wnd : hWnd; wParam : word; lParam : longint);

wParam должен быть набран не word, а Windows.WPARAM, что на самом деле является длинным целым (в Win32).

...