【问题标题】:Unusual Glitch when Opening Forms打开表单时出现异常故障
【发布时间】:2017-11-18 04:02:58
【问题描述】:

当我在我的项目中最大化一个表单并从中打开另一个表单(使用按钮)时,我遇到了一个不寻常的故障,我只能使用下面的屏幕截图来解释。

在这张图片中,我有一个订单屏幕和一个货运屏幕。当我点击“添加货运”按钮时,订单屏幕最大化为 MDI 屏幕,然后在打开货运管理屏幕时,它将两个表单都设置为 WindowState.Normal,我正在以编程方式执行此操作,我理解它为什么同时设置窗体到正常的窗口状态,但是,您可以在最大化视图中留下订单屏幕的痕迹。

为了更清楚地解释,表格已经从WindowState.Maximized更改为WindowState.Normal,并且在图像中左上角的表格很好,但是订单表格仍然显示为标准化和最大化,但是最大化的窗口不存在,当您移动其他屏幕时它会消失。

最奇怪的是,我在程序的其他地方以完全相同的方式使用相同的代码打开其他窗口,但这个故障并没有发生。

只有 2 个“父”表单在从其中打开其他表单时会执行此操作。

有没有其他人遇到过这个问题?有什么办法解决它?即使我以最大化模式打开另一个表单也会发生这种情况,因此它不像以最大化视图打开它那么简单。

示例中打开表单的代码如下:

ugProducts.UpdateData()

  Try
     Dim dt As New DataTable
     dt = ugProducts.DataSource

     Dim ordnum As Integer
     Dim osql As New OleDbCommand
     osql.CommandType = CommandType.Text

     osql.Connection = con
     osql.CommandText = "SELECT [Order_Number] FROM [Order_Freight] WHERE [Order_Reference] = ?"
     osql.Parameters.AddWithValue("@onum", lblReference.Text.ToString)

     ordnum = Convert.ToInt32(osql.ExecuteScalar)

     Dim ORef As String
     ORef = lblReference.Text

     Dim FNumber As Integer

     Dim fsql As New OleDbCommand
     fsql.CommandType = CommandType.Text

     fsql.Connection = con
     fsql.CommandText = "SELECT [Freight_Number] FROM [Order_Freight] WHERE [Order_Reference] = ?"
     fsql.Parameters.AddWithValue("@fnum", lblReference.Text.ToString)

     FNumber = Convert.ToInt32(fsql.ExecuteScalar)

     Dim PC As String
     Try
         PC = ugProducts.ActiveRow.Cells("Product_Code").Text.ToString
     Catch
         PC = ugProducts.Rows(0).Cells("Product_Code").Text.ToString
     End Try

     Dim SC As String
     Try
         SC = ugProducts.ActiveRow.Cells("Supplier_Code").Text.ToString
     Catch
          SC = ugProducts.Rows(0).Cells("Supplier_Code").Text.ToString
     End Try

     Dim f As New frmEditFreight(con, dt, Me, cmbCustCode.Text, ordnum, ORef, FNumber, PC, SC)
     f.MdiParent = Me.MdiParent
     f.Show()

 Catch ex As Exception
     errorLog(ex)

 End Try

