I am programming for Windows Phone 8.1.
When I click on a button, I Call cmdDeleteBlock_Click.
AddHandler cmdDelete(1).Click, AddressOf cmdDeleteBlock_Click
AddHandler cmdDelete(2).Click, AddressOf cmdDeleteBlock_Click
AddHandler cmdDelete(3).Click, AddressOf cmdDeleteBlock_Click
...
How can get name of button (ID) that was clicked in cmdDeleteBlock_Click.
Private Sub cmdDeleteBlock_Click(sender As Object, e As RoutedEventArgs)
' Get button name (Id) of button that clicked **here**
End Sub
You can get the name from the object received in the event handler. Stating an example in c#
protected void btn_click(object sender, RoutedEventArgs e)
{
string Name = ((Button)sender).Name;
}
Similarly you can get other properties as well.
Related
I am trying to link controls on a form that I have created in a Class Module and am having trouble getting it to work properly.
'Class Name is CustForm
Option Explicit
Private WithEvents btnTest as CommandButton
Public Function showForm()
Dim tempForm as Form
Dim formName as String
Set tempForm = CreateForm
formName = tempForm.Name
Set btnTest = CreateControl(formName,
acCommandButton,acDetail,,,300,300,1000,500)
Dim btnName As String
btnName = btnTest.Name
Docmd.RunCommand acCmdFormView
End Function
Private Sub btnTest_Click()
MsgBox "Test"
End Sub
In a separate form I create the object and call the showForm in a click event
Private Sub Command0_Click()
Dim tstForm as CustForm
set tstForm= New CustForm
tstForm.showForm
End Sub
But nothing happens when I click the button created in the CustForm
I have tried using a temporary CommandButton in the showForm and after the docmd.runcommand acCmdFormView
set btnTest = Forms(formName).Controls(btnName)
under the assumption that maybe the instance of the command button changes when the form goes to Form View. Again no joy.
However if I add this to the CustForm Class
Public Function init(lclBtn as CommandButton)
set btnTest = lclBtn
btnTest.OnClick = "[Event procedure]"
End Function
And then I delete the OnClick and add this code to the form's module
Option Explicit
Dim tester as CustForm
Private Sub Form_Open(Cancel as Integer)
Set tester = new CustForm
tester.init Me.Command0
End Sub
Then it fires the MsgBox when I click the button.
But I need to be able to eventually build a form factory class that allows me to build forms for class objects dynamically and handle the events in the object class. I would rather not make a bunch of purpose built forms for each class and have the form instantiate the class. I want to do it the other way around. Class builds the form.
Can this be done?
As can be read in the documentation of the Form.HasModule property, there are two kinds of forms and reports: lightweight forms and reports that don't have a class module and don't support events, and full forms and reports that do have a class module and support events.
This means you still have to toggle this property for it to support events:
Private WithEvents btnTest as CommandButton
Public Function showForm()
Dim tempForm as Form
Dim formName as String
Set tempForm = CreateForm
tempForm.HasModule = True
formName = tempForm.Name
Set btnTest = CreateControl(formName, acCommandButton,acDetail,,,300,300,1000,500)
btnTest.OnClick = "[Event Procedure]"
Dim btnName As String
btnName = btnTest.Name
DoCmd.RunCommand acCmdFormView
End Function
Private Sub btnTest_Click()
MsgBox "Test"
End Sub
Do note that setting Form.HasModule modifies the VB Project part of the Access database (it adds a class module), and thus every time you do this, your database will need to be recompiled. Generally, you want to avoid that, as it might lead to problems.
Instead, I recommend having a single form with a module and all the controls you might want. Then, you can move around the controls, change their caption, and resize them, bind them to table fields, and set up event handlers, all without modifying the VB Project behind the database (note that you can't add controls to a full form or change the names of controls without modifying the VB Project).
Note that a second issue is the persistence of your class object. Currently, there are no references to the class so it's destroyed. You can easily make your class persist indefinitely by using code like this:
Private WithEvents btnTest as CommandButton
Private Myself As Object
Public Function showForm()
Set Myself = Me 'Circular reference, object won't get destroyed until myself is set to nothing
For more information about gracefully handling classes with references to forms, you can see this answer by me. You should probably listen to the Form_Unload event and clean up when that occurs.
Here is the code for Form2:
Private sub regularupdate_load (sender As system.object, e as system..eventargs) handles maybase.Load
Txtusername.text = Form1.txtusername.Text
End sub
You can do it with saving text of textbox in a Module. So in your solution explorer, right click and click choose Add => Module... Then choose a name for your module. When, in your module create a public string like this:
Public UserNameSaved As String
Then and form1 closing write:
UserNameSaved = txtusername.Text
and on form2 load:
Txtusername.Text = UserNameSaved
I have a form with numerous images, each of which performs a series of actions when clicked. I can create a Private Sub with all of the actions for each button, however I think this is inefficient. Rather, I'd like to record all the actions in one Macro and then call this Macro when each image is clicked. To do so, I'd need the single Macro to refer to the current image selected and not refer to any image by name. Is this possible?
My current code includes the following:
Me.Image001.BorderColor = RGB(1, 1, 1)
Me.Image001.BorderWidth = 2
Me.Image001.BorderStyle = 1
I'd need to amend this so that it amends the border colour/width/style etc of whichever image is selected, and not a specific named image ('Image001').
Thanks!
You should use event sinking.
With event sinking you could bind to an event your own procedures.
You can see an example here http://p2p.wrox.com/access-vba/37472-event-triggered-when-any-control-changed.html
In simple words you create a module where you bind the event to your specific implementation . Then on the form you are interested you create a collection where you register the controls you want to "follow" the event sinking...
My sub sinking for checkboxes (i have alot)
1st a class module name SpecialEventHandler
Option Compare Database
Private WithEvents chkbx As CheckBox
Private m_Form As Form
Private Const mstrEventProcedure = "[Event Procedure]"
Public Function init(chkbox As CheckBox, frm As Form)
Set chkbx = chkbox
Set m_Form = frm
'Debug.Print frm.Name
chkbx.AfterUpdate = mstrEventProcedure
End Function
Private Sub chkbx_AfterUpdate()
'your Code here
End Sub
Private Sub Class_Terminate()
Set chkbx = Nothing
Set m_Form = Nothing
End Sub
Then on the form you want to use event sinking
Option Compare Database
Dim spEventHandler As SpecialEventHandler
Private colcheckBoxes As New Collection
Private Sub Form_Open(Cancel As Integer)
Dim ctl As Control
For Each ctl In Me.Detail.Controls
Select Case ctl.ControlType
Case acCheckBox
Set spEventHandler = New SpecialEventHandler
spEventHandler.init Controls(ctl.NAME), Me
colcheckBoxes.Add spEventHandler
End Select
Next ctl
End Sub
You could always create a Standard Sub, then call it on the click of the button. Something like
Public Sub changeColor(frm As Form, ctrl As Control)
frm.Controls(ctrl.Name).BorderColor = RGB(1, 1, 1)
frm.Controls(ctrl.Name).BorderWidth = 2
frm.Controls(ctrl.Name).BorderStyle = 1
End Sub
So when you click an image all you have to do is,
Private Sub Image001_Click()
changeColor Me, Image001
End Sub
I just want to know what is the difference between "Public function" and "Function"
if anyone can help , and that will be highly appreciated..
thanks
In addition to the answer of Ekkehard.Horner, in QTP it is also possible to load Qtp Function Libraries (QFL) as .qfl or .vbs files.
A function, const or variable in a QFL that is private, can not be used in another QFL, Module or Action, while a public one can.
Functions, Constants and Variables are by default public:
' All public:
Dim MyVariable
Public MyOtherVariable
Const PI = 3.1415
Function GetHello
GetHello = "Hello"
End Function
Sub SayHello
MsgBox GetHello
End Sub
' All private:
Private myPrivates
Private Const HELLO = "HELLO!"
Private Function getHelloToo
getHelloToo = HELLO
End Function
Private Sub sayHelloToo
MsgBox getHelloToo
End Sub
Class Dog
Public Function Bark
Print "Bark! Bark! Bark!"
End Function
End Class
Yes, classes are always private in a module. You have to return it from a function to make them public available:
' Placed in the same module as Class Dog
Public Function GiveMeADog
Set GiveMeADog = new Dog
End Function
The concept of Public vs. Private accessability is best explained by using a class:
Option Explicit
Class cPubPrivDemo
Public m_n1
Dim m_n2
Private m_n3
Private Sub Class_Initialize()
m_n1 = 1
m_n2 = 2
m_n3 = 3
End Sub
Sub s1()
WScript.Echo "s1 (Public by default) called"
End Sub
Public Sub s2()
WScript.Echo "s2 (Public by keyword) called"
End Sub
Private Sub s3()
WScript.Echo "s3 (Private by keyword) called"
End Sub
Public Sub s4()
WScript.Echo "(public) s4 can call (private) s3 from inside the class"
s3
End Sub
End Class
Dim oPPD : Set oPPD = New cPubPrivDemo
WScript.Echo "Can access public member variables of oPPD:", oPPD.m_n1, oPPD.m_n2
WScript.Echo "No access to oPPD's private parts:"
Dim n3
On Error Resume Next
n_3 = oPPD.m_n3
WScript.Echo Err.Description
On Error GoTo 0
WScript.Echo "Can call public subs:"
oPPD.s1
oPPD.s2
WScript.Echo "Can't call private sub .s3:"
On Error Resume Next
oPPD.s3
WScript.Echo Err.Description
On Error GoTo 0
WScript.Echo "private sub s3 can be called from inside the class:"
oPPD.s4
From the script's output:
Can access public member variables of oPPD: 1 2
No access to oPPD's private parts:
Object doesn't support this property or method
Can call public subs:
s1 (Public by default) called
s2 (Public by keyword) called
Can't call private sub .s3:
Object doesn't support this property or method
private sub s3 can be called from inside the class:
(public) s4 can call (private) s3 from inside the class
s3 (Private by keyword) called
you can see:
A private component (variable, sub; the same holds for functions and properties) can be accessed from the inside of the component (here: class)
A public component can be accessed from the outside (not shown but probably plausible: publics can be used from the inside too)
Not specifying an access right/mode (?) explicitly (m_n2, s1) defaults to "Public"
Short answer to your question: None - because of (3)
The VBScript Docs for "Public statement" say
Declares public variables and allocates storage space. Declares, in a
Class block, a public variable.
and
Public statement variables are available to all procedures in all
scripts.
So one could research/test whether and how the accessability rules apply to (combined) scripts (source code files). As I don't know anything about QTP's handling of multiple source files, I can't help you there.
The issue of public and private would only matter when used within a class. Inside a VBScript class, the functions are public by default, therefore there would be no difference between the two. Using Private makes the function inaccessible from outside of the class.
Problem
I have a complex search form that I need to open several times (at the same time) to allow users to do multiple searches at the same time. I have found the ability to open an instance of the form (as it is a class) using:
Option Compare Database
Option Explicit
'Array to hold Form Instances
Private MyFormCollection(1 To 4) As Form_frmTest
Private Sub cmd_CloneMe_Click()
Dim intCounter As Integer
For intCounter = 1 To 4
Set MyFormCollection(intCounter) = New Form_frmTest
MyFormCollection(intCounter).Caption = "Form #" & intCounter
MyFormCollection(intCounter).Visible = True
Next intCounter
Forms!frmTest.SetFocus
End Sub
This is an example to open multiple instances of a form and not what I will use for the final code as I will only need to open one instant per click BUT will likely have other already open!
BUT I can't work out a way to one of those duplicates as an acDialog (so calling function pauses until you hide or close the new dialog form). Here is the way I would normally open a normal form (not a copy):
Call DoCmd.OpenForm("SomeForm", acNormal, , , , acDialog)
Question
How can I open a new instance of a form as an Dialog box (so calling function pauses until new form is closed or hidden)?
Thanks
You can use this code to check if a form is visible:
Private Function IsVisible(intObjType As Integer, strObjName As String) As Boolean
Dim intObjState As Integer
intObjState = SysCmd(acSysCmdGetObjectState, intObjType, strObjName)
IsVisible = intObjState And acObjStateOpen
End Function
If yes, do nothing but wait:
Do While IsVisible(acForm, "frmInfo")
DoEvents
Loop
==================
Ok, another idea: you either have the choice of opening a dialog modal and stop the code in the calling function, or live with more dialogs and have the calling function running.
I think the only way of solving this is a counter of the dialogs open, and refusing to do anything in the calling function when the count is still > 0.
You can write a public function in your called form and until that function returns (by closing the form) the calling method is blocked. In the example below clicking a "Done" button might set the return
Option Explicit
Private m_dlgResult As VbMsgBoxResult
Public Function ShowDialog() As VbMsgBoxResult
m_dlgResult = vbCancel
Me.Show vbModal
ShowDialog = m_dlgResult
End Function
Private Sub Done_Click()
m_dlgResult = vbOK
Unload Me
End Sub