1

新しいフォームを動的に作成するボタンが付いたフォームがあります。テキスト ファイルに基づいて、すべてのラベル、テキスト ボックス、およびボタンをオンザフライで追加します。フォームにコントロールが多すぎる場合、「 frmDynamic.AutoScroll = True 」コマンドを使用してスクロール バーを追加できると思っていましたが、機能していません。フォームに関連する設定は次のとおりです。

 frmDynamic = New Form()
            frmDynamic.AutoScaleDimensions = New System.Drawing.SizeF(6.0F, 13.0F)
            frmDynamic.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
            frmDynamic.Name = "frmDynamicMerchantApplication"

            'dimension is irrelevant at the moment
            frmDynamic.ClientSize = New System.Drawing.Size(10, 10)
            'the parent will be the current form
            'frm.MdiParent = this;

            frmDynamic.ControlBox = True
            frmDynamic.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable
            ' This needs to be GrowOnly for the auto scroll to work. - otherwise you have to add scrollbars manually along with the handlers and so forth.
            frmDynamic.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly

            ' Add auto scroll since the form could grow out of range when adding multiple references and owners
            frmDynamic.AutoScroll = True

さらに、「pad.AutoScrollMinSize = new System.Drawing.Size(300, 0)」プロパティも設定しようとしましたが、何も機能していないようです-スクロールバーが表示されません。

最終テストとして、メイン フォームで AutoScroll プロパティを true に設定しました。フォームのサイズがオブジェクトの位置よりも小さい場合に正常に動作します。最終テストとして、次のコードを使用してメイン フォームに別のボタンを追加し、autoscroll を true に設定してフォームを作成し、正常に動作しました。

 ' Create a new form.
        Dim form2 As New Form()
        ' Create a button to add to the new form.
        Dim button1 As New Button()
        ' Set text for the button.
        button1.Text = "Scrolled Button"
        ' Set the size of the button.
        button1.Size = New Size(100, 30)
        ' Set the location of the button to be outside the form's client area.
        button1.Location = New Point(form2.Size.Width + 200, form2.Size.Height + 200)

        ' Add the button control to the new form.
        form2.Controls.Add(button1)
        ' Set the AutoScroll property to true to provide scrollbars.
        form2.AutoScroll = True

        ' Display the new form as a dialog box.
        form2.ShowDialog()

この機能を停止する可能性のあるフォーム設定はありますか?

