(VB.net)自定义TableLayoutPanel使它能够在运行时用鼠标改变行高和列宽。

喜欢看C#的童鞋,这里有个工具,你们可以自己转换:http://converter.telerik.com/

想达到这个效果,首先新建一个新的项目。在项目名字上面右击,新增一个类,类名为:TableLayoutPanelEx.vb。 然后只要复制下面的代码到类中即可。

Public Class TableLayoutPanelEx
    Inherits TableLayoutPanel

    Private Const WM_NCHITTEST As Integer = &H84
    Private Const WM_MOUSEMOVE As Integer = &H200
    Private Const WM_LBUTTONDOWN As Integer = &H201
    Private Const WM_LBUTTONUP As Integer = &H202
    Private Const MK_LBUTTON As Integer = &H1

    Private VBorders As New List(Of Integer)
    Private HBorders As New List(Of Integer)
    Private selColumn As Integer = -1
    Private selRow As Integer = -1

    Public Sub New()
        Me.DoubleBuffered = True
        Me.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single
    End Sub

    Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs)
        MyBase.OnHandleCreated(e)
        If Not Me.DesignMode Then ResetSizeAndSizeTypes()
    End Sub

    Public Shadows Property ColumnCount() As Integer
        Get
            Return MyBase.ColumnCount
        End Get
        Set(ByVal value As Integer)
            MyBase.ColumnCount = value
            If Me.Created And Not Me.DesignMode Then ResetSizeAndSizeTypes()
        End Set
    End Property

    Public Shadows Property RowCount() As Integer
        Get
            Return MyBase.RowCount
        End Get
        Set(ByVal value As Integer)
            MyBase.RowCount = value
            If Me.Created And Not Me.DesignMode Then ResetSizeAndSizeTypes()
        End Set
    End Property

    Public Sub ResetSizeAndSizeTypes()
        Dim cW As Single = CSng((Me.ClientSize.Width \ Me.GetColumnWidths.Length) - 1)
        For c As Integer = 0 To Me.GetColumnWidths.Length - 1
            Me.ColumnStyles(c).SizeType = SizeType.Absolute
            Me.ColumnStyles(c).Width = cW
        Next

        Dim cH As Single = CSng((Me.ClientSize.Height \ Me.GetRowHeights.Length) - 1)
        For r As Integer = 0 To Me.GetRowHeights.Length - 1
            Me.RowStyles(r).SizeType = SizeType.Absolute
            Me.RowStyles(r).Height = cH
        Next
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        MyBase.WndProc(m)
        If Me.Created And Not Me.Disposing Then
            If m.Msg = WM_NCHITTEST Then
                Dim loc As Point = Me.PointToClient(MousePosition)
                VBorders.Clear()
                HBorders.Clear()
                If Me.ColumnCount > 1 Then
                    For w As Integer = 0 To Me.GetColumnWidths.Length - 2
                        If w = 0 Then
                            VBorders.Add(Me.GetColumnWidths(w))
                        Else
                            VBorders.Add(VBorders(VBorders.Count - 1) + Me.GetColumnWidths(w))
                        End If
                    Next
                End If
                If Me.RowCount > 1 Then
                    For h As Integer = 0 To Me.GetRowHeights.Length - 2
                        If h = 0 Then
                            HBorders.Add(Me.GetRowHeights(h))
                        Else
                            HBorders.Add(HBorders(HBorders.Count - 1) + Me.GetRowHeights(h))
                        End If
                    Next
                End If

                Dim onV As Boolean = (VBorders.Contains(loc.X) Or VBorders.Contains(loc.X - 1) Or VBorders.Contains(loc.X + 1))
                Dim onH As Boolean = (HBorders.Contains(loc.Y) Or HBorders.Contains(loc.Y - 1) Or HBorders.Contains(loc.Y + 1))
                If onV And onH Then
                    Me.Cursor = Cursors.SizeAll
                ElseIf onV Then
                    Me.Cursor = Cursors.VSplit
                ElseIf onH Then
                    Me.Cursor = Cursors.HSplit
                Else
                    Me.Cursor = Cursors.Default
                End If

            ElseIf m.Msg = WM_LBUTTONDOWN And Me.Cursor <> Cursors.Default Then
                Dim loc As Point = Me.PointToClient(MousePosition)
                selColumn = -1
                selRow = -1
                For c As Integer = 0 To VBorders.Count - 1
                    If VBorders(c) >= loc.X - 1 And VBorders(c) <= loc.X + 1 Then
                        selColumn = c
                        Exit For
                    End If
                Next
                For r As Integer = 0 To HBorders.Count - 1
                    If HBorders(r) >= loc.Y - 1 And HBorders(r) <= loc.Y + 1 Then
                        selRow = r
                        Exit For
                    End If
                Next

            ElseIf m.Msg = WM_MOUSEMOVE And m.WParam.ToInt32 = MK_LBUTTON Then
                Dim loc As Point = Me.PointToClient(MousePosition)
                If Me.Cursor <> Cursors.Default Then

                    If selRow > -1 And loc.Y >= 1 And loc.Y <= Me.ClientSize.Height - 2 Then
                        Me.RowStyles(selRow).SizeType = SizeType.Absolute

                        Dim ref As Single = loc.Y - Me.RowStyles(selRow).Height
                        If selRow > 0 Then ref -= HBorders(selRow - 1)

                        If Me.RowStyles(selRow).Height + ref > 0 Then

                            If Me.RowCount > selRow + 1 Then
                                If Me.RowStyles(selRow + 1).Height - ref < 1 Then Exit Sub
                                Me.RowStyles(selRow + 1).Height -= ref
                            End If

                            Me.RowStyles(selRow).Height += ref
                        End If
                    End If

                    If selColumn > -1 And loc.X >= 1 And loc.X <= Me.ClientSize.Width - 2 Then
                        Me.ColumnStyles(selColumn).SizeType = SizeType.Absolute

                        Dim ref As Single = loc.X - Me.ColumnStyles(selColumn).Width
                        If selColumn > 0 Then ref -= VBorders(selColumn - 1)

                        If Me.ColumnStyles(selColumn).Width + ref > 0 Then

                            If Me.ColumnCount > selColumn + 1 Then
                                If Me.ColumnStyles(selColumn + 1).Width - ref < 1 Then Exit Sub
                                Me.ColumnStyles(selColumn + 1).Width -= ref
                            End If

                            Me.ColumnStyles(selColumn).Width += ref
                        End If

                    End If

                End If

            ElseIf m.Msg = WM_LBUTTONUP Then
                selColumn = -1
                selRow = -1
            End If
        End If
    End Sub
