Rubberband Line with ScrollBar 
Author Message
 Rubberband Line with ScrollBar

I have a {*filter*}band line tool which works well as long as both datapoints
are on the picturebox.    However if either datapoint is off the picturebox
how do i keep the mouse active (holding the line endpoint) and at the
same time scroll the picturebox forward / backward or up / down?


Sun, 04 Sep 2011 08:43:56 GMT  
 Rubberband Line with ScrollBar


Quote:
>I have a {*filter*}band line tool which works well as long as both datapoints
>are on the picturebox.    However if either datapoint is off the picturebox
>how do i keep the mouse active (holding the line endpoint) and at the
>same time scroll the picturebox forward / backward or up / down?

Sorry, I don't have an answer to your problem, but I am keen on
knowing more about this {*filter*}band line tool since I am into moving
objects around on the form or picturebox at the moment. Can you
explain a bit more about it? Home-brew? URL? Thanks!

MM



Sun, 04 Sep 2011 14:55:48 GMT  
 Rubberband Line with ScrollBar
MM:

A {*filter*}band line is used normally in drawing applications.  Instead of
just placing a line using coordinates (x1, y1) - (X2, Y2), the user can use
the mouse to stake the initial position and then drag the mouse and the line
follows the mouse until it is placed in the second position.


Quote:


>>I have a {*filter*}band line tool which works well as long as both datapoints
>>are on the picturebox.    However if either datapoint is off the
>>picturebox
>>how do i keep the mouse active (holding the line endpoint) and at the
>>same time scroll the picturebox forward / backward or up / down?

> Sorry, I don't have an answer to your problem, but I am keen on
> knowing more about this {*filter*}band line tool since I am into moving
> objects around on the form or picturebox at the moment. Can you
> explain a bit more about it? Home-brew? URL? Thanks!

> MM



Sun, 04 Sep 2011 19:45:34 GMT  
 Rubberband Line with ScrollBar
FWIW the follow code appears to work.
Not as smooth looking as I want and I'm loosing the initial anchor point for
my line (most likely an unrelated issue.)

'-------
If frmChild(Index).HScroll1.Value > frmChild(Index).HScroll1.max Then

   If x < objPBoxScaleLeft Then
      frmChild(Index).HScroll1.Value = frmChild(Index).HScroll1.Value + 1
      objPBox.Refresh
   End If

   If x > TChart(Index).XAxisWidth Then
      frmChild(Index).HScroll1.Value = frmChild(Index).HScroll1.Value - 1
      objPBox.Refresh
   End If

End If
-----------------


Quote:


>>I have a {*filter*}band line tool which works well as long as both datapoints
>>are on the picturebox.    However if either datapoint is off the
>>picturebox
>>how do i keep the mouse active (holding the line endpoint) and at the
>>same time scroll the picturebox forward / backward or up / down?

> Sorry, I don't have an answer to your problem, but I am keen on
> knowing more about this {*filter*}band line tool since I am into moving
> objects around on the form or picturebox at the moment. Can you
> explain a bit more about it? Home-brew? URL? Thanks!

> MM



Sun, 04 Sep 2011 20:19:19 GMT  
 Rubberband Line with ScrollBar


Quote:
> I have a {*filter*}band line tool which works well as long as both datapoints
> are on the picturebox.    However if either datapoint is off the picturebox
> how do i keep the mouse active (holding the line endpoint) and at the
> same time scroll the picturebox forward / backward or up / down?

This isn't perfected, but it will get you started.

Add a Picturebox to a new form, and paset in the code below.
Run the program and click the mouse in the the middle of the form,
then drag it (like you had a {*filter*}band line) off an edge of the form.

Basically you test for when the X and Y are out of view and move the
picture box appropreately.  But do note that moving the picturebox
will fire another MouseMove event which will move the picturebox, which
will fire another MouseMove, etc.  You'll have to add code to break that
chain as well as update your scroll bars....

HTH
LFS

-----
Option Explicit
Private Drawing As Boolean