フォーム作成コード全体は次のとおりです。

 ' Creating dynamic form and dynamic objects in it.
        If Not IsNothing(colMerchApplicationFromWebService) Then
            ' vertical position of current object we are working with on the form
            Dim intVertPos As Integer = 35

            'variables to hold dimensions for objects on the form. Used in calculations for creating objects and their placement
            Dim intMaxWidthLabel As Integer = 0
            Dim intMaxWidthText As Integer = 0
            Dim iFrmMaxHeight As Integer = 0
            Dim intWidthTextBox As Integer = 0
            Dim intGapHeight As Integer = 0
            Dim measureString As String = ""
            Dim stringFont As Font = Nothing
            Dim stringSize As SizeF
            Dim iTabIndex As Integer = 0
            Dim iNewLineCount As Integer = 0
            Dim iNewColumnPosition As Integer = 0

            ' Font settings
            Dim sFont As String = "Arial"
            Dim sSizeFont As String = "10"
            Dim sTextSize As String = "15"
            Dim pictureBox1 As New PictureBox

            ' use an invisible picture box that will help to graphically
            ' measure strings according their font and font size
            Dim myGraphics As Graphics = pictureBox1.CreateGraphics()

            ' Calculate the height gap that has to be generated for this calculation, we have to follow the principles listed:
            '   The gap should be determined only by the height of the tallest object on window: the textBox.
            '   Simulate the drawing of a dummy textBox, that will never be shown, and retrieve its height for spacing purposes.
            Dim dummyTextBox As New TextBox()
            dummyTextBox.Font = New System.Drawing.Font(sFont, Single.Parse(sSizeFont), System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CByte(0))
            Dim intHeight As Integer = Integer.Parse(sSizeFont) + Integer.Parse(sSizeFont) / 2
            dummyTextBox.Name = "TextBoxDummy"
            intGapHeight = dummyTextBox.Height

            'close the dynamic form if existing already
            If frmDynamic IsNot Nothing Then
                frmDynamic.Close()
            End If

            ' Now create a new fresh one
            frmDynamic = New Form()
            frmDynamic.AutoScaleDimensions = New System.Drawing.SizeF(6.0F, 13.0F)
            frmDynamic.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
            frmDynamic.Name = "frmDynamicMerchantApplication"

            'dimension is irrelevant at the moment
            frmDynamic.ClientSize = New System.Drawing.Size(10, 10)
            'the parent will be the current form
            'frm.MdiParent = this;

            frmDynamic.ControlBox = True
            frmDynamic.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable
            ' This needs to be GrowOnly for the auto scroll to work. - otherwise you have to add scrollbars manually along with the handlers and so forth.
            frmDynamic.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly

            ' Add auto scroll since the form could grow out of range when adding multiple references and owners
            frmDynamic.AutoScroll = True
            frmDynamic.BackColor = System.Drawing.Color.LightGray

            'for each parameter returned add a data entry control to the form
            For Each itemMerchantAppField As TestApp.parameter In colMerchApplicationFromWebService
                ' if we run into a collection it is used for detailed information. We store the collections in the collections dictionary so we can write values and pass them around as needed
                If itemMerchantAppField.ParameterType = "System.Collections" Then
                    ' Create a form level variable to hold the collection
                    dicCollections.Add(itemMerchantAppField.ParameterName, itemMerchantAppField.SubCollection)
                End If

                ' I assume a max of 35 fields in one column for my form and its size. (The field count is based on what looked right for my monitor not exactly Dynamic but its only a test form) 
                If iNewLineCount > 35 Then
                    ' Reset vertical position and counter
                    iNewLineCount = 0
                    iNewColumnPosition = iNewColumnPosition + (intMaxWidthLabel + intMaxWidthText + 20)
                    If intVertPos > iFrmMaxHeight Then
                        iFrmMaxHeight = intVertPos
                    End If
                    intVertPos = 35
                End If

                ' Kick the counter
                iNewLineCount = iNewLineCount + 1

                'add a label object
                Dim aLabel As New Label()
                aLabel.Font = New System.Drawing.Font(sFont, Single.Parse(sSizeFont), System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CByte(0))
                'back color is for testing purposes, to see if the control fits correctly
                aLabel.BackColor = System.Drawing.Color.AliceBlue
                aLabel.Location = New System.Drawing.Point(iNewColumnPosition, intVertPos)

                ' Set up string.
                measureString = itemMerchantAppField.ParameterName
                stringFont = New Font(sFont, Single.Parse(sSizeFont))
                ' Measure string.
                stringSize = New SizeF()
                stringSize = myGraphics.MeasureString(measureString, stringFont)
                Dim intWidthLabel As Integer = 10 + Integer.Parse(stringSize.Width.ToString("####0"))
                'store the biggest width, so that the textboxes can be vertically aligned
                If intWidthLabel > intMaxWidthLabel Then
                    intMaxWidthLabel = intWidthLabel
                End If
                aLabel.Size = New System.Drawing.Size(intWidthLabel, intGapHeight)
                aLabel.Name = "lbl" & itemMerchantAppField.ParameterName
                aLabel.Text = itemMerchantAppField.ParameterName

                frmDynamic.SuspendLayout()
                aLabel.SuspendLayout()
                frmDynamic.Controls.Add(aLabel)

                ' Size of textBox padding with "W" the largest char in ascii representation.
                ' Basically we are setting the textbox widths based on the lengths of the field name plus 15 w's
                ' We should be setting this based on the allowed field length as w's up to the max amount we allow(here is it coded to be 30)
                ' this section needs to be corrected
                Dim chrPadding As Char = "W"c
                If Integer.Parse(sTextSize) > 30 Then
                    measureString = measureString.PadRight(30, chrPadding)
                Else
                    measureString = measureString.PadRight(Integer.Parse(sTextSize), chrPadding)
                End If
                stringFont = New Font(sFont, Single.Parse(sSizeFont))
                ' Measure string.
                stringSize = New SizeF()
                stringSize = myGraphics.MeasureString(measureString, stringFont)
                intWidthTextBox = Integer.Parse(stringSize.Width.ToString("####0"))

                ''For Each item As wsMerchantApp.parameter In itemMerchantAppField 
                ' Add a text box object
                Dim aTextBox As New TextBox()
                aTextBox.Font = New System.Drawing.Font(sFont, Single.Parse(sSizeFont), System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CByte(0))
                aTextBox.BackColor = System.Drawing.Color.Yellow
                aTextBox.Location = New System.Drawing.Point(iNewColumnPosition + 5 + intMaxWidthLabel, intVertPos)
                aTextBox.Size = New System.Drawing.Size(intWidthTextBox + 10, intGapHeight)

                ' Add a double click handler for each text box - I use this for getting additional information on the field in focus
                AddHandler aTextBox.DoubleClick, AddressOf TextBoxShowDesc

                'store the biggest width, so that the textboxes can be vertically aligned
                If intWidthTextBox > intMaxWidthText Then
                    intMaxWidthText = intWidthTextBox
                End If

                ' giving a name to all your objects will be the only way to retrieve them and use them in code. I use the names from
                ' the parameter class so it is easier to work with
                aTextBox.Name = itemMerchantAppField.ParameterName
                'giving the maximum size in characters for the textbox.
                aTextBox.MaxLength = Integer.Parse(itemMerchantAppField.ParameterLength)
                ' Create a useful tooltip
                ToolTip1.SetToolTip(aTextBox, itemMerchantAppField.ParameterDesc & IIf(itemMerchantAppField.ParameterRequired, " This field is required.", " This field is not required."))

                'tab have to be ordered so we can navigate the form with ease
                aTextBox.TabIndex = iTabIndex
                ' Now kick the counter
                iTabIndex += 1

                'Vertical position is to be manage according the 
                'tallest object in the form, in this case the textbox it self
                intVertPos += intGapHeight

                'adding the textbox to the form
                frmDynamic.SuspendLayout()
                aTextBox.SuspendLayout()
                frmDynamic.Controls.Add(aTextBox)
            Next

            'put an action button to the right
            Dim btnFill As Button = New System.Windows.Forms.Button()
            btnFill.Location = New System.Drawing.Point(iNewColumnPosition + (intMaxWidthLabel + intMaxWidthText), 0) 'intMaxWidthLabel + intWidthTextBox + 20, 0)
            btnFill.Name = "btnFill"
            btnFill.Size = New System.Drawing.Size(75, 23)
            btnFill.TabIndex = iTabIndex
            btnFill.Text = "&Fill"

            'put another action button to the under the first
            Dim btnSendApp As Button = New System.Windows.Forms.Button()
            btnSendApp.Location = New System.Drawing.Point(iNewColumnPosition + (intMaxWidthLabel + intMaxWidthText), 0 + intGapHeight) 'intMaxWidthLabel + intWidthTextBox + 20, 0)
            btnSendApp.Name = "btnSubmit"
            btnSendApp.Size = New System.Drawing.Size(75, 23)
            btnSendApp.TabIndex = iTabIndex
            btnSendApp.Text = "&Submit"

            'define a click_event on the buttons - now we can handle the click event code in the parent form.
            AddHandler btnFill.Click, AddressOf btnFillClick
            AddHandler btnSendApp.Click, AddressOf btnSendAppClick

            ' Add the buttons
            frmDynamic.Controls.Add(btnFill)
            frmDynamic.Controls.Add(btnSendApp)

            ' Grow the form if needed to fir objects
            frmDynamic.Width = iNewColumnPosition + (intMaxWidthLabel + intMaxWidthText + 95) 'intMaxWidthLabel + intMaxWidthText + 95
            frmDynamic.Height = iFrmMaxHeight + 35 'intVertPos + 35
            If frmDynamic.Height > Screen.PrimaryScreen.WorkingArea.Height OrElse frmDynamic.Width > Screen.PrimaryScreen.WorkingArea.Width Then
                ' If the form is too big we should warn the user. 
                MessageBox.Show("Beware! The size of the window is bigger than your actual definitions...", "Warning", MessageBoxButtons.OK)
            End If

            frmDynamic.Show()
        Else
            MsgBox("ERROR: Nothing returned from the web service. The form can not be created.")
        End If
