Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

User resizing of controls at run time. 11

Status
Not open for further replies.
Hi,
Could somebody show me a sample of the picture box/ frame combo. I can't get it to work.
Thanks

SOL
I'm only guessing but my guess work generally works for me.
 
Back to the first topic. Most controls can be resized by just changing the
Code:
Height
and
Code:
Width
properties. I wrote a class to do that, based on the current size of the form the controls are in.

On my downloads page ( ) You can see examples of it (The Oh No Analyzer and Java-to-VB). When you look at the examples, please note that the object must be destroyed (with the clear method) when the form closes. This has to be done because the form and the object reference each other.

Best regards
 
Well, this thread certainly picked up a few entries while I was out of town.

I'm not sure I understand Don's statement about setting the height & width. Certainly this is possible, but kind of awkward for the user to have to enter values for this when they want to resize the controls. It's much easier to just use the mouse and click & drag the control to the size they want.

Don, this thread isn't about resizeing the controls based on the form size ( like when the user resizes the form, or to automatically acount for different screen resolutions ). The thread is about the user manually resizing a *single* control at run time. Sometimes the user resizing of this control can also trigger resize events for other controls, if they are contained inside the control the user changed.

SpirtOfLennon:

As to your question, the commands I've listed don't work with the frame control. If you look further up the thread you'll see a link that ZEMP supplied, that shows another way of doing this, which may work for frame controls.

But, here's how you can do it with my code.

1: Set up a picturebox and use my code to make it resizeable.

2: Place a frame control inside of the picturebox.

3: In the resize event for the picturebox, place code to resize the frame to the interior size of the picturebox.

Example:

Private Sub Picture1_Resize()

Frame1.Top = 1
Frame1.Left = 1
Frame1.Height = Picture1.ScaleHeight
Frame1.Width = Picture1.ScaleWidth

End Sub


There's not much you can do about the border for the picturebox. The very nature of making it resizeable makes the border look like that. If I had more time, I might experiment with it to see if there was a way to turn the border on only when you wanted to resize, possibly whenever the ALT key was held down, or some such method.

Hope this helps,

Robert
 
As you are now back in town Vampire, do you happen to know the answer to my question:

"Is there a way to do this without changing the physical appearance of the control?"
 
Glasgow,

As I mentioned at the end of my last post, the very nature of the API call changes the border for the control. The THICKFRAME is what makes the resizing possible.