End Class

  然后你需要build一下你的工程。build之后在工具箱中会自动生成TableLayoutPanelEx控件。你需要把他拉到form中即可。然后有个重要的地方需要注意下:你需要设置RowCountColumnCount属性,达到你想达到的最大值,我们假设为10行10列吧,就设置RowCount等于10,ColumnCount等于10,这些都是在窗口设计模式中做到的。
  接下来,我们再加两个NumericUpDown控件到Form中,命名为 (NUD_Rows) 和 (NUD_Columns)

  最后把下面的代码放到Form中即可。

Public Class Form1

    Public Sub New()
        InitializeComponent()

        ‘Set the minimum of the 2 NumericUpDown controls for the rows and columns to 1
        ‘Set the maximum of the 2 NumericUpDown controls to the number of rows and columns you have set in the [Design] tab properties
        NUD_Rows.Minimum = 1
        NUD_Rows.Maximum = TableLayoutPanelEx1.RowCount
        NUD_Columns.Minimum = 1
        NUD_Columns.Maximum = TableLayoutPanelEx1.ColumnCount

        ‘Set to the rows and columns counts back to what you want for the default
        TableLayoutPanelEx1.ColumnCount = 4
        TableLayoutPanelEx1.RowCount = 4

        ‘Set the 2 NumericUpDown control values to the current count of rows and columns
        NUD_Rows.Value = TableLayoutPanelEx1.RowCount
        NUD_Columns.Value = TableLayoutPanelEx1.ColumnCount
    End Sub

    Private Sub NUD_Rows_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NUD_Rows.ValueChanged
        If Me.Created Then TableLayoutPanelEx1.RowCount = CInt(NUD_Rows.Value)
    End Sub

    Private Sub NUD_Columns_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NUD_Columns.ValueChanged
        If Me.Created Then TableLayoutPanelEx1.ColumnCount = CInt(NUD_Columns.Value)
    End Sub
End Class

你可以运行和调试了。Good lucy baby!

理想的效果应该是你可以用鼠标改变行高和列宽了。可以通过 NumericUpDown控件改变行数和列数。

这边是我的效果图:

时间: 2024-10-29 19:06:37

(VB.net)自定义TableLayoutPanel使它能够在运行时用鼠标改变行高和列宽。的相关文章

windows客户端开发--使你的客户端运行时记住上次关闭的大小和位置

