VB.NET How can I popup a game-safe notification? - vb.net

How can I, in VB.NET, display a notification on-screen, such as that this will be "game-safe".
Eg: "Theres only 30 minutes left until you will be logged out!".
The notification should not take focus from the game (eg "steal input") and the notification should only be shown for like 5-10 seconds and then disappear by itself.
The notification should also be safe when talking about anticheats, like Punkbuster, VAC and such.
Any ideas?

I don't know about "game safe" as I don't know what those games are looking for to trigger an alert.
What you can do is override ShowWithoutActivation() and return true so that your form does not get focus when shown. Additionally, you can set the WS_EX_TRANSPARENT extended window style so that all mouse messages literally go right through your form. Apps underneath won't even know your form is there. Finally, set Opacity so that you can see through it partially. Oh...the timer is in there to close it after ten seconds:
Public Class frmNotification
Private WithEvents Tmr As New System.Windows.Forms.Timer
Private Sub frmNotification_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Opacity = 0.5 ' Make it so you can see thru it partially
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
' make it appear in the bottom right of the screen
Me.StartPosition = FormStartPosition.Manual
Dim rc As Rectangle = Screen.GetWorkingArea(Me)
Me.Location = New Point(rc.Right - Me.Width, rc.Bottom - Me.Height)
Tmr.Interval = TimeSpan.FromSeconds(10).TotalMilliseconds
Tmr.Start()
End Sub
Private Const WS_EX_TRANSPARENT As Integer = &H20
' Make all mouse events PASS RIGHT THRU IT:
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or WS_EX_TRANSPARENT
Return cp
End Get
End Property
' Show it without activating it:
Protected Overrides ReadOnly Property ShowWithoutActivation() As Boolean
Get
Return True
End Get
End Property
Private Sub Tmr_Tick(sender As Object, e As EventArgs) Handles Tmr.Tick
Me.Close()
End Sub
End Class

Related

How to stop a timer when mouse is scrolling or on top of scrollbar in listbox

I'm looking for a way to detect and switch off a timer when the mouse cursor is scrolling a listbox.
There is an easy way despite to create a new class like this one?link
Would be possible to check rectangle location of listbox 1 scroll bar and say: if mouse is in this range then timer1.stop?
EDIT1:
In order to create a rectangle I'm using
If e.X >= 364 AndAlso e.X <= 446 AndAlso e.Y >= 86 AndAlso e.Y <= 144 Then
MessageBox.Show("Clicked within the rectangle")
Else
MessageBox.Show("Clicked outside the rectangle")
End If
449-359 are the Top left corner location of the rectangle
while the rectangle size is x30 y156
The problem is I don't know in which event let it run!
Listbox click event doesn't recognize scrollbar as "inside of listbox"
Form_mouse click event doesn't recognize listbox scroll bar as a click in the form.
There is an event that despite the control you are on, it will let you play with this workaround?
Thanks
Here is what I posted on MSDN using this C# code. There is no code presented below that will restart the Timer.
Public Class BetterListBox
Inherits ListBox
' Event declaration
Public Delegate Sub BetterListBoxScrollDelegate(ByVal Sender As Object, ByVal e As BetterListBoxScrollArgs)
Public Event Scroll As BetterListBoxScrollDelegate
' WM_VSCROLL message constants
Private Const WM_VSCROLL As Integer = &H115
Private Const SB_THUMBTRACK As Integer = 5
Private Const SB_ENDSCROLL As Integer = 8
Protected Overrides Sub WndProc(ByRef m As Message)
' Trap the WM_VSCROLL message to generate the Scroll event
MyBase.WndProc(m)
If m.Msg = WM_VSCROLL Then
Dim nfy As Integer = m.WParam.ToInt32() And &HFFFF
If (nfy = SB_THUMBTRACK OrElse nfy = SB_ENDSCROLL) Then
RaiseEvent Scroll(Me, New BetterListBoxScrollArgs(Me.TopIndex, nfy = SB_THUMBTRACK))
End If
End If
End Sub
Public Class BetterListBoxScrollArgs
' Scroll event argument
Private mTop As Integer
Private mTracking As Boolean
Public Sub New(ByVal top As Integer, ByVal tracking As Boolean)
mTop = top
mTracking = tracking
End Sub
Public ReadOnly Property Top() As Integer
Get
Return mTop
End Get
End Property
Public ReadOnly Property Tracking() As Boolean
Get
Return mTracking
End Get
End Property
End Class
End Class
Then in your form subscribe to the Scroll event. Requires the ListBox above in your project, one Timer enabled and a Label.
Private Sub BetterListBox1_Scroll(Sender As Object, e As BetterListBox.BetterListBoxScrollArgs) _
Handles BetterListBox1.Scroll
Timer1.Enabled = False
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.Text = Now.ToString()
End Sub