Private Sub Form_Load()
  Picture1.Move 0, 0, ScaleWidth * 1.4, ScaleHeight * 1.4
End Sub

Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  Drawing = True
  Picture1.Circle (X, Y), 45, vbBlack
End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  If Drawing Then
      With Picture1
      'Debug.Print X, Y, .Left + X, .Top + Y
        If (.Left + X) < 0 Then
          If .Left < 0 Then
            .Left = .Left + 30
          End If
        End If
        If X > (.Left + Me.ScaleWidth) Then
          If (.Left + .Width) > Me.ScaleWidth Then
            .Left = .Left - 30
          End If
        End If

        If (.Top + Y) < 0 Then
          If .Top < 0 Then
            .Top = .Top + 30
          End If
        End If
        If Y > (.Top + Me.ScaleHeight) Then
          If (.Top + .Height) > Me.ScaleHeight Then
            .Top = .Top - 30
          End If
        End If
      End With
  End If

End Sub

Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  Drawing = False
End Sub



Sun, 04 Sep 2011 21:14:48 GMT  
 Rubberband Line with ScrollBar

Quote:
> . . . I am keen on knowing more about this {*filter*}band line
> tool since I am into moving objects around on the form or
> picturebox at the moment.

Not sure whether this is the sort of thing you are after but it allows you
to use the mouse to reposition and resize a number of Picture Boxes (or
other controls) on the Form. It's not actually finished code because, as
usual, I got side tracked onto something else ages ago and I just left it on
the back burner, but it should give you a start. I had originally written it
to handle a number of PictureBoxes and RichTextBoxes (which need to be
handled slightly differently to get them to update correctly) but I've cut
out all the RichTextBox stuff to simplify it. You should be easily able to
modify it to handle various other controls. It's a bit more complex than I
originally planned because for various reasons I wanted to pick up mouse
movements and clicks on the 3D border of the controls (which VB does not
fire a mouse event for) and so I had to add some subclassing code. The
subclassing makes it easier to detect the mouse movement anyway because it
can be detected on a "Form Wide" basis regardless of the control it is over,
which can sometimes be a help.

To try it out, start a new project using one Form and one Module. Place a
PictureBox on the Form and set its Index property to zero in the IDE. Then
paste in the following two blocks of code, one into the Module and one into
the Form. Change the hard coded picture path in the Form Load event to a
picture that exists on your own machine. When you run the code there will
appear to be just one picture on the Form, but if you click and drag this
with the mouse you will see that there are actually ten PictureBoxes,
initially in top of each other, each of which can be moved and resized with
the mouse. Naturally in a real application you would probably use a
different picture for each of the picture boxes, but for simplicity I've
used the same picture for each of them in the testbed code.

Mike

' ***** START OF FORM CODE *****
Option Explicit
Private Declare Function SendMessage Lib "user32" _
  Alias "SendMessageA" (ByVal hwnd As Long, _
  ByVal wMsg As Long, ByVal wParam As Integer, _
  ByVal lParam As Any) As Long
Private Declare Function ReleaseCapture _
  Lib "user32" () As Long
Private Const HTLEFT = 10
Private Const HTRIGHT = 11
Private Const HTTOP = 12
Private Const HTBOTTOM = 15
Private Const HTBOTTOMLEFT = 16
Private Const HTBOTTOMRIGHT = 17
Private Const HTTOPLEFT = 13
Private Const HTTOPRIGHT = 14
Private Const HTCAPTION = 2
Private Const WM_NCLBUTTONDOWN = &HA1
Private pic(0 To 9) As StdPicture

Private Sub Form_Load()
Dim n As Long
Me.ScaleMode = vbPixels
Me.WindowState = vbMaximized
' Normally we would load ten different images
' into the array of ten StdPic objects but for
' test purposes we are loading the the same
' image into each of them
Set pic(0) = LoadPicture("c:\temp\Jessica1.jpg")
For n = 1 To 9
  Set pic(n) = pic(0)