几乎所有的windows客户端都可以调整大小,所以用户根据自己的喜好调整客户端的大小和位置. 但是当该客户端退出后,重新运行客户端的时候,我们往往又要调整自己喜好的大小和位置. 微信的windows客户端做了记住客户端退出时候的大小和位置,下次运行的时候直接,窗口直接显示为你喜好的大小和位置. 现在的任务就是八一八这个小小的功能. 首先,你肯定是想到了使用配置文件.再客户端退出的时候,把客户端窗口的信息记录在一个配置文件中,一般都是.ini文件.读写配置文件 很简单,这里就不再赘述了. 但是使用

自定义TextView使之具有跑马灯的效果

一.问题的引入 使用普通的textview跑马的效果,一开始没有焦点事件不会进行滚动,button有焦点事件,但是比较难看,因此需要自定一个TextView 一出生就有焦点 然后需要自定义一个textview FocusedTextView.java package com.xuliugen.mobilesafe.ui; import android.content.Context; import android.util.AttributeSet; import android.view.Vi

WebAssembly,可以作为任何编程语言的编译目标,使应用程序可以运行在浏览器或其它代理中——浏览器里运行其他语言的程序?

Mozilla.谷歌.微软和苹果已经决定开发一种面向Web的二进制格式.该格式名为WebAssembly,可以作为任何编程语言的编译目标,使应用程序可以运行在浏览器或其它代理中. 几年前,我们在InfoQ上讨论过面向Web的通用字节码的优点(见<讨论:我们是否需要一种通用的Web字节码?>),概括了创建这样一种格式的困难.其中提及的一个主要问题是主要的浏览器制造商无法达成一致:Mozilla在推asm.js,谷歌支持PNaCI,苹果在开发FLTJIT,而微软没有对其中的任何一种表示出兴趣.但现

linux使脚本在后台运行

一.为什么要使程序在后台执行 我们计算的程序都是周期很长的,通常要几个小时甚至一个星期.我们用的环境是用putty远程连接到日本Linux服务器.所以使程序在后台跑有以下三个好处: 1:我们这边是否关机不影响日本那边的程序运行.(不会像以前那样,我们这网络一断开,或一关机,程序就断掉或找不到数据,跑了几天的程序只能重头再来,很是烦恼) 2:不影响计算效率 2:让程序在后台跑后,不会占据终端,我们可以用终端做别的事情. 二.怎么样使程序在后台执行 方法有很多,这里主要列举两种.假如我们有程序pso

自定义注解之运行时注解(RetentionPolicy.RUNTIME)

对注解概念不了解的可以先看这个:Java注解基础概念总结 前面有提到注解按生命周期来划分可分为3类: 1.RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃: 2.RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期: 3.RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在: 这3个生

自动布局下的自定义行高约束问题

昨天晚上被自动布局里自定义行高磨了一晚上,简直快要疯掉.我是利用Masonry来进行自动布局的,布局很简单,就是cell里面放两个label,可是,在我添加完约束之后,控制台就会打印一大堆东西,约束是这样的: _titleLab.font = [UIFont systemFontOfSize:28*TTScreenWith/640]; [_titleLab mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.mas_equ

自定义提示用户授权使用地理定位功能时的提示语

以前程序的地理定位功能若查询GPS授权情况,返回的是CLAuthorizationStatus.NotDetermined,意思是授权状态未定. 需要在使用CoreLocation前调用方法 requestWhenInUseAuthorization() 或者 requestAlwaysAuthorization() 并在Info.plist中加入两个缺省没有的字段 NSLocationAlwaysUsageDescription NSLocationWhenInUseUsageDescript

自定义 ThreadPoolExecutor 处理线程运行时异常

自定义 ThreadPoolExecutor 处理线程运行时异常 最近看完了ElasticSearch线程池模块的源码,感触颇深,然后也自不量力地借鉴ES的 EsThreadPoolExecutor 重新造了一把轮子,对线程池的理解又加深了一些.在继承 ThreadPoolExecutor实现自定义的线程池时,ES先重写了Runnable接口,提供了更灵活的任务运行过程中出现异常处理逻辑.简而言之,它采用回调机制实现了线程在运行过程中抛出未受检异常的统一处理逻辑,非常优美.实在忍不住把源码cop

自定义函数使字符串中的某个字符更改样式

设定现在有一个字符串 str = "hello, kitty is not cat": 假设要把其中的 is 变成红色样式: 先自定义一个函数 red(); red(str,redstr)函数传递两个参数,一个是整个字符串,另一个是要变样式的字符串. var str = "hello, kitty is not cat"; var red = (a, redstr = "参数默认") => { let zzr = new RegExp(&q