PictureBox
Description
The PictureBox control allows the placement of text, images and drawings on the screen. It is a very powerful control, based on HTML5’s Canvas element.
To add a PictureBox to your app, choose the PictureBox icon in the Toolbar, then position it on the Design Screen. Use the Property Editor to set the properties you need, then add functions to your code to respond to the events that come from the button.
Images should be in your project folder or a subfolder. Add the name of the file or folder to the manifest in Project Properties.
The PictureBox acts as a container for a runtime context which contains the actual images and drawing. Use getContext("2d") to get the context. Once you have the context, you can manipulate its contents using the Runtime Context Properties and Methods shown below.
If you change the content of a scrolling PictureBox, do Picturebox1.refresh() to reset the scrolling.
To set an image in a PictureBox, have a look at the sample below. Since loading an image can take some time, it is divided into two parts. First, the image is loaded into a variable. When that complete, an event is sent to your program. Respond to that event by having an _onload() function to draw the image into the PictureBox.
Resizing at Runtime
PictureBoxes do not work well when sized by percentages. Here's an explanation I recently typed up:
PictureBoxes (which are based on the HTML5 Canvas element) are a bit trickier than most other controls. The main thing to keep in mind is that a canvas has both dimensions (specified by CSS - that is, PB.style.height), and a canvas size, specified by attributes on the actual tag (that is PB.height - NOT PB.Height).
Keeping that in mind, the next thing to be aware of is that AppStudio tries to do the right thing in most cases - so, when you set PB.Height, it not only sets the dimensions, of the canvas, but also sets the canvas size as well. So, setting PB.Height actually does two things:
1. Sets PB.style.height 2. Sets PB.height
Now, problems start to happen when you use percentages. If you read the HTML5 spec, you'll see that the canvas size CANNOT be specified with anything other than integers. If you specify the canvas size as 66%, for instance, the result is fairly implementation dependent, but most browsers seem to interpret this as 66px. So, when you set PB.Height = "66%", what happens is that PB.style.height is set to 66%, but PB.height is set to 66. This is obviously a problem.
The solution is to set the dimensions and canvas size discretely. Probably the easiest way to do this would be to size the PictureBox using percentages in the IDE. Then, on form load, I'd run the following code before drawing:
Dim actualHeight = PB.getBoundingClientRect().height Dim actualWidth = PB.getBoundingClientRect().width PB["height"] = actualHeight PB["width"] = actualWidth
You may notice that I had to trick AppStudio by typing PB["height"] as opposed to PB.height. The syntax is actually equivalent, but since we're trying to explicity set only the canvas size, we trick the IDE - otherwise, it would think we were trying to use PB.Height and set both dimensions.
Properties
Standard properties are supported. To change the height at runtime, change the value of height.
refresh() | Recalculates the size of the scrolling area after additions or deletions. |
scroll_options | This control makes use of iScroll. It has a number of options, including:
bounce: true/false. When the end of the scroll area is reached, should the image bounce? zoom: true/false. Allow two finger zoom in gesture? The full list of options is documented here: http://cubiq.org/iscroll-4 |
scrolling | Allow choices in the menu to scoll? On or off. (design time) |
Runtime Properties and Methods
getContext("2d") | Gets the drawing context. Returns the object that the PictureBox Context functions use. "2d" is currently the only valid argument. |
refresh() | Redraws the entire PictureBox. Required after resizing the box or scrolling. |
toDataURL(type) | Returns the current picturebox in a Base64 string image. If type is not specified, it is in PNG format. Type can also be "image/jpeg" or "image/gif". |
Runtime Context Properties and Methods
The following functions can be performed on the result of a getContext("2d") call.
addColorStop(stop,color) | Specifies the positions (0-1) and colors in a gradient object. |
arc(x, y, radius, startAngle, endAngle, counterclockwise) | Adds an arc to the current path using a radius and specified angles(in radians). |
arcTo(x1, y1, x2, y2, radius) | Adds an arc of a circle to the current sub path by using a radius and tangent points. |
beginPath() | Creates a new path in the canvas and sets the starting point to the coordinate (0,0). |
bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y) | Adds a cubic Bezier's curve to the current sub path using two control points. |
clearRect(x, y, width, height) | Clears the specified rectangle region and makes it transparent. |
clip() | Clips the current rectangle of any shape and size from the original canvas. |
closePath() | Closes an open path and attempts to draw a straight line from the current point to starting point of the path. The use of closePath() is optional. |
createImageData(width, height) | Creates a new, blank ImageData object. |
createLinearGradient(x1, y1, x2, y2) | The createLinearGradient(x1, y1, x2, y2) method takes four arguments that represent the start point (x1, y1) and end point (x2, y2) of the gradient. |
createPattern(image, repetitionStyle) | Creates a pattern by repeating an image. repetitionStyle can be repeat, repeat-x, repeat-y, no-repeat. |
createRadialGradient(x1, y1, radius1, x2, y2, radius2) | Radially interprets colors between two circles. |
drawImage(image, x, y, width, height) | Draw an image. |
fill() | Closes the current path and paints the area within it. |
fillRect(x, y, width, height) | Draws a filled rectangle. |
fillStyle | gradient|pattern |
fillText(text, x, y) | Writes text using current settings of font, textAlign and textBaseline. |
font | The font to use for text. It is a string with three parts: "style size fontname". style can be normal, italic or bold. Example: "italic 40px Calibri" |
getImageData(x,y,height,width) | Return the image data for a portion of the image. Includes width, height, data array [rgba]. |
globalAlpha | The transparency value. Must be a number between 0.0 (fully transparent) and 1.0 (no transparancy). |
globalCompositeOperation(source-over, source-atop, source-in, source-out, destination-over, destination-atop, destination-in, destination-out, lighter, copy, xor ) | Sets or returns how a source (new) images are drawn onto a destination (existing) image. |
isPointInPath(x,y) | Returns true if the specified point is in the current path, otherwise false. |
lineCap | Sets style of end caps for a line. "butt", "round" or "square". |
lineJoin | Set style where two lines meet. "bevel", "round" or "mitre". |
lineWidth | The current line width, in pixels. |
lineTo(x, y) | Adds a line segment from the current point to the specified coordinate. The appearance of the line can be set by the following properties: fillStyle, strokeStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor |
measureText(text) | Returns a rectangle object with text's size. |
miterLimit | The miterLimit property sets or returns the maximum miter length for line ends. |
moveTo(x, y) | Moves the starting point to a new coordinate specified by x,y values. |
putImageData(imgData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight) | Puts the image data (from a specified ImageData object) back onto the canvas. |
quadraticCurveTo(x, y, x1, y1) | Adds a quadratic Bezier's curve to the current sub path. |
rect(x, y, width, height) | Adds a rectangle. |
restore() | Restores the state of the saved context space. |
rotate(angle) | Rotate the entire context on specified angle(in radians). |
save() | Save the state of the original context space so that you can restore later. |
scale(x, y) | Add the scaling transformation described by the arguments to the transformation matrix. The x argument represents the scale factor in the horizontal direction and the y argument represents the scale factor in the vertical direction. The factors are multiples. |
scale(x, y) | Add the scaling transformation described by the arguments to the transformation matrix. The x argument represents the scale factor in the horizontal direction and the y argument represents the scale factor in the vertical direction. The factors are multiples. |
setTransform(a,b,c,d,e,f) | Transforms drawing. Scale horizontal, skew horizontal, skew vertical, scale vertical, move horizontal, move vertical. |
stroke() | Actually draws the path you have defined |
strokeRect(x, y, width, height) | Draws a rectangular outline. |
strokeStyle | gradient|pattern |
strokeText(text, x, y, maxWidth) | Draws text (with no fill) on the canvas. |
textAlign | Controls text alignment. Possible values are start , end , left , right and center .
|
textBaseline | Controls where the text is drawn relative to the starting point. Possible values are top , hanging , middle , alphabetic , ideographic and bottom .
|
style(x, y, width, height) | Any valid style string. |
translate(x, y) | Translate the origin of the context space to the specified of the canvas. |
Events
Standard events are supported.
Example 1: Display an image, drawing and text
dim pb Image1=new Image() Sub Main() pb = PictureBox1.getContext("2d") 'Draw a red oval with black border pb.strokeStyle = vbBlack pb.fillStyle = vbRed pb.beginPath() pb.arc(100,100,50,0,Math.PI*2,true) pb.closePath() pb.stroke() pb.fill() 'do some text as well pb.textBaseline = "top" pb.font="16px sans-serif" pb.fillText("This is a picturebox",0,0) Image1.src="mario.jpg" End Sub Function Image1_onload() pb.drawImage(Image1,0,0) End Function
Output
Sample code to just display an image.
LogoImage=new Image() pb = PictureBox1.getContext("2d") Sub Main() LogoImage.src="TestImage.png" End Sub Function LogoImage_onload() pb.drawImage(LogoImage,0,0) End Function
Example 2: Resize an image
resize = PictureBox1.style resize.width = "200px"
Example 3: Process some image data
Sub Main Image1.src="image001.jpg" Image2.src="image002.jpg" End Sub Function Button1_onclick() ImageMatch=True Pix1 = pb1.getImageData(0,0,199,199) Pix2 = pb2.getImageData(0,0,199,199) For i=0 To 199*199*4 Step 4 r = Pix1.data[i] <> Pix2.data[i] g = Pix1.data[i+1] <> Pix2.data[i+1] b = Pix1.data[i+2] <> Pix2.data[i+2] If r | g | b Then ImageMatch=False Pix1.data[i] = 255 - Pix1.data[i] Pix1.data[i+1] = 255 - Pix1.data[i+1] Pix1.data[i+2] = 255 - Pix1.data[i+2] End If Next i pb1.putImageData(Pix1,0,0) If !ImageMatch Then MsgBox "These cards are MARKED !" End Function
Example 4: Draw a red box
'Do some drawing: start by setting our colors. pb.strokeStyle = vbBlack pb.fillStyle = vbRed 'Now, we define the lines we want to draw in a path. pb.beginPath() pb.moveTo(10,10) pb.lineTo(10,50) pb.lineTo(50,50) pb.lineTo(50,10) pb.lineTo(10,10) pb.closePath() 'Path is complete: draw it pb.stroke() 'and paint the area inside the path pb.fill()
Other Examples
Make a PictureBox not selectable:
Function PictureBox1_onselectstart() return False End Function
JavaScript version
PictureBox1.onselectstart = function () { return false; }