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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Creating run-time resizable objects and screen splitter.

Windows API

Creating run-time resizable objects and screen splitter.

by  TheVampire  Posted    (Edited  )
Having a control set so that it can be re-sized with a mouse click & drag at run time by the user allows for customization of your interface, and many interesting effects.

A note: There are some controls this will not work with. The control must have a windows handle, so it won't work with imageboxes and labels. Also, frames do not seem to work either. There is a workaround that can be used, and I will cover this later.

First, you need these API declarations and constants:
Code:
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

Second, you have to perform these operations on each of the controls that you want resizeable.

In the case of the aforementioned imageboxes, labels and frames, what you want to do is use a picturebox and place the control inside of it. Set the picturebox to be resizeable, and in the picturebox resize event, use code to resize the control to fit the inside dimensions ( scaleheight and scalewidth ) of the picturebox.

Perform these operations on the control.
Code:
SetWindowLong Control.hwnd, GWL_STYLE, GetWindowLong(Control.hwnd, GWL_STYLE) Or WS_THICKFRAME

SetWindowLong Control.hwnd, GWL_EXSTYLE, GetWindowLong(Control.hwnd, GWL_EXSTYLE) Or WS_EX_STATICEDGE

SetWindowPos Control.hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOZORDER Or SWP_FRAMECHANGED

Now, when you move your mouse to the border of the control, you will get a sizeing arrow.

( Another forum member pointed out that the web page at http://www.burningbox.com/vb/ shows how to resize controls, and get the grab handles at the same time. )

If you left click and drag, you can make the control resize!

Different controls act different ways to this. List boxes will automatically show or hide scroll bars as necessary. Combos will not size up or down, but will size left and right.


I mentioned before that you can make a splitter box. here's how to do it.

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.

You'll need the declarations and constants like above and this code.
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

You can resize the picture boxes by putting your mouse over the center 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.

Robert
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top