Cursor drag preview similar to web browser? - vb.net

After playing around with the DragDrop feature, I learn that I could update and use my own custom cursor during the Drag operation through the GiveFeedback event.
Within the GiveFeedback I create an image and then set the cursor to that image.
Private Sub Form1_GiveFeedback(sender As Object, e As GiveFeedbackEventArgs) Handles Form1.GiveFeedback
e.UseDefaultCursors = False
Dim pb As New PictureBox
pb.Size = New Drawing.Size(100, 100)
pb.Image = TextToImage("My Text")
pb.BackColor = Color.LightGray
Dim myPic As New Bitmap(pb.Image)
Cursor.Current = New Cursor(CType(myPic, Bitmap).GetHicon())
End Sub
The issue with this is that the cursor now becomes just the image so you can't really tell where your actual cursor is at, it becomes harder to drop the item accurately onto another control.
How do I do something like when you copy text/images in a web browser where it has a preview of what you're dragging?
For example: When I drag highlighted text and images, the drag has a preview of the content AND the cursor changes to show if the content can be dropped.

Related

VB.Net Print Form to PDF Printer

I am trying (and failing) right now to print a Windows Form as a PDF File in VB.Net
Now I know from doing some research that VB.Net does not have any built in function which could allow me to do this without using a third party application.
My way to get around this, was to attempt to print my Form using a PDF Printer, since logically that should work no? My issue is getting that to work properly.
This is currently my code for attempting to print:
Private Sub SelectPrinterThenPrint()
Dim PrintersDialog As New PrintDialog()
If PrintersDialog.SHowDialog(Me) = System.Forms.DialogResult.OK Then
Try
p_Document = New PrintDocument()
PrintersDialog.Document = p_Document
AddHandler p_Document.PrintPage, AddressOf HandleOnPrintPage
Catch ex As Exception
End Try
End If
End Sub
Private Sub HandleOnPrintPage(ByVal sender As Object, ByVal e As PrintPageEventArgs) Handles p_Document.PrintPage
Dim MorePagesPending = False
Dim bmp As New Bitmap(pnlContainer.Width, pnlContainer.Height)
pnlContainer.DrawToBitmap(bmp, pnlContainer.ClientRectangle)
e.Graphics.DrawImage(bmp, New Point(0,0))
If MorePagesPending Then
e.HasMorePages = True
Else
e.HasMorePages = False
End If
End Sub
The SelectPrinterThenPrint() method is called when a button on my Form is clicked. Right now I am having two issues.
1) I don't know how to setup where the file gets saved. The Print Dialog opens, and I get to select my PDF Printer, but it doesn't let me set a filename. So how do I set the filename I want to be printing to?
2) Because I can't tell if the file is actually being saved, I can't tell if I am actually setting up the print properly or not. I am trying to print the entire contents of a panel, which holds all the elements I want on my PDF file. One thing I am unsure about however, is that the form the panel is displayed in, is not the same size as the panel. The Form the panel is in has the same width, but not the same height, with the form being set up for auto scrolling. Will I get the whole Panel to print? Or just the part the is visible in the form at the time of printing?

How to create any one dynamic controls with a for loop without using location property and the form should grow automatically

How to create multiple button controls with a for loop without getting the controls overlapped and without using location property in Vb.Net.
I have created 'n' number of vb controls dynamically but the created controls are getting overlapped to each other. When I use location property to each controls all the controls are getting displayed as per the location value.
The real problem is, I'm using a panel of width 300 and height 300, under that I need to display the dynamically created controls. I have figured it out which is tedious work and does take a lot of time. My idea is to find the panel width and height then need to check whether the new control which is getting created has ample of space to fit inside the panel.
I need to know few things,
1) How to display the controls dynamically using for loop without getting overlapped over each other and without using location property.
2) I need the container or the panel to grow as per the number of controls which gets created dynamically.
3) Accessing each controls which got displayed using an ID or educate or explain me any better idea.
I created a new WinForms project and added a Button to the top of the form. I added a FlowLayoutPanel under that and made it narrow enough to fit a single Button widthwise. I set the AutoSize property of the FLP to True and the FlowDirection to TopDown. I then added this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Create the new Button.
Dim btn As New Button
'Add it to the FLP
FlowLayoutPanel1.Controls.Add(btn)
'Get the position of the bottom, left of the Button relative to the form.
Dim pt = PointToClient(btn.PointToScreen(New Point(0, btn.Height)))
'Resize the form to provide clearance below the new Button.
ClientSize = New Size(ClientSize.Width, pt.Y + 10)
End Sub
I then ran the project and started clicking the Button I added. As expected, each click added a new Button to the FLP in a vertical column and the form resized to fit. In order to access such controls in code, you can simply index the Controls collection of the FLP.
try this helps you.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
'Do Something
Else
'Do Something else
End If
Panel1.Controls.Clear()
For i As Integer = 0 To 10 Step 1
Dim b15 As New Button
b15.Text = "Test3"
b15.ID = "a" & i
AddHandler b15.Click, AddressOf updateFunc
Panel1.Controls.Add(b15)
Next
End Sub

Show dragged item while dragging vb.net

I'm wanting to show the dragged control while dragging in my form. I have a list of controls (textboxes and a picturebox) which are draggable. I would like to show the dragged control all the time, as long as the control is being dragged, even if the user cannot drop it. I also have an issue with dragging the picture box. It shows a dragged image of the control, however it flickers.
Code for drag feedback for picture box
Private Sub qrCode_GiveFeedback(ByVal sender As Object, ByVal e As GiveFeedbackEventArgs) Handles QRCodeDrag.GiveFeedback
Dim bitmap As Bitmap
bitmap = New Bitmap(QRCodeDrag.Width, QRCodeDrag.Height)
QRCodeDrag.DrawToBitmap(bitmap, New Rectangle(Point.Empty, bitmap.Size))
'bitmap.MakeTransparent(Color.White)
Dim cursor As New Cursor(bitmap.GetHicon)
Cursor.Current = cursor
End Sub
Any ideas?
I forgot to add
e.UseDefaultCursors = False
This solved the issue of the flicker