Next n
Picture1(0).ScaleMode = vbPixels
Picture1(0).Visible = True
Picture1(0).Move 300, 200, 240, 180
For n = 0 To 9
  If n <> 0 Then
    Load Picture1(n)
  End If
  totalWindows = totalWindows + 1
  windowHandles(totalWindows, 1) = Picture1(n).hwnd
  windowHandles(totalWindows, 2) = 2 ' to signify a picbox
  windowHandles(totalWindows, 3) = n ' the index
  Picture1(n).Visible = True
  Picture1(n).AutoRedraw = True
  ' the following line causes a resize so that the
  ' test image gets painted straight away
  Picture1(n).Width = Picture1(n).Width + 1
Next n
Me.MousePointer = vbArrow
SetFormHook Me
End Sub

Private Sub Form_Unload(Cancel As Integer)
ReleaseFormHook
End Sub

Private Sub Picture1_MouseDown(Index As Integer, _
  Button As Integer, Shift As Integer, _
  X As Single, Y As Single)
Dim SizingOp As Long
If Button = vbLeftButton Then
  Picture1(Index).ZOrder
  Refresh
  SizingOp = Val(Picture1(Index).Tag)
  ReleaseCapture  ' Release Mouse Capture
  SendMessage Picture1(Index).hwnd, WM_NCLBUTTONDOWN, _
    SizingOp, 0&
End If
If Button = vbRightButton Then
  Picture1(Index).ZOrder 1
End If
End Sub

Private Sub Picture1_MouseMove(Index As Integer, _
  Button As Integer, Shift As Integer, X As Single, _
  Y As Single)
Dim SizingOp As Long, pointer As Long, EdgeSense As Long
Dim boxScaleWide As Long, boxScaleHigh As Long
EdgeSense = Me.ScaleX(6, vbPixels, Me.ScaleMode)
boxScaleWide = Picture1(Index).ScaleWidth
boxScaleHigh = Picture1(Index).ScaleHeight
pointer = vbSizeAll 'vbDefault
SizingOp = HTCAPTION
Select Case True
  Case X < EdgeSense And Y < EdgeSense
    SizingOp = HTTOPLEFT
    pointer = vbSizeNWSE
  Case X >= boxScaleWide - EdgeSense And Y < EdgeSense
    SizingOp = HTTOPRIGHT
    pointer = vbSizeNESW
  Case X < EdgeSense And Y >= boxScaleHigh - EdgeSense
    SizingOp = HTBOTTOMLEFT
    pointer = vbSizeNESW
  Case X >= boxScaleWide - EdgeSense And _
        Y >= boxScaleHigh - EdgeSense
    SizingOp = HTBOTTOMRIGHT
    pointer = vbSizeNWSE
  Case X < EdgeSense
    SizingOp = HTLEFT
    pointer = vbSizeWE
  Case X >= boxScaleWide - EdgeSense
    SizingOp = HTRIGHT
    pointer = vbSizeWE
  Case Y < EdgeSense
    SizingOp = HTTOP
    pointer = vbSizeNS
  Case Y >= boxScaleHigh - EdgeSense
    SizingOp = HTBOTTOM
    pointer = vbSizeNS
End Select
If Picture1(Index).MousePointer <> pointer Then
  Picture1(Index).MousePointer = pointer
  Picture1(Index).Tag = Str$(SizingOp)
End If
End Sub

Private Sub Picture1_Resize(Index As Integer)
If Picture1(Index).Width < 18 Then
  Picture1(Index).Width = 18
End If
If Picture1(Index).Height < 18 Then
  Picture1(Index).Height = 18
End If
If Picture1(Index).ScaleWidth > 0 And _
          Picture1(Index).ScaleHeight > 0 Then
Picture1(Index).PaintPicture pic(Index), 0, 0, _
  Picture1(Index).ScaleWidth, Picture1(Index).ScaleHeight
