i have added following coe in my view class but still it's not working.
BOOL CtestView::PreCreateWindow(CREATESTRUCT& cs)
{
if (CView::PreCreateWindow(cs))
{
WNDCLASS wc;
// Get the class information for the default MFC view class.
::GetClassInfo(AfxGetInstanceHandle(),cs.lpszClass,&wc);
// Register a new class using the attributes of the default
// view class, and make it the new default class.
cs.lpszClass = AfxRegisterWndClass(wc.style | CS_DBLCLKS,
wc.hCursor,wc.hbrBackground,wc.hIcon);
return TRUE;
}
return FALSE;
}
Is your window set to receive double click events? See this MSDN article. Quote:
An application-defined window does
not, by default, receive double-click
messages. Because of the system
overhead involved in generating
double-click messages, these messages
are generated only for windows
belonging to classes that have the
CS_DBLCLKS class style. Your
application must set this style when
registering the window class.
You can also create your own double-clicks by managing up/down events, the delta between the cursor locations of those events and the time between them.
So for example, this sequence:
Down message (save control)
start timer
less than 250 milliseconds passed
up message (on same control)
less than 250 milliseconds
Down message (on same control)
less than 250 milliseconds
up message (on same control)
= double click
If in that sequence your timeout expires or the control changes you reset your counters and variables since the action was not a double click.
Related
I am trying to set up a MFC C++ App in Visual Studio 2019 such that modifies the user's text as they are typing.
Current layout is 2 radio buttons,
ID= rdbOn (set to Group = True, with Value int variable m_isOn = 1)
ID= rdbOff, m_isOn value would be = 0
and 1 Edit Control,
ID= txtInputBox, with Value CString variable m_inputString
Currently, for testing I can see how it would work for a button on click, it would take something like the following and just SetDlgItemText of the result. But that would be after they have typed, not WHILE they are typing.
void Onsomebtnclick()
{
//convert CString to String of m_inputString
//do some string manipulation
//convert back to CString
//SetDlgItemText(txtInputBox, result)
}
Update:
got EN_CHANGE to work
I was able to get EN_CHANGE working with the flag suggestion from user #GoGoWorx. However, now I just have a slight problem that the cursor is back to the beginning of the edit control txtInput.
I'm reading about using a CEdit::SetSel but don't know how to use that directly in my code. I tried
CEdit control MFC, placing cursor to end of string after SetWindowText
someDlg::someFunction()
{
//some logic stuff to get a result string
SetDlgItemText(txtInputBox, result);
//need it to set the cursor to the end
//I tried these, but it didn't recognize (expression must have class type?)
//txtInputBox.SetSel(0, -1);
//txtInputBox.SetSel(-1);
}
It sounds like you need to use the ON_EN_CHANGE message-map notification (called after the control has been updated due to typing or pasting for example)
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_EN_CHANGE(IDC_EDIT_CONTROL, &CMyDialog::OnEnChangeEditControl)
END_MESSAGE_MAP()
void CMyDialog::OnEnChangeEditControl()
{
// Copy or call your Onsomebtnclick() here
}
I'm not sure what you're using for the numeric identifier for the edit control, since these are typically upper case defines - replace IDC_EDIT_CONTROL above with your define (possibly txtInputBox, but again, these are normally upper case, so I'm not sure).
Also change CMyDialog for the name of your dialog class too.
Note that we're using the ON_EN_CHANGE message-map handler here instead of the ON_EN_UPDATE, since the ON_EN_CHANGE message is sent after the control has been updated, whereas ON_EN_UPDATE is called just before it's updated.
The message-map handlers are described in the Remarks section of the CEdit control documentation: https://learn.microsoft.com/en-us/cpp/mfc/reference/cedit-class?view=msvc-160
Regarding your concern about modifying things as the user types - this should be fine, since every change (keystroke or paste from clipboard, etc.) should trigger this handler to be called, where you can change whatever you need. Just be sure that when you're updating the control, you don't trigger the ON_EN_CHANGE again and end up in a recursive 'change' loop.
You might be able to do this with some sort of flag to indicate you're the one updating the control, as opposed to the user, however it's probably better to subclass the CEdit control to do what you're wanting. There are a few examples out there of how to do this (it's not as difficult as it might sound), for example:
https://www.codeproject.com/Articles/27376/Avoiding-EN-CHANGE-notifications
In WPF, there is a Closing event on <Window... tag, where we can hook up some dispose code in MainWindow_OnClosing.
But there is no such event in UWP app. The closing I guess is Unloaded, not even Unloading is there.
I just placed my disposing code there but still feel concerned. Is Unloaded event supposed for this type of work? Is there something I need to take note?
According to the MSDN, the Window class has a Closed event.
I'm mentioning this as you posted the Closing event of a window component, but keep in mind the remark of the event:
The Closed event occurs when a Window closes. However, Windows Store
apps typically use a single Window instance, and do not open and close
additional Window instances.
Now, when using the Frame navigation system of the main window with Pages, I advise you to use the OnNavigatedTo and OnNavigatedFrom events to manipulate all initialisation and dispose functionality of the class.
You may want to pay attention to the OnNavigationFrom as it is invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
A really simple example:
Windows.ApplicationModel.Resources.ResourceLoader loader;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
loader = new Windows.ApplicationModel.Resources.ResourceLoader();
var navigationPageContentFormat = loader.GetString("NavigationPageContent");
var navigationPageContentWhenEmpty = loader.GetString("NavigationPageContentWhenEmpty");
this.ParameterTextBlock.Text = String.Format(navigationPageContentFormat, e.Parameter?.ToString() ?? navigationPageContentWhenEmpty);
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
loader = null;
}
Nowadays, I am working on a java swing application using DJ NativeSwing as my embed browser to do something automatic work. The scenario of my application is that a user click start button and the embed browser auto click some position of the current page and then redirect to another one and then execute some other operations like click or something other. Now here is my solution. First, I will define a webbrowser class (extends JWebBrowser) and webbrowser listener class (implements WebBrowserListener), which represents a webbrowser and contains loadingProgressChanged, windowOpening and so on separately. Second, I define a thread class to do some logic computing and execute my browser operations as mentioned above by webbrowser.executeJavascript. At last, I add mouseListener for start and stop button to start or stop the task. When I open my application, the JFrame add the browser and its listener class. I click the start button, the browser works and will click the target position as I expected and then the page will redirect to another one. As we all know, js code can’t be executed until the page was loaded completely. So I set a global flag to check whether the page has loaded completely or not in loadingProgressChanged (code:if(e.getWebBrowser().getLoadingProgress() == 100)globalflag = true;) within webbrowser listener class. And in the thread class, I use code( while(globalflag == false){Thread.sleep(500);}) after first click to detect if the current page was loaded completely. However, when browser first click the target position and the page redirects successfully, I find that the current page has changed but blocked. After some debugging, I find it. In my thread class, browser will execute js code by webbrowser.executeJavascript("document.getElementById(‘target’).click();") to click the target position and then java code (while(globalflag == false){Thread.sleep(500);}) to detect if the current page was loaded completely and then execute some other java code. I find that the globalflag will never change and the current page’s loadingProgressChanged listener will never work because the java code (while(globalflag == false)). Because after I remove all java code after the first webbrowser.executeJavascript("document.getElementById(‘target’).click();"), the current page’s loadingProgressChanged listener works and the page was not blocked. With the DJ NativeSwing demo, I could execute my js in the loadingProgressChanged. However, I want to do a series of operations with my browser and also want to stop the task whenever need. So, I prefer to my solution for my demand rather than the provided one by demo. So, I wonder that after webbrowser.executeJavascript the DJ NativeSwing thread will wait my thread? And, in my software architecture, does anyone could have any suggestions? Thanks a lot. Any suggestion is appreciated!
PS.my application works fine with jdic-0.9.5, but it supports IE7 only.
I paste my code here to demonstrate my problem:
After I click the start button in JFrame, I will new a thread as follow
public class MyVisit implements Runnable{
private void doClick1(){
webbrowser.executeJavascript("document.getElementById('n').value='test'");
webbrowser.executeJavascript("document.getElementById('f').submit()");
}
public void run() {
globalFlag=false;
webbrowser.executeJavascript("document.getElementById(‘t’).click();") ;
while(!globalFlag){
Thread.sleep(500);
}
this.doClick1();
}
}
listener:
public class MyListener implements WebBrowserListener {
…
public void loadingProgressChanged(WebBrowserEvent e) {
if (e.getWebBrowser().getLoadingProgress() == 100) {
globalFlag=true;
}
}
}
DJ Native Swing enforces the Swing approach to threading: manipulate the components in the AWT Event Dispatch thread (a.k.a. UI thread). But also, do not block that thread, because listeners are triggered in that thread too.
So, you should not have a "while" loop in the UI thread, but should instead spawn a new thread. I hope your global variable is volatile, or AtomicBoolean or all accesses to it protected by synchronized block, otherwise you might have interesting threading side effects.
I have a basic question. I have developed a Python component that just prints the value of a simple property to the console screen and a waveform that just runs the component.
I'm trying to create a component control panel that displays the current property value (a string) and also allows me to change the value of the property. When I change the value of the property, I would like the value printed to the console window to change too. My understanding is that I need to bind the property to a text box on the control panel.
I attempted to follow the binding example in section 24.4.1 of the documentation (http://redhawksdr.github.io/Documentation/mainch24.html), by adding their bind code to the refresh() function that was automatically generated by the SCA Component Control Panel wizard. However, when I view the control panel, I get the error:
An internal error occurred during: "Refresh Component".
null argument: Validation realm cannot be null
I am fairly new to Java, but my guess is that I'm receiving the error because there was some problem when creating the local copy of the SCA component (variable named "component" in the code below).
Here is my control panel code:
public void createPartControl(final Composite main) {
main.setLayout(new GridLayout(2, false));
propValue = new Text(main, SWT.BORDER);
propValue.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
}
public void refresh() {
Job refreshJob = new Job("Refresh Component") {
#Override
protected IStatus run(IProgressMonitor monitor) {
// bind text box to component property value
final ScaComponent component = getInput();
EMFDataBindingContext context = new EMFDataBindingContext();
IObservableValue observable = SCAObservables.observeSimpleProperty(component,"someText");
context.bindValue(WidgetProperties.text().observeDelayed(5000, propValue),observable);
return Status.OK_STATUS;
}
};
refreshJob.setSystem(true);
refreshJob.schedule();
}
For reference, I am running REDHAWK version 1.8.2 on RHEL 5.8.
I believe the problem here is you are trying to create a binding from within a Job.
Creation of bindings should be done within the SWT thread. The error you are getting is indicating that was unable to acquire a realm to execute within. If this code is executed within the SWT thread it will correctly acquire the SWT realm.
Text propValue = new Text(main, SWT.BORDER);
EMFDataBindingContext context = new EMFDataBindingContext();
IObservableValue observable = SCAObservables.observeSimpleProperty(component, "simplePropId");
context.bindValue(WidgetProperties.text().observeDelayed(5000, propValue), observable);
Notice in the example how the bindings are immediately created. This ensures the bindings are within the correct realm.
Control panels will have the input model change occasionally. Therefore it may be necessary to create the bindings within the refresh or setInput methods. These methods are also called from the SWT thread.
Note you should free the old context before rebinding to the new model by using context.dispose and creating a new context.
For an example on how data bindings work checkout: http://www.vogella.com/articles/EclipseDataBinding/article.html
I use the scrollview to display multipage view, which have more than 10 pages. (scrollview.PageEnabled=true)
And every single page in scrollview has about 6 sub-view(named:ABCUI) which every one is loaded from nib :
this.scrollview.DecelerationEnded+= scrollView_DecelerationEnded(...);
public void LoadSubView(int nPageNo)
{
if (this.PageLoaded(nPageNo))
return;
for (int i=0;i<6;i++)
{
ABCViewController abcUI=MonoTouch.Foundation.NSBundle.MainBundle.LoadNib ("ABCUI", this, null); //XIB file size: 20K
abcui.SetTitle(...);
abcui.SetXXXX(...);
abcui.frame = .. pageFrame.X += this.ScrollView.Frame.Width+nPage*...;
this.scrollview.addsubview(abcUI.view,...);
}
}
public void scrollView_DecelerationEnded (object sender, EventArgs e)
{
int nPageNo=(int)Math.Ceiling((this.ScrollView.ContentOffset.X+1)/this.ScrollView.Frame.Width);
this.LoadSubView(nPageNo +1);
this.LoadSubView(nPageNo - 1);
}
public void Button1Clicked(object sender, EventArgs e)
{
this.ClearViewsInScrollView();
this.LoadSubView(1);
}
When the user trigger the button1 click, it will load the first page into scrollview(only 1 page oncetime, but 1 page has 6 sub-view), and when user scroll the scrollview , it will load the next page.
But it will take a long time when load the first page or switch page in scrollview , so the user must waiting:
ipad1: about 1000ms
iPad2: about 600ms
in simulator: 100ms;
how to optimize the performance(reduce to less 300ms/ipad1)?
Very good question and excellent timing, since I have been working on something like this the past few days.
Now, I am not sure if this solution will get you < 300ms loading, however in theory it is faster.
(You'll see both "XIB" and "NIB" terms. I am referring to the same thing. After all, a NIB is a "compiled" XIB.)
The key to the whole thing is to prevent loading of each XIB file multiple times. There is no reason for it, since what you (we) basically need from it, are instances from the objects in the XIBs, and not the XIBs themselves occupying memory.
Fortunately, the iOS SDK provides the UINib class which can do what we want. With this class, we can create multiple instances of the contents of a XIB, without having to load the XIB itself each time, just once in the "beginning".
Here's how to do it:
First, create a UINib object for each XIB file you want.
// Loads a NIB file without instantiating its contents.
// Simplified here, but to have access to a NIB for the whole lifecycle of the app,
// create a singleton somewhere.
static UINib abcuiNib = UINib.FromName("ABCUI", NSBundle.MainBundle);
Second, after you have loaded the NIB into memory, you can now get the objects from it.
abcuiNib.InstantiateWithOwneroptions(this, new NSDictionary());
Note the "this" parameter. Since it is a view controller you want to load, the above line should be somewhere early in the object's life cycle, eg in the constructor:
public partial class ABCViewController : UIViewController
{
public ABCViewController()
{
// The first parameter is needed to set an owner (File's Owner) for the objects
// that will be instantiated.
// The second parameter is for various options. It does not accept null in MonoTouch,
// but you can just pass an empty NSDictionary.
// If you have all your outlets correctly set up, the following line is all
// that is needed.
abcuiNib.InstantiateWithOwneroptions(this, new NSDictionary());
}
// We don't need the following, as it will load the XIB every time
//public ABCViewController() : base("ABCUI", null) {}
// view controller implementation
}
Mind you, I have not tested the above, as so far I have tested it with various single objects in XIBs. If (and when) I use it with UIViewControllers in XIBs, this is the direction I will move in. I'll also prepare an article with more in-depth findings and info in due time.
Also note that the same "rules" apply, eg. you will still have to release all outlets in the ViewDidUnload override.
If after this, you do not find any improvement in performance, I think you will need to redesign your XIBs. Apple suggests it is better to have multiple XIBs with few objects in each one, instead of few XIBs packed with objects.
Useful reading: Apple docs on NIB management