Как сохранить диалог свойств открытым при закрытии приложения, которое его открыло? - PullRequest
0 голосов
/ 23 октября 2019

Я работаю над тем, что вызывает контекстное меню. Я хочу иметь возможность закрыть приложение, оставляя открытыми такие вещи, как "свойства". Что произойдет, если вы откроете контекстное меню, выберите «свойства», он откроет диалоговое окно свойств и просто закроет контекстное меню. Но когда я закрываю свое приложение, окно свойств также закрывается.

Вопрос в том, как держать это окно открытым? Если вы не можете, как приложение может определить, зависит ли от него окно / диалоговое окно? EnumWindows не показывает это;Spy ++ показывает, что Диалог свойств также стоит отдельно (под рабочим столом).

CComPtr<IContextMenu> pMenu;
CComPtr<IShellFolder> pFolder;
PCUITEMID_CHILD pidl = NULL;
SHBindToParent(item.pidl, IID_IShellFolder, (void**)&pFolder, &pidl);
pFolder->GetUIObjectOf(NULL, 1, &pidl, IID_IContextMenu, NULL, (void**)&pMenu);
UINT flags = CMF_NORMAL | CMF_CANRENAME;
pMenu->QueryContextMenu(menu, CID_FIRST, CID_LAST, 0x7fff, flags);
.
.
.
// command invocation
CMINVOKECOMMANDINFOEX info;
memset(&info, 0, sizeof(info));
info.cbSize = sizeof(info);
info.fMask = CMIC_MASK_NOASYNC | CMIC_MASK_PTINVOKE; // I've played around with flags
info.hwnd = toolbar.m_hWnd; // I've played around with this value
info.lpVerb = MAKEINTRESOURCEA(cid - CID_LAST);
info.nShow = SW_SHOWNORMAL;
info.ptInvoke = point;
pMenu->InvokeCommand((CMINVOKECOMMANDINFO*)&info);  

TIA !!

Ответы [ 2 ]

0 голосов
/ 23 октября 2019

Диалог свойств находится в процессе.

Вам нужно вызвать SHSetInstanceExplorer и , чтобы ваш процесс оставался активным до тех пор, пока этот COM-объект не будет освобожден :

int main()
{
    struct CoInit { HRESULT m_hr; CoInit() { m_hr = CoInitialize(0); } ~CoInit() { if (SUCCEEDED(m_hr)) CoUninitialize(); } } coinit;
    ProcessReference ref;
    IShellItem*pSI;
    HRESULT hr = SHCreateItemInKnownFolder(FOLDERID_Windows, KF_FLAG_DEFAULT, L"Explorer.exe", IID_IShellItem, (void**) &pSI);
    if (hr) return hr;
    IContextMenu*pCM;
    hr = pSI->BindToHandler(NULL, BHID_SFUIObject, IID_IContextMenu, (void**) &pCM);
    pSI->Release();
    if (hr) return hr;
    //HMENU menu = CreatePopupMenu();
    //pCM->QueryContextMenu(menu, 0, 1, 0x7fff, CMF_NORMAL);
    CMINVOKECOMMANDINFO info;
    memset(&info, 0, sizeof(info));
    info.cbSize = sizeof(info);
    info.fMask = CMIC_MASK_NOASYNC; // I've played around with flags
    info.hwnd = NULL; // I've played around with this value
    info.lpVerb = "Properties";
    info.nShow = SW_SHOWNORMAL;
    //info.ptInvoke = point;
    hr = pCM->InvokeCommand((CMINVOKECOMMANDINFO*)&info);
    pCM->Release();
    return hr;
}
0 голосов
/ 23 октября 2019

EnumWindows не показывает его

Если я что-то неправильно понял, пожалуйста, скажите мне.

Это мой тест:

enter image description here

enter image description here

Второй снимок экрана - это то, что я получил с EnumWindows, по моему мнению, для некоторых диалоговых окон свойств приложения выможно получить с помощью EnumWindows.

В то же время, как сказал @Jonathan Potter, диалоговое окно свойств оболочки выполняется в процессе, это правда, что вы можете открыть диалоговое окно свойств независимо с помощью ShellExecuteEx.

Только в качестве дополнения, если вы просто хотите открыть диалоговое окно свойств независимо, вы можете использовать API выше. Таким образом, когда вы закрываете приложение, вы можете снова открыть диалоговое окно свойств, если вас это не беспокоит. .

Пример минимального кода:

#include <windows.h>
#include <shlobj_core.h>

#pragma comment(lib,"Shell32.lib")

class ProcessReference : public IUnknown {
public:
    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
    {
        if (riid == IID_IUnknown) {
            *ppv = static_cast<IUnknown*>(this);
            AddRef();
            return S_OK;
        }
        *ppv = NULL; return E_NOINTERFACE;
    }
    STDMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&m_cRef);
    }
    STDMETHODIMP_(ULONG) Release()
    {
        LONG lRef = InterlockedDecrement(&m_cRef);
        if (lRef == 0) PostThreadMessage(m_dwThread, WM_NULL, 0, 0);
        return lRef;
    }
    ProcessReference()
        : m_cRef(1), m_dwThread(GetCurrentThreadId())
    {
        SHSetInstanceExplorer(this);
    }
    ~ProcessReference()
    {
        SHSetInstanceExplorer(NULL);
        Release();
        MSG msg;
        while (m_cRef && GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
private:
    LONG m_cRef;
    DWORD m_dwThread;
};

int main(void)
{
    struct CoInit { HRESULT m_hr; CoInit() { m_hr = CoInitialize(0); } ~CoInit() { if (SUCCEEDED(m_hr)) CoUninitialize(); } } coinit;
    ProcessReference ref;
    IShellItem*pSI;
    HRESULT hr = SHCreateItemInKnownFolder(FOLDERID_Windows, KF_FLAG_DEFAULT, L"Explorer.exe", IID_IShellItem, (void**)&pSI);
    if (hr) return hr;
    IContextMenu*pCM;
    hr = pSI->BindToHandler(NULL, BHID_SFUIObject, IID_IContextMenu, (void**)&pCM);
    pSI->Release();
    if (hr) return hr;

    SHELLEXECUTEINFO info = { 0 };

    info.cbSize = sizeof info;
    info.lpFile = "C:\\Users\\strives\\Desktop\\print.txt";
    info.nShow = SW_SHOW;
    info.fMask = SEE_MASK_INVOKEIDLIST;
    info.lpVerb = "properties";

    ShellExecuteEx(&info);


}

Обновлено:

SHELLEXECUTEINFO info = { 0 };

info.cbSize = sizeof info;
info.lpFile = "C:\\Users\\strives\\Desktop\\Test.txt";
info.nShow = SW_SHOW;
info.fMask = SEE_MASK_INVOKEIDLIST;
info.lpVerb = "openas";

ShellExecuteEx(&info);

Отладка:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...