I will try to implement a script that will fill some fields when the user press a button.
In SAP GuiSession Object documentation, I don't understand what "record mode" is.
Change Public Event Change( ByVal Session As GuiSession, ByVal Component As GuiComponent, ByVal CommandArray As Variant )
In record mode, the session collects changes to elements of the user interface and sends these changes to a listening application whenever server communication is about to start or if the record mode is turned off. The change events are raised immediately before the startRequest event. There is at least one event for every modified element in the recorded session.
Look right above in GuiSession Object:
Record (Read-write)
Public Property Record As Byte
Setting this property to True enables the recording mode of the session. In this mode changes to elements of the user interface are recorded within SAP GUI and sent to a recording application using the Change event described later.
Related
I am writing an application in VB.Net in which a user can schedule emails to be sent in the future. Is there a way to keep my listener thread running in the background after the base form on the application is closed? I would also need to start up the listener when the system boots, but wouldn't want any forms to open at that time.
Example (desired) functionality: I open the application in the morning and schedule three emails, one of which should be sent in three hours, and the other two of which should be sent tomorrow morning. I close the application. In three hours, the first one sends. At the end of the day, I shut down my machine. When I turn it back on tomorrow morning, the other two are sent without me ever opening the application.
I am thinking I need to separate the listener into a service, but want to make sure there isn't an easier way before going down that road.
If I do end up having a separate service and application, can I create an installer that will install both at once?
In the options of your project, set the “Startup Object” to “Sub Main” instead of of a form name. You might have to disable the setting “Application Framework” first.
Now you have to launch the form manually because it’s no longer done automatically, but on the other hand you can now control when to launch it, and your application will exit when it reaches the end of the Main method (or when it’s quit explicitly) rather than when the form closes.
If all you want is to keep the program running, you could supply it with the definition for a TaskBar icon, and represent state in your application using the icon's graphic. It would appear over on the right next to the system clock.
Then it's just a matter of reconfiguring your development project so that the application close event is triggered off that icon's menu instead of off the fact that the form is closed.
Use a NotifyIcon control and when the user close the mainform capture the OnClosing Event to Ask the Question if he want to minimize to the tray or exit the application.
Here is the documentation of NotifyIcon control from Microsoft:
NotifyIcon Control
I have a possible solution for you here. In the form closing event you can place the following code:
Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Me.Visible = False
e.Cancel = True
End Sub
This will hide the form and allow it to run in the background until you shutdown the computer. To handle the restart and then send emails I'd suggest adding the emails to be sent to a text file that can be accessed after restart and then adding the program to startup. An even better solution might be to have 2 programs, one that is on startup and is always hidden that checks the text file every 15 minutes (for example) and a second program that is launched when a new email is to be added to the list and it appends the text file with new emails to be sent.
(Sorry if i am wrong, just proposing a probable solution here)
I think attaching a simple db to hold the email sending schedule information/date-time and loading the application at startup with Notification Icon (or without Notification Icon but with a shortcut to show user interface/form to feed the emails and schedule information/date-time, if required + BackgroundWorker, if you want the application to go to sleep mode and wake it later to send first scheduled email; after X hours). After sending first email update the db then exit the application. Check the db on startup to send the first email or go to sleep mode if pc boots before sending first email. But, if first email is already sent then send other two scheduled emails (check db date-time). This should do the job...
:)
I'd like to create a listener in my app that will be notified when the user sets focus to a text input element in any application (essentially to be notified when there is a blinking text cursor in the frontmost app). I am trying to use this to notify an external hardware device that the user wants to input text, and to switch to text input mode.
I've been through NSObserver, the shared workspace notificationCenter, etc, and not found anything like this. Is it possible?
I suppose I could try constantly polling the current focus object, but I'd rather have a listener.
I have created an application that starts when windows starts (on startup) but i want to unload my form or close my vb application securely without losing data
The FormClosing event should be the place where you handle expected or unexpected closing of your forms.
This event receives a FormClosingEventArgs that contains the reason for the shutdown of your form.
There is also a more generic Application.ApplicationExit but it lacks the details given by the FormClosingEventArg parameter passed to the FormClosing event.
How you handle the data that need to be saved could be the discriminant factor in choosing between the two methods.
I have a vb.net based windows application, where when "GO" button is clicked a bunch of data is loaded into DB. So in my application as soon as "GO" button is clicked I want to just disable it and would like to enable it back when the uploading has completed.
Now in my specific method for btnGo_Click() I have:
btnGo.Enabled = False
as first line and
btnGo.Enabled = True
as last line in the same method.
But I fail to understand why the "GO" though appears as being disabled still allows click when processing is going on. Also if I remove the last line, it gets disabled permanently and doesn't allow the click event.
Kindly suggest what am I doing wrong?
Edit (Dated: 25th Jan 2012): I made changes as suggested by our collegues, but I am facing a new issue here. I am facing an issue where the textbox gets updated but not always. I have updated my textbox in "_ProgressChanged" event of the background worker thread. In my case if there is 10 records uploaded. Then there are 10 lines of updates that are expected in the texbox. But only few lines are shown in the textbox. Is it the repaint issue again? Kindly suggest...Because all other things are done as per your suggestion
You're not doing anything wrong. The problem is that the UI doesn't get updated until the code inside of your event handler method finishes executing. Then, the button is disabled and immediately enabled in rapid sequence.
That explains why if you forget to reenable the button control at the end of the event handler method, it is still disabled—because you told it to disable the button in the first line of the method.
This is a classic case of why you should never perform long-running computational tasks inside of an event handler method, because it blocks the UI from being updated. The computation actually needs to happen on a separate thread. But don't try to create the thread manually, and definitely don't try to update your UI from a separate thread. Instead, use the BackgroundWorker component to handle all of this for you automatically. The linked MSDN documentation has a great sample on how to use it.
Disable the button before starting the BackgroundWorker, and then re-enable it in its Completed event, signaling the completion of your database load.
Since you're trying to execute a function that can take some time, I'd advise you to make use of threading. In .NET there's a BackgroundWorker component which is excellent for performing tasks asynchronous.
On button click, invoke the BackgroundWorker like this:
if not bgwWorker.IsBusy then
btnGo.enabled = false
bgwWorker.RunWorkerAsync()
end if
And use the completed event to enable the button again:
Private Sub bgwWorker_DoWork(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles bgwWorker.DoWork
' Do your things
End Sub
Private Sub bgwWorker_RunWorkerCompleted(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles bgwWorker.RunWorkerCompleted
' Called when the BackgroundWorker is completed.
btnGo.enabled = true
End Sub
In the example above, I've used bgwWorker as the instance of a BackgroundWorker.
The button click event is handled as soon as the UI thread has idle time.
After you disable your button, the UI thread is keept busy by your code. At the end of your method, you re-enable the button, and after that you exit the method and allow for idle time.
As a consequence, the button will already be enabled at the point in time where the click event is handled, so your click is "recognized".
The solution is, as others already suggested, to use a Backgroundworker.
Dont try to use doEvents() as a solution (never do), since this would be prone to introduce other subtle problems. That said, you can prove the above explanation with some experimental doEvents in your code. You will see that the click is discarded if a doEvents is performed before the button gets re-enabled. On the other hand, performing a doEvents directly after the button.disable (to "update the GUI") will not help if it is executed before the click.
If your btnGo_Click() is ran inside main thread, UI could not be updated correctly inside a time-consuming task.
The best way you can do what you need is running your method in a BackgroundWorker.
I just tried disabling a button, Updateing the form, Sleeping, and enabling it again. It still performed the click (A click that was done while it "slept" with the button disabled) after it was enabled.
I guess forms "remember" clicks.
(EDIT: I did this in C#.)
It's usually not a good idea to manage the state of a submit button. Instead, perform validation on submit.
I would like to add 2 enhancements to the answer generally described here which is to 'do the work in another thread'.
Ensure button.enable=true always gets called
1.a. You should use a try block in button_click . If there is an error in launching the thread, CATCH should re-enable the button.
1.b. The task complete call back should also ensure the button is enabled using try/catch/finally
1.c The task timeout should also re-enable the button
A common error based on exactly the situation described here is rapid-clicker-person clicks the button twice in rapid succession.
This is possible because its possible, even if unlikely, that 2 click messages get queued and processed before the button is disabled. You can not assume the events happen synchronously.
IMHO a best practice is to use a static variable. Initialize it to 0. Set it to one as the very first statement and set it to 0 following the guidelines in POINT 1.
The second statement in button click should simply RETURN/EXIT if the value > 0
If you are using a worker thread, the static variable may have to be located in that code. I would not advise making it a form level variable.
I had a slightly different issue not being able to call click.
I have a routine that turns the UI on/off based on a validation routine.
i will say that I disagree w/ the suggestion to do validation in the submit. The button should not be enabled if we are able to tell the form is invalid.
My issue was that I was calling the validation from several places. One of the calls was the CustomCellDraw event of a grid which was firing very frequently.
So while it appeared that I was simply disabling/enabling the button a few times, I really was doing this almost continually.
I was able to trouble shoot by placing a label on the form and kind of doing a console.log thing. I immediately realized button.Enabled was flickering, which led me down the correct trouble shooting path.
I realize this addresses a different root cause than op described. But it does address the problem the op describes.
I have a series of methods being called for my networking code. An event gets fired from the networking thread. Inside this event, which I've hooked into from a singleton class, I route messages to form level methods which they register on form load to handle certain messages they care about. Inside of these form message hooks I need to close the current form (which I was able to do) but also show a different one (which is giving me the trouble).
The new form sort of shows but it's hanging/not updating. I'm sure this has something to do with that form because it's .Show() was basically called from another thread (sort of) doesn't have a message loop, but I'm not sure how else to solve this. The network message that gets received indicates on the client machine what forms to close and show.
The flow might be confusing so I'll try better to explain.
Login form attaches user defined functions inside that form to a singleton class list of messages. For example when a message called LOGIN_STATUS is fired I assign a function from the Login form to a list defined in this singleton class.
The singleton class has the network class defined in it which actually runs on another thread, but this is all handled inside the class. In the private ctor I subscribe to the OnData event of this network class.
When OnData gets fired from the network class to the singleton class it passes to it the type of data. I loop through the list of function pointers to see if any of them are linked to LOGIN_STATUS and if so call them. This will call the Login forms function. Inside that function I need to close the Login form and open the Lobby form. That's when the Lobby form shows, but is hung up and not updating.
Hope that makes sense.
This is all being done in VB.NET where I have the "close when last form closed" setting on which is what I want. VB.NET also makes it easier to manage forms since I can just for formname.Show() instead of having to keep a list of the forms and manage them myself like in C# so if that's still possible with the solution that would be ideal.
If you want to ensure all forms are created on the same thread, and hence the same message loop, use the main from's Invoke method. The Form.Invoke and Form.BeginInvoke methods cause the code to run from the form's message loop. BeginInvoke allows the event calling thread to return immediately, where-as Invoke blocks the event thread until the method is complete. It depends how time sensitive your code is.
Private Sub OpenFormEvent(sender As Object, e As EventArgs)
If MainForm.InvokeRequired Then
Dim args As Object() = {sender, e}
MainForm.BeginInvoke(New EventHandler(AddressOf OpenFormEvent), args)
Else
Dim SecondForm As New Form()
SecondForm.Show()
End If
End Sub