ContextMenuStrip Location Point - vb.net

How to open the ContextMenuStrip programmatically at the cursor on right mouse button down/clicked over PictureBox?
I need to open ContextMenuStrip only in some areas of an Image (Schedule) in a PictureBox, so I disconnected the PictureBox.ContextMenuStrip property from the ContextMenuStrip1 and I'm firing it manually. That means I need to provide a point, which appears to be surprisingly challanging.
My question is similar to "How to get location of ContextMenuStrip", but I need to account for both vertical and horizontal scrolling, which it doesn't (unless I messed something).
So when I'm trying something like this (in PictureBoxPlan.MouseDown):
Dim rpt As Point = Me.PointToClient(PictureBoxPlan.Parent.PointToScreen(e.Location))
...it has a fundamental flaw, because the e.Location is in context of Image, regardless how it is scrolled within the PictureBox. I tried to Form.MouseDown event, but it's not fired, when [right] clicked on a PictureBox.
Just for confirmation, I still need the point in PictureBox context to analyze whether the ContextMenuStrip should be shown or not and to lookup associated ID.
I am now trying to use some constants (may not work if windows "font size" is set to other than 100%) together with scroll bars values, which is not optimal at all.

OK, I found what is breaking the logic in the ContextMenuStrip.Show(Point) documentation:
Show(Point)
Positions the `ToolStripDropDown` relative to the specified screen location.
So the ContextMenuStrip, to my surprise, takes the screen coordinates, not the Form ones. I then just removed PointToClient and everything works as a charm, regardless of window position on the screen or scrollbars position of the Image container:
Dim rpt As Point = PictureBoxPlan.PointToScreen(New Point(e.Location.X, e.Location.Y))
No need to take into account PanelPlan.VerticalScroll.Value or PanelPlan.HorizontalScroll.Value.

Related

Make Form Maximized, but not Full Screen

I would like to make my Form1 Maximized, but not Full Screen, as differentiated by Maximized taking the entirety of the screen while leaving space dedicated to the Taskbar at the bottom. To clarify, I'd like my application to work how other applications traditionally work, such as Chrome or the MS Office suite when maximized. Definitely nothing fancy.
To make my application resize itself dynamically, I've calculated where buttons will fit relative to the height and width of the application. However, I discovered quickly that my application, in Maximized state, actually continued underneath the task bar (or, in reverse, the taskbar is entirely cut off by the application - it is Full Screen). My bottom-most buttons are actually cut off by the taskbar. After experimenting with different Form settings, I discovered this appears to be entirely the result of WindowState = FormWindowState.Maximized setting.
I've tried various routes to counteract this behavior. First, I attempted to resize the maximum bounds programmatically, while leaving the Form's MaximumSize set to "0,0" (the default "resize me as needed" setting). I have this code in the Form_Load event:
Me.MaximizedBounds = Screen.PrimaryScreen.WorkingArea
and
Me.MaximizedBounds = Screen.FromHandle(Me.Handle).WorkingArea
However, these did not have any affect, even though the working area height is confirmed smaller than the form height. In fact, upon further testing, I have not been able to programmatically change the maximizedbounds at all, apart from manually in the form properties, setting the MaximumSize to 100,100. Does anyone have suggestions here?
I also tried to change the WindowsState = FormWindowState.Manual and readjust the form height this way:
Width = Screen.PrimaryScreen.WorkingArea.Width
Height = Screen.PrimaryScreen.WorkingArea.Height
Which makes the form closer to the dedicated dimensions, but makes the window movable and no longer covers the entirety of a traditionally maximized screen (it leaves about 20 pixels padding on all sides).
In the end, I'm at a bit of a loss on how to do this and would really appreciate some clarification. I have attempted other code I'd be glad to share, as well as similar questions on the forum, but none have helped me get my targeted behavior. I have a locked Taskbar on the most recent update to Windows 10, if those details make any difference.

Controls change place and form size changes

I have designed a form in VB.NET. At design time I have placed two buttons on it.
When I run it, the form size looks smaller and the buttons I have placed at the bottom are not visible. Also the alignment of the text and picture box is also different from what I set at design time.
Computer at which I am running the form is using a different resolution.
change the properties (F4) of the buttons: in ANCHOR put Bottom, Right
your buttons will be tied to the bottom and the right of the screen, instead of to the top, left, which is the default.
Grab the screen size at runtime with
Dim screen as System.Windows.Forms.Screen = System.Windows.Forms.Screen.PrimaryScreen
and using a scale factor depending on the current size (in design), scale the window to match. Check the coordinates of the buttons by hand to make sure they are not outside of the visible portion of the window.
You may not have to leave this feature in if you can debug it to the point that you know the exact resolution that you need.

How can I show scrollbars on a PictureBox control?