End If
End Sub
' ***** END OF FORM CODE *****
'
' ***** START OF MODULE CODE *****
Option Explicit
Private Declare Function SetWindowsHookEx _
  Lib "user32" Alias "SetWindowsHookExA" _
  (ByVal idHook As Long, ByVal lpfn As Long, _
  ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx _
  Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function CallNextHookEx _
  Lib "user32" (ByVal hHook As Long, _
  ByVal nCode As Long, ByVal wParam As Long, _
  lParam As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" _
  Alias "RtlMoveMemory" (Destination As Any, _
  Source As Any, ByVal Length As Long)
Private Declare Function WindowFromPoint _
  Lib "user32.dll" (ByVal xPoint As Long, _
  ByVal yPoint As Long) As Long
Private Declare Function GetWindowRect Lib "user32" _
  (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function ClientToScreen Lib "user32" _
  (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function ScreenToClient Lib "user32" _
  (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Type POINTAPI
  X As Long
  Y As Long
End Type
Private Type RECT
  Left As Long
  Top As Long
  Right As Long
  Bottom As Long
End Type
Private Type MOUSELLHOOKSTRUCT
  point As POINTAPI
  data As Long
  flags As Long
  time As Long
  extra As Long
End Type
Private mousedata As MOUSELLHOOKSTRUCT
Private Const HC_ACTION = 0
Private Const WH_MOUSE As Long = 7 ' app level hook
Private Const WM_LBUTTONUP As Long = &H202
Private Const WM_MOUSEMOVE As Long = &H200
Private Const WM_NCMOUSEMOVE As Long = &HA0
Private Hook As Long
Private HookedForm As Form
Public LastActiveRTB As Long
Public windowHandles(1 To 100, 1 To 3) As Long
Public totalWindows As Long

Public Sub SetFormHook(f1 As Form)
Set HookedForm = f1
Hook = SetWindowsHookEx(WH_MOUSE, _
    AddressOf MouseProc, App.hInstance, App.ThreadID)
End Sub

Public Sub ReleaseFormHook()
UnhookWindowsHookEx Hook
End Sub

Private Function MouseProc(ByVal nCode As Long, _
   ByVal wParam As Long, ByVal lParam As Long) As Long
Dim n As Long, mouseWindow As Long
Dim r1 As RECT, p1 As POINTAPI, wide As Long, high As Long
If (nCode = HC_ACTION) Then
  Select Case wParam
    Case WM_NCMOUSEMOVE
      ' It is a mousemove in the non client area
      ' of a window (in other words, in its border).
      ' This event is not passed on to VB so it does
      ' not trigger a VB MouseMove event, so we need
      ' to use this subclassing routine to change the
      ' pointer of the active control to the same as the
      ' Form (vbArrow) to signify that the window cannot
      ' be dragged using our code when the pointer is on
      ' the border (because mouse moves and clicks in
      ' a border do not generate a VB mousemove or
      ' mouseclick event)
      CopyMemory mousedata, ByVal lParam, Len(mousedata)
      mouseWindow = WindowFromPoint _
        (mousedata.point.X, mousedata.point.Y)
      For n = 1 To totalWindows
        If windowHandles(n, 1) = mouseWindow Then Exit For
      Next n
      If n <= totalWindows Then
        ' we have found the window handle in our list
        If windowHandles(n, 2) = 2 Then ' it is a PicBox
          HookedForm.Picture1 _
            (windowHandles(n, 3)).MousePointer = vbArrow
        End If
      End If
    Case WM_MOUSEMOVE
    '
    Case Else
      '
  End Select
End If
' job done so allow the system to carry on as normal
MouseProc = CallNextHookEx _
    (0, nCode, wParam, ByVal lParam)
End Function
' ***** END OF MODULE CODE *****



Sun, 04 Sep 2011 22:13:39 GMT  
 Rubberband Line with ScrollBar
Mr. Serflaten:

Have to study your response as on first review seems non-intuitive
to move  the Picturebox (.Left = .Left + 30) when your interested in moving
the contents displayed in the Picturebox client area.


Quote:


>> I have a {*filter*}band line tool which works well as long as both datapoints
>> are on the picturebox.    However if either datapoint is off the
>> picturebox
>> how do i keep the mouse active (holding the line endpoint) and at the
>> same time scroll the picturebox forward / backward or up / down?

> This isn't perfected, but it will get you started.

> Add a Picturebox to a new form, and paset in the code below.
> Run the program and click the mouse in the the middle of the form,
> then drag it (like you had a {*filter*}band line) off an edge of the form.

> Basically you test for when the X and Y are out of view and move the
> picture box appropreately.  But do note that moving the picturebox
> will fire another MouseMove event which will move the picturebox, which
> will fire another MouseMove, etc.  You'll have to add code to break that
> chain as well as update your scroll bars....

> HTH
> LFS

> -----
> Option Explicit
> Private Drawing As Boolean

> Private Sub Form_Load()
>  Picture1.Move 0, 0, ScaleWidth * 1.4, ScaleHeight * 1.4
> End Sub

> Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As
> Single, Y As Single)
>  Drawing = True
>  Picture1.Circle (X, Y), 45, vbBlack
> End Sub

> Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As
> Single, Y As Single)
>  If Drawing Then
>      With Picture1
>      'Debug.Print X, Y, .Left + X, .Top + Y
>        If (.Left + X) < 0 Then
>          If .Left < 0 Then
>            .Left = .Left + 30
>          End If
>        End If
>        If X > (.Left + Me.ScaleWidth) Then
>          If (.Left + .Width) > Me.ScaleWidth Then
>            .Left = .Left - 30
>          End If
>        End If

>        If (.Top + Y) < 0 Then
>          If .Top < 0 Then
>            .Top = .Top + 30
>          End If
>        End If
>        If Y > (.Top + Me.ScaleHeight) Then
>          If (.Top + .Height) > Me.ScaleHeight Then
>            .Top = .Top - 30
>          End If
>        End If
>      End With
>  End If

> End Sub

> Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As
> Single, Y As Single)
>  Drawing = False
> End Sub



Sun, 04 Sep 2011 22:36:50 GMT  
 Rubberband Line with ScrollBar


Quote:


>>I have a {*filter*}band line tool which works well as long as both datapoints
>>are on the picturebox.    However if either datapoint is off the picturebox
>>how do i keep the mouse active (holding the line endpoint) and at the
>>same time scroll the picturebox forward / backward or up / down?

> Sorry, I don't have an answer to your problem, but I am keen on
> knowing more about this {*filter*}band line tool since I am into moving
> objects around on the form or picturebox at the moment. Can you
> explain a bit more about it? Home-brew? URL? Thanks!

> MM

To the OP, in your mouse move event can't you check on your picture box, in relation to
the pointer, and scroll it accordingly?

Galen



Sun, 04 Sep 2011 22:46:48 GMT  
 Rubberband Line with ScrollBar

Quote:
>I have a {*filter*}band line tool which works well as long as both datapoints
> are on the picturebox.    However if either datapoint is off the
> picturebox
> how do i keep the mouse active (holding the line endpoint) and at the
> same time scroll the picturebox forward / backward or up / down?

Use SetCapture() to capture the mouse. When you capture the mouse, mouse
events still fire outside your control, even when the mouse leaves the form
to anywhere in the screen, until you call ReleaseCapture() or certain events
occur, like clicking on another window created by another thread.

The coordinates in the events will go below and beyond the control limits
and you can use that to tell where the mouse is being dragged relative to
the PictureBox.

The sample below illustrate this. First, move the mouse around(without
clicking) and the coordinates displayed will only change when you are moving
the mouse within the PictureBox. Second, press and hold the left mouse and
drag the mouse outside the picture box, now the coordinates are showing the
mouse pointer location regardless of the location on the screen. Release the
mouse button to finish.

To try the sample, add a PictureBox to Form1, and paste the following code
in the general section of Fom1:

Option Explicit

Private Declare Function SetCapture Lib "user32" ( _
    ByVal hwnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long

Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, _
    X As Single, Y As Single)
    Debug.Print "Picture1_MouseDown: " & Str(X) & ", " & Str(Y)
    SetCapture Picture1.hwnd
End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, _
    X As Single, Y As Single)
    Me.Caption = Str(X) & ", " & Str(Y)
End Sub

Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, _
    X As Single, Y As Single)
    Debug.Print "Picture1_MouseUp: " & Str(X) & ", " & Str(Y)
    ReleaseCapture