然后,在加载的表单上,我有这个

   Me.Location = New Point(0, 0)
    Me.WindowState = FormWindowState.Normal

    txtTotal.ReadOnly = True
    lftable = New DataTable

    If isNewOrder = False Then
        Try
            For Each dc As DataColumn In lineTable.Columns
                If dc.ColumnName = "Order_Number" OrElse dc.ColumnName = "Product_Code" OrElse dc.ColumnName = "Supplier_Code" Then
                    lftable.Columns.Add(New DataColumn(dc.ColumnName, dc.DataType))
                End If
            Next

            Dim product As String = ""
            Dim supplier As String = fOrder.cmbSupplier.Text

            Dim ds As New DataSet

            Dim da As New OleDbDataAdapter("SELECT * FROM [Order_Freight] WHERE [Order_Number] = ?", con)
            da.SelectCommand.Parameters.Add("@num", OleDbType.Integer).Value = orderNum
            da.Fill(ds)
            Dim nDt As New DataTable
            nDt = ds.Tables(0).Copy()

            For Each row As DataRow In nDt.Rows
                product = row.Item("Product_Code")

                For Each dr As DataRow In lineTable.Rows
                    If dr.RowState <> DataRowState.Deleted Then
                        If dr.Item("Product_Code") = product Then
                            dr.Delete()
                        Else
                        End If
                    Else
                        If dr.Item("Product_Code", DataRowVersion.Original) = product Then
                            dr.Delete()
                        Else
                        End If
                    End If
                Next
            Next

            For Each dr As DataRow In lineTable.Rows
                If dr.RowState <> DataRowState.Deleted Then
                    dr.Item("Order_Number") = orderNum
                End If
            Next

            Me.ugProducts.DataSource = lineTable

            For Each dc As UltraGridColumn In ugProducts.DisplayLayout.Bands(0).Columns
                Dim cName As String = dc.ToString

                Select Case cName
                    Case "Product_Code"
                        dc.Hidden = False
                    Case "Order_Number"
                        dc.Hidden = False
                    Case "Supplier_Code"
                        dc.Hidden = False
                    Case Else
                        dc.Hidden = True
                End Select
            Next

            loadAddresses(custCode, con)

            dtEstDelivery.Value = Date.Today

            ugProducts.DisplayLayout.Bands(0).Override.CellClickAction = CellClickAction.RowSelect

            selectedTable.Columns.Add("Product_Code")
            selectedTable.Columns.Add("Supplier_Code")
            selectedTable.Columns.Add("RowIndex")

            freightTable = New DataTable

            With freightTable.Columns
                .Add("Freight_Number")
                .Add("Address_Code")
                .Add("Est_Delivery")
                .Add("Product_Code")
                .Add("Freight_Desc")
                .Add("Freight_Val", GetType(Decimal))
                .Add("Supplier_Code")
                .Add("freeDelivery", GetType(Boolean))
            End With

            ugFreight.DataSource = freightTable

            ugSelected.DataSource = selectedTable
            ugSelected.DisplayLayout.Bands(0).Override.CellClickAction = CellClickAction.RowSelect

        Catch ex As Exception
            errorLog(ex)

        End Try
    Else
        Try
            Me.ugProducts.DataSource = lineTable

            For Each dc As UltraGridColumn In ugProducts.DisplayLayout.Bands(0).Columns
                Dim cName As String = dc.ToString

                Select Case cName
                    Case "Product_Code"
                        dc.Hidden = False
                    Case "Product_Description"
                        dc.Hidden = False
                        dc.Header.Caption = "Description"
                    Case "Supplier_Code"
                        dc.Hidden = False
                        dc.Header.Caption = "Supplier"
                    Case Else
                        dc.Hidden = True
                End Select
            Next

            loadAddresses(custCode, con)

            dtEstDelivery.Value = Date.Today

            ugProducts.DisplayLayout.Bands(0).Override.CellClickAction = CellClickAction.RowSelect

            selectedTable.Columns.Add("Product_Code")
            selectedTable.Columns.Add("Supplier_Code")
            selectedTable.Columns.Add("RowIndex")

            freightTable = New DataTable

            With freightTable.Columns
                .Add("Freight_Number")
                .Add("Address_Code")
                .Add("Est_Delivery")
                .Add("Product_Code")
                .Add("Freight_Desc")
                .Add("Freight_Val", GetType(Decimal))
                .Add("Supplier_Code")
                .Add("freeDelivery", GetType(Boolean))
            End With

            ugFreight.DataSource = freightTable

            ugSelected.DataSource = selectedTable
            ugSelected.DisplayLayout.Bands(0).Override.CellClickAction = CellClickAction.RowSelect

        Catch ex As Exception
            errorLog(ex)

        End Try
    End If

    bLoading = False

接下来是一些普通的东西,设置DataTables,加载数据等。

