In the mouse move event handler of a picturebox I change the mouse pointer conveniently near the borders so as to let the user know he an drag to stretch it. But I just don't remember how to restore the pointer to default when not moving over the picturebox, i.e. I need to implement some sort of mouse leave event.
Last edited by krtxmrtz; Mar 17th, 2010 at 11:48 AM.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
In the code below picCW is contained in a parent picturebox just 2 pixels larger on all 4 sides (border width is 1 pixel for both).
Code:
Private Sub picCW_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
If (Abs(X) > 0 And Abs(X) < picCW(Index).ScaleWidth) And (Abs(Y) <= 1 Or Abs(Y - picContCW(0).ScaleHeight) <= 1) Then
MousePointer = ccSizeNS
Else
MousePointer = ccDefault
End If
End Sub
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
Private Sub picCW_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
be
Private Sub picCW_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
It's an array of 2 pictureboxes.
Originally Posted by koolsid
2. If my understanding is correct then you want the cursor to change back to normal the moment it is out of picContCW?
That's right.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
Thank you, it works as I meant it to.
I'm a bit surprised we have to resort to API functions to accomplish such a -apparently- simple task
Final code:
VB Code:
Private Sub PicCW_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
With picCW(Index)
If X < 0 Or X > .ScaleWidth Or Y <> 0 And Y <> .ScaleHeight - 1 Then
ReleaseCapture
'The mouse is no longer over the picture box
MousePointer = ccDefault
ElseIf GetCapture() <> .hwnd Then
SetCapture .hwnd
'The mouse is over the picture box
MousePointer = ccSizeNS
End If
End With
End Sub
Last edited by krtxmrtz; Mar 11th, 2010 at 05:42 AM.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
Now, I want to code differently depending on whether the mouse is on the border or inside the picturebox: stretch or move it. But after GetCapture has been issued, if the mouse over is triggered, then no more mouse over events are fired until you move it out of the picturebox.
I've tried to play around with the *Capture functions but I've got into a mess.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
What I want to do is use the mouse down, move and up events to drag the edges of a picturebox (pic2) to change its size or to drag inside to move it throughout its parent control, pic1, another picturebox.
I don't know if I must use Picture1's or Picture2's events and how to code it so that the appropriate mouse cursors are assigned.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
If cursor is outside of pic2 (ie, somewhere in pic1), then you don't care
If cursor is "on the border" of pic2, pic2 events would trigger -- would be "stretch" situation
If cursor is "well inside" of pic2, pic2 events still would trigger -- could be "move" situation.
So, it seems that pic2 events are the relevant ones.
Now it comes down to defining what "on the border" means. I'd
guess you'd want to give some cushion (5 to 10 pixels maybe).
What I want to do is use the mouse down, move and up events to drag the edges of a picturebox (pic2) to change its size or to drag inside to move it throughout its parent control, pic1, another picturebox.
I don't know if I must use Picture1's or Picture2's events and how to code it so that the appropriate mouse cursors are assigned.
You can change the style of controls at runtime so they can be resized, and you'll get the resize arrow icons when the mouse is on the edge of the control. Just a thought......
Code:
Option Explicit
Private Const SWP_DRAWFRAME As Long = &H20
Private Const SWP_NOMOVE As Long = &H2
Private Const SWP_NOSIZE As Long = &H1
Private Const SWP_NOZORDER As Long = &H4
Private Const SWP_FLAGS As Long = SWP_NOZORDER Or SWP_NOSIZE Or SWP_NOMOVE Or SWP_DRAWFRAME
Private Const GWL_STYLE As Long = (-16)
Private Const WS_THICKFRAME As Long = &H40000
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const WM_NCLBUTTONDOWN = &HA1
Private Const HTCAPTION = 2
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Dim OrigStyle As Long ' stores original style
Private Sub Form_Load()
' save current style of Picture1 Control
OrigStyle = GetWindowLong(Picture1.hwnd, GWL_STYLE)
End Sub
Private Sub Command1_Click()
' allow resizing of control
Dim style As Long
style = GetWindowLong(Picture1.hwnd, GWL_STYLE)
style = style Or WS_THICKFRAME
SetStyle style, Picture1
End Sub
Private Sub Command2_Click()
'disable resizing / restore control to original style
SetStyle OrigStyle, Picture1
End Sub
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
' move control with mouse
If Button = vbLeftButton Then
ReleaseCapture
SendMessage Picture1.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&
' code continues here on mouse up.
End If
End Sub
Private Sub SetStyle(style, Cntrl As Control)
' set style
If style Then
Call SetWindowLong(Cntrl.hwnd, GWL_STYLE, style)
Call SetWindowPos(Cntrl.hwnd, Form1.hwnd, 0, 0, 0, 0, SWP_FLAGS)
End If
End Sub
If cursor is outside of pic2 (ie, somewhere in pic1), then you don't care
If cursor is "on the border" of pic2, pic2 events would trigger -- would be "stretch" situation
If cursor is "well inside" of pic2, pic2 events still would trigger -- could be "move" situation....
If you read the rest of the posts in this thread you'll see it's not so straightforward, that's why Hack came up with some API stuff.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
You can change the style of controls at runtime so they can be resized, and you'll get the resize arrow icons when the mouse is on the edge of the control. Just a thought......
...
Yes, this could be it. Now, in your example, the command buttons are used to enable/disable control resizing. How could you also enable or disable control moving? Do I have to use a flag or is there some other way?
Last edited by krtxmrtz; Mar 18th, 2010 at 05:56 AM.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
Yes, this could be it. Now, in your example, the command buttons are used to enable/disable control resizing. How could you also enable or disable control moving? Do I have to use a flag or is there some other way?
The ReleaseCapture & SendMessage API calls in Picture1_MouseDown allow the control to be moved with the mouse, so just skip that if you want to disable the move control option.
If we wanted to only allow moving when resizing is also enabled we could test the current style.
Code:
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
If Button = vbLeftButton Then
' only allow moving when control resizing is also enabled
If GetWindowLong(Picture1.hwnd, GWL_STYLE) <> OrigStyle Then
ReleaseCapture
SendMessage Picture1.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&
' code continues here on mouse up.
End If
End If
End Sub
...Do I have to use a flag or is there some other way?
Well, using a flag works fine. But I can't use the code: the problem is I need the mouse_move event to fire before mouse_up.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
Well, using a flag works fine. But I can't use the code: the problem is I need the mouse_move event to fire before mouse_up.
You could just use VB code to move a control..,
Code:
Private bPressed As Boolean
Private iX As Long
Private iY As Long
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbLeftButton Then
bPressed = True
iX = X
iY = Y
End If
End Sub
Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If bPressed = True Then
With Picture1
.Move .Left + X - iX, .Top + Y - iY
End With
End If
End Sub
Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
bPressed = False
End Sub
You could just use VB code to move a control..,
...
Right, and this is the way I started already.The trouble is not actually moving but setting the appropriate mouse cursor depending on whether I'm stretching -dragging at the edges- (cursor = ccSizeNS) or moving -dragging inside- (cursor = ccSize) or not doing anything (cursor back to default). The first 2 are easy, but then there is no mouse_leave event to set the cursor back to default when it fires.
That's why this thread is lasting so long...
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
It seems that your first 2 situations (stretching or moving) would occur
only when mouse button is "down." And, that your 3rd situation, not doing
anything (cursor back to default), would occur only when the mouse button
is "up".
Would it be appropriate, then, to use the Picture2.MouseUp event to
detect your 3rd situation?
It seems that your first 2 situations (stretching or moving) would occur
only when mouse button is "down." And, that your 3rd situation, not doing
anything (cursor back to default), would occur only when the mouse button
is "up".
Would it be appropriate, then, to use the Picture2.MouseUp event to
detect your 3rd situation?
Spoo
Yes, stretching or moving require mouse down, but I want the cursors to be displayed when the mouse is moved over the borders of or inside picture2, like any other app by Microsoft. And this poses the problem.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
Yes, stretching or moving require mouse down, but I want the cursors to be displayed when the mouse is moved over the borders of or inside picture2, like any other app by Microsoft. And this poses the problem.
Just to be sure, you are now just talking about mouse moves only, such
that the mouse "button" is always "up", right?
And I take it you want:
- at vert edge of pic2, left-right arrow cursor
- at horiz edge of pic2, up-dn arrow cursor
- at upper-left or lower-right of pic2, 45% dn cursor
- at upper-right or lower-left of pic2, 45% up cursor
This is intended to give you/the user a visual clue that pic2 is stretchable.
So far so good?
If so, couldn't those all be detected by Picture2.MouseMove event?
You'd need a few If branches to determine "where you are" based on
coords of mouse vis-a-vis coords of Picture2's perimeter, but I don't
think that should be too hard to code.
Just to be sure, you are now just talking about mouse moves only, such
that the mouse "button" is always "up", right?
And I take it you want:
- at vert edge of pic2, left-right arrow cursor
- at horiz edge of pic2, up-dn arrow cursor
- at upper-left or lower-right of pic2, 45% dn cursor
- at upper-right or lower-left of pic2, 45% up cursor
This is intended to give you/the user a visual clue that pic2 is stretchable.
So far so good?
Yes
Originally Posted by Spoo
If so, couldn't those all be detected by Picture2.MouseMove event?
You'd need a few If branches to determine "where you are" based on
coords of mouse vis-a-vis coords of Picture2's perimeter, but I don't
think that should be too hard to code.
Spoo
I already tried this, it's no difficult to code using Picture2's mouse_move event. Then I thought I could use the container picturebox's mouse_move event (Picture1) to reset the cursor to default, but it¡'s almost the same size so it's no good.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
Just to be clear, your only remaining issue is to return cursor to
default once you "leave" PB2, right
I'm a little confused to hear that PB1 (container) is almost same size as PB2.
-- Does it start out like this? If so, how can you stretch/move PB2?
-- Or is that the end condition (after PB2 has been stretched/moved)?
If the former, then I'm really confused. Could you explain.
If the latter, could you possibly restrict the max allowable stretch/move so that
PB1 events will have an opportunity to trigger (in order for cursor to be reset to
default). If not, then could the control that contains PB1 (I assume that
would be the form itself), could its events be used?
Just to be clear, your only remaining issue is to return cursor to
default once you "leave" PB2, right
That's right.
Originally Posted by Spoo
I'm a little confused to hear that PB1 (container) is almost same size as PB2.
-- Does it start out like this? If so, how can you stretch/move PB2?
-- Or is that the end condition (after PB2 has been stretched/moved)?
If the former, then I'm really confused. Could you explain.
If the latter, could you possibly restrict the max allowable stretch/move so that
PB1 events will have an opportunity to trigger (in order for cursor to be reset to
default). If not, then could the control that contains PB1 (I assume that
would be the form itself), could its events be used?
Spoo
It's the former. At the start, the inner (borderless) picturebox has the same size as the containing picturebox, which has a shape very much like a vertical scrollbar. So you cannot move it but you can stretch it and make it shorter (the idea is to allow only vertical stretching and movement). The shorter it becomes the more range of movement becomes available.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
Thanks for clarification.
Given your new information, let me play out one hypothetical.
1. Begin with Pic2 same size as Pic1: Top = 0, Left = 0, Width = 200, Height = 3000
2. You move cursor to 100, 0 (x, y) - ie, top at center; cursor is up/dn arrow (not an issue)
3. You drag down to 100, 500. Cursor is still up/dn arrow (not an issue)
4. You release mouse button. You are still at 100, 500. Cursor is still up/dn arrow - a problem here?
5. You move cursor up to 100, 495. Cursor should become default arrow - a problem here?
...
4. You release mouse button. You are still at 100, 500. Cursor is still up/dn arrow - a problem here?
Here the cursor should become a four sided arrow cross indicating that a drag applied at this position would cause movement.
Originally Posted by Spoo
5. You move cursor up to 100, 495. Cursor should become default arrow - a problem here?
Spoo
At (100,495) we'rw still inside the picturebox. The cursor should become a default arrow the moment you're out of the picturebox.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
re 4: release mouse button at (100,500) -- you'd like to see a 4-sided "drag cursor"
Not that it matters (since this is your app), but to my way of thinking, the cursor
"should" remain an up/dn arrow.
For example: a chart on an Excel spreadsheet
up/dn arrow:
If you move cursor to top edge (on a "grab square") , you have
an up/dn arrow. If you mouse-dn and drag down, top of chart moves down,
cursor is still up/dn arrow as you drag (actually, it becomes "+", but not germaine
here). When you release mouse button, cursor is still up/dn arrow. If you then move
cursor down a tad, it turns into default arrow cursor.
4-sided "drag=movement" arrow:
If you move cursor to a spot just inside of border, cursor is default arrow. If you then
mouse-dn, cursor is still default arrow. Only when you move the
mouse with the button down does cursor become 4-sided drag arrow.
OK, I have "greyed out" the foregoing as it is only my way of seeing things,
and as such, is not important here. Back to what you would like to see,
which is 4-sided arrow cursor.
Wouldn't this be detected by pic2_MouseUp event?
re 5: move mouse to (100,495) - cursor should become default arrow.
We agree that it should become default arrow. I assume that it is NOT
behaving that way. But, you are now "in" pic1, right?
So, wouldn't this be detected by pic1_MouseMove event, as in:
-- if cursor is up/dn arrow, change to default arrow
-- if cursor is default arrow, do nothing.
Krtx re 4: release mouse button at (100,500) -- you'd like to see a 4-sided "drag cursor"
Not that it matters (since this is your app), but to my way of thinking, the cursor
"should" remain an up/dn arrow.
...
You're right, offhand I overlooked the fact that after mouse up the dragged on border has moved just to where the mouse now is. So, yes, it should remain up/down arrow. Sorry if I have misled you somewhat.
Originally Posted by Spoo
... 4-sided "drag=movement" arrow:
If you move cursor to a spot just inside of border, cursor is default arrow. If you then
mouse-dn, cursor is still default arrow. Only when you move the
mouse with the button down does cursor become 4-sided drag arrow....
Actually, I want the cursors to change already in the move event with mouse not yet down, for example like when you move it over objects in MS PowerPoint.
Originally Posted by Spoo
... re 5: move mouse to (100,495) - cursor should become default arrow.
We agree that it should become default arrow. I assume that it is NOT
behaving that way. But, you are now "in" pic1, right?
So, wouldn't this be detected by [COLOR="blue"]pic1_MouseMove event, as in:
-- if cursor is up/dn arrow, change to default arrow
-- if cursor is default arrow, do nothing.
Spoo
The problem here is twofold:
1. After pic2's upper border has been dragged down, if the mouse button is released and then it is moved up we will be on pic1 and the latter's mouse_move event can indeed be used to restore the cursor to default. But if the mouse is moved too fast, pic1 may be skipped altogether and the first event to respond will be the form's (or some other neighbouring control's) mouse_move event. I'd like to avoid having to write mouse cursor restoring code for the mouse_move events of all the controls the mouse may be moved over.
2. Pic1 and pic2 are still the same size horizontally so, if the mouse is moved horizontally out of pic2 it will now be on the form or on some other control.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
This thing is getting sort of complicated and this brings back to memory what Hack mentioned in post #8 above: "mouse_leave" (or whatever it's called) is a built in event in VB.NET, so that cursor may be restored as soon as pic2's leave event is fired.
So, maybe I should start from scratch and do it some other way, like building a more intuitive control such that you don't need the hint of the mouse cursor changing.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)
After pic2's upper border has been dragged down, if the mouse button is released and then it is moved up we will be on pic1 and the latter's mouse_move event can indeed be used to restore the cursor to default.
Good.. on this we agree
2. Pic1 and pic2 are still the same size horizontally so, if the mouse is moved horizontally out of pic2 it will now be on the form or on some other control.
Haha.. you anticipated what was going to be my next hypothetical.
Add to that your observation regarding the mouse being moved too
fast for the pic1 event to get triggered.
I was going to suggest that you could merely rely on the Form_MouseMove
event to be a "catch all", but as you say, other controls could be involved
as well.
I'm sorry to hear you contemplate going back to the drawing board, but
if you want to avoid coding for all other controls, then perhaps that is
what is best. I suppose that there is no right answer.
...
So, maybe I should start from scratch and do it some other way, like building a more intuitive control such that you don't need the hint of the mouse cursor changing.
Here's this patch control made from different ingredients. Drag on the arrows or on the central part. As it bears some similarities with scrollbars maybe no strange mouse cursors are necessary after all.
Lottery is a tax on people who are bad at maths
If only mosquitoes sucked fat instead of blood...
To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)