End Sub



Sun, 04 Sep 2011 23:28:59 GMT  
 Rubberband Line with ScrollBar
Mr. Somerville:

I believe in my example (see prev Post) that is what I'm doing.
Have other alternative (code) in mind?


Quote:





>>>I have a {*filter*}band line tool which works well as long as both datapoints
>>>are on the picturebox.    However if either datapoint is off the
>>>picturebox
>>>how do i keep the mouse active (holding the line endpoint) and at the
>>>same time scroll the picturebox forward / backward or up / down?

>> Sorry, I don't have an answer to your problem, but I am keen on
>> knowing more about this {*filter*}band line tool since I am into moving
>> objects around on the form or picturebox at the moment. Can you
>> explain a bit more about it? Home-brew? URL? Thanks!

>> MM

> To the OP, in your mouse move event can't you check on your picture box,
> in relation to the pointer, and scroll it accordingly?

> Galen



Sun, 04 Sep 2011 23:31:27 GMT  
 Rubberband Line with ScrollBar


Quote:
> Use SetCapture() to capture the mouse.

That would be redundant as the mouse is already captured on
mousedown....

LFS



Sun, 04 Sep 2011 23:35:45 GMT  
 Rubberband Line with ScrollBar

Quote:


>> Use SetCapture() to capture the mouse.

