I used to use VB 6.0 and now I'm switching to .net and I'm finding lots of things have changed. Back in the day, I used to store graphics assets in pictureboxes, make them invisible, and then bitblt them to the form / screen / canvas when I needed to. This was a nice, tidy way of doing it but now I'm trying to do the same thing in VB.NET and it wont work.
If the picturebox is on screen and visible, everything works perfectly, however making the picturebox invisible or moving it offscreen messes up the graphics that bitblt draws. I can successfully load a bitmap that's stored externally, but what I wanted to know was, what is the best way to store graphics (bitmap) assets inside a VB.NET application for use with bitblt?
for reference, here is a code snippet:
#Region " Members "
Public mouseX As Integer
Public mouseY As Integer
Public srcGraphics As Graphics
Public TargetGraphics As Graphics
Public srcHdc As IntPtr
Public targetHdc As IntPtr
Public srcSize As Size
Private blnShowWheel As Boolean
#End Region
#Region " Internals "
Const SRCCOPY As Integer = &HCC0020
' Wraping things up
Private Sub MyBitBlt(ByVal SourceGraphics As Graphics, ByVal TargetHDC As IntPtr, ByVal width As Integer, ByVal Height As Integer)
' Creating a DeviceContext to capture from
Dim SourceHDC As IntPtr = SourceGraphics.GetHdc
' Blitting (Copying) the data
BitBlt(TargetHDC, 0, 0, width, Height, SourceHDC, 0, 0, SRCCOPY)
' Releasing the Device context used
SourceGraphics.ReleaseHdc(SourceHDC)
End Sub
Private Sub MyBitBlt(ByVal SourceHDC As IntPtr, ByVal TargetHDC As IntPtr, ByVal width As Integer, ByVal Height As Integer, ByVal PosX As Integer, ByVal PosY As Integer)
' Copying data to a specific position on the target Device Context
BitBlt(TargetHDC, PosX, PosY, width, Height, SourceHDC, 0, 0, SRCCOPY)
End Sub
' Cleanning Up
' Before Destroying this class, dispose of objects to reclaim memory
Protected Overrides Sub Finalize()
DisposeObjects()
MyBase.Finalize()
End Sub
' Disposing of objects
Private Sub DisposeObjects()
TargetGraphics.Dispose()
srcGraphics.Dispose()
End Sub
#End Region
Private Sub cmdExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdExit.Click
Finalize()
End
End Sub
Private Sub frmMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Finalize()
End Sub
Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Width = 800
Me.Height = 600
Me.Left = (Screen.PrimaryScreen.Bounds.Width - Me.Width) / 2
Me.Top = (Screen.PrimaryScreen.Bounds.Height - Me.Height) / 2
srcSize = picColourWheel.Size
End Sub
Private Sub frmMain_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
srcGraphics = picColourWheel.CreateGraphics
TargetGraphics = Me.CreateGraphics
srcHdc = srcGraphics.GetHdc
targetHdc = TargetGraphics.GetHdc
If Not blnShowWheel = True Then
blnShowWheel = True
Else
blnShowWheel = False
End If
If blnShowWheel = True Then
MyBitBlt(srcHdc, targetHdc, srcSize.Width, srcSize.Height, mouseX - (srcSize.Width / 2), mouseY - (srcSize.Height / 2))
Else
Me.Refresh()
End If
srcGraphics.ReleaseHdc(srcHdc)
TargetGraphics.ReleaseHdc(targetHdc)
End Sub
Private Sub frmMain_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
mouseX = e.X
mouseY = e.Y
End Sub
In Solution Explorer, Right Click the Project --> Add --> Existing Item --> Select Image.
Select newly added Image entry in Solution Explorer.
Down below in the Properties Pane, change "Build Action" to "Embedded Resource".
Now the image will be embedded in the application, and you can draw it like this:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim bmp As New Bitmap(Me.GetType, "Smiley1.jpg") ' <-- Exactly as it appears in Solution Explorer (it IS cAsE-sEnSiTiVe!)
Using G As Graphics = Me.CreateGraphics
G.DrawImage(bmp, New Point(25, 25))
End Using
End Sub
End Class
Related
I'm trying to get a picture or more specifically an animation to follow the mouse across the whole computer, not just inside of a form. I found this little snippet of code
Public Class Form1
Private Sub Form1_MouseMove(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles Me.MouseMove
PictureBox1.Top = MousePosition.Y - Me.Top
PictureBox1.Left = MousePosition.X - Me.Left
End Sub
End Class
and that works dandy so now I'd like to do this without the form.
Any help would be greatly appreciated.
You can't really ditch the form but you can work your way around it. Create form, set Borderstyle to none and TopMost to true. Add a Picturebox and set the .Dock property of the picturebox to All.
The timer in my code is used because we will make the form click-trough and then the Mouseevents will not work properly.
Use the following code to make the form follow the mousecursor.
Public Class Form1
<System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="GetWindowLong")> Public Shared Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="SetWindowLong")> Public Shared Function SetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
End Function
Const xOff As Integer = 0 'How far the form will be away from the curson in x-direction
Const yOff As Integer = 0 'How far the form will be away from the curson in y-direction
Private WithEvents Timer1 As Timer
Private Sub Timer1_Tick(sender As Object, e As EventArgs)
Me.SetDesktopLocation(MousePosition.X - xOff, MousePosition.Y - yOff) 'Set the form's position
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Setup a timer
Timer1 = New Timer
Timer1.Interval = 1
AddHandler Timer1.Tick, AddressOf Timer1_Tick
Timer1.Start()
'Set the form to clickthrough
'See http://stackoverflow.com/questions/18294658/vb-net-click-through-form
Dim InitialStyle As Integer
InitialStyle = GetWindowLong(Me.Handle, -20)
SetWindowLong(Me.Handle, -20, InitialStyle Or &H80000 Or &H20) 'Makes the window "click-throughable"
End Sub
End Class
It has problems with other TopMost-windows and switching programs through the taskbar but it's a start.
i have simple form without border and without title bar. There is only single label on it showing stopwatch. I need form to be movable by clicking mouse anywhere on form and then drag.
I solved that, but the problem is when i click on form on spot occupied by label, form will not move. In another words, i need Label only to be seen, not having any other function. How do i make label click through?
There is already an answer for this in this site, but that was in C#, so I repeat that answer here but translated in VB.NET. If you think that this is useful don't esitate the upvote that answer also....
The important thing to note here is the handling of the mousedown also for the Label1 and not only for the form
Public Class Form1
<DllImportAttribute("user32.dll")> _
Public Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As Integer) As Integer
End Function
<DllImportAttribute("user32.dll")> Public Shared Function ReleaseCapture() As Boolean
End Function
Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown, Label1.MouseDown
Const WM_NCLBUTTONDOWN As Integer = &HA1
Const HT_CAPTION As Integer = &H2
If e.Button = MouseButtons.Left Then
ReleaseCapture()
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0)
End If
End Sub
End Class
Hello I have some example source to make form moveable
Public Class Form1
Dim drag As Boolean
Dim mousex As Integer
Dim mousey As Integer Private Sub
Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown drag = True
mousex = Windows.Forms.Cursor.Position.X - Me.Left
mousey = Windows.Forms.Cursor.Position.Y - Me.Top
End Sub Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
If drag Then
Me.Top = Windows.Forms.Cursor.Position.Y - mousey
Me.Left = Windows.Forms.Cursor.Position.X - mousex
End If
End Sub
Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles
Me.MouseUp`enter code here`
I hope this can help you
Cheers :)
Public Class Form1
Dim drag As Boolean
Dim mousex As Integer
Dim mousey As Integer
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown, Label1.MouseDown
drag = True
mousex = Windows.Forms.Cursor.Position.X - Me.Left
mousey = Windows.Forms.Cursor.Position.Y - Me.Top
End Sub
Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp, Label1.MouseUp
drag = False
End Sub
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove, Label1.MouseMove
If drag Then
Me.Top = Windows.Forms.Cursor.Position.Y - mousey
Me.Left = Windows.Forms.Cursor.Position.X - mousex
End If
End Sub
End Class
I have a form without borders that I would like the user to be able to move. I have not been able to find anything that would allow me to do so.
Is it possible to move a window with the border set to None?
Introduce a Boolean variable which holds the state if the form is currently dragged and variables which hold the starting point of the drag. Then OnMove move the form accordingly. As this has already been answered elsewhere, I just copy&paste it here.
Class Form1
Private IsFormBeingDragged As Boolean = False
Private MouseDownX As Integer
Private MouseDownY As Integer
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseDown
If e.Button = MouseButtons.Left Then
IsFormBeingDragged = True
MouseDownX = e.X
MouseDownY = e.Y
End If
End Sub
Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseUp
If e.Button = MouseButtons.Left Then
IsFormBeingDragged = False
End If
End Sub
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseMove
If IsFormBeingDragged Then
Dim temp As Point = New Point()
temp.X = Me.Location.X + (e.X - MouseDownX)
temp.Y = Me.Location.Y + (e.Y - MouseDownY)
Me.Location = temp
temp = Nothing
End If
End Sub
End Class
stolen from http://www.dreamincode.net/forums/topic/59643-moving-form-with-formborderstyle-none/
All 'simple' VB answers made my form jump all over the place with multiple screens. So i derived this from same answer in C# and it works like a charm :
Public Const WM_NCLBUTTONDOWN As Integer = 161
Public Const HT_CAPTION As Integer = 2
then
<DllImport("User32")> Private Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As Integer) As Integer
End Function
<DllImport("User32")> Private Shared Function ReleaseCapture() As Boolean
End Function
and finally
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
If (e.Button = MouseButtons.Left) Then
ReleaseCapture()
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0)
End If
End Sub
Dim offSetX As Integer
Dim offSetY As Integer
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Location = New Point(Cursor.Position.X - offSetX, Cursor.Position.Y - offSetY)
End Sub
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
offSetX = PointToClient(Cursor.Position).X
offSetY = PointToClient(Cursor.Position).Y
Timer1.Enabled = True
End Sub
Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
Timer1.Enabled = False
End Sub
This is slightly scruffy way of doing it xD
Hope it helps though =]
Another way of doing this is to handle the WM_NCHITTEST message . This allows you to have parts of your form respond to mouse events as the title bar, borders, etc. would for a window with borders. For example, if you have a label on your form and you return HTCAPTION in the WM_NCHITTEST handler, you will be able to move the form by dragging this label just as you can move a regular window by dragging on its title bar. See this Stack Overflow question for example code.
I wanted an effect of fading a panel control and the controls / object inside it. I found some containers with opacity property it only changes the background color's opacity.
So I came up my own solution. I created another form containing the controls I need and I got what I want but I got some problems with positioning the new form created. I don't know how to get the working area of its parent form to set the initial position. What I mean for working area is that, it won't include the control box / title bar. Different OS has different title bar sizes (as far as I know) so I need to adjust it correctly
Form2, the one holding the Opaque Controls
Public Class Form2
Private Const dif As Integer = 23
Private Const GWL_EXSTYLE As Integer = (-20)
Private Const WS_EX_TRANSPARENT As Integer = &H20
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As IntPtr, ByVal nIndex As Integer) As Integer
Public Sub resizeFrom(ByVal parent As Form)
Me.Height = parent.Height - dif
Me.Width = parent.Width
Me.Top = (parent.Top + ((parent.Height - Me.Height) / 2) + (dif / 2))
Me.Left = parent.Left + ((parent.Width - Me.Width) / 2)
End Sub
Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.TopMost = True
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Me.BackColor = Color.Red
SetWindowLong(Me.Handle, GWL_EXSTYLE, GetWindowLong(Me.Handle, GWL_EXSTYLE) Or WS_EX_TRANSPARENT)
End Sub
End Class
The Parent/Main Form
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Show()
Form2.Show()
Form2.resizeFrom(Me)
End Sub
Private Sub Form1_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Move
Form2.resizeFrom(Me)
End Sub
Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
Form1_Move(Me, New EventArgs)
End Sub
Private Sub HScrollBar1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles HScrollBar1.Scroll
Form2.Opacity = HScrollBar1.Value / 100
Me.Text = "Opacity: " & HScrollBar1.Value & "%"
End Sub
End Class
It should look like this
http://i48.tinypic.com/25qubk0.jpg
Opaque Form is for display purposes, it was set to "Ghost Like Form" or "Click-through Form"
Is there any solution so I can get the proper WorkingArea of the Form?
Please help.
Thanks
What you need is the absolute location of the ClientRectangle. The Location of this is (0, 0) but you can magically convert it to screen values:
Form2.Location = PointToScreen(Me.ClientRectangle.Location)
Form2.Size = Me.ClientRectangle.Size
Is there any way to embed a vb.net form to another vb.net form. What I am trying to do is to make Form-A semi-transparent and Form-B as the embedded main form. So that the final application has a semi transparent border around it . Also I don't want to use a MDI form.
Edit: How to make the border of a vb.net form semi-transparent without using MDI form.
I've simplified the code a bit and hooked up most of the events to a single method. There is no longer a Form-A, just a Form-B. Form-B now creates it's own Form-A on the fly without any need to actually make a code file. I moved the border size to a variable so it would be easy to adjust it.
Imports System.Runtime.InteropServices
Public Class InnerForm
Private borderSize As Integer = 10
Private border As Form = New Form()
Private Sub InnerForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
border.FormBorderStyle = Windows.Forms.FormBorderStyle.None
border.ShowInTaskbar = False
border.BackColor = Color.Blue
border.Opacity = 0.5
border.Enabled = False
RefreshBorder()
End Sub
Private Sub DrawRectangle()
Dim p As New Drawing2D.GraphicsPath()
p.StartFigure()
p.AddArc(New Rectangle(0, 0, 40, 40), 180, 90)
p.AddLine(40, 0, border.Width - 40, 0)
p.AddArc(New Rectangle(border.Width - 40, 0, 40, 40), -90, 90)
p.AddLine(border.Width, 40, border.Width, border.Height - 40)
p.AddArc(New Rectangle(border.Width - 40, border.Height - 40, 40, 40), 0, 90)
p.AddLine(border.Width - 40, border.Height, 40, border.Height)
p.AddArc(New Rectangle(0, border.Height - 40, 40, 40), 90, 90)
p.CloseFigure()
border.Region = New Region(p)
End Sub
Private Sub RefreshBorder()
border.Show()
border.Size = New Size(Me.Width + borderSize * 2, Me.Height + borderSize * 2)
border.Location = New Point(Me.Location.X - borderSize, Me.Location.Y - borderSize)
DrawRectangle()
SetWindowPos(border.Handle, Me.Handle, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOACTIVATE)
Me.BringToFront()
End Sub
Private Sub frmMAin_Refresh(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.GotFocus, Me.Move, Me.Activated, Me.SizeChanged, MyBase.Shown
'dont show when maximized or minimized, else show it'
If Me.WindowState = FormWindowState.Maximized Or Me.WindowState = FormWindowState.Minimized Then
border.Hide()
Else
RefreshBorder()
End If
End Sub
<DllImport("user32.dll")> _
Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As Integer) As Boolean
End Function
Public Const SWP_NOSIZE As Int32 = &H1
Public Const SWP_NOMOVE As Int32 = &H2
Public Const SWP_NOACTIVATE As Int32 = &H10
End Class
Let me know if this works for you.
You should check this out. It is in C# but you could try to get help translating it. Extending Form with Non-Client Area Painting. It is way above my head and since you are new to, it might be pretty tricky.
First of, since you did not specify, I am assuming you are using winforms and not WPf or Asp.net, both of which I have next to no experience with.
I have a method that is just messing with a bunch of winforms property's. It is kinda glitchy on my winxp, box but it works :). Here is the code for the two forms, I have included th property's in code to simplify things.
The Main form
Public Class frmMAin
Dim border As Form = New frmBackground()
Private Sub frmMAin_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.GotFocus
RefreshBorder()
End Sub
Private Sub frmMAin_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RefreshBorder()
End Sub
Private Sub RefreshBorder()
border.Show()
border.Size = New Size(Me.Width + 20, Me.Height + 20)
border.Location = New Point(Me.Location.X - 10, Me.Location.Y - 10)
End Sub
Private Sub frmMAin_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LostFocus
border.Hide()
End Sub
Private Sub frmMAin_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Move
RefreshBorder()
End Sub
End Class
The Background Form
Public Class frmBackground
Private Sub frmBackground_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Me.ShowInTaskbar = False
Me.BackColor = Color.Blue
Me.Opacity = 0.5
End Sub
End Class
And it turns out something like this.
This code still has some issues with focus but is mostly functional. Also keep in mind this is not the most "elegant" way to solve this problem, there is most likely a better way to do this with some system dll. You also might try WPF, as I hear you have much more control over look then in winforms.