Как изменить положение диалогового окна OPENFILENAME в Windows?

#c #winapi #common-dialog

#c #winapi #диалог

Вопрос:

Это моя попытка с помощью функции hook получить дескриптор диалогового окна. Оба SetWindowPos() и GetLastError() возвращают правильные значения, но диалоговое окно остается неизменным и отображается в положении 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(amp;ofn, sizeof(ofn));
  ofn.lStructSize = sizeof(OPENFILENAMEW);
  ofn.nMaxFile = MAX_PATH;
  ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
  ofn.lpfnHook = OFNHookProc;
  GetOpenFileNameW(amp;ofn);
  return 0;
}
 

Комментарии:

1. Это обречет вас на использование ужасного диалогового окна XP legacy

2. Возвращаемое значение GetLastError не имеет смысла в то время, когда вы его вызываете. Он сообщает значимое значение только при SetWindowPos сбое и только тогда, когда вы вызываете его сразу после неудачного вызова API. Операторы перемежающегося потока могут изменять записанный последний код ошибки вызывающего потока.

Ответ №1:

При использовании OFN_EXPLORER вам необходимо переместить hdlg родительское окно, поскольку HWND, переданный вашему обратному вызову, не является фактическим диалоговым окном. Это четко указано в документации:

Функция обратного вызова OFNHookProc

hdlg [in]
дескриптор дочернего диалогового окна диалогового окна Открыть или Сохранить как. Используйте функцию getParent, чтобы получить дескриптор диалогового окна Открыть или Сохранить как.

Кроме того, вы должны дождаться обратного вызова, чтобы получить CDN_INITDONE уведомление, а WM_INITDIALOG не сообщение.

Попробуйте это:

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