另一个有问题的表单有这个代码:

 Try
    Dim grid As UltraGrid = DirectCast(sender, UltraGrid)
    Dim lastElement As UIElement = ugRates.DisplayLayout.UIElement.LastElementEntered
    Dim rowElement As RowUIElement

    If TypeOf lastElement Is RowUIElement Then
         rowElement = DirectCast(lastElement, RowUIElement)
    Else
         rowElement = DirectCast(lastElement.GetAncestor(GetType(RowUIElement)), RowUIElement)
    End If

     If rowElement Is Nothing Then Return

     Dim row As UltraGridRow = DirectCast(rowElement.GetContext(GetType(UltraGridRow)), UltraGridRow)

     If (row Is Nothing) Then Return

     Dim MousePosition As Point = grid.PointToClient(Control.MousePosition)

     If Not lastElement.AdjustableElementFromPoint(MousePosition) Is Nothing Then Return

 Select Case row.Cells("cType").Value
     Case "Acquisition Rate"
       Dim supplier As String

       If rbtnAllSuppliers.Checked = True Then
          supplier = row.Cells("Supp_Code").Value
       Else
          supplier = cmbSupplier.Text
       End If

       Dim f As New frmCommission(con, row.Cells("Comm_Code").Value, supplier, True)
       f.MdiParent = Me.MdiParent
       f.Show()

下面的选择案例的其余部分。在这种情况下打开的表单有代码

  Me.Location = New Point(0, 0)
  Me.WindowState = FormWindowState.Normal
  Me.Cursor = Cursors.Default

  isUpdate = False

  Me.ugComm.ContextMenuStrip = cmCommRate

  With updateDT.Columns
      .Add("Apply", GetType(Boolean)).DefaultValue = False
      .Add("Product_Code")
      .Add("Commission_Rate")
      .Add("Multiplier")
  End With

  btnCustomerSearch.Enabled = False

  Try
      Dim da As New OleDb.OleDbDataAdapter
      Dim ds As New DataSet

      sql = "SELECT * FROM [System Settings]"
      da = New OleDb.OleDbDataAdapter(sql, con)

      Dim dt As New DataTable
      da.Fill(dt)

      If dt.Rows(0).Item("enableAqDate") = False Then
          rbtnAcq.Enabled = False
      End If

      If cCode <> "" And sCode <> "" Then
          cmbSupp.Text = sCode
          cmbSupp_ValueChanged(sender, New EventArgs)
      End If

      disableControls()

      cmbSupp.Refresh()
      txtCommCode.Refresh()
      ugComm.Refresh()
      cmbSupp.Enabled = False

      isLoad = False

      If isEnquiry = True Then
          txtCommCode.Text = cCode
          loadEnquiry()
          ugComm.Enabled = True
          cmdAddRange.Enabled = False
          cmdUpdateRange.Enabled = True
          cmbSupp.Value = sCode
          txtCommCode.Text = cCode
      End If

  Catch ex As Exception
      errorLog(ex)

  End Try

当尝试插入建议用于制作 dpiaware = True 的代码时,我无法在代码中的任何地方看到这会发生什么?

【问题讨论】:

  • 您能发布您遇到问题的代码吗?奇怪的是,我不得不在这种情况下添加Application.DoEvents(),因为一个表单可能比下一个表单需要更多的内存和加载时间。
  • 您必须向我们展示创建这些表单的代码。有油漆代码吗?任何调整大小的代码?
  • @JimmySmith 代码已添加。
  • @LarsTech 不,不是任何那种代码,我已经发布了我所拥有的。
  • 如果应用程序不支持 DPI,请尝试这样做,然后报告结果。这些伪影可能是由 DPI 虚拟化引起的。

标签: vb.net forms winforms


【解决方案1】:

当活动的 mdi 子窗体最大化时,罪魁祸首似乎是在 mdi 子窗体的 Load 事件中将 WindowState 属性设置为 Normal

此时目标窗体处于某种中间状态——该事件作为窗口句柄创建的一部分被调用,句柄已经创建,Visible 属性为True(但窗体并没有真正显示在屏幕),WindowState 返回 Maximized 并尝试将其设置为 Normal 在内部导致 ShowWindow API 调用。

很难确定错误到底出在哪里(Form 类内部有很多内部标志和 windows 消息处理),但最终结果是 MDIClient 和当前活动的 mdi 子窗体是未正确失效,因此您正在体验的视觉效果。

话虽如此,有几种解决方法:

(1) 在表格显示的一侧:

Me.WindowState = FormWindowState.Normal 移动到Shown 事件。

(2) 在调用方:

(A) 在f.Show()之前添加Me.WindowState = FormWindowState.Normal

(B) 在f.Show() 之后添加Me.MdiParent.Invalidate(True)

(C) 在f.Show() 之后添加Me.MdiParent.Refresh()

我个人的偏好是选项 (1),因为它封装了特定于该表单内被调用表单的逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多