I am writing a chrome plugin in which I want to register click event, means whenever we click on DOM window, the handler inside plugin will be called. For that I am using CPlugin class. The constructor is called from NPP_New(/argument/).
When I run the browser and click anywhere, I noticed that ScriptablePluginObject's HasProperty and GetProperty function called with identifier name "handleEvent".
I don't understand how to handle the event.
Can anyone guide me please?
/////////////CODE///////////////////
static NPIdentifier sFunction_id;
// Called from NPP_New()
CPlugin::CPlugin(NPP pNPInstance) :
m_pNPInstance(pNPInstance),
m_pNPStream(NULL),
m_bInitialized(FALSE),
m_pScriptableObject(NULL)
{
bool boRet;
NPError rv;
char szText[300];
LogMessage("CPlugin::CPlugin::Enter");
sFunction_id = NPN_GetStringIdentifier("handleEvent");
rv = NPN_GetValue(m_pNPInstance, NPNVWindowNPObject, &sWindowObj);
if (NPERR_NO_ERROR != rv)
{
LogMessage("CPlugin::CPlugin::NPN_GetValue() failed.");
}
NPObject *scriptObj = NPN_CreateObject(m_pNPInstance, GET_NPOBJECT_CLASS(ScriptablePluginObject));
if (!scriptObj)
{
LogMessage("CPlugin::CPlugin::NPN_CreateObject failed");
}
NPVariant params[3];
// arg0: event type
STRINGZ_TO_NPVARIANT("click", params[0]);
// arg1: listener
params[1].type = NPVariantType_Object;
params[1].value.objectValue = scriptObj;
// arg2: useCapture
params[2].type = NPVariantType_Bool;
params[2].value.boolValue = true;
NPIdentifier addEventListener_id = NPN_GetStringIdentifier("addEventListener");
NPVariant result_add;
// windowObject.addEventListener("click", listener, false);
if (!NPN_Invoke(m_pNPInstance, sWindowObj, addEventListener_id, ¶ms[0], 3, &result_add))
{
LogMessage("CPlugin::CPlugin::NPN_Invoke for addEventListener failed");
}
NPIdentifier removeEventListener_id = NPN_GetStringIdentifier("removeEventListener");
NPVariant result_remove;
// windowObject.removeEventListener("click", listener, false);
if (!NPN_Invoke(m_pNPInstance, sWindowObj, removeEventListener_id, ¶ms[0], 3, &result_remove))
{
LogMessage("CPlugin::CPlugin::NPN_Invoke for removeEventListener failed");
}
NPN_ReleaseVariantValue(&result_add);
NPN_ReleaseVariantValue(&result_remove);
NPN_ReleaseObject(scriptObj);
const char *ua = "This is test plugin";//NPN_UserAgent(m_pNPInstance);
strcpy(m_String, ua);
LogMessage("CPlugin::CPlugin::Exit");
}
// In HasProperty and GetProperty, nothing has been done.
bool
ScriptablePluginObject::HasProperty(NPIdentifier name)
{
LogMessage("ScriptablePluginObject::HasProperty");
char *nam = NPN_UTF8FromIdentifier(name);
LogMessage(nam);
NPN_MemFree(nam);
return true;
}
bool
ScriptablePluginObject::GetProperty(NPIdentifier name, NPVariant *result)
{
LogMessage("ScriptablePluginObject::GetProperty");
char *nam = NPN_UTF8FromIdentifier(name);
LogMessage(nam);
NPN_MemFree(nam);
return true;
}
///////////CODE///////////
Both of the above classes are taken from google code. I am only adding event listener on NPObject.
What is wrong with it? Any idea?
-Abhay
Your on the track, but you require some more changes:
Create a brand new NPClass, you can name this MouseClickEvent or some sort.
Implement your mouse event listener functionality in the InvokeDefault of the MouseClickEvent class.
Now with NPN_CreateObject create your NPObject from the instance of MouseClickEvent
You pass that NPObject as a second parameter to the addEventListener you mentioned above.
Hope that helps!
Related
The program returns: CANCELED: Reason=Error ErrorDetails=WebSocket Upgrade failed with an authentication error (401). Please check for correct subscription key (or authorization token) and region name. SessionId: cbfcdf7f26304343a08de6c398652053
I'm using my free trial subscription key and westus region. This is the sample code found here: https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/quickstarts/speech-to-text-from-microphone?tabs=unity%2Cx-android%2Clinux%2Cjava-runtime&pivots=programming-language-csharp
using UnityEngine;
using UnityEngine.UI;
using Microsoft.CognitiveServices.Speech;
#if PLATFORM_ANDROID
using UnityEngine.Android;
#endif
#if PLATFORM_IOS
using UnityEngine.iOS;
using System.Collections;
#endif
public class Helloworld : MonoBehaviour
{
// Hook up the two properties below with a Text and Button object in your UI.
public Text outputText;
public Button startRecoButton;
private object threadLocker = new object();
private bool waitingForReco;
private string message;
private bool micPermissionGranted = false;
#if PLATFORM_ANDROID || PLATFORM_IOS
// Required to manifest microphone permission, cf.
// https://docs.unity3d.com/Manual/android-manifest.html
private Microphone mic;
#endif
public async void ButtonClick()
{
// Creates an instance of a speech config with specified subscription key and service region.
// Replace with your own subscription key and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("yourSubscriptionKey", "yourRegion");
// Make sure to dispose the recognizer after use!
using (var recognizer = new SpeechRecognizer(config))
{
lock (threadLocker)
{
waitingForReco = true;
}
// Starts speech recognition, and returns after a single utterance is recognized. The end of a
// single utterance is determined by listening for silence at the end or until a maximum of 15
// seconds of audio is processed. The task returns the recognition text as result.
// Note: Since RecognizeOnceAsync() returns only a single utterance, it is suitable only for single
// shot recognition like command or query.
// For long-running multi-utterance recognition, use StartContinuousRecognitionAsync() instead.
var result = await recognizer.RecognizeOnceAsync().ConfigureAwait(false);
// Checks result.
string newMessage = string.Empty;
if (result.Reason == ResultReason.RecognizedSpeech)
{
newMessage = result.Text;
}
else if (result.Reason == ResultReason.NoMatch)
{
newMessage = "NOMATCH: Speech could not be recognized.";
}
else if (result.Reason == ResultReason.Canceled)
{
var cancellation = CancellationDetails.FromResult(result);
newMessage = $"CANCELED: Reason={cancellation.Reason} ErrorDetails={cancellation.ErrorDetails}";
}
lock (threadLocker)
{
message = newMessage;
waitingForReco = false;
}
}
}
void Start()
{
if (outputText == null)
{
UnityEngine.Debug.LogError("outputText property is null! Assign a UI Text element to it.");
}
else if (startRecoButton == null)
{
message = "startRecoButton property is null! Assign a UI Button to it.";
UnityEngine.Debug.LogError(message);
}
else
{
// Continue with normal initialization, Text and Button objects are present.
#if PLATFORM_ANDROID
// Request to use the microphone, cf.
// https://docs.unity3d.com/Manual/android-RequestingPermissions.html
message = "Waiting for mic permission";
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
{
Permission.RequestUserPermission(Permission.Microphone);
}
#elif PLATFORM_IOS
if (!Application.HasUserAuthorization(UserAuthorization.Microphone))
{
Application.RequestUserAuthorization(UserAuthorization.Microphone);
}
#else
micPermissionGranted = true;
message = "Click button to recognize speech";
#endif
startRecoButton.onClick.AddListener(ButtonClick);
}
}
void Update()
{
#if PLATFORM_ANDROID
if (!micPermissionGranted && Permission.HasUserAuthorizedPermission(Permission.Microphone))
{
micPermissionGranted = true;
message = "Click button to recognize speech";
}
#elif PLATFORM_IOS
if (!micPermissionGranted && Application.HasUserAuthorization(UserAuthorization.Microphone))
{
micPermissionGranted = true;
message = "Click button to recognize speech";
}
#endif
lock (threadLocker)
{
if (startRecoButton != null)
{
startRecoButton.interactable = !waitingForReco && micPermissionGranted;
}
if (outputText != null)
{
outputText.text = message;
}
}
}
}
The sample code you pasted above still has the placeholder values for region and subscription key. Just double checking that you did in fact replace those strings with your own subscription key and region? If that's true, can you please turn on logging, run the code again, and then provide the log? We can help diagnose from there...
To turn on logging, see https://aka.ms/speech/logging.
I've got a GUI with a TabControl. Each new TabPage is created via a new Thread. I want to call this->tabControl->TabCount, but the tabControl is owned by a thread other than the one I'm calling from. Therefore, I need to Invoke a delegate. However, all the examples I find online show printing to std::cout from each of the delegate methods. I need a return value, in this case an int.
delegate int MyDel();
int InvokeTabCount()
{
if (this->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &MyTabControl::InvokeTabCount);
auto temp = this->Invoke(del); // can't just "return this->Invoke(del)"
return temp; // Invoke() returns a System::Object^
}
else
{
return this->tabControl->TabCount;
}
}
void CreateNewTab()
{
// do stuff
this->tabControl->TabPages->Insert(InvokeTabCount() - 1, myNewTab); // insert a tab
this->tabControl->SelectTab(InvokeTabCount() - 2); // OutOfBounds and tabPageNew
}
System::Void MethodToAddNewTabPage() //actually a click event but whatever
{
System::Threading::Thread^ newThread =
gcnew System::Threading::Thread(
gcnew System::Threading::ThreadStart(this, &MyTabControl::CreateNewTab));
newThread->Start();
}
Currently, my InvokeTabCount() method is returning -1 when I simply this->Invoke(del) without returning it. And I am unable to return it because my method expects to return an int instead of a System::Object^ which is what Invoke() returns. However, when debugging I find that auto temp contains the value 2 which is correct. And temp->ToString() contains the value "2" which would also be correct.
How do I return this->Invoke(del)?
Do I need to set the value of a global variable from within my InvokeTabCount() method? I suppose I could find a way to translate from System::String^ to std::string to utilize std::stoi(), but that seems like an odd workaround.
Current solution:
delegate int MyDel();
int InvokeTabCount()
{
if (this->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &MyTabControl::InvokeTabCount);
auto temp = this->Invoke(del);
return int::Parse(temp->ToString());
}
else
{
return this->tabControl->TabCount;
}
}
The result is an integer, boxed and contained in an Object^ reference. You should be able to simply cast it to int.
If you want to be extra safe, do a null check and verify that temp->GetType() returns int::typeid, but that's probably overkill since you're creating the delegate (still in the typed form) right there.
I want to add an event handler to the "go" button on the UIKeyboard that appears when entering into an EntryElement. Here is my code
EntryElement cPassword;
//
cPassword = new EntryElement (" ", "Password", "", true) {
ReturnKeyType = UIReturnKeyType.Go
};
//
cPassword.ShouldReturn += () => { Login (); };
The Login method return void and performs a basic logging operation with the entry details provided by the user.
private void Login ()
{
// Do login stuff
//
}
But I think it requires a method of return type func as this is the error message I get when trying to use the current code:
Not all code paths return a value in anonymous method of type 'System.Func<bool>'
(CS1643)
This is the first time I've come up against this type of thing, never seen func<> before :/ and hope that someone could point me in the right direction to using it correctly. Thanks!
Your anonymous method should return a bool:
cPassword.ShouldReturn = () => {
Login();
return true;
};
Also note that since ShouldReturn is a property of a delegate type, the best practice is to assign the value, not add to it like you would do with events ("+=").
I have a class with a method (CreateDocument) that fires an event at the end. The event args contain a FixedDocument. In my MainWindow code I try to set a DocumentViewer's Document like:
void lpage_DocCreated(object sender, LabelDocumentEventArgs e)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new DispatcherOperationCallback(delegate
{
FixedDocument fd = e.doc;
documentViewer1.Document = fd;
documentViewer1.FitToWidth();
return null;
}), null);
}
I receive "The calling thread cannot access this object because a different thread owns it." on line documentViewer1.Document = fd;
I am able to update a progress bar in another event handler that the same method fires while it is working:
Int32 progress = Int32.Parse(sender.ToString());
progBar.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new DispatcherOperationCallback(delegate
{
progBar.Value = progress;
return null;
}), null);
I can't figure out why I can't set the document when I'm essentially doing the same type of thing when I set the progress bar value.
The FixedDocument element also has thread-affinity. So if you are creating it in a separate thread than the documentViewer1, then you would get that exception.
Basically, anything that derives from DispatcherObject has a thread-affinity. FixedDocument derives from DispatcherObject, just like the viewer controls.
From a modal MFC dialog, I want to extract text from an edit box after the dialog is closed. I attempted this:
CPreparationDlg Dlg;
CString m_str;
m_pMainWnd = &Dlg;
Dlg.DoModal();
CWnd *pMyDialog=AfxGetMainWnd();
CWnd *pWnd=pMyDialog->GetDlgItem(IDC_EDIT1);
pWnd->SetWindowText("huha max");
return TRUE;
It does not work.
The dialog and its controls is not created until you call DoModal() and as already pointed, is destroyed already by the time DoModal() returns. Because of that you cannot call GetDlgItem() neither before, nor after DoModal(). The solution to pass or retrieve data to a control, is to use a variable in the class. You can set it when you create the class instance, before the call to DoModal(). In OnInitDialog() you put in the control the value of the variable. Then, when the window is destroyed, you get the value from the control and put it into the variable. Then you read the variable from the calling context.
Something like this (notice I typed it directly in the browser, so there might be errors):
class CMyDialog : CDialog
{
CString m_value;
public:
CString GetValue() const {return m_value;}
void SetValue(const CString& value) {m_value = value;}
virtual BOOL OnInitDialog();
virtual BOOL DestroyWindow( );
}
BOOL CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
SetDlgItemText(IDC_EDIT1, m_value);
return TRUE;
}
BOOL CMyDialog::DestroyWindow()
{
GetDlgItemText(IDC_EDIT1, m_value);
return CDialog::DestroyWindow();
}
Then you can use it like this:
CMyDialog dlg;
dlg.SetValue("stackoverflow");
dlg.DoModal();
CString response = dlg.GetValue();
Open your dialog resource, right-click on the textbox and choose "Add variable", pick value-type and CString
In the dialog-class: before closing, call UpdateData(TRUE)
Outside the dialog:
CPreparationDlg dlg(AfxGetMainWnd());
dlg.m_myVariableName = "my Value";
dlg.DoModal();
// the new value is still in dlg.m_myVariableName
DoModal() destroys the dialog box before it returns and so the value is no longer available.
It's hard to tell why you are setting m_pMainWnd to your dialog. To be honest, I'm not really sure what you are trying to do there. That's bound to cause problems as now AfxGetMainWnd() is broken.
Either way, you can't get the dialog box's control values after the dialog has been destroyed.
I often use
D_SOHINH dsohinh = new D_SOHINH();
dsohinh.vd_kichthuoc=v_kichthuocDOC;
dsohinh.vd_sohinh=v_soluongDOC;
if(dsohinh.DoModal()==IDOK)
{
v_soluongDOC=dsohinh.vd_sohinh;
v_kichthuocDOC=dsohinh.vd_kichthuoc;
}
SetModifiedFlag(true);
UpdateAllViews(NULL);
With dsohinh is Dialog form that you want to get data to mainform .
After get data then call SetModifiedFlag(true) to set view data updated.
call UpdateAllViews(NULL) to Set data to mainform
This solution may seem long, meaning that so much code has been written for this seemingly small task.
But when we have a list or tree inside the child window where all the items are created in the child window
and the items have to be moved to the parent window,
then it makes sense.
This source code can easily create a window and transfer information from the window before closing to the parents.
//copy the two functions in your code
//1- bool peek_and_pump(void)
// template<class T,class THISCLASS>
//2- void TshowWindow(int id,T *&pVar,THISCLASS *ths)
//and make two member variable
// bool do_exit;
// bool do_cancel;
//in child dialog class.
//set true value in do_exit in child dialog for exit
CchildDialog *dlg;
template<class T,class THISCLASS>
void TshowWindow(int id,T *&pVar,THISCLASS *ths)
{
T *p=pVar;
if(!p)
p= new T;
if(p->m_hWnd)
{
p->SetForegroundWindow();
}
else
{
delete p;
p= new T;
if(!(p->m_hWnd && IsWindow(p->m_hWnd)))
{
p->Create(id,ths);
if(IsWindow(p->m_hWnd))
p->ShowWindow(TRUE);
}
}
pVar=p;
}
bool peek_and_pump(void)
{
MSG msg;
#if defined(_AFX) || defined(_AFXDLL)
while(::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
{
if(!AfxGetApp()->PumpMessage())
{
::PostQuitMessage(0);
return false;
}
}
long lIdle = 0;
while(AfxGetApp()->OnIdle(lIdle++))
;
#else
if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
#endif
return true;
}
void CparentPage::OnBnClick1()
{
if(dlg)
{
dlg->DestroyWindow();
}
TshowWindow<CchildDialog,CparentPage>(IDD_DIALOG_child,dlg,this);
dlg->GetDlgItem(IDC_EDIT_1)->SetWindowText("");
dlg->m_temp_window.EnableWindow(FALSE);//enable or disable controls.
dlg->UpdateData(false);//for to be done enable of disable or else.
dlg->do_exit=false;
dlg->do_cancel=false;
while(dlg->do_exit==false)
{
peek_and_pump();//wait for dlg->do_exit set true
}
if( dlg->do_cancel==false )
{
CString str1;
dlg->GetDlgItem(IDC_EDIT_1)->GetWindowText(str1);
//or other member variale of CchildDialog
//after finish all work with dlg then destroy its.
}
dlg->DestroyWindow();
}
void CchildDialog::OnBnClickedOk()
{
UpdateData();
OnOK();
do_exit=true;
do_cancel=false;
}
void CchildDialog::OnBnClickedCancel()
{
OnCancel();
do_exit=true;
do_cancel=true;
}