This question already has answers here:
How to move form without form border (visual studio)
(9 answers)
Closed 5 years ago.
I wanna make simple form application with FormBorderStyle set to None, but the problem is I cant move this form, its just.. static? I wanna make something like this:
http://i.imgur.com/TlQCWJx.png
Any ideas how to fix it?
You can use code like this to make the form draggable:
Public Class Form1
Private Const HTCLIENT As Integer = &H1
Private Const HTCAPTION As Integer = &H2
Private Const WM_NCHITTEST As Integer = &H84
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
If m.Msg = WM_NCHITTEST AndAlso m.Result = HTCLIENT Then
m.Result = HTCAPTION
End If
End Sub
End Class
You could take a look at WPF.
It's a newer version of WinForms and you have much more possibilities to design your dialogs.
But it's also very different to WinForms. You will need time to find into WPF.
Microsoft Docs about WPF
Here's a very simple example of moving a borderless form to get you started:
Add a panel to your form, name it pnlTopBorder and dock it to the top. When you mousedown on the panel, capture the mouse position. When you mousemove on the panel, if the left button is pressed, then you calculate and set the new form position.
Public Class Form1
Private newpoint As System.Drawing.Point
Private xpos1 As Integer
Private ypos1 As Integer
Private Sub pnlTopBorder_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles pnlTopBorder.MouseDown
xpos1 = Control.MousePosition.X - Me.Location.X
ypos1 = Control.MousePosition.Y - Me.Location.Y
End Sub
Private Sub pnlTopBorder_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles pnlTopBorder.MouseMove
If e.Button = Windows.Forms.MouseButtons.Left Then
newpoint = Control.MousePosition
newpoint.X -= (xpos1)
newpoint.Y -= (ypos1)
Me.Location = newpoint
End If
End Sub
End Class
If you want the window title and form controls, you'll have to draw them in the Paint event and handle all the events to get them to work. It's all doable, but it's just more complex.
Related
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
I'm trying to do some non-client area painting to get a MS Office like windowsform. I have one or two other posts of the sort, but here is the one that is done with Graphics.FromHwnd passing IntPtr.Zero as arg. I consulted a lot of information, that I tried and just simply cannot get it to work. Dwm functions, GetWindowDC, and or combination of these. Nothing works. Except this example that I post.
Public Class Form6
Protected Overrides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
Select Case m.Msg
Case WinAPI.Win32Messages.WM_ACTIVATEAPP
Me.Invalidate()
End Select
End Sub
Private Sub Form6_LocationChanged(sender As Object, e As EventArgs) Handles Me.LocationChanged
Me.Invalidate()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Dim usedColor As Color = Color.Beige
Me.BackColor = usedColor
Dim usedBrush As Brush = New SolidBrush(usedColor)
'Dim hDC As IntPtr = WinAPI.GetWindowDC(Me.Handle.ToInt64)
Using g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
'Using g As Graphics = Graphics.FromHdc(hDC)
'Caption
Dim rect As Rectangle = New Rectangle(Me.Left, Me.Top, Me.Width, SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height)
g.FillRectangle(usedBrush, rect)
'left border
rect = New Rectangle(Me.Left, Me.Top + SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height, (Me.Width - Me.ClientSize.Width) / 2, Me.ClientSize.Height)
g.FillRectangle(usedBrush, rect)
'right border
rect = New Rectangle(Me.Right - 2 * SystemInformation.FrameBorderSize.Width, Me.Top + SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height, (Me.Width - Me.ClientSize.Width) / 2, Me.ClientSize.Height)
g.FillRectangle(usedBrush, rect)
'bottom border
'If on maximize this border isn't drawn, by default the windowsize "drawing" is correct
If Me.WindowState <> FormWindowState.Maximized Then
rect = New Rectangle(Me.Left, Me.Bottom - 2 * SystemInformation.FrameBorderSize.Width, Me.Width, 2 * SystemInformation.FrameBorderSize.Height)
g.FillRectangle(usedBrush, rect)
End If
End Using
'WinAPI.ReleaseDC(Me.Handle.ToInt64, hDC)
End Sub
Private Sub Form6_Resize(sender As Object, e As EventArgs) Handles Me.Resize
Me.Invalidate()
End Sub
Private Sub Form6_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
Me.Invalidate()
End Sub
End Class
To generate graphics, I pass IntPtr.Zero for the hole screen.
I tried the GetWindowDC API (commented in code), and nothing happens. The handle was passed as Me.Handle, Me.Handle.ToInt32 and .ToInt64, and no result.
The invalidate called is to try to draw in every situation possible.
Problems that bring me here:
Form does not start up painted (can't figure it out);
Resizing flickers a lot (probably because the handle is to the entire screen, even form being double-buffered);
On the resizing, it's visible the painting over the cursor (again probably because of the handle for the graphics isn't the form's handle);
On mouse over control buttons (min, max and close), all drawing disappears;
Although I can detect problems, I can't get other ways to work, like the famous GetWindowDC, regardless of how many examples I tried that don't work, or even the DWM functions.
Being the purpose of getting my own "Office" like form, I ask some help in getting improvements to this code or some other ideas, that are welcome.
[EDIT]
Another flavor of the above code. This code was tried in form_load event, but nothing happened.
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
If Not DwmAPI.DwmIsCompositionEnabled(True) Then
Dim myHandle As IntPtr = WinAPI.FindWindow(vbNullString, Me.Text)
Dim hDC As IntPtr = WinAPI.GetWindowDC(myHandle)
Dim rect As WinAPI.RECT
With rect
.Left = 0
.Right = Me.Width
.Top = 0
.Bottom = 30
End With
Using g As Graphics = Graphics.FromHdc(hDC)
g.DrawString("TESTER", New Font(Me.Font.Name, 50), Brushes.Red, New Point(0, 0))
End Using
WinAPI.ReleaseDC(myHandle, hDC)
End If
End Sub
The result is this:
http://postimg.org/image/yyg07zf87/
As it would be clear, I want to have whatever if graphics drawn over titlebar and not under, although it's visible that the coords for the drawing are from full form area and not client area. If I doublebuffer the form, nothing is drawn. Any ideas?
Thanks for your patience. Best regards.
Like the image below:
![The transparency effect i mean ][1]
http://i.stack.imgur.com/ststz.jpg
That effect in vb.You can actually see the background but its not purely transparent .Its translucent afaik.
I give you some ideas:
You can set the BackColor and TransparencyKey Color properties of your form to the same color.
Then assign the transparent image that you want, through handling the Mybase.Paint event, in this way:
Private Sub frmLogin_Paint(ByVal sender As Object,
ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
If Not Me.cObjImagen Is Nothing Then
e.Graphics.DrawImage(Me.cObjImagen, 0, 0, Me.Width, Me.Height)
End If
End Sub
Where 'cObjImagen' is a system.drawing.Image loaded from 'form_load' event, or from ' public sub new() ', for example...
If you need to move the form, this will help you to process the messages correctly:
Private Const WM_NCHITTEST As Integer = 132
Private Const HTCAPTION As Integer = 2
Protected Overloads Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_NCHITTEST Then
m.Result = New IntPtr(HTCAPTION)
Else
MyBase.WndProc(m)
End If
End Sub
I have been using the NodeMouseClick event to handle left and right clicks on my TreeNodes for a while. Now I want to add an effect to middle clicking as well, but the NodeMouseClick event doesn't seem to fire on a middle click. Is this a known bug, or should it work fine and I'm just doing something wrong? If it is a bug (or just intended to function this way), how can I make a middle click on a TreeNode do something specific with that node?
Here's a bit of my code:
Private Sub TreeView1_NodeMouseClick(sender As Object, e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseClick
If e.Button = Windows.Forms.MouseButtons.Left Then
Call nodeLeft(e.Node)
ElseIf e.Button = Windows.Forms.MouseButtons.Middle Then
Call nodeMiddle(e.Node)
ElseIf e.Button = Windows.Forms.MouseButtons.Right Then
Call nodeRight(e.Node)
End If
End Sub
You can try this version:
Public Class MyTreeView
Inherits TreeView
Private Const WM_MBUTTONDOWN As Integer = &H207
Protected Overrides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
If m.Msg = WM_MBUTTONDOWN Then
Dim p As Point = Me.PointToClient(MousePosition)
Dim mouseNode As TreeNode = Me.GetNodeAt(p)
If mouseNode IsNot Nothing Then
Me.OnNodeMouseClick(New TreeNodeMouseClickEventArgs(mouseNode, MouseButtons.Middle, 1, p.X, p.Y))
End If
End If
End Sub
End Class
It will fire the NodeMouseClick event with the middle value set for the Button property. It won't select the node though. To do that, add the line Me.SelectedNode = mouseNode above the OnNodeMouseClick call.
In accordance to this Post I'm trying to mimic the behavior of
Enabled = False
without actually disable the Control. (In my case a multiline TextBox)
The next I'm trying to accomplish is to mimic the focus behavior by mouse of a disabled control. If I click on a disabled control it won't get the focus and the control that previously had focus won't loose the focus.
What I came up with so far: I can intercept the WM_SETFOCUS message in WndProc so my control won't recieve focus.
Private Const WM_SETFOCUS = &H7
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If Me.ReadOnly AndAlso (m.Msg = WM_SETFOCUS) Then Exit Sub
MyBase.WndProc(m)
End Sub
The problem with that is, that the previous contol lost the focus, which isn't intended. How do I prevent that even the click by mouse will do anything in the focus behaviour? Is there any way to do this?
Update: 06.08.12
As suggested by Justin I solved the problem by changing it to a label in an autoscroll panel. A minimal code example is as followed:
Imports System.Windows.Forms
Public Class ScrollableDisabledTextBox
Inherits TextBox
Private xLabel As Label
Private xPanel As Panel
Public Sub New()
InizializeComponent()
End Sub
Private Sub InizializeComponent()
xPanel = New Panel
xPanel.AutoScroll = True
xPanel.BorderStyle = BorderStyle.FixedSingle
xLabel = New Label
xLabel.Enabled = False
xLabel.AutoSize = True
xPanel.Controls.Add(xLabel)
Me.Me_SizeChanged()
End Sub
Private Sub Me_EnabledChanged() Handles Me.EnabledChanged
If Me.Enabled Then
Me.Show()
xPanel.Hide()
Else
xPanel.Show()
Me.SendToBack()
Me.Hide()
End If
End Sub
Private Sub Me_TextChanged() Handles Me.TextChanged
xLabel.Text = Me.Text
End Sub
Private Sub Me_SizeChanged() Handles Me.SizeChanged
xPanel.Size = Me.Size
xLabel.MaximumSize = New System.Drawing.Size(xPanel.Size.Width, 0)
End Sub
Private Sub Me_ParentChanged() Handles Me.ParentChanged
xPanel.Location = Me.Location
'If parent changed multiple times, remember to remove panel from old parent!
If Not Me.Parent.Controls.Contains(xPanel) Then
Me.Parent.Controls.Add(xPanel)
End If
End Sub
End Class
I do not believe what you want to do is possible. If you do not have focus, then the scrolling will not work.
However, I posit that you should rethink your original problem. Why not use an AutoSize = true, MaximumSize.Width = ParentWidth label (which could be disabled) inside of a panel that will autoscroll. This sounds like what you are really looking for.