Qt documentation says:
"Note that on Windows the dialog will spin a blocking modal event loop that will not dispatch any QTimers, and if parent is not 0 then it will position the dialog just under the parent's title bar."
Not in the center of the parent window, as one expecting.
But WinAPI provides a very simple way to define native file dialog's positions. In few words - you have to assign a hook function pointer in OPENFILENAME structure and position dialog properly in that function.
This function creates correct OPENFILENAME (don't forget to make similar changes in qt_win_make_OFNA function)
static OPENFILENAME
* qt_win_make_OFN
(QWidget *parent,
const QString& initialSelection,
const QString& initialDirectory,
const QString& title,
const QString& filters,
{
// ....
OPENFILENAME* ofn = new OPENFILENAME;
memset(ofn, 0, sizeof(OPENFILENAME));
// ....
ofn->lpfnHook = qt_win_ofn_hook; // custom hook
ofn->lCustData = (LPARAM)parent; // parent of dialog window
ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK); // OFN_ENABLEHOOK enables ofn hook fields
// ....
}
static OPENFILENAME* qt_win_make_OFN(QWidget *parent,
const QString& initialSelection,
const QString& initialDirectory,
const QString& title,
const QString& filters,
QFileDialog::FileMode mode,
QFileDialog::Options options)
{
// ....
OPENFILENAME* ofn = new OPENFILENAME;
memset(ofn, 0, sizeof(OPENFILENAME));
// ....
ofn->lpfnHook = qt_win_ofn_hook; // custom hook
ofn->lCustData = (LPARAM)parent; // parent of dialog window
ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK); // OFN_ENABLEHOOK enables ofn hook fields
// ....
}
To copy to clipboard, switch view to plain text mode
And this is a hook function:
UINT_PTR CALLBACK qt_win_ofn_hook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
// process initialization message
if(uiMsg == WM_INITDIALOG)
{
OPENFILENAME* ofn;
HWND frame_dlg;
RECT frame_rect;
int dlg_left;
int dlg_top;
// this should work even if lParam points to OPENFILENAMEA
ofn = (OPENFILENAME*)lParam; // ofn goes to lparam (as MSDN says)
parent
= (QWidget*)ofn
->lCustData;
// custom data filled in ofn
if(parent == 0)
{
// using desktop if no parent window
}
else
{
// getting parent rect
parent_topleft
= parent
->mapToGlobal
(QPoint(0,
0));
parent_rect
= QRect(parent_topleft, parent
->size
());
}
frame_dlg = GetParent(hdlg); // file dialog handle
GetWindowRect(frame_dlg, &frame_rect); // file dialog frame rect
// compute left and top of final rect
dlg_left = (parent_rect.left() + parent_rect.right()) / 2 -
(frame_rect.right - frame_rect.left) / 2;
dlg_top = (parent_rect.top() + parent_rect.bottom()) / 2 -
(frame_rect.bottom - frame_rect.top) / 2;
// position file dialog
SetWindowPos(frame_dlg, 0, dlg_left, dlg_top, 0, 0, SWP_NOSIZE);
}
return FALSE;
}
UINT_PTR CALLBACK qt_win_ofn_hook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
// process initialization message
if(uiMsg == WM_INITDIALOG)
{
OPENFILENAME* ofn;
QWidget* parent;
HWND frame_dlg;
RECT frame_rect;
QRect parent_rect;
int dlg_left;
int dlg_top;
// this should work even if lParam points to OPENFILENAMEA
ofn = (OPENFILENAME*)lParam; // ofn goes to lparam (as MSDN says)
parent = (QWidget*)ofn->lCustData; // custom data filled in ofn
if(parent == 0)
{
// using desktop if no parent window
parent_rect = QApplication::desktop()->geometry();
}
else
{
// getting parent rect
QPoint parent_topleft;
parent_topleft = parent->mapToGlobal(QPoint(0, 0));
parent_rect = QRect(parent_topleft, parent->size());
}
frame_dlg = GetParent(hdlg); // file dialog handle
GetWindowRect(frame_dlg, &frame_rect); // file dialog frame rect
// compute left and top of final rect
dlg_left = (parent_rect.left() + parent_rect.right()) / 2 -
(frame_rect.right - frame_rect.left) / 2;
dlg_top = (parent_rect.top() + parent_rect.bottom()) / 2 -
(frame_rect.bottom - frame_rect.top) / 2;
// position file dialog
SetWindowPos(frame_dlg, 0, dlg_left, dlg_top, 0, 0, SWP_NOSIZE);
}
return FALSE;
}
To copy to clipboard, switch view to plain text mode
Full qfiledialog_win.cpp file is in the attachments.
Hope it will help. Or may be, in one beautiful day, it will be commited to the main repository.
Bookmarks