how to re-enable the close(X) button - vb.net

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

Related

How to prevent ALT+F4 of a WinForm but allow all other forms of closing a WinForm?

I've searched around the interwebs and various parts of this resource where this question was asked and noticed I got the following bits of code:
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
Const CS_NOCLOSE As Integer = &H200
cp.ClassStyle = cp.ClassStyle Or CS_NOCLOSE
Return cp
End Get
End Property
Which works as intended, this does disable ALT+F4 from being used. However, as an unintended side effect of this code: closing the window via the Control Box is disabled:
Is there a version of this code that disables ALT+F4 BUT still allows for the closing of the window via its control box or other UI options (such as a close button and a Close option in a menu.)
I know someone will say to check the e.CloseReason of the form, however UserClosing is the only reason the resembles what I would like to do, however... that still disables the UI from being used. Unless there is a code that I forgot about.
Set KeyPreview = True and handle the KeyDown event:
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.Alt AndAlso e.KeyCode = Keys.F4 Then
e.Handled = True
End If
End Sub
Answer to your comment, handling KeyDown from a separate class.
Documentation:
AddHandler statement
Shared access modifier
Public NotInheritable Class MainInterface
Private Sub New() 'No constructor.
End Sub
Public Shared Sub DisableAltF4(ByVal TargetForm As Form)
TargetForm.KeyPreview = True
AddHandler TargetForm.KeyDown, AddressOf Form_KeyDown
End Sub
Private Shared Sub Form_KeyDown(sender As Object, e As KeyEventArgs)
e.Handled = (e.Alt AndAlso e.KeyCode = Keys.F4)
End Sub
End Class
Now in every form's Load event handler you can do:
Private Sub yourForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MainInterface.DisableAltF4(Me)
End Sub
As Olaf said you can also make all forms inherit from a base class. However this might get a little bit more complicated as you have to tell both the yourForm.vb and the yourForm.Designer.vb file that you want to inherit from the base form.
Public Class BaseForm
Inherits Form
Protected Overrides Sub OnLoad(e As System.EventArgs)
MyBase.OnLoad(e)
Me.KeyPreview = True
End Sub
Protected Overrides Sub OnKeyDown(e As System.Windows.Forms.KeyEventArgs)
MyBase.OnKeyDown(e)
e.Handled = e.Handled OrElse (e.Alt AndAlso e.KeyCode = Keys.F4)
End Sub
End Class
In yourForm.vb:
Public Class yourForm
Inherits BaseForm
...code...
End Class
In yourForm.Designer.vb:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class yourForm
Inherits yourNamespace.BaseForm
...code...
End Class
You should also remove the corresponding CLOSE menu item from the forms system menu using a RemoveMenu() interop call. This disables all default window close options.
Of course you can call Form.Close() in your code to close your form. That can be triggered by a Click event handler of a custom button, menu item etc. Additionally, you can implement an System.Windows.Forms.IMessageFilter to handle a custom key sequence (instead of ALT+F4) to close your form, e.g. C+L+O+S+E.
Easy:
In C#
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Alt | Keys.F4))
{
return true; // The key is manually processed
}
else
return base.ProcessCmdKey(ref msg, keyData);
}
In VB.Net
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
If keyData = (Keys.Alt Or Keys.F4) Then
Return True
Else
Return MyBase.ProcessCmdKey(msg, keyData)
End If
End Function

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

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

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

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.