C++ - Open Control Panel item in the same window - c++

I have a Windows-based application. I'm trying to open a Control Panel item the following way:
EnumWindows(EnumWindowsProcMy, ppid);
IOpenControlPanel *pPanel = NULL;
CoInitialize(nullptr);
HRESULT hr = CoCreateInstance(CLSID_OpenControlPanel, NULL,
CLSCTX_INPROC_SERVER, IID_IOpenControlPanel,
(void**)&pPanel);
if (FAILED(hr)) {
return -1;
}
pPanel->Open(CUSTOM_GUID, NULL, NULL);
This however opens the Control Panel Item in a new Window. Is there any way to navigate to the Control Panel item in an already Open Window? I have the Handle to the Window.

If you already have a running instance of control panel you can do somewhat like.
Retrieves a pointer to a running object that has been registered.
Sample code
IUnknown *puk = NULL;
HRESULT hr = GetActiveObject(CLSID_OpenControlPanel, 0, &puk);
return (hr == S_OK);

Related

Windows FileOpenDialog returning wrong path

I want to have a simple file dialog in which the user can select a folder like the following.
When executing the following code snippet on Windows 10 build with the current Visual Studio 2017, I run into a weird problem. What I do
create a new folder within the opened filedialog
type in a new name for the folder
while the text cursor is still visible for the new folder, I click on "Select Folder".
Instead of the name I typed in for the selected folder, pszFilePath is "New folder".
Instead I would expect the Dialog to first remove the focus from the new folder when I click on "Select Folder" and then I need a second click, to actually select the folder.
Strangely enough this doesn't happen on all Windows 10 systems I tested this code on. Sometimes I can't reproduce the issue.
Anyone with the same problem and maybe a workaround?
#include <shobjidl.h>
#include <windows.h>
void winOpenFileDialog ()
{
HRESULT hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED (hr))
{
IFileOpenDialog* pFileOpen;
// Create the FileOpenDialog object.
hr = CoCreateInstance (CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog,
reinterpret_cast<void**> (&pFileOpen));
if (SUCCEEDED (hr))
{
pFileOpen->SetOptions (FOS_PICKFOLDERS);
// Show the Open dialog box.
hr = pFileOpen->Show (NULL);
FILEOPENDIALOGOPTIONS opt;
pFileOpen->GetOptions (&opt);
// Get the file name from the dialog box.
if (SUCCEEDED (hr))
{
IShellItem* pItem;
hr = pFileOpen->GetResult (&pItem);
if (SUCCEEDED (hr))
{
PWSTR pszFilePath;
hr = pItem->GetDisplayName (SIGDN_FILESYSPATH, &pszFilePath);
// Display the file name to the user.
if (SUCCEEDED (hr))
{
MessageBox (NULL, pszFilePath, L"File Path", MB_OK);
CoTaskMemFree (pszFilePath);
}
pItem->Release ();
}
}
pFileOpen->Release ();
}
CoUninitialize ();
}
}

Embedding Window Media Player in mfc

I am embedding a window media player activex control in a dialog based mfc application. Now all play/pause button is getting disabled. I want to enable them.
As I have put put_uiMode(_T("mini"));
and when writingthese lines
hr = m_spWMPPlayer->put_fullScreen(VARIANT_TRUE)
hr = m_spWMPPlayer->get_fullScreen(&b); // returned b = VARIANT_FALSE
value of b is coming FALSE.
What could be the error? Any one knows this?
Thank You
BOOL CLuminPlayerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
CComPtr<IWMPPlayer> m_spWMPPlayer;
CComPtr<IWMPRemoteMediaServices> m_spServices;
CComPtr<IWMPControls> m_spControls;
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
HRESULT hr = NULL;
if(SUCCEEDED(hr))
{
hr = CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER, IID_IOleObject, (void**)&m_spServices);
if(SUCCEEDED(hr))
{
BSTR str = NULL;
VARIANT_BOOL b ;
hr = m_spServices->QueryInterface(__uuidof(IWMPPlayer), (void**)&m_spWMPPlayer);
if(SUCCEEDED(hr))
{
hr = m_spWMPPlayer->get_enabled(&b); // returned b= VARIANT_TRUE
hr = m_spWMPPlayer->get_enableContextMenu(&b); //returned b = VARIANT_TRUE
hr = m_spWMPPlayer->get_uiMode(&str); // returned str = L"full"
hr = m_spWMPPlayer->put_uiMode(_T("mini")); //hr = S_OK
hr = m_spWMPPlayer->get_uiMode(&str); // str = L"mini"
hr = m_spWMPPlayer->put_fullScreen(VARIANT_TRUE);
hr = m_spWMPPlayer->get_fullScreen(&b); // returned b = VARIANT_FALSE
hr = m_spWMPPlayer->put_URL(_T("C:\\Visual Studio 2012\\Projects\\Lumin-Player\\Debug\\abc.mp4")); //returned hr = S_OK
hr = m_spServices->QueryInterface(__uuidof(IWMPControls), (void**)&m_spControls); // returned hr = S_OK
if(SUCCEEDED(hr))
{
hr = m_spControls->play(); //returned hr = S_OK
}
}
}
}
return TRUE; // return TRUE unless you set the focus to a control
}
MSDN says:
For full-screen mode to work properly when embedding the Windows Media Player control, the video display area must have a height and width of at least one pixel. If the BSTR specified in IWMPPlayer::put_uiMode is set to "mini" or "full", the height of the control itself must be 65 pixels or greater to accommodate the video display area in addition to the user interface.
This assumes that the player is already properly initialized as ActiveX control. In your code, you simply create a COM object without doing any ActiveX Control initialization. Presumably the player detects this and reports error.
Your hr in respective put_fullScreen call should have 0xC00D0FD2 NS_E_WMPOCX_NO_ACTIVE_CORE "The requested method or property is not available because the Windows Media Player ActiveX control has not been properly activated." to indicate the problem.

