[RESOLVED] Form larger than screen but still sizeable
Ok, this is one I could probably figure out, but I'm trying to get other stuff done too, so I'll throw it out here and see if anyone has anything canned.
I've got a form that's quite wide. It's also sizable.
Now, I've got a subclassing procedure named 'SubclassFormFixedSize". I use this in several places with large fixed-size forms to keep Windows from resizing them on small monitors. However, this form is a bit different.
Yeah, it's large (wide) but it also needs to maintain its ability to be resized.
I want it to be shown wide, even if it's wider than the monitor, and I'd like people to be able to drag it partially off the monitor and keep resizing even bigger if they want.
Any ideas?
Thanks In Advance,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
I assume you have to resort to using an API call or perhaps some trickery.
Whenever I've had resizing code the form has always restricted itself to the size of the desktop, as shown in this simple example. Drag on the form with the left button to move, right button to resize. It always stops when it reaches the size of the desktop.
Code:
Private Sub Form_DblClick()
Unload Me
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
Static lx As Single, ly As Single
If Button = vbLeftButton Then
Move Left + (x - lx), Top + (y - ly)
ElseIf Button = vbRightButton Then
Move Left, Top, Width + (x - lx), Height + (y - ly)
lx = x: ly = y
Else
lx = x: ly = y
End If
End Sub
Private Sub Form_Paint()
Dim x As Integer, y As Integer
Dim toggleColr As Long
Dim colr As Long
Dim toggle As Boolean
toggleColr = vbRed Xor vbGreen
For x = 0 To Width Step 1000
toggle = Not toggle
If toggle Then
colr = vbRed
Else
colr = vbGreen
End If
For y = 0 To Height Step 1000
colr = colr Xor toggleColr
Line (x, y)-Step(1000, 1000), colr, BF
Next
Next
End Sub
I'm thinking with "trickery", if you had a transparent form that you filled the screen with and a container that looked like a form that you could resize and move around you would give the impression that you were creating a form that could be larger than the desktop and moved around.
Well, I've already got code I use to make forms that are larger than the target screen size. However, it only works with fixed-size forms.
Also, I don't mind doing subclassing to get this done. In fact, I'm virtually certain it's going to take subclassing. I'm playing around with some stuff now, but I'm getting all kinds of flicker, and it's not really working.
Also, I really don't think I need I need a transparent form. I'll get it done with subclassing. It's just a trial-and-error thing to get it right.
Thank You,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Here's another way to put it. I want a sizable form that pays no attention whatsoever to the size of the screen.
And I also need a way to set its initial size.
P.S. Let's not worry about moving it around. I've got that one handled.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Okay, I was just way over-thinking this thing. Once I got my head around it, it was actually quite easy.
Here's my BAS module with the subclassing that does it:
Code:
Option Explicit
'
Public gbAllowSubclassing As Boolean
'
Private Const WM_DESTROY As Long = &H2&
'
Private Declare Function SetWindowSubclass Lib "comctl32.dll" Alias "#410" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
Private Declare Function GetWindowSubclass Lib "comctl32.dll" Alias "#411" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, pdwRefData As Long) As Long
Private Declare Function RemoveWindowSubclass Lib "comctl32.dll" Alias "#412" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
Private Declare Function NextSubclassProcOnChain Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'Private Declare Function DefSubclassProc Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'
Dim bSetWhenSubclassing_UsedByIdeStop As Boolean ' Never goes false once set by first subclassing, unless IDE Stop button is clicked.
'
'
'**************************************************************************************
' The following MODULE level stuff is specific to individual subclassing needs.
'**************************************************************************************
'
Private Type POINTAPI
x As Long
y As Long
End Type
'
Private Type MINMAXINFO
ptReserved As POINTAPI
ptMaxSize As POINTAPI
ptMaxPosition As POINTAPI
ptMinTrackSize As POINTAPI
ptMaxTrackSize As POINTAPI
End Type
'
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Dest As Any, ByRef Source As Any, ByVal Bytes As Long)
'
'**************************************************************************************
'**************************************************************************************
'**************************************************************************************
'
' Generic subclassing procedures (used in many of the specific subclassing).
'
'**************************************************************************************
'**************************************************************************************
'**************************************************************************************
Private Sub SubclassSomeWindow(hWnd As Long, AddressOf_ProcToHook As Long, Optional dwRefData As Long)
' This just always uses hWnd for uIdSubclass, as we never have a need to subclass the same window to the same proc.
' The uniqueness is pfnSubclass and uIdSubclass (second and third argument below).
'
' This can be called AFTER the initial subclassing to update dwRefData.
'
If Not gbAllowSubclassing Then Exit Sub
'
bSetWhenSubclassing_UsedByIdeStop = True
Call SetWindowSubclass(hWnd, AddressOf_ProcToHook, hWnd, dwRefData)
End Sub
Private Function GetSubclassRefData(hWnd As Long, AddressOf_ProcToHook As Long) As Long
' This one is used only to fetch the optional dwRefData you may have specified when calling SubclassSomeWindow.
' Typically this would only be used by the hooked procedure, but it is available to anyone.
Call GetWindowSubclass(hWnd, AddressOf_ProcToHook, hWnd, GetSubclassRefData)
End Function
Private Sub UnSubclassSomeWindow(hWnd As Long, AddressOf_ProcToHook As Long)
' Only needed if we specifically want to un-subclass before we're closing the form (or control),
' otherwise, it's automatically taken care of when the window closes.
'
' Be careful, some subclassing may require additional cleanup that's not done here.
Call RemoveWindowSubclass(hWnd, AddressOf_ProcToHook, hWnd)
End Sub
Private Function ProcedureAddress(AddressOf_TheProc As Long)
' A private "helper" function for writing the AddressOf_... functions (see above notes).
ProcedureAddress = AddressOf_TheProc
End Function
Private Function IdeStopButtonClicked() As Boolean
' The following works because all variables are cleared when the STOP button is clicked,
' even though other code may still execute such as Windows calling some of the subclassing procedures below.
IdeStopButtonClicked = Not bSetWhenSubclassing_UsedByIdeStop
End Function
'**************************************************************************************
'**************************************************************************************
'**************************************************************************************
Public Sub SubclassFormMaxSize(frm As VB.Form, MaxWidth As Long, MaxHeight As Long)
' MUST be done in Form_Load event so Windows doesn't resize form on small monitors.
' Also, move (such as center) the form after calling so that WM_GETMINMAXINFO is fired.
' Can be called repeatedly to change MaxWidth and/or MaxHeight with no harm done.
SubclassSomeWindow frm.hWnd, AddressOf MaxSize_Proc, CLng(MaxHeight * &H10000 + MaxWidth)
End Sub
Private Function MaxSize_Proc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
If uMsg = WM_DESTROY Then
UnSubclassSomeWindow hWnd, AddressOf_MaxSize_Proc
MaxSize_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
Exit Function
End If
If IdeStopButtonClicked Then ' Protect the IDE. Don't execute any specific stuff if we're stopping. We may run into COM objects or other variables that no longer exist.
MaxSize_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
Exit Function
End If
'
Dim MaxWidth As Long
Dim MaxHeight As Long
Dim MMI As MINMAXINFO
Const WM_GETMINMAXINFO As Long = &H24&
'
Select Case uMsg
Case WM_GETMINMAXINFO
MaxWidth = dwRefData And &HFFFF&
MaxHeight = (dwRefData And &H7FFF0000) \ &H10000
'
CopyMemory MMI, ByVal lParam, LenB(MMI)
MMI.ptMaxTrackSize.x = MaxWidth
MMI.ptMaxTrackSize.y = MaxHeight
CopyMemory ByVal lParam, MMI, LenB(MMI)
Exit Function ' If we process the message, we must return 0 and not let more hook code execute.
End Select
'
' Give control to other hooks, if they exist.
MaxSize_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
End Function
Private Function AddressOf_MaxSize_Proc() As Long
AddressOf_MaxSize_Proc = ProcedureAddress(AddressOf MaxSize_Proc)
End Function
And here's some code you can throw into a Form1 to watch it in action.
Code:
Option Explicit
Private Sub Form_Load()
gbAllowSubclassing = True
SubclassFormMaxSize Me, 10000, 400
End Sub
I also attached a sample project, but it's all pretty straightforward.
Best Regards,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: [RESOLVED] Form larger than screen but still sizeable
Originally Posted by Spooman
Another approach might be to use a PictureBox-in-a-PictureBox
Hi Spoo,
You are correct, but that's not what I wanted. This was all for a form that pieces of can be seen here or here. It's just a really wide form.
I'm currently at a client's office who really likes the form, but they'll be using it on a monitor with a 4/3 aspect ratio and not very high resolution. I haven't checked but I think it's 800x600, and the form's width just didn't fit at all. Therefore, I just needed a way to make that form work better on that monitor. My above solution worked perfectly.
Thanks for the ideas though.
Take Care,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: [RESOLVED] Form larger than screen but still sizeable
Wouldn't it make sense to make it a "scrollable form" though?
Just a PictureBox or a borderless Frame as a container, and vertical and horizontal scrollbars that slide the container to implement scrolling. Size the container to fit all of your other controls that are "on" it.
When the Form gets resized just move and size the scrollbar controls to fit the new Form client area, perhaps adjusting the position of the container as well when more space is available to hold it.
Re: [RESOLVED] Form larger than screen but still sizeable
an mdi-child with a non sizeble border can have almost any dimentions
Code:
Private Sub Command1_Click()
Me.Width = Me.Width + 150
Me.Height = Me.Height + 150
Label1.Caption = Me.Height & " " & Me.Width
End Sub
Private Sub Form_DblClick()
Unload Me
End Sub
Private Sub Form_Load()
Me.BorderStyle = vbFixedToolWindow
End Sub
do not put off till tomorrow what you can put off forever
Re: [RESOLVED] Form larger than screen but still sizeable
One snag with using MDI to get scrollable child forms is that you can only have one MDI Parent in a Project. Not always a deal breaker, but some people want multiple forms and may want more than one to support this stuff.
Re: [RESOLVED] Form larger than screen but still sizeable
just tried Elroy's example form as a mdichild
works a charm
Code:
Private Sub Form_DblClick()
Me.Caption = Me.Width & " " & Me.Height
End Sub
Private Sub Form_Load()
gbAllowSubclassing = True
SubclassFormMaxSize Me, 10000, 10000
Me.Move 0, 0, 100000, 100000
End Sub
remark the forms width/height 100000
>10000 ??
do not put off till tomorrow what you can put off forever
Re: [RESOLVED] Form larger than screen but still sizeable
I think the size is limited to 10000 by 10000 pixels.
Form's height and Width are reported in Twips, so the max size may be reported for example as 120000 if you have 12 twips per pixel, or 150000 if you have 15 twips per pixel.
Use Screen.TwipsPerPixelX or TwipsPerPixelY to see what your Twips to Pixel ratio is.
Re: [RESOLVED] Form larger than screen but still sizeable
Hi all,
Sorry, been taking care of other things and haven't had time to check in.
I'm hesitating to even make another post, as I really do have what I want. I actually did think about the MDI approach (or possibly controls on a picturebox in a picturebox). And I'm also delighted that others are coming up with other ideas. It may help others who stumble across all of this in the future.
Personally, and I know I'm not in unanimous company, but I just really don't like the MDI approach to things. I've just never seen the purpose of hiding portions of the desktop with grayness. Again, that's just my preference, and my programming style.
@Passel: Yeah, I figured there was some limit. I thought about seeing what it was, but I knew I wouldn't be bumping into it with my current problem. I suppose I could test and see where I bump into it, but I'll probably save that for another time. Also, it makes me wonder if there's a Windows limit that might be separate from a VB6 limit. I've really got no idea.
Y'all Take Care,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: [RESOLVED] Form larger than screen but still sizeable
I believe the limit is 32K pixels, based on the fact that in your api call you extract the MaxWidth and MaxHeight values from the upper and lower half of a 32-bit value, so the maximum size would have to fit in a signed 16-bit value (I believe).
Option Explicit
'
Dim lPelWidth As Long
Dim lPelHeight As Long
Private Sub Command1_Click()
lPelWidth = lPelWidth + 1024 ' Make max bigger.
lPelHeight = lPelHeight + 1024 ' Make max bigger.
SubclassFormMaxSize Me, lPelWidth, lPelHeight ' Inform subclassing of changes.
Me.Width = lPelWidth * Screen.TwipsPerPixelX
Me.Height = lPelHeight * Screen.TwipsPerPixelY
Text1 = CStr(Me.Width / Screen.TwipsPerPixelX) & " " & CStr(Me.Height / Screen.TwipsPerPixelY)
End Sub
Private Sub Form_Load()
lPelWidth = 8192
lPelHeight = 8192
gbAllowSubclassing = True
SubclassFormMaxSize Me, lPelWidth, lPelHeight
End Sub
With this test, I hit the limit (in both width and height) at 16383, which is 2^14-1.
However, as I was putting this post together, it dawned on me that I limited my max storage to 15 bits, but I didn't hit that limit either, so this 16383 is either a VB6 limit or a Windows limit.
EDIT1: With this knowledge, I modified my subclassing a bit as follows:
Code:
Public Sub SubclassFormMaxSize(frm As VB.Form, MaxWidth As Long, MaxHeight As Long)
' Limits for both is 16383 (3FFF), and can't be negative.
MaxWidth = MaxWidth And &H3FFF&
MaxHeight = MaxHeight And &H3FFF&
' MUST be done in Form_Load event so Windows doesn't resize form on small monitors.
' Also, move (such as center) the form after calling so that WM_GETMINMAXINFO is fired.
' Can be called repeatedly to change MaxWidth and/or MaxHeight with no harm done.
SubclassSomeWindow frm.hWnd, AddressOf MaxSize_Proc, CLng(MaxHeight * &H10000 + MaxWidth)
End Sub
Last edited by Elroy; Oct 10th, 2017 at 01:39 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: [RESOLVED] Form larger than screen but still sizeable
I know this is resolved, but I came across something that might be of future interest to you, and members watching this thread.
Presumably VB.NET (pause whilst I wash my mouth out with soap), has controls that would make this easier (not to mention lots of other goodies, VB6 programmers might salivate over)
The approach used in this, might be transferable to other VB.NET controls ? - https://www.codeproject.com/Articles...Controls-in-VB
Re: [RESOLVED] Form larger than screen but still sizeable
Hi Bobbles,
I'm not sure I see it. I actually do some graphics on the form I was working with, but that wasn't my problem. Stated quite simply, I wanted a sizable form that could be resized larger than the Windows desktop space (i.e., Screen.Width & Screen.Height). Not to be critical, but I don't see where your link addresses that issue at all.
Take Care,
Elroy
EDIT1: Hey Bobbles, let me apologize for being curt. I can just still get upset by what I see as a betrayal by Microsoft when they abandoned VB6. The mere mention of .NET still raises my blood-pressure by a couple of points. Take Care.
Last edited by Elroy; Oct 12th, 2017 at 12:00 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: [RESOLVED] Form larger than screen but still sizeable
Elroy,
I did not expect it to be taken as a replacement for your solution to your problem.
I assume that .NET could have had a solution if you did not already have one.
I just felt that the ability generally to use .NET controls may be of interest to our members.