Finding coordinates of subform within form, in specific area - vb.net

I'm using the Adobe Reader control AxAcroPdf in VB to show a pdf file within a form. In this form, there is an option to popup a subform, which shows a barcode. The user should be able to drag the subform where they want on the PDF, and upon hitting Enter, the barcode is stamped on that location where the subform was located.
So I've got the stamping down and the barcode design, but I can't seem to pinpoint the exact location this thing should go. I've tried a number of variations of this, and I can't seem to get anything to work.
'coordinates of barcodeform relative to the pdf control
Dim pt3 As Point = rdrAdobePdf.PointToClient(barCodeForm.Location)
'This comes close but is always 10-50 pixels off
Dim clientBarCode As Point = New Point(0.5 * (PointToClient(barCodeForm.Location).X - 5), (CInt(pdfReader.GetPageSize(1).Height) - PointToClient(barCodeForm.Location).Y - 80))
'Dim clientBCTry1 As Point = Point.op_Subtraction(PointToClient(screenBarCode), topLeftCorner)
'Dim clientBCtry2 As Point = rdrAdobePdf.PointToClient(screenBarCode)
I understand the basics about PointToClient and PointToScreen and I also understand the concepts of (X,Y) coordinates. Yet after days of trying things nothing works. Any help is appreciated.

This almost seems like a hardcoded solution, but this code somewhat helps. It does position the barcode accurately if stamped at the top of the PDF page. However, if stamped toward the bottom, it becomes less and less accurate... even though the dimensions of the page don't change. If anyone has any other solutions feel free to post them.
Dim x As Integer = CInt(0.5 * (PointToClient(screenBarCode).X))
Dim y As Integer = (CInt(pdfReader.GetPageSize(1).Height) - PointToClient(screenBarCode).Y)
If x < 0 Then x = 0
If y < 0 Then y = 0
Dim clientBarCode As Point = New Point(x, y)

Related

How to identify which monitor a winform is displayed on, in a multi monitor setup?

I have found a lot of answers researching this, but non address my question.
Assume that user has 2 monitors, say a laptop screen with 1600×1200 res, and external monitor of 2560×1440 res. Regardless how the 2 displays are set up, if a client moves the main-form of the program to the external monitor, I would like it to report that its on 2560×1440 res. When the main-form is moved on to the laptop it should report the 1600x1200.
Is this possible? I know how to report the res, I just do not know how to identify which monitor the main-form is sitting on.
You need to first identify what you mean by the form being on a screen, because it's possible for a single form to span multiple screens. You're going to be using the Screen class regardless, but the calculations will be different. The simplest option would be to use the Location property, e.g.
For Each scrn In Screen.AllScreens
If scrn.Bounds.Contains(Location) Then
MessageBox.Show($"Resolution: {scrn.Bounds.Width} x {scrn.Bounds.Height}")
Exit For
End If
Next
Another option would be to use the screen that contains the largest proportion of the form, e.g.
Dim maxArea = 0
Dim resolution = Size.Empty
For Each scrn In Screen.AllScreens
Dim intersection = Rectangle.Intersect(scrn.Bounds, Bounds)
Dim area = intersection.Width * intersection.Height
If area > maxArea Then
maxArea = area
resolution = scrn.Bounds.Size
End If
Next
MessageBox.Show($"Resolution: {resolution.Width} x {resolution.Height}")
Note that this code will display the resolution of the first encountered if the equal parts of the form are on multiple screens.
There may be other options too, although these seem the most likely.
EDIT:
It's also worth noting that the first code won't work for a maximised form because the actual Location value will be outside the bounds of the screen it's on, so you'd need a bit of jiggery-pokery to handle that. The second code will handle that without issue.

Resize image when pasted to RichTextBox - or another solution?

I have a Windows form with a TabControl. In Tab 1 I have a RichTextBox (rtb1) and a Picturebox (pbx). In Tab 2 I have another RichTextBox (rtb2).
When I click a button, text from rtb1 and the current picture in pbx is put into rtb2. Problem is that the picturesize won't always fit. My current code is this:
Dim text = rtb1.Text
rtb2.AppendText(text)
Clipboard.SetImage(pbx.Image)
rtb2.Paste()
Is it possible to have the code resize the image as it's pasted?
It is possible to get the image from a windows path, I just didn't know how to resize this in a RichTextBox either. If this makes it easier?
Edit: This did it!
Dim newWidth = 500
Dim newHeight = 500
Clipboard.SetImage(New Bitmap(pbxDatasheet.Image, newWidth, newHeight))
rtbArmy.Paste()
Edit 2: It still doesn't work.
With the exact same code these things happen:
1. Most of the time the pasted picture(s) are the same size. But not the right size. I can change newWidth and newHeight all I want, they rarely differ in size. Although sometimes the picture is way larger than the others.
2. Sometimes it doesn't even add the picture to the RichTextBox. There's no pattern to when it happens.
The same lines of code can do all the above things. I have no idea what to do here.

Creating an object for click and dragging as oppose to repeated code for multiple drag sources.

I am currently developing a project in which part of its functionality consists of a timeline where the user can drag and drop dates to their corresponding events and vice versa. The dates and events are images.
The system currently works by repeating code for every "image source" and "drag location". I have six different image sources and hence repeat this code 6 times.
(code for initiating the click and drag)
If (e.Button = MouseButtons.Left) Then
Dim source As PictureBox = DirectCast(sender, PictureBox)
PicDragSource.DoDragDrop(source.Image, DragDropEffects.Copy)
End If
(code for the empty picture box to receive the image copy)
Dim bm As Bitmap = DirectCast(
e.Data.GetData(DataFormats.Bitmap, True), Bitmap)
PicDropTarget.Image = bm
Is there a way to replicate this using object oriented methods to make my code a bit more elegant as appose to the CTRL + C, CTRL + V state it is currently in? My experience with VB and OOP is very limited but i would like to add another level of complexity to my project.
I apologise for any ignorance in advance,
cheers
(code above taken from this website for my student project)

