How to implement code for multiple buttons using c++ in Silverlight for Windows Embedded - c++

I have referred the following link:
Silverlight for Windows Embedded
By referring this link i created a demo application which consist of two buttons created using Microsoft expression blend 2 tools. And then written a code referring the above site. Now my button names are "Browser Button" and "Media Button". On click of any one of the button i should able to launch the respective application. I was able to do for "Browser Button" but not for "Media Button" and if i do for "Media Button" then i am not able to do for "Browser Button".. I mean to say that how should i create event handler for both the buttons.
This is the code in c++ which i should modify
class BtnEventHandler
{
public:
HRESULT OnClick(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
{
RETAILMSG(1,(L"Browser event"));
Execute(L"\\Windows\\iesample.exe",L"");
return S_OK;
}
};
// entry point for the application.
INT WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,int nCmdShow)
{
PrintMessage();
int exitCode = -1;
HRESULT hr = S_OK;
if (!XamlRuntimeInitialize())
return -1;
HRESULT retcode;
IXRApplicationPtr app;
if (FAILED(retcode=GetXRApplicationInstance(&app)))
return -1;
if (FAILED(retcode=app->AddResourceModule(hInstance)))
return -1;
XRWindowCreateParams wp;
ZeroMemory(&wp, sizeof(XRWindowCreateParams));
wp.Style = WS_OVERLAPPED;
wp.pTitle = L"Bounce Test";
wp.Left = 0;
wp.Top = 0;
XRXamlSource xamlsrc;
xamlsrc.SetResource(hInstance,TEXT("XAML"),MAKEINTRESOURCE(IDR_XAML1));
IXRVisualHostPtr vhost;
if (FAILED(retcode=app->CreateHostFromXaml(&xamlsrc, &wp, &vhost)))
return -1;
IXRFrameworkElementPtr root;
if (FAILED(retcode=vhost->GetRootElement(&root)))
return -1;
IXRButtonBasePtr btn;
if (FAILED(retcode=root->FindName(TEXT("BrowserButton"), &btn)))
return -1;
IXRDelegate<XRMouseButtonEventArgs>* clickdelegate;
BtnEventHandler handler;
if(FAILED(retcode=CreateDelegate
(&handler,&BtnEventHandler::OnClick,&clickdelegate)))
return -1;
if (FAILED(retcode=btn->AddClickEventHandler(clickdelegate)))
return -1;
UINT exitcode;
if (FAILED(retcode=vhost->StartDialog(&exitcode)))
return -1;
return exitCode;
}
I have to add event handler for both the button so that on emulator whenever i click on any one of the button i should be able to launch the respective applications.
Thanks in advance

