Search code examples
winapiwindows-8windowsetforegroundwindow

In Windows 8+, how do I bring Window Desktop App to foreground when Metro App in foreground via API?


My desktop application hook some hot keys eg: CTRL+SHIFT+F12, while the hot keys are pressed, it will bring my desktop application window into foreground or stay on top. But in Window 8 or 8.1, while it is in Window Start Screen or Metro App is running in foreground, my program unable to switch back to desktop mode and bring my window into foreground. I have tried the following API, SetFocus(hwnd); ShowWindow(hwnd, SW_SHOW); SetActiveWindow(hwnd); SetForegroundWindow(hwnd); SwitchToThisWindow(hwnd);

I even try on ShellExecute on "explorer.exe shell:::{3080F90D-D7AD-11D9-BD98-0000947B0257}", it doesn't work.

I'm not sure how Classic Shell latest version (http://www.classicshell.net) able to do this, when I pressed SHIFT+WIN key, it able to switch from Metro Mode back to desktop mode and show the Classic Shell Window.

Thanks.


Solution

  • You should be able to set a User Model ID to your application and use some of the newer APIs to bring it in focus when the user is in "Metro". Here are some code fragments in C++ to illustrate:

    Somewhere shared:

    const wchar_t MY_APP_USER_MODEL_ID[] = L"CompanyName.ProductSuite.AppName";
    

    In your "desktop" application startup:

    HRESULT hr = SetCurrentProcessExplicitAppUserModelID(const_cast<PWSTR>(MY_APP_USER_MODEL_ID));
    // Check that SUCCEEDED(hr)
    

    In your bring-into-focus-code:

    IApplicationActivationManager* appMgr = nullptr;
    if(SUCCEEDED(::CoCreateInstance(CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&appMgr)))) {
      DWORD pid = 0;
      appMgr->ActivateApplication(MY_APP_USER_MODEL_ID, nullptr, AO_NOERRORUI, &pid);
      appMgr->Release();
    }
    

    Your shortcut:

    Microsoft introduce some other goofy rules tied to all of this as well. You may have to add some additional information to your application's shortcut and have that shortcut pinned to the start menu for all of this to work (no, seriously). If you find this to be the case, here is a bit of code for updating your shortcut and adding the Model ID:

    // Assuming you already have a valid IShellLink to work with
    ComPtr<IPropertyStore> propertyStore;
    if(SUCCEEDED(shellLink.As(&propertyStore))) {
      PROPVARIANT appIdPropVar;
      if(SUCCEEDED(::InitPropVariantFromString(MY_APP_USER_MODEL_ID, &appIdPropVar))) {
        if(SUCCEEDED(propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar)) &&
          SUCCEEDED(propertyStore->Commit()))
        {
         // go on to save your link/shortcut to disk...
        }
      }
    }