I have created a simple form in VB6, and added a simple, blank user control. The only code are Debug.Print statements in all major events.
For some reason, when the form is closed, the order of events in the User Control are:
Terminate
Initialize
Read Properties
Resize
Why is this happening? Why are Initialize, ReadProperties and Resize called after Terminate? I could not find any evidence of this in Microsoft documentation.
EDIT:
Here is the code.
User control:
VERSION 5.00
Begin VB.UserControl UserControl1
ClientHeight = 3600
ClientLeft = 0
ClientTop = 0
ClientWidth = 4800
ScaleHeight = 3600
ScaleWidth = 4800
End
Attribute VB_Name = "UserControl1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private Sub UserControl_Initialize()
Debug.Print "Initialize"
End Sub
Private Sub UserControl_InitProperties()
Debug.Print "InitProperties"
End Sub
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
Debug.Print "ReadProperties"
End Sub
Private Sub UserControl_Resize()
Debug.Print "Resize"
End Sub
Private Sub UserControl_Show()
Debug.Print "Show"
End Sub
Private Sub UserControl_Terminate()
Debug.Print "Terminate"
End Sub
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
Debug.Print "WriteProperties"
End Sub
Form:
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3030
ClientLeft = 120
ClientTop = 450
ClientWidth = 4560
LinkTopic = "Form1"
ScaleHeight = 3030
ScaleWidth = 4560
StartUpPosition = 3 'Windows Default
Begin Project1.UserControl1 UserControl1
Height = 2535
Left = 240
TabIndex = 0
Top = 240
Width = 4095
_extentx = 7223
_extenty = 4471
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Debug.Print means your running this in debug mode in the IDE.
When debugging you would see a Terminate when the form unloads, you then see the reinitialisation of the User Control as its re-loaded in the Form in the Form Designer for editing.
This won't happen from a compiled EXE, you can replace Debug.Print with MsgBox to verify this.
Related
Hi im trying to create a simple program involving an object and a class within
VB 6.0.
The error message i get is: "User-defined type not defined"
The highlighted code that VB suspects is "Dim Bob As Ball"
My defined class is as follows:
Dim Bob As Object
Public Sub Ball()
Dim Circlex As Integer
Dim Circley As Integer
Public Sub makeBall()
Circlex = 3000
Circley = 3000
End Sub
Private Sub moveBall()
Circle (Circlex, Circley), 200
End Sub
End Sub
My code for the only form in my project is:
Private Sub Command1_Click()
Command1.Visible = False
Command1.Enabled = False
vbalProgressBar1.Visible = True
Timer1.Enabled = True
Beep
End Sub
Private Sub Form_Load()
Form1.Width = 6000
Form1.Height = 6000
Dim Bob As Ball
Dim Bob As New Ball
End Sub
Private Sub Form_Unload(Cancel As Integer)
If MsgBox("Are you sure you want to be a quitter?!"
, vbYesNo,"Quit?") = vbYes Then
Unload Me
Set Form1 = Nothing
Else
Cancel = 1
End If
End Sub
Private Sub Timer1_Timer()
Bob = moveBall(Circlex, Circley)
End Sub
Im not sure why the suspected line of code is incorrect, but any help would be appreciated!
VB6 doesn't use code style that you coded.
You have to follow these method to make code work with your intention.
1. make classmodule
2. set its name 'Ball'
3. paste this code on classmodule
Dim Circlex As Integer
Dim Circley As Integer
Public Sub makeBall()
Circlex = 3000
Circley = 3000
End Sub
Private Sub moveBall()
Circle (Circlex, Circley), 200
End Sub
paste code on your form
Private Sub Command1_Click()
Command1.Visible = False
Command1.Enabled = False
vbalProgressBar1.Visible = True
Timer1.Enabled = True
Beep
End Sub
Private Sub Form_Load()
Form1.Width = 6000
Form1.Height = 6000
Dim Bob As New Ball
End Sub
Private Sub Form_Unload(Cancel As Integer)
If MsgBox("Are you sure you want to be a quitter?!"
, vbYesNo,"Quit?") = vbYes Then
Unload Me
Set Form1 = Nothing
Else
Cancel = 1
End If
End Sub
Private Sub Timer1_Timer()
Bob.moveBall(Circlex, Circley)
End Sub
Additionally, VB6 doesn't support style like
Sub A()
Sub B()
End Sub
End Sub
I am new with vb6 and communication app, I try to run a example that transmitting and receiving data between two serial ports ( I install two serial ports by com0com soft).
In this example, I want User to type charracters in textbox1, then click command button, and charracters in textbox1 display in textbox2.
Private Sub Command1_Click()
com1.Output = Text1.Text
End Sub
Private Sub Form_Load()
com1.CommPort = 1
com1.Settings = "9600,n,8,1"
com1.PortOpen = True
com2.CommPort = 2
com2.Settings = "9600,n,8,1"
com2.PortOpen = True
Text1.Text = ""
Text2.Text = ""
End Sub
Private Sub com2_OnComm()
If com2.CommEvent = comEvReceive Then
Text2.Text = Text2.Text + com2.Input
End If
End Sub
I screened form in the example and setting in com0com port, I don't have enought reputation to post image, so I upload this to flickr.
http://farm8.staticflickr.com/7627/16740707238_6b1d9ec3ab_b.jpg
But when I try to run this example by type charracters in textbox1 and click button, nothing happen.
So what am I doing wrong?. If so, how can I do to get data from com1 port to com2port? Or any advice for anything!
thanks for reading !
I think you need to look a little harder at the documentation.
Here's a minimal example where COM3/COM4 are the looped ports on my machine:
Option Explicit
Private Sub Command1_Click()
If Len(Text1.Text) > 0 Then
MSComm1.Output = Text1.Text
Text1.Text = vbNullString
End If
Text1.SetFocus
End Sub
Private Sub Form_Load()
With MSComm1
.CommPort = 3
.Settings = "256000,n,8,1"
.Handshaking = comNone
.SThreshold = 0 'No events after send completions.
.RThreshold = 0 'No events after receive completions.
.PortOpen = True
End With
With MSComm2
.CommPort = 4
.Settings = "256000,n,8,1"
.EOFEnable = False
.Handshaking = comNone
.InputMode = comInputModeText
.RThreshold = 1 'Event for each character received. Terribly
'inefficient but if char-by-char events are
'required there isn't much choice.
.SThreshold = 0 'No events after send completions.
.PortOpen = True
End With
End Sub
Private Sub Form_Unload(Cancel As Integer)
MSComm1.PortOpen = False
MSComm2.PortOpen = False
End Sub
Private Sub MSComm2_OnComm()
With MSComm2
If .CommEvent = comEvReceive Then
.InputLen = 0
Text2.SelStart = &H7FFF
Text2.SelText = .Input
End If
End With
End Sub
I have below macro.
Could you please modify it in such ways that it will show slide number on the top and also extract notes page.
I tried all ways but couldn't get answer-:
Sub WriteToWord()
Dim aSlide As Slide, MyDoc As New Word.Document, MyRange As Word.Range
Dim aTable As Table, aShape As Shape, TablesCount As Integer, ShapesCount As Integer
Dim i As Word.Paragraph
On Error Resume Next
With MyDoc
.Application.Visible = False
.Application.ScreenUpdating = False
For Each aSlide In ActivePresentation.Slides
For Each aShape In aSlide.Shapes
Set MyRange = .Range(.Content.End - 1, .Content.End - 1)
Select Case aShape.Type
Case msoAutoShape, msoPlaceholder, msoTextBox
If aShape.TextFrame.HasText Then
aShape.TextFrame.TextRange.Copy
MyRange.Paste
With MyRange
.ParagraphFormat.Alignment = wdAlignParagraphLeft
For Each i In MyRange.Paragraphs
If i.Range.Font.Size >= 16 Then
i.Range.Font.Size = 14
Else
i.Range.Font.Size = 12
End If
Next
End With
End If
Case msoPicture
aShape.Copy
MyRange.PasteSpecial DataType:=wdPasteMetafilePicture
ShapesCount = .Shapes.Count
With .Shapes(ShapesCount)
.LockAspectRatio = msoFalse
.Width = Word.CentimetersToPoints(14)
.Height = Word.CentimetersToPoints(6)
.Left = wdShapeCenter
.ConvertToInlineShape
End With
.Content.InsertAfter Chr(13)
Case msoEmbeddedOLEObject, msoLinkedOLEObject, msoLinkedPicture, msoOLEControlObject
aShape.Copy
MyRange.PasteSpecial DataType:=wdPasteOLEObject
ShapesCount = .Shapes.Count
With .Shapes(ShapesCount)
.LockAspectRatio = msoFalse
.Width = Word.CentimetersToPoints(14)
.Height = Word.CentimetersToPoints(6)
.Left = wdShapeCenter
.ConvertToInlineShape
End With
.Content.InsertAfter Chr(13)
Case msoTable
aShape.Copy
MyRange.Paste
TablesCount = .Tables.Count
With .Tables(TablesCount)
.PreferredWidthType = wdPreferredWidthPercent
.PreferredWidth = 100
.Range.Font.Size = 11
End With
.Content.InsertAfter Chr(13)
End Select
Next
If aSlide.SlideIndex < ActivePresentation.Slides.Count Then .Content.InsertAfter Chr(12)
.UndoClear ' Clear used memory
Next
' Change white font to black color
With .Content.Find
.ClearFormatting
.Format = True
.Font.Color = wdColorWhite
.Replacement.Font.Color = wdColorAutomatic
.Execute Replace:=wdReplaceAll
End With
MsgBox "PPT Converted to WORD completed, Please check and save document", vbInformation + vbOKOnly, "ExcelHome/ShouRou"
.Application.Visible = True
.Application.ScreenUpdating = True
End With
End Sub
Sub Auto_Open() ' Add PPTtoWord to Tool Bar when Powerpoint start
Dim MyControl As CommandBarControl
On Error Resume Next
Application.CommandBars("Standard").Controls("PPTtoWord").Delete
Set MyControl = Application.CommandBars("Standard").Controls.Add(Before:=1)
With MyControl
.Caption = "PPTtoWord"
.FaceId = 567 ' Word Icon
.Enabled = True
.Visible = True
.Width = 100
.OnAction = "WriteToWord"
.Style = msoButtonIconAndCaption
End With
End Sub
Sub Auto_Close() ' Delete PPTtoWord from Tool Bar when Powerpoint close
On Error Resume Next
Application.CommandBars("Standard").Controls("PPTtoWord").Delete
End Sub
You are running this from Word and automating PowerPoint using early binding, you need to fully qualify any PowerPoint reference.
Have you added a reference to PowerPoint library.
Change to aShape As PowerPoint.Shape
Grab the reference to the running instance of PowerPoint. PowerPoint is single instance multi-use so you can use this.
Dim PPT as PowerPoint.Application
Set PPT = CreateObject("PowerPoint.Application")
Fully qualify all references to ActivePresentation with PPT.ActivePresentation
Your macro should run then and generate something so that you can continue debugging.
I have some problems accessing informations from a new created element.This is my code
Private Sub c1_Click()
Refresh
Timer1.Enabled = Not Timer1.Enabled
If Timer1.Enabled Then
c1.Caption = "Stop"
Else
c1.Caption = "Start"
End If
a = l.X2 - l.X1
choice = a
End Sub
Private Sub Form_Load()
Dim l As Line
Set l = Controls.Add("VB.Line", "l", Me)
With l
.X1 = 2760
.Y1 = 3000
.X2 = 5640
.Y2 = 3000
.Visible = True
.BorderStyle = 1
.BorderWidth = 2
.BorderColor = vbRed
End With
End Sub
I get an error when i click the button:"Object required".On the form i can see the line but i can't access it from another sub.Where is the problem?
Your Line variable l is private to the Form_Load procedure and goes out of scope.
Move Dim l As Line from Form_Load to the top of your form's code module (outside of any method or function). This will make it available to any method or procedure on your form:
Dim l As Line
Private Sub c1_Click()
Refresh
Timer1.Enabled = Not Timer1.Enabled
If Timer1.Enabled Then
c1.Caption = "Stop"
Else
c1.Caption = "Start"
End If
a = l.X2 - l.X1
choice = a
End Sub
Private Sub Form_Load()
Set l = Controls.Add("VB.Line", "l", Me)
With l
.X1 = 2760
.Y1 = 3000
.X2 = 5640
.Y2 = 3000
.Visible = True
.BorderStyle = 1
.BorderWidth = 2
.BorderColor = vbRed
End With
End Sub
Note: This is probably a shot in the dark, and its purely out of curiosity that I'm asking.
When using the ImageList control from the Microsoft Common Control lib (mscomctl.ocx) I have found that VB6 generates FRM code that doesn't resolve to real property/method names and I am curious as to how the resolution is made. An example of the generated FRM code is given below with an ImageList containing 3 images:
Begin MSComctlLib.ImageList ImageList1
BackColor = -2147483643
ImageWidth = 100
ImageHeight = 45
MaskColor = 12632256
BeginProperty Images {2C247F25-8591-11D1-B16A-00C0F0283628}
NumListImages = 3
BeginProperty ListImage1 {2C247F27-8591-11D1-B16A-00C0F0283628}
Picture = "Form1.frx":0054
Key = ""
EndProperty
BeginProperty ListImage2 {2C247F27-8591-11D1-B16A-00C0F0283628}
Picture = "Form1.frx":3562
Key = ""
EndProperty
BeginProperty ListImage3 {2C247F27-8591-11D1-B16A-00C0F0283628}
Picture = "Form1.frx":6A70
Key = ""
EndProperty
EndProperty
End
From my experience, a BeginProperty tag typically means a compound property (an object) is being assigned to, such as the Font object of most controls, for example:
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 10950
ClientLeft = 60
ClientTop = 450
ClientWidth = 7215
BeginProperty Font
Name = "MS Serif"
Size = 8.25
Charset = 0
Weight = 400
Underline = 0 'False
Italic = -1 'True
Strikethrough = 0 'False
EndProperty
End
Which can be easily seen to resolve to VB.Form.Font.<Property Name>.
With ImageList, there is no property called Images. The GUID associated with property Images indicates type ListImages which implements interface IImages. This type makes sense, as the ImageList control has a property called ListImages which is of type IImages. Secondly, properties ListImage1, ListImage2 and ListImage3 don't exist on type IImages, but the GUID associated with these properties indicates type ListImage which implements interface IImage. This type also makes sense, as IImages is in fact a collection of IImage.
What doesn't make sense to me is how VB6 makes these associations. How does VB6 know to make the association between the name Images -> ListImages purely because of an associated type (provided by the GUID) - perhaps because it's the only property of that type? Secondly, how does it resolve ListImage1, ListImage2 and ListImage3 into additions to the collection IImages, and does it use the Add method? Or perhaps the ControlDefault property?
Perhaps VB6 has specific knowledge of this control and no logical resolution exists?
You can see what's going on with this fairly contrived example. Start with an ActiveX project and add Class1 and mark it as Persistable = 1
' Class1
Option Explicit
Private m_sText As String
Property Get Text() As String
Text = m_sText
End Property
Property Let Text(sValue As String)
m_sText = sValue
End Property
Private Sub Class_ReadProperties(PropBag As PropertyBag)
With PropBag
m_sText = .ReadProperty("txt", "")
End With
End Sub
Private Sub Class_WriteProperties(PropBag As PropertyBag)
With PropBag
.WriteProperty "txt", m_sText, ""
End With
End Sub
Add UserControl1
' UserControl1
Option Explicit
Private m_oData As Class1
Property Get Data() As Class1
Set Data = m_oData
End Property
Private Sub UserControl_Initialize()
Set m_oData = New Class1
m_oData.Text = "this is a test"
End Sub
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
With PropBag
Set m_oData = .ReadProperty("rs", Nothing)
End With
End Sub
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
With PropBag
.WriteProperty "rs", m_oData, Nothing
End With
End Sub
Add Form1 and place a UserControl1 on it as save it. You might wan to add Module1 for Sub Main
' Module1
Sub Main()
With New Form1
.Show
End With
End Sub
Here is my Form1.frm file
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 2400
ClientLeft = 48
ClientTop = 432
ClientWidth = 3744
LinkTopic = "Form1"
ScaleHeight = 2400
ScaleWidth = 3744
StartUpPosition = 3 'Windows Default
Begin Project1.UserControl1 UserControl11
Height = 516
Left = 924
TabIndex = 0
Top = 588
Width = 1020
_ExtentX = 1799
_ExtentY = 910
BeginProperty rs {326250A4-CA0D-4F88-8F20-DAA391CF8E79}
txt = "this is a test"
EndProperty
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
So UserControl1 determines that object m_oData is persisted as property rs in its WriteProperty overload. Class1 determines that its m_sText member variable (or Text public property) is persisted as txt member in the IPropertyBag the frm is passing. There is nothing that requires public property names to match internal property bag names. I would personally use shorted IDs just to minimize bloat (if possible with VB6 at all).
I am guessing that the GUID ({2C247F25-8591-11D1-B16A-00C0F0283628}) points to the associated ImageList control and ListImage1, ListImage2, etc... is just there to enumerate all the images.
It's kind of like an early version of WPF associated controls (e.g. a TextBox can reference its enclosing grid for placement).