Bold window borders with fixed size - vb6

From Windows Vista, although some windows are not resizable, but the borders are bold. Is there a way to make bold window borders(unresizable) in VB6?

Your Form's BorderStyle property dictates if the window will be resizable or not. You can chose between the following:
0 - None (no border)
1 - Fixed Single
2 - Sizable
3 - Fixed Dialog
4 - Fixed ToolWindow
5 - Sizable ToolWindow
As far as the visual appearance of the window in Vista, the resizing behavior shouldn't be affected.
Edit
If you want to prevent the form from resizing while keeping the resizable border style, you can override the Height and Width in the Form_Resize event:
Private Sub Form_Resize()
Me.Width = m_lngOriginalWidth
Me.Height = m_lngOriginalHeight
End Sub
You will need to store the original Height and Width at some point. You can do this in Form_Load or declare constants to store the original values:
Dim m_lngOriginalWidth As Long
Dim m_lngOriginalHeight As Long
Private Sub Form_Load()
m_lngOriginalWidth = Me.Width
m_lngOriginalHeight = Me.Height
End Sub

Related

How to automatically resize or reposition controls on a form when the form is resized?

So I'm trying to make my form fit to all monitors. Some have different display resolution and scale.
I can resize my form to fit to the display but all properties of its contents don't adjust to that new size.
What I want is if the form is scaled to fit to the display, the controls on the Form should adjust as well. Specifically properties like Left, Top, Width, Height, and so one, on every control.
The size could be scaled down or up.
It's possible to iterate through all of the controls on the form (mostly) programmatically, rather than having to explicitly adjust each control. You may have to put in some exceptions for some types of controls (such as timers, which I've put in the example), but generally you can use something like:
Option Explicit
Private Type ControlInfo_type
Left As Single
Top As Single
Width As Single
Height As Single
FontSize As Single
End Type
Dim ControlInfos() As ControlInfo_type
Private Sub Form_Load()
Dim ThisControl As Control
ReDim Preserve ControlInfos(0 To 0)
ControlInfos(0).Width = Me.Width
ControlInfos(0).Height = Me.Height
For Each ThisControl In Me.Controls
ReDim Preserve ControlInfos(0 To UBound(ControlInfos) + 1)
On Error Resume Next ' hack to bypass controls with no size or position properties
With ControlInfos(UBound(ControlInfos))
.Left = ThisControl.Left
.Top = ThisControl.Top
.Width = ThisControl.Width
.Height = ThisControl.Height
.FontSize = ThisControl.FontSize
End With
On Error GoTo 0
Next
End Sub
Private Sub Form_Resize()
Dim ThisControl As Control, HorizRatio As Single, VertRatio As Single, Iter As Integer
If Me.WindowState = vbMinimized Then Exit Sub
HorizRatio = Me.Width / ControlInfos(0).Width
VertRatio = Me.Height / ControlInfos(0).Height
Iter = 0
For Each ThisControl In Me.Controls
Iter = Iter + 1
On Error Resume Next ' hack to bypass controls
With ThisControl
.Left = ControlInfos(Iter).Left * HorizRatio
.Top = ControlInfos(Iter).Top * VertRatio
.Width = ControlInfos(Iter).Width * HorizRatio
.Height = ControlInfos(Iter).Height * VertRatio
.FontSize = ControlInfos(Iter).FontSize * HorizRatio
End With
On Error GoTo 0
Next
End Sub
I tested this with the default form with a CommandButton, Frame, Timer, and TextBox, and it seemed to work OK. You'll probably want to tune the limits on the minimum and maximum sizes for appearance, and my handling of the font is very crude; this could be optimized also. But perhaps this could be a starting point.
This code depends upon the controls iterating the same way each time, which could conceivably break. One way around this would be to use a Collection or other data structure with the name of the control as a key; when iterating in the .Resize event, each control would be looked up by name. Additional structure will be necessary if any of the controls are themselves arrays, and even more if controls are loaded or unloaded dynamically.

VB6 Don't Auto-Activate Child Form on Form-Resize Windows 10