Replacement for SHDOCLC.DLL file to customize the context menu of a webbrowser

I'm using the code, from this article to customize the context menu of a webbrowser.
but when i run this code
HRESULT CBrowserHost::ShowContextMenu(DWORD dwID,
POINT *ppt,
IUnknown *pcmdTarget,
IDispatch *pdispObject)
{
#define IDR_BROWSE_CONTEXT_MENU 24641
#define SHDVID_GETMIMECSETMENU 27
#define SHDVID_ADDMENUEXTENSIONS 53
HRESULT hr;
HINSTANCE hinstSHDOCLC;
HWND hwnd;
HMENU hMenu;
CComPtr<IOleCommandTarget> spCT;
CComPtr<IOleWindow> spWnd;
MENUITEMINFO mii = {0};
CComVariant var, var1, var2;
hr = pcmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
hr = pcmdTarget->QueryInterface(IID_IOleWindow, (void**)&spWnd);
hr = spWnd->GetWindow(&hwnd);
hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL")); //here the exception is raised
if (hinstSHDOCLC == NULL)
{
// Error loading module -- fail as securely as possible.
return;
}
hMenu = LoadMenu(hinstSHDOCLC,
MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
hMenu = GetSubMenu(hMenu, dwID);
// Get the language submenu.
hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
mii.hSubMenu = (HMENU) var.byref;
// Add language submenu to Encoding context item.
SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
// Insert Shortcut Menu Extensions from registry.
V_VT(&var1) = VT_INT_PTR;
V_BYREF(&var1) = hMenu;
V_VT(&var2) = VT_I4;
V_I4(&var2) = dwID;
hr = spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
// Remove View Source.
DeleteMenu(hMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);
// Show shortcut menu.
int iSelection = ::TrackPopupMenu(hMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
ppt->x,
ppt->y,
0,
hwnd,
(RECT*)NULL);
// Send selected shortcut menu item command to shell.
LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
FreeLibrary(hinstSHDOCLC);
return S_OK;
}
This error is raised
"The specified module could not be found"
I search on my system (Windows 7 x64, IE9) and I not found the SHDOCLC.DLL file, the question is exist any replacement for this file in the newers versions of IE or I must use another way to load the context menu and customize it?
You shouldn't use or rely on the Internet Explorer's internal resources anymore. As it's stated in the article you've pointed out:
In Internet Explorer 7, the technique for overriding the context menu
from a DocObject host is the same as Internet Explorer 6; however, the
host must implement its own menu resources. The internal resources of
Internet Explorer should not be used as they may change or move (as
has been done in Internet Explorer 7).
if the Windows version is newer than VISTA(included), try LoadLibrary("IEFRAME.DLL") instead.
And you can find more infomation here

Problems using IFileDialog on Windows 7

I'm facing some weird (at least for me) behavior on using the Common Item Dialogs in my MFC Windows application running on Windows 7 or Vista.
According to the MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/bb776913(v=vs.85).aspx I'm using the new interfaces to display file open and save dialogs:
bool OpenFileDialog(CString& strFile, CString strTitle, CStringArray& astrFilter, CStringArray& astrFilterExtension, ULONG nFlags, HWND hParentWnd)
{
USES_CONVERSION;
INT_PTR nResult = 0;
INT_PTR nFilterCount = astrFilter.GetCount();
IFileDialog* pfod = 0;
HRESULT hr = ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfod));
if(SUCCEEDED(hr))
{
// New dialog starting with Vista/Windows 7
COMDLG_FILTERSPEC* pOpenTypes = 0;
if((nFilterCount > 0) && (nFilterCount == astrFilterExtension.GetCount()))
{
pOpenTypes = new COMDLG_FILTERSPEC[nFilterCount];
for(int nIdx = 0; nIdx < nFilterCount; nIdx++)
{
pOpenTypes[nIdx].pszName = astrFilter[nIdx].GetBuffer();
pOpenTypes[nIdx].pszSpec = astrFilterExtension[nIdx].GetBuffer();
}
}
// Set the file types to display.
if(pOpenTypes)
{
hr = pfod->SetFileTypes(nFilterCount, pOpenTypes);
if(SUCCEEDED(hr))
hr = pfod->SetFileTypeIndex(0);
}
if(!strFile.IsEmpty())
pfod->SetFileName(strFile);
if(!strTitle.IsEmpty())
pfod->SetTitle(strTitle);
if(SUCCEEDED(hr))
{
// Ensure the dialog only returns file system paths.
DWORD dwFlags;
hr = pfod->GetOptions(&dwFlags);
if(SUCCEEDED(hr))
{
dwFlags |= FOS_FORCEFILESYSTEM;
if(nFlags & OFN_FILEMUSTEXIST)
dwFlags |= FOS_FILEMUSTEXIST;
if(nFlags & OFN_PATHMUSTEXIST)
dwFlags |= FOS_PATHMUSTEXIST;
hr = pfod->SetOptions(dwFlags);
if(SUCCEEDED(hr))
{
// Create an event handling object, and hook it up to the dialog.
IFileDialogEvents* pfde = NULL;
DWORD dwCookie;
// Actually only added for debugging purposes
/*hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
if(SUCCEEDED(hr))
{
// Hook up the event handler.
hr = pfod->Advise(pfde, &dwCookie);
if(!SUCCEEDED(hr))
{
pfde->Release();
pfde = 0;
}
}*/
// Now show the dialog. Usually called with hParent == 0
if(hParentWnd)
hr = pfod->Show(::GetWindow(hParentWnd, GW_OWNER));
else
hr = pfod->Show(0);
// do something with the path when the dialog was closed...
So the dialog appears and works fine if I want to select a file from a normal drive. I can navigate through the folders and select any file I want. On leaving the dialog I also get the correct file information.
But it doesn't work for one of the Libraries in the navigation pane on the left side. Whenever I try to select a Library like Documents, Videos or Pictures the dialog doesn't update the right pane which shows the folder/library content.
What I noticed is that on clicking a Library in the file open/save dialog the OnFolderChanging() event of the IFileDialogEvents interface is fired but the OnFolderChange() and OnSelectionChange() are not. Those events are fired if I click and navigate on a "normal" drive like C.
I also tried to call the dialogs early in my InitInstance method to avoid possible side-effects with my other code but this didn't help either.
Is there someone who had the same behavior and was able to resolve this?
Thanks a lot!
So I finally found the answer to this issue. Creating the new MFC project for the application was the actual hint to solve this. The reason was that the "Stack reserve size" was too big. The settings in the old VS6.0 project had the stack size increased to more than 100MB. Apparently the IFileDialog based dialogs do not work properly when the reserved stack size is simply too large (other thing might don't work also as expected). So I had to set it back to 15MB in my case.

DirectDraw question - running the application as a regular Windows application

I am developing an application for video recording and I want to overlay the video preview with a logo and recording timer.
I tried to run the full-screen application and everything worked fine. Then I tried to run the application as a regular Windows application and it returned an error.
Could anyone take a look at the code below if there's a way to modify it to run the application as a regular Windows app?
HRESULT CViewfinderRenderer::OnStartStreaming()
{
HRESULT hr = S_OK;
DDSURFACEDESC ddsd;
m_pDD = NULL;
//full screen settings
hr = DirectDrawCreate(NULL, &m_pDD, NULL);
hr = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_FULLSCREEN);
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
ddsd.dwBackBufferCount = 1;
//end full screen settings
//normal settings
/*hr = DirectDrawCreate(NULL, &m_pDD, NULL);
hr = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = 1;*/
//end normal settings
hr = m_pDD->CreateSurface(&ddsd, &m_pSurface, NULL);
if (hr != DD_OK) {
return hr;
}
// Get backsurface
hr = m_pSurface->EnumAttachedSurfaces(&m_pBackSurface, EnumFunction);
return S_OK;
}
Even when running windowed, you need to create a primary surface, only it is not a flippable surface.
//full screen settings
hr = DirectDrawCreate(NULL, &m_pDD, NULL);
hr = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
Besides of creating a surface, most likely you will want to create a clipper for the window. For a complete sample see paragraph Running windowed in this GameDev article.
What error did it return?
Also try this instead:
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;