Transparent Overlay

I'm trying to make an application which can overlay my screen with a transparent image in the middle. My goal is to make a crosshair for a game with no crosshair. My thinking is to detect if the active window title matches the game name, and if so display the overlaying crosshair. How would i make a screen overlay? This is my current code:
Private Function GetCaption() As String
Dim Caption As New System.Text.StringBuilder(256)
Dim hWnd As IntPtr = GetForegroundWindow()
GetWindowText(hWnd, Caption, Caption.Capacity)
Return Caption.ToString()
End Function
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If GetCaption() = "Game NameOf" Then
'Display Crosshair
End If
End sub
This methods works for most games but only in windowmode!
Place a picturebox on your Form and maximize yout picturebox
Disable your Windowboarders:
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Set your transperency key to black. Th
Me.TransparencyKey = Color.Black
Set background color to black:
Me.PictureBox1.BackColor = Color.Black
Set your window to foreground:
Me.TopMost = true
Maximize your window:
Me.WindowState = FormWindowState.Maximized
Now you can draw on your Picturebox in a Timer1_Tick or Form1_Paint event. Everything that is not Black will be drawn to your Desktop.
Dim g As = GraphicsPictureBox1.CreateGraphics
...
g.DrawLine(Pens.Red, 10, 10, 200, 200)
Important:
To pass input from mouse and keyboard through your window, your have to add the WS_EX_TRANSPARENT flag while .net creates your form. This can be done by overriding CreateParams proterty:
Const WS_EX_TRANSPARENT As Long = &H20
...
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim SecPerm As New SecurityPermission(SecurityPermissionFlag.UnmanagedCode)
SecPerm.Demand()
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or WS_EX_TRANSPARENT
Return cp
End Get
End Property
Hope I could help you.

How to Activate the pervious active Window in VB?

I am trying to create a windows form app using visual studio to capture the screen shot of an active window application. I created a capture button which captures the form itself and not the Previous active window. Thus i want to toggle to the previous active window and a screen shoot should be captured considering that as the current active window. I am relatively new to VB. kindly help me out with this issue.
thank you.
One approach is to prevent your Form from getting Focus, thus keeping the "previous" form as the active selected one.
See WS_EX_NOACTIVATE:
A top-level window created with this style does not become the
foreground window when the user clicks it.
Public Class Form1
Private Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
Private Const WM_MOVING As Integer = &H216
Private Const WS_EX_NOACTIVATE As Integer = &H8000000
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or WS_EX_NOACTIVATE
Return cp
End Get
End Property
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_MOVING Then
Dim r As RECT = DirectCast(Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, GetType(RECT)), RECT)
Me.Location = New Point(r.Left, r.Top)
End If
MyBase.WndProc(m)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Console.WriteLine("...your active screen capture code here...")
End Sub
End Class

how to re-enable the close(X) button

I am working on vb6.net winforms. I have created two buttons named yes and no Respectively.I have disabled the close button use the following code shown below:
Private Const CP_NOCLOSE_BUTTON As Integer = &H200
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim myCp As CreateParams = MyBase.CreateParams
myCp.ClassStyle = myCp.ClassStyle Or CP_NOCLOSE_BUTTON
Return myCp
End Get
End Property
My question is I want to re - enable it when the user completes his requirement by clicking on the yes button.
There is no need to Override the CreateParams. You could easily turn off/on the Close button changing the property ControlBox of your form
Private Sub ClickMe(sender as Object, e as EventArgs) Handles Button1.Click
Me.ControlBox = True
End Sub

Form on top but not clickable when modal dialog is shown