Sometimes, I have a picturebox lets say 100x100. But the image it will display is actually 100x400.
I don't want to increase the size of the picturebox itself. Instead, I would like to create a vertical scrollbar (or horizontal if needed).
I could not find a scrollbar in the toolbox, so I guess I have to code it. But, how?
And I still wonder if I didn't make a mistake and didn't see the scrollbar in the toolbox. My apologies then :(
I suppose you could add separate scrollbar controls and sync their Scroll events up with the offset at which the picture in the PictureBox is drawn, but that sounds like actual work. There's a better way.
Add a Panel control to your form, and set its AutoScroll property to "True". This will cause the control to automatically show scrollbars when it contains content that lies outside of its currently visible bounds. The .NET Framework will take care of everything for you under the covers, without you having to write a single line of code.
Drag and drop your PictureBox control inside of the Panel control that you just added. The Panel control will then detect that one of its child controls is larger than its visible area and show scrollbars, thanks to the AutoScroll property. When the user moves the scrollbars, the portion of the image in your PictureBox that is visible will be automatically adjusted. Magic.
(The reason you have to use a Panel control as a container is because PictureBox does not inherit directly from the ScrollableControl base class, which is what provides the AutoScroll property.)
I tried this and it worked well. But I noted that if the picturebox is docked in the panel, the picturebox is automatically set to the size of the parent panel, and can't be set larger (at least not in any way I could find). This defeats the purpose of the technique. So -- put the picturebox on the panel, but don't dock it, and it will work perfectly.
There are no automatic scroll bars on a picture box, but you can add the VScrollBar (and HScrollBar) control to the form and handle the image scrolling manually by redrawing it at a different offset each time the Scroll event is fired.

VB.NET: Scrollbar "button"?

I plan on using a scrollbar for, well, scrolling an image. The image is 200x500, however, the only visible area is 200x250.
So I set the max value to 250, and the min value to 0. The idea is that if I drag the scrollbar's button to the bottom, 250 pixels will have moved for the image, right?
But wait, the scrollbar's button is.... very small. And the scrollbar is actually pretty long. Is there a way to make the scrollbar's button longer?
How did you create this scrollbar? Is it a separate control all together, or it is a component of another control? I do know that scrollbars added separately act kinda funny at times.
What I would suggest is using the scollbars built into another container control, which should achieve the exact same effect.
Create a new panel control on your form, and name it. (I suggest something like panelPicture)
Position the panel where you want your picture to be.
Set the panel's size to 200x250.
Set the panel's "Autoscroll" property to True.
Put a PictureBox inside this panel, and name it. (I suggest something like picMyPicture.)
Set the PictureBox's position to 0, 0.
Set the PictureBox's size to 200x500 (or whatever is necessary).
Set the PictureBox's Image property as desired.
Now, the scrollbar should automatically appear on the picture, and it should look normal.
As a side note (which may or may not be relevant), users typically don't like having to scroll to see the rest of an image, so if you don't need the user to scroll down on the image for some definitive purpose (or because you don't know what the size of the image that will be handled is), I'd try and change the size of things on your form so scrolling will not be necessary.
I hope this helps!

Rectangles & Parsing in vb.net

This is kinda....a two part question. The first one is much more important than the second one, both of these are in the same project, and in vb.net.
How can I constrain the bounds of a rectangle object, which is controlled by a mouse, so it cannot be drawn outside a PictureBox? It is kindof a standard lasso control, the user can click and drag and it will draw a box from the initial click point to the mouse's current location. The starting point is at (rectX,rectY), and the box is drawn to the bottom right using rectDimX and rectDimY (to set the width and height) to see how much of a change has occurred with the mouse. Basically, its what you get with a click and drag on a Windows desktop. The issue here is that the rectangle is able to be drawn outside the PictureBox it is being drawn on, and the next part of the code attempts to reference this location, and then fails with an OutOfMemory exception. This leads me to my second question:
How can I make the rectangle draw in more than the fourth quadrant, which is only positive numbers? If it goes anywhere else, it does not show the rectangle, though it does still have the correct values. I know i could code this four times based on starting location and mouse location, but that would be a huge hassle and a rewrite of the whole rectangle code.
Is there an easy solution for either of these? The first one is a much bigger hassle, as it will be very time consuming if there is no easy way.
Thanks for the help!
For the first part of your question, even if the user drags the mouse beyond the edge of your picture box, you don't have to use those coordinates for your drawing routine. Simply do something like
If (DrawingPoint.X > PictureBox.Right)
DrawingPoint.X = PictureBox.Right // Right-hand limit of picture box
End If
And similar for the Y direction.
As for the negative numbers while drawing, you want to translate screen coordinates to client area coordinates. Have a look at ScreenToClient and ClientToScreen.