如何在 Windows 中更改 OPENFILENAME 对话框的位置?

How to change position of an OPENFILENAME dialog in Windows?

这是我尝试使用挂钩函数来获取对话框 window 句柄。 SetWindowPos()GetLastError() return 均正确值,但对话框 window 不受影响并显示在位置 0,0.

#include <windows.h>
#include <iostream>

static UINT_PTR CALLBACK OFNHookProc (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) {
  using namespace std;
  switch (uiMsg) {
    case WM_INITDIALOG: {
      // SetWindowPos returns 1
      cout << SetWindowPos(hdlg, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE ) << endl;
      // GetLastError returns 0
      cout << GetLastError() << endl;
      break;
    }
  }
  return 0;
}

int main() {
  OPENFILENAMEW ofn;
  ZeroMemory(&ofn, sizeof(ofn));
  ofn.lStructSize = sizeof(OPENFILENAMEW);
  ofn.nMaxFile = MAX_PATH;
  ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
  ofn.lpfnHook = OFNHookProc;
  GetOpenFileNameW(&ofn);
  return 0;
}

使用 OFN_EXPLORER 时,您必须移动 hdlg 父级 window,因为传递给回调的 HWND 不是实际对话 window。这在文档中有明确说明:

OFNHookProc callback function

hdlg [in]
A handle to the child dialog box of the Open or Save As dialog box. Use the GetParent function to get the handle to the Open or Save As dialog box.

此外,您应该等待回调接收 CDN_INITDONE 通知,而不是 WM_INITDIALOG 消息。

试试这个:

static UINT_PTR CALLBACK OFNHookProc (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
  if ((uiMsg == WM_NOTIFY) &&
      (reinterpret_cast<OFNOTIFY*>(lParam)->hdr.code == CDN_INITDONE))
  {
    SetWindowPos(GetParent(hdlg), HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE);
  }
  return 0;
}