You can create two seperate functions to be the handlers for each button.
If you want the same handler to identify which button was pressed and act accordingly you can read the following MSDN article that demonstrates that.
I have not tried this, but you can also use IXRDependencyObject::GetName of the source object to know which button was pressed.
Your handler would look like:
HRESULT OnClick(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
{
BSTR pName[50];
source->GetName(pName);
if (_tcscmp(L"BrowserEvent", LPCWSTR(pName)) == 0)
{
RETAILMSG(1,(L"Browser event"));
Execute(L"\\Windows\\iesample.exe",L"");
}
else if (_tcscmp(L"BrowserEvent", LPCWSTR(pName)) == 0)
{
/* Handle another button or element */
}
return S_OK;
}

Related

WIN32 - Create a WebView2 synchronously does not work - I don't get a white rectangle for my integrated web browser

In brief, I explain you my problem. In my application, I've a button to load the browser. When I click on the button, it opens and creates well the webBrowser (white rectangle).
BUT when I try to create the web Browser when I open a window (who contains different components : buttons, edittext,...) of my application through the Event WM_SHOWWINDOW, I don't see my web browser EXCEPTED IF I put in comment all the loop "while" in the constructor EdgeBrowser.
Why ? Can you give me a solution please ? It would be friendly.
I created a class EdgeBrowser with a constructor who receives the handle of my WIN32 component (HWND component). In my constructor, I do something like that :
EdgeBrowser::EdgeBrowser(HWND hwnd)
{
_hwnd = hwnd;
EdgeBrowser::_beginAsyncOperation = true;
this->CreateWebView();
while (EdgeBrowser::_beginAsyncOperation)
{
Sleep(10);
MSG msg;
for (int nmsg = 0; nmsg < 50; ++nmsg)
{
int rc = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
if (rc == 0)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
And in a part of my "CreateWebView" function with the different listeners :
void EdgeBrowser::CreateWebView
{
// other code
HRESULT hr = CreateCoreWebView2EnvironmentWithOptions(nullptr, userDataDir.c_str(),nullptr,Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(this,&EdgeBrowser::OnCreateCoreWebView2EnvironmentCompletedHandler).Get());
}
HRESULT EdgeBrowser::OnEnvironmentReadyCompletedHandler(HRESULT result, ICoreWebView2Environment* env)
{
HRESULT createBrowserControlsResult = m_uiEnv->CreateCoreWebView2Controller(this->_thisHandler, Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(this,&EdgeBrowser::OnCreateCoreWebView2ControllerCompletedHandler).Get());
HRESULT createBrowserOptionsResult = m_uiEnv->CreateCoreWebView2Controller(this->_thisHandler,Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>( this,&EdgeBrowser::OnCreateCoreWebView2ControllerOptionsCompletedHandler).Get());
}
HRESULT EdgeBrowser::OnCreateCoreWebView2ControllerOptionsCompletedHandler(HRESULT result, ICoreWebView2Controller* host)
{
m_optionsController = host;
HRESULT getOptWebViewResult = m_optionsController->get_CoreWebView2(&m_optionsWebView);
//other code
EdgeBrowser::_beginAsyncOperation = false;
return S_OK;
}
The WebView2 control requires a message loop to run on the UI thread on which it is created (see this page for more info on WebView2 threading). You can see the WebView2APISample sample app as a sample C++ Win32 HWND based application.

Disabling "Script Error" popup IWebBrowser2 c++ WinApi

Having a HWND with IWebBrowser2 on it. IWebBrowser2 is new CLSID_WEBBROWSER.
When I navigating to youtube,google and etc, sometimes it shows me Script Error. And I want to disable it. How can I do it?
if (MoneyHWND == NULL) {
if (SUCCEEDED(OleInitialize(NULL)))
{
vector<wchar_t> fn(1000);
GetModuleFileName(0, fn.data(), 1000);
PathStripPath(fn.data());
RKEY k(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION");
k[fn.data()] = 11001UL; // Use IE 11
MoneyHWND = CreateDialog(GetModuleHandle(0), MAKEINTRESOURCE(IDD_FORMVIEW1), hWnd, MoneyProc);
pBrowser2 = new WebBrowser(MoneyHWND);
RECT rc;
GetClientRect(MoneyHWND, &rc);
pBrowser2->SetRect(rc);
pBrowser2->Navigate(site);
OleUninitialize();
}
}
IWebBrowser2::Silent:
Sets or gets a value that indicates whether the object can display dialog boxes.
Note, that the property is exposed to C and C++ programs using the following signatures:
HRESULT IWebBrowser2::get_Silent(VARIANT_BOOL *pbSilent);
HRESULT IWebBrowser2::put_Silent(VARIANT_BOOL bSilent);
In other words:
// ...
auto hr{ pBrowser2->put_Silent(VARIANT_TRUE) };
if FAILED(hr)
{
// Handle error
// ...
}

Detecting CTRL+Wheel with CHtmlView

I know how to set the zoom factor for a CHtmlView:
HRESULT CChristianLifeMinistryHtmlView::SetZoomFactor(long iZoom, bool bRefreshBrowser /*true*/)
{
HRESULT hr = S_OK;
VARIANT vZoom;
m_lZoomFactor = iZoom;
if (bRefreshBrowser)
{
vZoom.vt = VT_I4;
vZoom.lVal = iZoom;
hr = ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &vZoom, nullptr);
}
return hr;
}
HRESULT CChristianLifeMinistryHtmlView::ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
HRESULT hr;
ASSERT(m_pBrowserApp != NULL);
hr = m_pBrowserApp->ExecWB(cmdID, cmdexecopt, pvaIn, pvaOut);
return hr;
}
I have just introduced a CStatusBar into the main editor that encompasses this view and one of my users has stated that they use CTRL + Wheel to change the zoom factor.
I have my menu structure with associated hotkeys that the user can use to change the zoom, thus my status bar pane is updated to the right value they selected.
But when they use the CTRL + Wheel to change the zoom my application is not detecting this. So they zoom in or out to a scale and my status bar pane is staying at the original zoom factor.
With MFC and the CHtmlView web browser control how to I detect when they have changed the zoom using CTRL + Wheel so I can update my status pane?
If this is CHtmlView with Doc/View structure, use PreTranslateMessage to catch messages.
Documentation for WM_MOUSEWHEEL suggests several macros for finding the state of virtual keys and wheel movement:
BOOL CMyHtmlView::PreTranslateMessage(MSG* pmsg)
{
if(pmsg->message == WM_MOUSEWHEEL)
{
int fwKeys = GET_KEYSTATE_WPARAM(pmsg->wParam);
int zDelta = GET_WHEEL_DELTA_WPARAM(pmsg->wParam);
if (fwKeys & MK_CONTROL)
{
//mousewheel + control key is down
TRACE("%d %d\n", zDelta, zDelta / WHEEL_DELTA);
//update statusbar, or return TRUE to handle this manually
}
}
return CHtmlView::PreTranslateMessage(pmsg);
}
CHtmlView also has its own CHtmlView::ExecWB method to set and get the zoom value etc.
CHtmlView::OnUpdateUI should also send notification for the change.
But the browser may not send a signal at the right time. Just make a timer to wait 1 second after detecting CTRL+WHEEL. Example:
BEGIN_MESSAGE_MAP(CMyHtmlView, CHtmlView)
ON_WM_TIMER()
END_MESSAGE_MAP()
const int ID_TIMER_ZOOM = 1;
BOOL CMyHtmlView::PreTranslateMessage(MSG* pmsg)
{
if(pmsg->message == WM_MOUSEWHEEL)
if (GET_KEYSTATE_WPARAM(pmsg->wParam) & MK_CONTROL)
SetTimer(ID_TIMER_ZOOM, 1000, NULL); //start timer for detecting zoom
return CHtmlView::PreTranslateMessage(pmsg);
}
void CMyHtmlView::OnTimer(UINT_PTR timer_id)
{
if(timer_id == ID_TIMER_ZOOM)
{
//get the zoom value
VARIANT vZoom;
vZoom.vt = VT_I4;
vZoom.lVal = 0;
ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, nullptr, &vZoom);
TRACE("zoom %d\n", vZoom.lVal);
//kill the timer
KillTimer(timer_id);
}
}

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.

MessageBox does not work in a catch of an exception

Well I have 2 issues but my main concern right now is my catch exception. Here is the code...
int GXRenderManager::Ignite(HINSTANCE * hinst, int * nCmd, GXDEVICE DeviceType, int width, int height)
{
try
{
GXRenderManager::hinstance = hinst;
GXRenderManager::nCmdShow = nCmd;
GXRenderManager::height = height;
GXRenderManager::width = width;
InitWindows();
switch(DeviceType)
{
case DIRECTX:
GXRenderManager::renderDevice = new GXDX;
break;
case OPENGL:
GXRenderManager::renderDevice = new GXGL;
break;
default:
throw GXException(L"Error Finding Video Device");
}
Device()->StartUp(GXRenderManager::mainWindow ,width, height); //Error happens here
}
catch(GXVideoException &e)
{
MessageBox(0,e.pReason,L"GXVideoException",1);//Catch happens but no message box
return 0;
}
catch(GXWindowsException &e)
{
MessageBox(0,e.pReason,L"Windows Error",1);
return 0;
}
catch(GXException &e)
{
MessageBox(0,e.pReason,L"Error",1);
return 0;
}
return 1;
}
Here is where the error happens
void GXDX::StartUp(HWND* mainWindow,int w, int h)
{
width = w;
height = h;
this->mainWindow = mainWindow;
ID3D10Texture2D *backBufferSurface;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
swapChainDesc.BufferCount = 2;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.OutputWindow = *mainWindow;
swapChainDesc.Windowed = TRUE;
D3D10_DRIVER_TYPE driverType = D3D10_DRIVER_TYPE_HARDWARE;
HRESULT hr = D3D10CreateDeviceAndSwapChain(NULL,driverType,NULL,0,
D3D10_SDK_VERSION, &swapChainDesc,&swapChain,&dxDevice);
if(FAILED(hr))
throw GXVideoException(L"Problems retrieving directX device");
}
When I do a walk through. the D3D10CreateDeviceAndSwapChain returns a failure, therefore triggering the GXVideoException error.
It then catches and returns back to GXRenderManager class as shown below.
catch(GXVideoException &e)
{
MessageBox(0,e.pReason,L"GXVideoException",1);
return 0;
}
At this point in time, If I put my cursor over the &e, I clearly see my message "Problems retrieving directX device". But the message box does not show
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
if(GXRenderManager::Ignite(&hInstance, &nCmdShow,DIRECTX) != 1)
return 0;
//NEVER REACHES THE RUN METHOD BELOW YET THE MAIN WINDOW REMAINS OPEN
GXRenderManager::Run();
return 0;
}
Another thing I find strange is that my created window remains showing but never reaches the main loop. It is like the application is idle due to the message box, but the message box is not showing...
I also would like to add that the static member renderDevice is a interface datatype. GXDX is of course a implemented class of the interface.
GXDX class includes the GXException Header so it is able to throw those exceptions so the main GXRenderManager can catch them.
[EDIT]
Another thing I would like to add is if I remove the Show window method
ShowWindow(*GXRenderManager::mainWindow, *GXRenderManager::nCmdShow);
It works. So as long as my main application window is not open. My message box appears like its suppose to.
[EDIT]
Prior to dauphic response which fixed part of the problem, I went on and edited my code. My catch now looks like this
catch(GXVideoException &e)
{
MessageBox(*GXRenderManager::mainWindow,e.pReason,L"GXVideoException",1);
return 0;
}
But now my application opens and then immediately closes without displaying the box. mainWindow is a pointer to my base window. So I had to dereference the pointer.
[EDIT]
The windows pointer is bad
If a dialog is present, MessageBox should always be passed a handle to it, rather than 0. Only pass MessageBox 0 if no dialog is available.
Side note, I don't understand the exact reason for this, so it would be great if someone else could give insight.
It's also possible that your message box is being attached to your dialog, and because your dialog isn't active, the message box isn't showing. Pressing alt when it hangs may cause it to show.