Detect how many screens are used end on which screen a form must load VB.net

I've searched the web and couldn't find much on the following questions:
How can i detect with vb.net how many screens i have (and which resolution they have).
How can i send out a identify monitor command (to know which number each screen has)
How can i (after detection) choose on which screen my form must open?
Can someone help me out?
In my case i have 4 screens but i have to choose from the main form on which screen i want to load a second form.
I found this on the web but this doesn't detect any screens:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim form As New Form
Dim screen As Screen
' We want to display a form on screen 1
screen = screen.AllScreens(1)
' Set the StartPosition to Manual otherwise the system will assign an automatic start position
form.StartPosition = FormStartPosition.Manual
' Set the form location so it appears at Location (100, 100) on the screen 1
form.Location = screen.Bounds.Location + new Point(100, 100)
' Show the form
form.ShowDialog(Me)
End Sub
The PrimaryScreen and AllScreens properties are Shared so you access them on the Screen class, not an instance of the Screen class. Check out this code:
Dim primaryScreen = Screen.PrimaryScreen
Dim allScreens = Screen.AllScreens
For Each screen In allScreens
Dim location = Point.Add(screen.Bounds.Location, New Size(100, 100))
Dim text = screen.DeviceName
If screen Is primaryScreen Then
text &= " (Primary)"
End If
Using dialogue As New Form With {.Text = text,
.StartPosition = FormStartPosition.Manual,
.Location = location}
dialogue.ShowDialog()
End Using
Next
That should demonstrate how the screens are named, and so how you can determine which is which, and also how to position a form on a specific screen. I just tested it on my four-monitor setup at work and it behaved as expected.

Darken a .Net Form

I have a 1080p touchscreen application. When a modal pops up, i want to emphasize that by darkening the main form.
Right now i use a second form, the size of the main form, that is black and has 50% opacity. Whenever a modal needs to appear, i open the opaque form, and then open the desired modal.
I feel this is a bit devious for my purpose. Its also not asshole-proof that when the user alt tabs, the forms will glitch out of sequence.
Is there a better way to achieve the darkening effect. Perhaps by darkening the main form from within itself?
Solved it myself by doing the following:
Place a hidden picturebox with dock:fill on the main form,
Take a screenshot of the current screen and darken it
assign the image to the picturebox and make it visible
open the modal in a new win
when the modal is dismissed
hide the picturebox
It really stupid that VB.net doesn't have this function built into it. Here's what you do to get around it:
Make a new form and call it Shade. I'm going to assume your main form is called frmMain. For the sake of clarity, lets assume the form you're launching is called dlgX.
Add the following lines in the Load event of dlgX (that's the sub with dlgX.Load or Me.Load or MyBase.Load):
Shade.Opacity = 0.001
Shade.Show()
Shade.Location = frmMain.Location ' Form location will only update if the form is visible.
Shade.Hide()
Shade.FormBorderStyle = Windows.Forms.FormBorderStyle.None 'This gets rid of the windows Titlebar and window border.
Shade.Size = frmMain.Size
Shade.BackColor = Color.Black
Shade.Opacity = 0.5
Shade.Show() ' Form size will only update the next time you show it.
Shade.TopMost = True ' Puts Shade over main form
Me.TopMost = True ' Puts current form over shade
Under all events that dismiss the form dlgX (OK.click, Cancel.click, etc), add the following lines:
Shade.Close
Or you can even make your own sub that handles all events where the form is closed:
Private Sub DispelShades(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.FormClosed
Shade.Close()
End Sub
This is way simpler than the PictureBox scenario and you don't have to mess with layering issues and having to ensure that the PictureBox renders on top of everything (for example, tabs really do not like having things rendered above them and they will not let you render a picture box above them). Rendering a black semi transparent form above your main form gets around all these headaches.
If you have multiple forms to shade, just make a Shad1, Shade2, Shade3 etc.
This is pretty obvious but it's worth stating: if you're shading the main form, you'll also want to make it unclickable by opening dlgX via dlgX.ShowDialog and not dlgX.Show
Here is some code, very similar to the method in Thomas's answer. Note to use the Darkness property in a Try...Finally block, to make sure you never leave the form in the dark state.
Public Class Form1
Private _PB As PictureBox
Public WriteOnly Property Darkness
Set(value)
If value Then
Dim Bmp = New Bitmap(Bounds.Size.Width, Bounds.Size.Height)
Me.DrawToBitmap(Bmp, New Rectangle(Point.Empty, Bounds.Size))
Using g = Graphics.FromImage(Bmp)
Dim Brush As New SolidBrush(Color.FromArgb(125, Color.Black))
g.FillRectangle(Brush, New Rectangle(Point.Empty, Bmp.Size))
End Using
_PB = New PictureBox
Me.Controls.Add(_PB)
_PB.Size = Bounds.Size
_PB.Location = Bounds.Location - PointToScreen(Point.Empty)
_PB.Image = Bmp
_PB.BringToFront()
Else
If _PB IsNot Nothing Then
Me.Controls.Remove(_PB)
_PB.Dispose()
End If
End If
End Set
End Property
Private Sub btnDialog_Click(sender As Object, e As EventArgs) Handles btnDialog.Click
Try
Darkness = True
MsgBox("Modal dialog")
Finally
Darkness = False
End Try
End Sub
End Class