Is there a vay to make this code faster? Drawing a point on chart is slow

is there any way to make this work faster?
Here is my sample code in vb.net. This adds a point on a chart at mouse position but it is quite slow.
Private Sub Chart2_MouseMove(sender As Object, e As MouseEventArgs) Handles Chart2.MouseMove
Dim coord() As Double = GetAxisValuesFromMouse(e.X, e.Y)
Dim test As Series
Try
Chart2.Series.RemoveAt(1)
Catch ex As Exception
End Try
Dim pt As New DataPoint
pt.XValue = coord(0)
pt.YValues(0) = coord(1)
test = New Series
Chart2.Series.Add(test)
Chart2.Series(test.Name).ChartType = SeriesChartType.Point
Chart2.Series(test.Name).Points.Add(pt)
End Sub
Function returns the coordinates of x and y axis at mouse position.
Private Function GetAxisValuesFromMouse(x As Integer, y As Integer) As Double()
Dim coord(1) As Double
Dim chartArea = Chart2.ChartAreas(0)
coord(0) = chartArea.AxisX.PixelPositionToValue(x)
coord(1) = chartArea.AxisY.PixelPositionToValue(y)
Return coord
End Function
Result:
In your Chart2 window, there's got to be a way to perform an Invalidate with a clipping rectangle.
Another method I use is not to paint directly to the window, but instead paint to a memory bitmap, which I then BLT to the visible window. That can actually be faster because in painting to the bitmap it's not having to slow down to do clipping. This also gives a (fake) impression of speed because I can't see the green lines being redrawn (even though they are).
Yet another method is, when painting the dot where the mouse is, XOR it to the screen.
Then when I move it, XOR it in the old location (to erase it), and then XOR it in the new location. That way, I'm not repainting all those little green lines that haven't moved.
Still another method is: if there are thousands of little lines in the graph, some of them have to be of length zero pixels. They take time to draw even though they contribute nothing to the image, so they could be omitted.
Use Flexcell Grid control
it is superb control it provide all those feature which provide by datagrid control and more
FlexCell is a flexible and easy to use grid control. ... It provides comprehensive functions such as Print, Print Preview, Chart, ... Using FlexCell Grid Control, you can create the professional user interfaces and report form in your application. ... your applications coded in Visual Basic, Visual FoxPro, Visual C++, VB.net, C#, etc.

Branching Slides in PowerPoint (VBA)

I am trying to create a back button but using hyperlinks it simply just takes me to the previous page and ends up in a loop... e.g. if I have slide 1 which has links to slide 3, 4 & 5 then slide 3 links to 6 & 7. If I'm currently on slide 7 and click back it successfully takes me back to slide 3 but then I want to click back and end up at slide 1 rather than back to slide 7 (hopefully I'm making some sense!).
I presume the only way for me to do this is with VBA can anyone give me some advice on best way to create a back button? (I'm using PowerPoint 2007)
I was struggling with a similar problem today and made a little "breadcrumb"- generator for powerpoint. There is no link feature yet, but you can implement it if you like:
Github Project
Essential parts of the code
Public Sub breadcrumbs(ByVal count As Integer, ByRef titles() As String)
Dim cntr As Integer
Dim content() As String
Dim margin As Integer
Dim width As Integer
'----------------------------
' Set Titles
content = titles
cntr = 0
' Set width
width = ((Application.ActivePresentation.PageSetup.SlideWidth - (margin * count * 2) - 20) / count) - 50
' Loop through all slides
For Each sld In Application.ActivePresentation.Slides
' generate breadcrumb for each title
For Each con In content
sld.Shapes.AddShape(1, (50 + (width * cntr)), 15, width, 50).TextFrame.TextRange.Text = con
cntr = cntr + 1
Next con
cntr = 0
Next sld
End Sub
It sounds like you want a 'breadcrumb trail' of visited slides, instead of a simple back button. Thus you need a way to preserve the trail.
This could be addressed with a dynamic array. New browsing would add records to the array. Your "Next" and "Previous" locations would be found by moving up or down the array. You'll have some mild logic puzzles. I hate to refer you a generic resource, but I'm out of specifics and an overview may be helpful.
UPDATE: I've wanted this in the past for MS Access, and thought I'd readily find a snippet solution. But now I go to search (thinking it will convert over for you easily as well), and I don't find anything. This is surprising because I imagine it would be fun to built. Or ... it's harder to build than I anticipate.
There is a really cumbersome way to do this in PPT directly with no programming. You'll need "forward-facing slides" and 2 sets of "backward-facing slides". Backwards ones are two types - direct-back and home-back. They can all be identical, but make the backward ones hidden (e.g. instead of "Slide 3" you'll need "Slide 3a" and "Slide 3b" and "Slide 3c".). They are hidden so that when you progress through normally, you won't see them, but when you link to them, they will appear. Your link list on the "a" slides should always point to the "b" slides and your "b" slides will point to the "c" slides. Your hyperlinks on "back button" on "a" slides should be "previous slide" and on the "c" slides should be "last slide viewed" and on "h" slides should be "first slide" (use 'action' to set this instead of 'hyperlink').
It takes a while to work through, but it can be done.