> That would be redundant as the mouse is already captured on
> mousedown....

> LFS

Maybe in buttons and some controls, but not in PictureBoxes. I tested the
sample on XP, and it seems there is a difference...


Sun, 04 Sep 2011 23:39:46 GMT  
 Rubberband Line with ScrollBar

Quote:
> To try it out, start a new project using one Form and one Module.
> Place a PictureBox on the Form and set its Index property to . . .

. . . one thing I forgot to mention is that when you are moving and sizing
the different PictureBoxes you should use the left mouse button as is
usually the case. Other than that, a left click will bring a PictureBox to
the front and a right click will send it to the back, allowing you to order
the PictureBoxes as well as size and move them.

Mike



Sun, 04 Sep 2011 23:51:08 GMT  
 Rubberband Line with ScrollBar
Nobody:

I'm with LFS on this one.  Going from the PBox client area coordinates
to Screen doesn't IMO gain any advantage.  Since the Scrollbar
controls the client area (what array elements are showing) the mouse
coordinates are dependent to the scrollbar and array.

David


Quote:



>>> Use SetCapture() to capture the mouse.

>> That would be redundant as the mouse is already captured on
>> mousedown....

>> LFS

> Maybe in buttons and some controls, but not in PictureBoxes. I tested the
> sample on XP, and it seems there is a difference...



Mon, 05 Sep 2011 01:03:11 GMT  
 Rubberband Line with ScrollBar

Quote:


>> Use SetCapture() to capture the mouse.

> That would be redundant as the mouse is already captured on
> mousedown....

> LFS

You are correct. I didn't bother to test it without SetCapture().


Mon, 05 Sep 2011 01:11:38 GMT  
 
 [ 25 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Rubberband Arc or Rubberband Curve

2. Rubberband Line

3. Flash Scrollbar or Change Scrollbar Color

4. When the Treeview scrollbar moves the FlexGrid Scrollbar should also move

5. RubberBand UserControls

6. Rubberband Rectangle in ACCESS-Form via WinApi

7. Drawing rubberband OVER controls

8. RubberBand TextBox

9. RubberBand TextBox

10. ?! Rubberband always at the background ?!

11. Continuing a line of code on the next line

12. Using Line Input to go back a line

 

 
Powered by phpBB® Forum Software