A window in this VB6 legacy system that I'm supporting hosts a Word 2007 instance as a child window. On Windows 7, the parent window can be resized without any issues: the window doesn't update until the mouse is released after resizing. On Windows 10, however, the window updates dynamically while being resized.
The issue I'm encountering in Windows 10 is that the child Word window is getting activated/focused upon the first update: you can only drag to resize the parent window by a couple pixels at a time, before the child window gets focused and the resize event on the parent window is canceled (the cursor is still on the resize icon, but continued dragging has no effect). Maximizing, minimizing, and restoring the parent window all work normally. Once the child Word window is closed (through the file menu in Word), the parent window can be resized normally, because there's no child window to activate/focus. The same automatic-child-window-activation-after-parent-window-resizing occurs in Windows 7, but because the resize event doesn't fire until after the parent window has actually updated, it's not an issue there.
My conundrum is that I don't see anything in the code that suggests why the child window is getting automatically activated/focused, unless that's just default Windows behavior. In either case, I'm pretty sure I need a way to make that not happen.
All that this code is explicitly doing (primarily the ResizeControls() sub; the rest is here mostly for context) is resizing/positioning the Word window to correspond to the new size of the container in the parent window, which is consistent with the behavior in Windows 7.
From what I can tell, I don't believe that GetWindow() actually activates the window it gets a handle to, but if it does, then that's likely the cause of the issue, in which case I need to be able to get a handle to the window without activating it.
PDFView.frm:
Begin VB.Form frmPDFView
Caption = "Untitled"
ClientHeight = 8655
ClientLeft = 1320
ClientTop = 1665
ClientWidth = 9270
' ...
Begin VB.PictureBox picContainer
BackColor = &H00FFFFFF&
Height = 4215
Left = 1080
ScaleHeight = 4155
ScaleWidth = 4995
TabIndex = 0
Top = 120
Width = 5055
End
End
Private Sub ResizeControls()
On Error Resume Next
Dim pWndChild As Long
Dim r As RECT
Dim rtn As Long
picContainer.Left = 100
picContainer.Height = Me.Height - 1300
picContainer.Width = Me.Width - 350
picContainer.Top = 300
pWndChild = GetWindow(picContainer.hWnd, GW_CHILD)
rtn = GetLastError
If (pWndChild) Then
rtn = GetClientRect(picContainer.hWnd, r)
rtn = SetWindowPos(pWndChild, 0, 0, 0, r.Right - r.Left, r.Bottom - r.Top, SWP_NOZORDER Or SWP_NOMOVE)
Else
rtn = GetLastError
End If
End Sub
Private Sub Form_Resize()
On Error GoTo ERROR_HANDLER
Call ResizeControls
Exit Sub
ERROR_HANDLER:
Err.Clear
Resume Next
End Sub
Turns out I'm blind and/or didn't read the documentation thoroughly enough for all the Windows functions used in the code. Found the solution the next day and forgot to come back and answer this, but as confirmed by #wqw's comment, the issue was with SetWindowPos(). The SWP_NOACTIVATE flag needed to be passed in to SetWindowPos() to prevent activation of the target window (in my case, the child Word window).

Can I go below a VB6 TextBox control's minimum height enforced by the used font?

