What I'm trying to do is tracing Ctrl+Tab keypress on my main form using following code
<DllImport("user32.dll", PreserveSig:=False)>
Private Shared Function GetAsyncKeyState(ByVal vKey As System.Windows.Forms.Keys) As Short
End Function
Private ReadOnly Property CtrlPressed As Boolean
Get
Dim keyval As Integer
keyval = GetAsyncKeyState(Keys.ControlKey)
If keyval = 0 Then
CtrlPressed = False
Else
CtrlPressed = True
End If
End Get
End Property
But while calling the property CtrlPressed I'm getting PInvokeStackImbalance error. I'm sure with declaration of GetAsyncKeyState and also have imported InteropServices but the CtrlPressed property has something syntactically wrong. How can I solve this issue?
Thanks
A stack imbalance error almost always means that your P/Invoke definition signature is wrong. The first thing to do is check carefully all of your types and make sure that they match the documented signature for the native function. In this case, it looks good.
Except that you've set PreserveSig to False, and I'm not really sure why. As the documentation for that field indicates, it is designed for use with unmanaged methods that return an error code (for example, an HRESULT code). It instructs the runtime to automatically convert those error codes into exceptions. But the GetAsyncKeyState method doesn't return an error code, so enabling this option doesn't make a lot of sense.
The following code works fine for me:
<DllImport("user32.dll")> _
Private Shared Function GetAsyncKeyState(ByVal vKey As Keys) As Short
End Function
Private ReadOnly Property IsCtrlPressed As Boolean
Get
Dim isPressed As Short = GetAsyncKeyState(Keys.ControlKey)
Return (isPressed & &H8000) != 0
End Get
End Property
Make sure that you've paid close attention to the documentation for the GetAsyncKeyState function. Specifically, the section on return values:
If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.
The return value is zero for the following cases:
The current desktop is not the active desktop
The foreground thread belongs to another process and the desktop does not allow the hook or the journal record.
Related
Premise
Suppose that we have a class in a dll with a simple public property "OldP". In a newer version of this dll, I want to change the name of this property in "NewP". I can't simply replace the property name, because this dll is used in a lot of program and I can't change them...
I want to hide this property and show only the newer property. How is this possible?
"Browsable" attempt
Before asking this, I searched similar questions on StackOverflow and read something about Browsable, but it doesn't work. Here is my code:
Public Class Example
Private _p As Integer
<System.Obsolete("Use NewP instead", False)>
<System.ComponentModel.Browsable(False)>
Public Property OldP() As Integer
Get
Return _p
End Get
Set(ByVal value As Integer)
_p = value
End Set
End Property
Public Property NewP() As Integer
Get
Return _p
End Get
Set(ByVal value As Integer)
_p = value
End Set
End Property
End Class
When I create a new Example object, I can still see "OldP":
Where I'm wrong?
You cannot completely prevent the old property from being used, but you can hide it from IntelliSense by adding this directive: <System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)>. The OldP property will no longer be suggested, but still be accessible normally.
Beside that, I recommend you change the OldP property so that it refers not to the _p object, but to the NewP property to make future management easier, so that you don't have to worry about the deprecated version in the future.
I am attempting to use the FindWindow API using Visual Studio 2017 (.NET Framework 4.6.1) and VB.NET to retrieve the window handle for a currently running instance of Microsoft Word. I am finding that, although it has worked in the past (and is working in another area of the code) in one particular instance, although the FindWindow call is returning a value, I am not able to assign it to a variable. I have verified this in debug mode (screenshots available). I am trying to figure why the API call is not working in this particular instance.
Screenshots link: https://imgur.com/a/NuwpUyz
I have executed this call in some areas of the .NET code I am working with, so I know that it does work. I've changed the type in the definition of the "assignee" variable (from Object, to Integer, to IntPtr, etc., etc.) and rerun the application, with the same results (the "assignee" variable ends up with a value of zero, but the FindWindow call itself returns a integer value which appears to be the correct window handle.
The FindWindow API definition:
<DllImport("user32.dll")>
Public Shared Function FindWindow(ByVal strclassName As String, ByVal strWindowName As String) As Integer
End Function
The FindWindow API call:
.
.
.
Public hndMDIWord As Integer
.
.
.
.
If Word_Previously_Running Then
Try
_mdiWordApp = GetObject(, "Word.Application")
Catch ex As Exception
_mdiWordApp = New Word.Application
End Try
Else
_mdiWordApp = New Word.Application
End If
hndMDIWord = FindWindow("Opusapp", "")
If hndMDIWord <> 0 Then
SetParent(hndMDIWord, Me.Handle.ToInt32())
End If
I am expecting FindWindow to return an integer representing the window handle of the currently running instance of Word and than have that result assigned to the hndMDIWord variable. FindWindow does return the expected result, but the assignment statement for the hndMDIWord variable does not execute properly; hndMDIWord ends up with a value of zero. There is no error and no exception is thrown.
Any suggestions and/or insights will, of course, be greatly appreciated.
Regards,
Chris Fleetwood
I think the problem is: IntPtr is not compatible with Integer.
You need to declare return type as IntPtr:
<DllImport("user32.dll")>
Public Shared Function FindWindow(ByVal strclassName As String, ByVal strWindowName As String) As IntPtr
End Function
Because:
FindWindow has HWND return type
From MSDN handles are marshaled as IntPtr
Also there is a pinvoke.net website with examples of .net interop with wast majority of WinAPI functions.
Also hndMDIWord need to be declared as IntPtr and used accordingly, and other WinAPI functions need to be declared to use IntPtr for handlers too:
Public hndMDIWord As IntPtr
. . . .
If hndMDIWord <> IntPtr.Zero Then
I am learning vb.net and I'm having issues searching for what I need. I want to create a button that is "re-usable" throughout my application without needing to write code for each instance. So, what I would like to start with is take a variable in a form, example, public integer value and when this value changes I want to write to the text of a button. I know I can easily do this by writing code in the form btn_xxx.text = variable, but what if I have several buttons and each button looks at the same variable? Currently what I do is create a component which inherits a button and have a timer that on tick will look at the variable and write to the text. I'm sure there is a better way. Can anyone point me in the right direction? I know part of my problem is I don't know the nomenclature on what things are called, so hopefully I asked my question without too much confusion.
I saw this, https://www.daniweb.com/programming/software-development/threads/124842/detect-variable-change, but I don't see how to adapt that to my situation.
Here is what I have:
Private WithEvents Active_Alarm As New Nav_Active_Alarm
Then inside of a sub that calculates the count:
Active_Alarm.Count = CInt(dt_Active_Alarms.Rows.Count)
The user control:
Public Class Nav_Active_Alarm
Private mActive_Alarm_Count As Integer
Public Event Active_Alarm_Count_Changed(ByVal mvalue As Integer)
Public Property Count() As Integer
Get
Count = mActive_Alarm_Count
End Get
Set(ByVal value As Integer)
mActive_Alarm_Count = value
If Not Me.DesignMode Then
RaiseEvent Active_Alarm_Count_Changed(mActive_Alarm_Count)
test()
End If
End Set
End Property
Private Sub test()
If Not Me.DesignMode Then
If mActive_Alarm_Count = 0 Then
Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Static
'console or msgbox will work but updating the image will not
Else
Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Animation
'console or msgbox will work but updating the image will not
End If
End If
End Sub
End Class
If I write to console or add a msgbox I will see the event working. But, the image will not change. If I call the test sub from a timer it will work. Why won't the button update (by the way, I did try refresh and update in the code)?
Observer pattern is what you probably looking for.
This is quick and dirty.
Create a class to hold the variable value. Add a method that adds a button instance to a list.
Then a button that needs to know about the variable calls the register method.
When the value of the variable changes, it iterates through the list of buttons and sets the Text property of each one.
You might have jumped in a bit too deep too quick here. Google Custom data binding in .net, there's loads of built in stuff you can use. Though do it yourself is a good exercise.
A simple method to do this might be:
Create a form level list to hold the buttons you are interested in
Add the buttons you are interested in, into the list (maybe in form load or some other place where you have initialization code)
Create a private property in your form with a backing variable to hold the value you want to have applied to the buttons. In the setter portion spin through the list and set each buttons text.
Dim lstButtons As New List(Of Button)
Sub SetupButtons()
'call from form load or other init code
lstButtons.Add(btnPopulate)
lstButtons.Add(btnPopulate)
End Sub
Private _buttonText As String
Private Property ButtonText As String
Get
Return _buttonText
End Get
Set(value As String)
_buttonText = value
For Each b As Button In lstButtons
b.Text = value
Next
End Set
End Property
When you set the property - which now acts as your variable - it will update all of your textboxes for you.
I realize you mentioned without having to write code - but something has to tie things together. Even if you used the observer pattern (which is an elegant solution for this - so props to those who suggested it) you'd probably end up creating a class to hold the property and have that class implement the INotifyPropertyChanged from System.ComponentModel, and then you'd also have to have each button have a databinding for its text property to the property in the object of your class. There isn't really a way (that I can think of) to get around having to write some code for each form you do this in (though the class part you'd only have to write once of course).
I have a simple question.
Is there a difference between a one-line ReadOnly Property and a ReadOnly Property with an explicit Get Statement?
For example, In Visual Studio 2010 I used to have to do this:
Private _Message As String = ""
Public ReadOnly Property Message As String
Get
Return _Message
End Get
End Property
Public Sub New(Message As String)
_Message = Message
End Sub
But now here I am in Visual Studio 2015 and it let's me get away with this:
Public ReadOnly Property Message As String
Public Sub New(Message As String)
Me.Message = Message
End Sub
Now I wasn't trying to me lazy, I just ran across it, expecting IntelliSense to force the Get Statement. So I'm left wondering if there is a difference that I should be aware of. Is it bad practice or does it do something different?
I've managed to find tons of topics and forums about ReadOnly in C#, but I seem to be coming up dry when searching the topic regarding vb.net.
I'll appreciate any input.
Thanks! =)
Properties without explicit getters and setters are simply a syntactic convenience. There's no difference in implementation. You should generally use the second option because it makes your code more readable. Only use the first option if you need extra functionality in the getter.
The accepted answer appears to be untrue, at least for me in Visual Studio 2022.
When a property is not a constant, you have to use the multiline declaration otherwise the initial value is cached
This
Private ReadOnly Property ConnectionFile As String
Get
Return gsapppath & "\connection.txt"
End Get
End Property
returns the correct path whereas this
Private ReadOnly Property ConnectionFile As String = gsapppath & "\connection.txt"
did not include the path because the variable gsapppath was not initialized at the time the class was created, yet it was initialized at the time the property was fetched.
So it's not just a syntactic convenience, there is a functional difference.
So I am working with Coded UI to run some automated tests and one of the tests takes an extremely long time to complete.
I used breakpoints and found that after End Get in the bottom block of code, nothing happens for minutes and then finally the Assert.AreEqual completes and the test passes.
I tried changing a few playback settings but nothing changed. Does anyone know what is going on, and how I can fix it?
-The first block of code is a generated Assert method that gets called by the test
-The second block of code is called in the Assert parameters
'''<summary>
'''assert_clicked_columnhead_requestor - Use 'assert_clicked_columnhead_requestorExpectedValues' to pass parameters into this method.
'''</summary>
Public Sub assert_clicked_columnhead_requestor()
Dim uINameCell As HtmlCell = Me.UIAppWindow1.UIAppDocument.UIX978532666mkrdataTblTable1.UINameCell
'Verify that 'Name' cell's property 'InnerText' equals 'Name'
Assert.AreEqual(Me.assert_clicked_columnhead_requestorExpectedValues.UINameCellInnerText, uINameCell.InnerText)
End Sub
Public Overridable ReadOnly Property assert_clicked_columnhead_requestorExpectedValues() As assert_clicked_columnhead_requestorExpectedValues
Get
If (Me.massert_clicked_columnhead_requestorExpectedValues Is Nothing) Then
Me.massert_clicked_columnhead_requestorExpectedValues = New assert_clicked_columnhead_requestorExpectedValues()
End If
Return Me.massert_clicked_columnhead_requestorExpectedValues 'PROBLEM HERE
End Get
End Property
As requested
'''<summary>
'''click_columnhead_requestor
'''</summary>
Public Sub click_columnhead_requestor()
Dim uIRequestorCell As HtmlHeaderCell = Me.UIAppWindow1.UIAppDocument.UIRequestorCell
'Click 'Requestor' cell
Mouse.Click(uIRequestorCell, New Point(51, 23))
End Sub
Public ReadOnly Property UIAppWindow1() As UIAppWindow1
Get
If (Me.mUIAppWindow1 Is Nothing) Then
Me.mUIAppWindow1 = New UIAppWindow1()
End If
Return Me.mUIAppWindow1
End Get
End Property
Public ReadOnly Property UIX978532666mkrdataTblTable1() As UIX978532666mkrdataTblTable1
Get
If (Me.mUIX978532666mkrdataTblTable1 Is Nothing) Then
Me.mUIX978532666mkrdataTblTable1 = New UIX978532666mkrdataTblTable1(Me)
End If
Return Me.mUIX978532666mkrdataTblTable1
End Get
End Property
Coded UI does searches for precisely what is given in the search and filter properties, that operates quite fast. However, if that search fails then Coded UI does a smart match trying to find something similar and that can take a long time. It is necessary because titles etc can change a little from run to run. Changing the tests to avoid needing a smart match can dramatically improve the search speed. The general approach is to modify the search from equality to contains and to remove the part of the string that changes. A Microsoft blog explains in more detail, see http://blogs.msdn.com/b/dave_froslie/archive/2012/08/10/why-do-my-coded-ui-tests-pause-during-playback.aspx
¿? have you tried changing the value of ..
Playback.PlaybackSettings.SearchTimeout = miliseconds;
msdn playbacksettings.searchtimeout
good luck and tell us something