What I want is a small notification message that is shown in the lower right corner when there are any messages to be shown. If there are none the notification message will not be shown. The notification message should not steal focus or block the main application.
What I have is an application that runs a Task as a kind of messageservice. This application contains multiple dialogs that opens as modal dialogs.
When a message arrives to the application it is added to a observable list. This fires an eventhandler in the form showing the notification message and it is redrawn to show the first item in the list.
When a message is read/closed it is removed from the list which fires the event again and the form is updated with the information from the first item in the list.
If the list is empty the form is hidden.
My problem is that if i get a message and the notification message form is shown, and before I close it a modal dialog is opened in the main application, my form with the notification message is still on top of everything, even the modal dialog, but it's not clickable.
I've searched and read several forums for an answer but haven't been able to come up with an answer.
A small testapplication that simulates this behaviour can be found at Github.
https://github.com/Oneleg/NotificationMessage
Some fast info:
The NotificationMessage form has:
FormBorderStyle = None
Topmost = False
Is shown with Show()
Overloads ShowWithoutActivation()
Overloads CreateParams with WS_EX_NOACTIVATE WS_EX_TOOLWINDOW WS_EX_TOPMOST
Any ideas on how I could solve this?
Looks like I'll be able to answer my own question.
The answer is to create the NotificationMessage as an application withs it's own messagepump.
Application.Run(New NotificationMessage(_messageList))
After some modifications my Main now looks like this:
Imports System.Threading
Imports System.Threading.Tasks
Public Class frmMain
Private _notificationMessage As NotificationMessage
Private _task As Task
Private _messageList As ObservableGenericList(Of String) = New ObservableGenericList(Of String)
Private ReadOnly _cancelMessages As CancellationTokenSource = New CancellationTokenSource()
Private Sub btnModal_Click(sender As System.Object, e As System.EventArgs) Handles btnModal.Click
frmModal.ShowDialog()
End Sub
Private Sub frmMain_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
AddHandler _messageList.Changed, AddressOf MessageListChanged
End Sub
Private Sub NotificationMessageLoop(mess As String)
_notificationMessage = New NotificationMessage(_messageList)
_messageList.Add(mess)
Application.Run(_notificationMessage)
End Sub
Private Sub btnMessage_Click(sender As System.Object, e As System.EventArgs) Handles btnMessage.Click
Dim newMessage = String.Format("Message no {0}", _messageList.Count + 1)
If _task Is Nothing Then
_task = Task.Factory.StartNew(Sub() NotificationMessageLoop(newMessage), _cancelMessages.Token)
Else
_messageList.Add(newMessage)
End If
End Sub
Private Sub MessageListChanged()
If Not _messageList.Any Then
_cancelMessages.Cancel()
End If
End Sub
End Class
And the NotificationMessage looks like this:
Imports System.Runtime.InteropServices
Public Class NotificationMessage
Public Sub New(messages As ObservableGenericList(Of String))
InitializeComponent()
_messages = messages
AddHandler _messages.Changed, AddressOf ListChanged
End Sub
Private ReadOnly _messages As ObservableGenericList(Of String)
Private Delegate Sub ListChangedDelegate()
Private Sub ListChanged()
If InvokeRequired Then
BeginInvoke(New ListChangedDelegate(AddressOf ListChanged))
Return
End If
If _messages.Any Then
Dim message As String = _messages.First
txtMessage.Text = message
lblCounter.Text = String.Format("({0} messages)", _messages.Count)
Show()
Else
Hide()
End If
End Sub
Private Sub MessageLoad(sender As System.Object, e As EventArgs) Handles MyBase.Load
Left = Screen.PrimaryScreen.WorkingArea.Width - Width
Top = Screen.PrimaryScreen.WorkingArea.Height - Height
End Sub
Private Sub btnClose_Click(sender As System.Object, e As System.EventArgs) Handles btnClose.Click
_messages.RemoveFirst()
End Sub
#Region "Overrides"
Private Const WS_EX_NOACTIVATE = &H8000000 ' Do not steal focus
Private Const WS_EX_TOOLWINDOW = &H80 ' Makes form hidden from Alt + Tab window
Private Const WS_EX_TOPMOST = &H8 ' Makes window topmost
''' <summary> Indicates whether the window will be activated when it is shown. </summary>
''' <remarks> http://msdn.microsoft.com/en-us/library/system.windows.forms.form.showwithoutactivation.aspx </remarks>
Protected Overrides ReadOnly Property ShowWithoutActivation() As Boolean
Get
Return True
End Get
End Property
''' <summary> Override for creation parameters that are set when control handle is created. </summary>
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim params As CreateParams = MyBase.CreateParams
params.ExStyle = params.ExStyle Or WS_EX_NOACTIVATE Or WS_EX_TOOLWINDOW Or WS_EX_TOPMOST
Return params
End Get
End Property
#End Region
End Class
I now have a notification message that is only visible when there are any messages to show, doesn't steal focus when a new message arrives, is always on top and is clickable even after a modal form is opened in the main application.