I have a TextBox control restricted to numeric input. Its font is Arial, Standard, 10 pt. The container's ScaleMode is set to pixels.
Since the textbox will accept and display only numbers, I do not need all that whitespace around, especially not in the vertical dimension, so I resize the TextBox' height in the designer. My goal is a 20 pixels tall TextBox control.
Attempting to set the Height property in the property window snaps the height to 24 pixels.
It is obvious, that the control's height is enforced by the used font. Using Arial, Standard, 7 pt., I can have my desired height of 20 px. Only that I need a font size of 10 pt.
When using the mouse, resizing works in the designer (for example can I achieve 19 pixels). But at run-time, the height is back to 24 pixels.
I've tried to trick VB in the Initialize event by first giving it a small font, sizing the height, then reset the font size to the original. Nope, 24 pixels.
I also tried to use Window's API function MoveWindow. The box displays at 24 pixels.
Is there any other possibly helpful API function, or is my only possibility to write an own VB user control? (I can make a user control consisting of a TextBox control as its only constituent control, then place its Top into the negative, and the user control's height to the desired height.)
Ok, so I went the stony road and created a user control suitable for me. Should you have the same problem, then this one solves it.
Add a new project of type ActiveX user control. Name the user control UTextBox. Modify the user control's font to what we want (Arial, Standard, 10 pt.), and set its ScaleMode property to pixels. Save the 2 files into a new project folder.
Place a TextBox control at position 0, 0 of the user control, and name it cTextBox. Then the whole core functionality is contained in the Resize event.
Option Explicit
'==============================================================================
'On resizing the control.
'------------------------------------------------------------------------------
Private Sub UserControl_Resize()
Dim lHeightDiff As Long
With cTextBox
'Let the TextBox control inherit the user control's new dimensions.
.Height = UserControl.ScaleHeight
.Width = UserControl.ScaleWidth
'The text box is always centered vertically on the same-sized or smaller
'user control, so that the text still is displayed also when the
'TextBox is larger than the user control's height.
.Top = (UserControl.ScaleHeight - .Height) / 2
End With
End Sub
'==============================================================================
Next is the tedious task to pass to and from the text box control all properties, methods and events, or at least all those you are interested in.
'==============================================================================
'Pass-through properties. Keep it alphabetical.
'------------------------------------------------------------------------------
Public Property Let Alignment(NewAlignment As AlignmentConstants)
cTextBox.Alignment = NewAlignment
PropertyChanged "Alignment"
End Property
'------------------------------------------------------------------------------
Public Property Get Alignment() As AlignmentConstants
Alignment = cTextBox.Alignment
End Property
'------------------------------------------------------------------------------
Public Property Let Enabled(NewState As Boolean)
cTextBox.Enabled = NewState
PropertyChanged "Enabled"
End Property
'------------------------------------------------------------------------------
Public Property Get Enabled() As Boolean
Enabled = cTextBox.Enabled
End Property
'------------------------------------------------------------------------------
Public Property Get hWnd() As Long 'Read-only.
hWnd = cTextBox.hWnd
End Property
'------------------------------------------------------------------------------
Public Property Let Text(NewText As String)
cTextBox.Text = NewText
PropertyChanged "Text"
End Property
...
'==============================================================================
There are (at least) two special properties which should be intercepted and applied onto the user control itself: Appearance and BorderStyle, because the text box can be placed outside the user control and would make these properties partially invisible. For these 2 properties, I was not able to locate their enumerations as shown in the property window, and consequently rolled own ones (there exists a naming convention, use your own names if you wish):
'==============================================================================
'Enumerations.
'------------------------------------------------------------------------------
'Used with the public Appearance property.
Public Enum ETxB_Appearance
TxBApp_2D = 0&
TxBApp_3D = 1&
End Enum
'------------------------------------------------------------------------------
'Used with the public BorderStyle property.
Public Enum ETxB_BorderStyle
TxBBSt_None = 0&
TxBBSt_FixedSingle = 1&
End Enum
'==============================================================================
These are the 2 special properties:
'==============================================================================
'All properties, methods and events which are currently needed are mediated
'to and from the outside world and the TextBox control, with the exception of
'BorderStyle and Appearance, which are properties of the user control, so that
'a frame can be displayed even when it would not fit into the TextBox control.
'------------------------------------------------------------------------------
Public Property Let Appearance(NewAppearance As ETxB_Appearance)
UserControl.Appearance = NewAppearance
PropertyChanged "Appearance"
End Property
'------------------------------------------------------------------------------
Public Property Get Appearance() As ETxB_Appearance
Appearance = UserControl.Appearance
End Property
'------------------------------------------------------------------------------
Public Property Let BorderStyle(NewStyle As ETxB_BorderStyle)
UserControl.BorderStyle = NewStyle
PropertyChanged "BorderStyle"
End Property
'------------------------------------------------------------------------------
Public Property Get BorderStyle() As ETxB_BorderStyle
BorderStyle = UserControl.BorderStyle
End Property
'==============================================================================
Now do the same for all methods.
And now for all events (and of course you need to add Event declarations as well.)
Finally, don't let's forget to happily code the property bag routines to make your user control have persistent properties.
'==============================================================================
'Initializing properties.
'------------------------------------------------------------------------------
Private Sub UserControl_InitProperties()
UserControl.Appearance = TxBApp_2D
...
cTextBox.Alignment = vbLeftJustify
...
End Sub
'==============================================================================
'==============================================================================
'Reading properties.
'------------------------------------------------------------------------------
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
With PropBag
UserControl.Appearance = .ReadProperty("Appearance", TxBApp_2D)
...
cTextBox.Alignment = .ReadProperty("Alignment", vbLeftJustify)
...
End With
End Sub
'==============================================================================
'==============================================================================
'Write properties.
'------------------------------------------------------------------------------
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
With PropBag
.WriteProperty "Appearance", UserControl.Appearance, TxBApp_2D
...
.WriteProperty "Alignment", cTextBox.Alignment, vbLeftJustify
...
End With
End Sub
'==============================================================================
Now the automatic minimum height enforcement is gone. For example can we fit our standard 10 pt Font into a 14 pixels tall control.

Automatically resize form/controls according to each computer's resolution

I've created a program that is fully functional and I have sent it to some clients. Some of them have really old computers with really low resolution and they can't access it easily since the form and the controls are oversized for them. Is there an easy way for me to make it to automatically resize both form and controls according to the resolution?
As I've said in the title, this is for Visual Basic 6.0. Thanks to all of you in advance.
You can store size and location of each control on the form, and move or resize controls according to your needs.
In the code below, I use "TabIndex" property as unique id for each control (I can't remember in my old VB6 memory if that's the right thing to do...).
I store the size of the form, and the size and location of each control in the Form_Load event.
Private lWidth As Long
Private lHeight As Long
Private Enum ePROPERTY
ep_Top = 0
ep_Left = 1
ep_Width = 2
ep_Height = 3
End Enum
Private aControlSize() As Long
Private Sub Form_Load()
Dim ctlTmp As Control
lWidth = Me.Width
lHeight = Me.Height
ReDim aControlSize(3, Form1.Controls.Count)
For Each ctlTmp In Form1.Controls
aControlSize(ctlTmp.TabIndex, ep_Top) = ctlTmp.Top
aControlSize(ctlTmp.TabIndex, ep_Left) = ctlTmp.Left
aControlSize(ctlTmp.TabIndex, ep_Width) = ctlTmp.Width
aControlSize(ctlTmp.TabIndex, ep_Height) = ctlTmp.Height
Next
End Sub
Then each time the form is resized (Form_resize event), you'll have to move or resize each control.
Some of them need to be anchored to the right or to the bottom (or both). Some need to be resized and moved. Others don't need nothing.
Private Sub Form_Resize()
Dim ctlTmp As Control
For Each ctlTmp In Form1.Controls
Select Case LCase$(ctlTmp.Name)
Case "text1"
' Text1 is anchored to the left and right borders of the form :
ctlTmp.Width = Me.Width - (lWidth - aControlSize(ctlTmp.TabIndex, ep_Width))
Case "command1"
' Command1 is anchored to the right border of the form :
ctlTmp.Left = aControlSize(ctlTmp.TabIndex, ep_Left) - (lWidth - Me.Width)
Case "check1"
' check1 is anchored to the bottom border of the form :
ctlTmp.Top = aControlSize(ctlTmp.TabIndex, ep_Top) - (lHeight - Me.Height)
End Select
Next
End Sub
Form loaded :
Form Resized :
Please be advised that my code is largely perfectible...
There's probably a more elegant solution that goes through overload each Control and to add properties/methods like the existing ones in dotnet.

Centre a form in VB6

I am writing a programme to be used internaly within our company and have come across the problem below:
How can you get a Child form to centre on the screen when using the MDI parent maximised form as the backgroung
In the MDI child screen, create a Form_Initialize function like this:
Private Sub Form_Initialize()
Me.Left = (MDIForm1.ScaleWidth - Me.Width) / 2
Me.Top = (MDIForm1.ScaleHeight - Me.Height) / 2
End Sub
Of course, you'll need to substitute the name of your MDI form where you see MDIForm1 in the code above.
From Microsoft:
"The initial size and placement of MDI child forms are controlled by the Microsoft Windows operating environment unless you specifically set them in the Load event procedure."
From the parent:
Private Sub MDIForm_Load()
CenterChildForm MDIForm1, Form1
End Sub
Sub CenterChildForm(Parent As Form, Child As Form)
If Parent.WindowState = 1 Then Exit Sub 'The Parent is minimized, centering is invalid.
Child.Top = (Parent.ScaleHeight - Child.Height) / 2
Child.Left = (Parent.ScaleWidth - Child.Width) / 2
End Sub
From the Child:
Private Sub Form_Load()
Me.Left = (MDIForm1.ScaleWidth - Me.Width) / 2
Me.Top = (MDIForm1.ScaleHeight - Me.Height) / 2
End Sub
Select from the properties in the IDE on the bottom right the WINDOWS PROPERTY - CENTER PARENT. It may be named something a little difference but is in the drop down with CENTER SCREEN
EDIT: I think it is WINDOWS POSITION - CENTER PARENT
As an addition to the above use the me.Move [left], [top], [width], [height] method
it is quicker and performs the positioning in a single action.

Resources