Theoretically, you could turn this on and off, so that it is only on when you want to resize. This would leave the control looking normal until you actually wanted to resize it. The user could signal this by pressing and holding the ALT key ( or some other key ) down ( there's another API call for this, GetAsyncKeyState, and a timer operation would be needed. ). You could keep a list of the controls you wanted to be resizeable in a collection, and when the ALT key is down, it runs through the collection and sets all of those controls with the appropriate API call. When the ALT key is released, the same collection is used to reset the controls back to their normal state.

At least then the control only looks like it has the thick border for just a few seconds. It is also a way for the user to keep from accidentally resizing the control.

Hope this helps,

Robert
 
Sorry, I failed to read to the end of your previous post as it appeared to be addressing SpiritofLennon's issues.

Agreed on switching on and off and this is the approach I was considering.

Thanks.
 
Thanks Vampire,
It works great, except for the fact that as soon as the frame get's resized there's nowhere on the picture box to grab hold of to move it as well. Oh well I'll investigate the other option suggested earlier.
Regards

SOL
I'm only guessing but my guess work generally works for me.
 
SOL,

Ah, you want to drag and drop it as well? I think that by using the code that you had listed above it will work. Use the mousedown and mousemove commands for the frame, but pass the MOVE command to the picturebox, and not to the frame itself. The frame will then move with the picturebox.

Robert
 
Excellent Vampire, that works fine. Now why didn't I think of that...

SOL
I'm only guessing but my guess work generally works for me.
 
the code is really great.

But is there any way I can adjust it, so it can only resize the right side of the picturebox?

 
nick,

As far I know, no.( doesn't mean that there isn't a way to do it though ). But you can write code in the resize event for the picturebox so that if the left side ( or top / bottom ) of the control is moved, that it is reset back to what it was before. This doesn't keep the user from trying to resize the wrong way, but at least it doesn't stay that way once they release the button.

Robert
 
Thank you Vampire
 
<With two ( or more ) pictureboxes set up like this, you can put other controls inside of them and resize them inside the picturebox resize event. This way you can set up a "Splitter", by resizeing one picturebox using the mouse, you can then set the other one's size in code. Like windows explorer and a lot of other programs.>

Do you have sample code for this Vampire - I've being trying to achieve this but have not being successful.

Thanks in advance.
John B

 
Well, this one's been pulled up from awhile back.

Sure, here's an example for you.

Open a new form, and place a fairly big picture box on it. ( Picture1 )

Place two other picture boxes inside the 1st picture box. ( Picture2 and Picture3 )

It helps for demonstration purposes if you make Picture2 and Picture3 have different background colors.

Here's the code you'll need

Code:
Option Explicit
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 Const GWL_STYLE = (-16)
Private Const GWL_EXSTYLE = (-20)
Private Const WS_THICKFRAME = &H40000
Private Const WS_EX_STATICEDGE = &H20000

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 SWP_FRAMECHANGED = &H20
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOZORDER = &H4
Private Const SWP_NOSIZE = &H1

Dim Flag As Boolean

Private Sub Form_Load()

' align the pictureboxes inside the big one.
Picture2.Top = 0
Picture2.Left = 0
Picture2.Height = Picture1.ScaleHeight
Picture2.Width = Picture1.ScaleWidth / 2
Picture3.Top = 0
Picture3.Left = Picture1.ScaleWidth - Picture2.Width
Picture3.Height = Picture1.ScaleHeight
Picture3.Width = Picture2.Width

' set the 2 boxes to be sizeable
SetWindowLong Picture2.hwnd, GWL_STYLE, GetWindowLong(Picture2.hwnd, GWL_STYLE) Or WS_THICKFRAME
SetWindowLong Picture2.hwnd, GWL_EXSTYLE, GetWindowLong(Picture2.hwnd, GWL_EXSTYLE) Or WS_EX_STATICEDGE
SetWindowPos Picture2.hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOZORDER Or SWP_FRAMECHANGED

SetWindowLong Picture3.hwnd, GWL_STYLE, GetWindowLong(Picture3.hwnd, GWL_STYLE) Or WS_THICKFRAME
SetWindowLong Picture3.hwnd, GWL_EXSTYLE, GetWindowLong(Picture3.hwnd, GWL_EXSTYLE) Or WS_EX_STATICEDGE
SetWindowPos Picture3.hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOZORDER Or SWP_FRAMECHANGED

' set the flag
Flag = True

End Sub

Private Sub Picture2_Resize()

If Flag = False Then Exit Sub

' If they changed the wrong part of the window, run the other resize routine to cancel.
If Not (Picture2.Left = 0) Or Not (Picture2.Top = 0) Or Not (Picture2.Height = Picture1.ScaleHeight) Then
    Call Picture3_Resize
    Exit Sub
End If

' Resize Picture 3 to fit. Set the flag to keep pic3 resize from firing and going into a loop.
Flag = False

Picture3.Top = 0
Picture3.Height = Picture1.ScaleHeight
Picture3.Left = Picture2.Width
Picture3.Width = Picture1.ScaleWidth - Picture2.Width

' reset the flag
Flag = True

End Sub

Private Sub Picture3_Resize()

If Flag = False Then Exit Sub

' If they changed the wrong part of the window, run the other resize routine to cancel.
If Not (Picture3.Left = Picture1.ScaleWidth - Picture3.Width) Or Not (Picture3.Top = 0) Or Not (Picture3.Height = Picture1.ScaleHeight) Then
    Call Picture2_Resize
    Exit Sub
End If

' Resize Picture 2 to fit. Set the flag to keep pic2 resize from firing and going into a loop.
Flag = False

Picture2.Left = 0
Picture2.Top = 0
Picture2.Height = Picture1.ScaleHeight
Picture2.Width = Picture1.ScaleWidth - Picture3.Width

' reset the flag
Flag = True

End Sub


OK, you can resize the picture boxes by putting your mouse over the ceter bar and click/dragging it to either side.

Any resizeing of the outside edges of the boxes will be ignored ( You'll see a line move, but it'll snap back as soon as you release the mouse )

Other components inside the pictureboxes ( say, for example, a treeview control or a listview control ) would be resized in the appropriate picturebox resize events.

Hope this helps you out.

Robert
 
Excellent - thanks very much Robert. This was exactly what I was looking for.

John B
 
Hi again Vampire (or anyone else that can help)

I have develpoed your splitter idea further. I can now split horizontally and vertically as many times as I want giving a multiple resizable boxes effect. I have a problem though. Because there are now several splitters involved both horizontal and vertical - when I move one border it can effect several other boxes (pictureboxes). The resize event code has got very large and quite complex as you can imagine.
My problem is that when I transfer onto another machine in the office - I am getting a different reaction. On my machine when I drag a border - I get a black border around the whole box I am dragging signifying the focus and that remains until I release the mouse button to signfy where I want to drop the border (I don't have a problem with this). Also on this machine I can put a break point in the resize event - then drag the border of a picturebox control to resize it and on letting go of the left click on the mouse to indicate the final place I want to resize to - the project then breaks into the resize event at the breakpoint. However on the other machine, the instant I try to drag the border - the resize event breakpoint engages straight away making debugging impossible. Also on the second machine - there is no black box around the box that I am dragging. the problem is my calclations seem to work on the first machine but are buggy on the second. I suspect this is happening because on the second machine the resize event is getting called continuously while I am dragging the box while it is only called once at the end of the drag on the first machine, but I can't prove this because debuggin is impossible on the second machine. Why is one different to the other?

I hope the above is clear and someone can help me - I've put a lot of time into this and I need it to work.

Thanks in advance
John B
 
John,

Your explaination seems clear enough. What are the differences between the two machines? Operating systems, etc.

I'd never tried doing 7 pictureboxes like this. The most I had done together was three. I can imagine what the resize code looks like.

One suggestion is that you might put a check in at the start of the resize event. It could check to see if the left mouse button is down, and if it is, exit the routine.

You'll need this API declaration

Code:
Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

And this code at the top of the resize event will check to see if the left mouse is down, and if it is, exits the routine.

Code:
If GetAsyncKeyState(vbKeyLButton) = True Then Exit Sub


Try this and see if you can debug then.

Hope it helps,

Robert
 
Hi Robert,
I've tried your suggestion about trapping the mouse down click at the start of the resize event but it doesn't seem to work. I've tried it on both my own project and the sample splitter one that you posted earlier but I can't seem to get it to work.

I've since found the reason for the differences in the 2 machines (in thread222-254153). Its a windows settings checkbox which is found in -Display properties - Appearance tab - Effects button - 'Show window contents when dragging' checkbox. When this is checked the resize event is called continuously during the moving of borders which throws my calculations into chaos. If I have to I can require the user to have this unchecked but its messy - I wonder is ther a way thru an API or something of automatically unchecking it while my application is running?

The other option is along the lines you were going of trappin the mouse down and up events but I'm stuck with that as regards getting it going. Any more ideas/suggestions?

Thanks
John B
 
Try this line instead. Sorry, my mistake.

Code:
If Not GetAsyncKeyState(vbKeyLButton) = 0 Then Exit Sub

Robert
 
Sorry vamp - that one doesn't work either - it works some of the time but is not consistant - any more suggestions please?

Thanks again for your time on this

John B
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top