My project uses a PictureBox to draw a price chart.
The user has the option to add text to the chart.
How I currently have it is that there is a textbox control on the picturebox that is normally visible = false. It is flat with no border and matches the color of the PictureBox background (white).
When the user clicks on the Add Text button, visible = true.
The text box then follows the mouse pointer around the PictureBox and updates its contents automatically with the date ("mm/dd") based on where the mouse points (the dates are relative to the X values of the PictureBox).
And made the following test project to 'sort of' demonstrate.
Place a picturebox (pctChart) onto a form (Form1) covering most of the form. Set AutoRedraw = True.
Leave room for a button at the bottom (cmdAddText) and caption "Add Text".
Add a text box about 300 pixels wide with Appearance 0, BackColor white, Text = "".
Code:
Option Explicit
Private bTextToolActive As Boolean
Private Function GetDateFromX(ByVal xRef As Single) As String
Dim sngInterval As Single
Dim dStartDate As Date
Dim sCurrDate As String
Dim iDays As Integer
dStartDate = CDate("07/01/2015")
sngInterval = Form1.ScaleWidth / 100
iDays = xRef / sngInterval
sCurrDate = DateAdd("d", iDays, dStartDate)
GetDateFromX = Format$(sCurrDate, "mm/dd")
End Function
Private Sub cmdAddText_Click()
txtTextTool.Visible = True
bTextToolActive = True
End Sub
Private Sub pctChart_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If bTextToolActive Then
With txtTextTool
.Left = X
.Top = Y
.Text = GetDateFromX(X)
End With
End If
End Sub
Private Sub txtTextTool_Click()
With txtTextTool
bTextToolActive = False
pctChart.CurrentX = .Left
pctChart.CurrentY = .Top
pctChart.Print .Text
.Visible = False
End With
End Sub
The above is pretty much how I currently add text to my chart.
What I don't know is if there is a better way to do this.
Also, I'd like to give the user an opportunity to CHANGE the contents prior to printing it on the chart (pctChart). However, this would require clicking inside the textbox again (where you want to add text) which triggers my Click routine again that currently locks the textbox at the location.
Another thing I would prefer doing is to have the mouse pointer at the bottom and center of the text as I'm moving it around, rather than to the left.
Tinkering with this made me think perhaps I'm going about this wrong.
Re: How Do I: Move Text Around PictureBox Then Apply
This is what I got so far.
It's a bit clunky still.
There has to be a cleaner way.
Code:
Option Explicit
Private bTextToolActive As Boolean
Private bTextPrint As Boolean
Private Function GetDateFromX(ByVal xRef As Single) As String
'Return the date for X
Dim sngInterval As Single
Dim dStartDate As Date
Dim sCurrDate As String
Dim iDays As Integer
dStartDate = CDate("07/01/2015")
sngInterval = Form1.ScaleWidth / 100
iDays = xRef / sngInterval
sCurrDate = DateAdd("d", iDays, dStartDate)
GetDateFromX = Format$(sCurrDate, "mm/dd")
End Function
Private Sub cmdAddText_Click()
txtTextTool.Visible = True
bTextToolActive = True
End Sub
Private Sub pctChart_Click()
'If the user clicks outside the textbox after editing, make sure to catch that
If bTextPrint Then
With txtTextTool
bTextToolActive = False
pctChart.CurrentX = .Left
pctChart.CurrentY = .Top
pctChart.Print .Text
.Text = ""
.Left = -100
.Visible = False
End With
bTextPrint = False
End If
End Sub
Private Sub pctChart_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
'Move the textbox around the picturebox with the mouse cursor at bottom/center of textbox
If bTextToolActive Then
Font = txtTextTool.Font
With txtTextTool
.Width = TextWidth(.Text) + 120
.Height = TextHeight(.Text) + 120
.Left = X - (.Width / 2)
.Top = Y - (.Height / 2)
.Text = GetDateFromX(X)
End With
End If
End Sub
Private Sub txtTextTool_Click()
'Print contents of text box to picturebox
If bTextPrint Then
With txtTextTool
bTextToolActive = False
pctChart.CurrentX = .Left
pctChart.CurrentY = .Top
pctChart.Print .Text
.Text = ""
.Left = -100
.Visible = False
End With
bTextPrint = False
End If
'Move cursor inside textbox to end of text for possible additional text
If bTextToolActive Then
txtTextTool.SelStart = Len(txtTextTool.Text)
bTextPrint = True
bTextToolActive = False
End If
End Sub
Private Sub txtTextTool_KeyUp(KeyCode As Integer, Shift As Integer)
Dim sngStartWidth As Single
'Adjust size of textbox to accomodate added text
If bTextPrint Then
Font = txtTextTool.Font
With txtTextTool
sngStartWidth = .Width
.Width = TextWidth(.Text) + 120
.Left = .Left - ((.Width - sngStartWidth) / 2)
End With
End If
End Sub
Last edited by webbiz; Aug 29th, 2015 at 08:00 PM.
Reason: Modified code
Re: How Do I: Move Text Around PictureBox Then Apply
If it were me, I probably wouldn't drag a textbox around.
You click a button to start the process, and I think I would have a textbox there to allow entry of additional text you might want to append.
I would implement it more as a drag and drop action, i.e. they would have to click down on the picture and drag to place, or move the text.
When the text is where they want it, they could either right click to end the operation, or go back up and click another button to finish the operation.
You can move the text around without altering the image by setting AutoRedraw to False at the start of the operation.
You would just issue a refresh in the mouse move (which will redraw the image, "erasing" the text) and print the text again at the new location.
When you want to actually update the drawing, set AutoRedraw to True and print the text again for the final time and disable the drag mode.
A quick example of the text drawing part (didn't bother offsetting to the center for the example).
Just load a picture in the picturebox, and then click and drag in the picturebox (with AutoRedraw set to False), and see how it appears you're dragging the text around.
p.s. Added a command button that when clicked makes the dragged text a permanent part of the image.
Code:
Option Explicit
Dim mx As Single, my As Single
Private Sub Command1_Click()
With Picture1
.AutoRedraw = True
.CurrentX = mx: .CurrentY = my
Picture1.Print "This is a test"
.AutoRedraw = False
End With
End Sub
Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbLeftButton Then
mx = X: my = Y
Picture1.Refresh
End If
End Sub
Private Sub Picture1_Paint()
With Picture1
.CurrentX = mx: .CurrentY = my
Picture1.Print "This is a test"
End With
End Sub
Last edited by passel; Aug 30th, 2015 at 09:28 PM.
Re: How Do I: Move Text Around PictureBox Then Apply
Originally Posted by passel
If it were me, I probably wouldn't drag a textbox around.
Thanks passel for your reply and suggestion.
I don't like dragging the textbox as well. It's a bit choppy for my liking and the drag/drop is definitely cleaner/smoother.
With your help, I think I'm getting closer to what I'd like to see this do.
Here's what I have so far.
Code:
Option Explicit
Private bTextToolActive As Boolean
Private bTextPrint As Boolean
Private mx As Single, my As Single
Private txtNotes As String
Private Function GetDateFromX(ByVal xRef As Single) As String
'Return the date for X
Dim sngInterval As Single
Dim dStartDate As Date
Dim sCurrDate As String
Dim iDays As Integer
dStartDate = CDate("07/01/2015")
sngInterval = Form1.ScaleWidth / 100
iDays = xRef / sngInterval
sCurrDate = DateAdd("d", iDays, dStartDate)
GetDateFromX = Format$(sCurrDate, "mm/dd")
End Function
Private Sub cmdAddText_Click()
bTextToolActive = Not bTextToolActive 'Toggles flag
End Sub
Private Sub pctChart_Click()
If bTextToolActive Then
txtNotes = GetDateFromX(mx)
With pctChart
.AutoRedraw = True
.CurrentX = mx: .CurrentY = my
pctChart.Print txtNotes
.AutoRedraw = False
End With
End If
End Sub
Private Sub pctChart_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If bTextToolActive Then
mx = X: my = Y
pctChart.Refresh
End If
End Sub
Private Sub pctChart_Paint()
If bTextToolActive Then
With pctChart
.CurrentX = mx: .CurrentY = my
txtNotes = GetDateFromX(mx)
pctChart.Print txtNotes
End With
End If
End Sub
You click the button which toggles activation.
As soon as the mousemove event fires, the date for the cursor location is printed and moves with the mouse.
When the pctChart click event fires, it prints the date.
Moving the mouse continues to show the dynamically changing date so you can print at other locations.
Click the button again to stop the process.
It's got some issues I've yet to figure out, like when I move the mouse to click the button to turn off it may leave a stray date half off the bottom of the pctChart.
I'll also need to figure out how to 'edit' this date text because the user may wish to add to it or change it completely to some other text.
Thanks again for the suggestion. I think it is improving.