4

1 に答える 1

1

簡単なテストの後、コードに問題がないことを確認できました。ほとんどの場合、適切なテストを行っていません。以下では、ポイントを示すために最初のコードにいくつかのビットを追加しています。

frmDynamic = New Form()
frmDynamic.AutoScaleDimensions = New System.Drawing.SizeF(6.0F, 13.0F)
frmDynamic.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
frmDynamic.Name = "frmDynamicMerchantApplication"

'dimension is irrelevant at the moment
frmDynamic.ClientSize = New System.Drawing.Size(50, 50)
'the parent will be the current form
'frm.MdiParent = this;

frmDynamic.ControlBox = True
frmDynamic.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable
' This needs to be GrowOnly for the auto scroll to work. - otherwise you have to add scrollbars manually along with the handlers and so forth.
frmDynamic.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly

' Add auto scroll since the form could grow out of range when adding multiple references and owners
frmDynamic.AutoScroll = True

Dim testButton As New Button()
frmDynamic.Controls.Add(testButton)
testButton.Top = frmDynamic.Height + 1

frmDynamic.Show()

このコードは、ポップアップするフォームとそれに対応する垂直スクロールバーを示しています (そうしないとスクロールバーが表示されないため、サイズを大きくしましたが、これはまったく効果がありません)。

の位置testButtonを -1 (または -100) に変更すると、スクロールバーが表示されなくなります。スクロールバーが表示されないのは、テスト オブジェクトの位置が間違っているためだと思います。

- アップデート

コード全体を調べた後、問題はすべてのfrmDynamic.SuspendLayout()ビット (これに関する MSDN の情報) にあるようです。それらを削除してください。コードの各ビットが正確に何をしているのかを知ることは良いことです。また、理解できない問題と適切に機能するコード(この回答のも​​の)がある場合、それがどんなに単純であっても; 適切な手順は、問題がどこにあるかを見つけるまで、問題のあるコードのビットを段階的に作業コードに含め始めることです。

于 2013-08-07T16:01:29.907 に答える