GetOpenFileName Focus

137 Views Asked by At

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;
}
1

There are 1 best solutions below

10
Ted Lyngmo On BEST ANSWER

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.