I have two simple programs written in C running at the same time. The first program has a GUI window, while the second program has no window (hidden).
The first program (GUI) sends a TCP command to the second program (hidden), and the second program opens a file dialogue using Win32 API GetOpenFileNameA()
. The issue is this file dialogue box shows behind the GUI window.
Question:
How do I run GetOpenFileNameA()
and force focus on it?
OPENFILENAMEA ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.lpstrFile = FILE_PATH;
ofn.nMaxFile = sizeof(FILE_PATH);
ofn.lpstrFilter = "All Files\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileNameA(&ofn)) {
return FILE_PATH;
}
You could probably force it on top by providing a callback function for messages intended for the dialog box:
UINT_PTR OFNHookProcOldStyle(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
BringWindowToTop(hdlg); // or SetWindowPos
return 0;
}
Then set
ofn.lpfnHook = OFNHookProcOldStyle;
before calling GetOpenFileNameA
.
Note: This does not change the foreground window or force focus on your dialog box, but may be enough to bring it out of hiding so it appears on top of the GUI window.
In Windows 11 it the flag OFN_ENABLEHOOK
must be specified for the hook procedure to be called. It was probably a requirement before W11 too, but it seemed to work anyway. Setting that flag alone makes it show an old-style dialog though - but adding the OFN_EXPLORER
flag and defining the hook function as below seems to work:
UINT_PTR Lpofnhookproc(HWND hdlgChild, UINT uiMsg, WPARAM wParam, LPARAM lParam) {
if (uiMsg == WM_INITDIALOG) {
BringWindowToTop(GetParent(hdlgChild)); // I think GetParent is needed
}
return 0;
}
// and then:
ofn.lpfnHook = Lpofnhookproc;
This dialog box is however not exactly as the default you'll get without a hook and I can't figure out how to make it so. It is possible to specify a template for the dialog but I wasn't successful in getting the same look as the default.
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ENABLEHOOK;
It's maybe possible to fix the look of the dialog box by figuring out what to specify as the lpTemplateName
:
ofn.lpTemplateName = MAKEINTRESOURCEA( ? ); // unsure about this one
and adding OFN_ENABLETEMPLATE | OFN_ENABLETEMPLATEHANDLE
to the flags.