使用对话框时无法使 DragAcceptFiles 工作

发布于 2024-11-03 09:40:53 字数 5522 浏览 0 评论 0原文

我正在使用 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 版本不起作用以及需要采取哪些措施才能使其起作用的人。

谢谢你,

约翰。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

仙女 2024-11-10 09:40:53
procedure ExecWM_DROPFILES(Wnd : hWnd; wParam : word; lParam : longint);

wParam 不应输入 word,而应输入 Windows.WPARAM,它实际上是一个 long int(在 Win32 上)。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文