VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
楼主: 410023425

[分享] VB入门技巧N例

[复制链接]
 楼主| 发表于 2007-1-21 13:25:09 | 显示全部楼层
VB实现按钮浮动效果


微软的Visual Basic确实是个好东东,编写应用程序快捷高效。但是入门容易,想玩转它可不简单。我个人学VB就深有体会:一个人在VB的殿堂里摸索是何等的辛苦啊!有时为了一个特技、一句代码甚至一个变量要反复调试运行几十遍,也未必能通过,真恨不得一枪崩了VB。所以,我连这一点点小技巧都不敢独品,拿出来与大家共享,也算抛砖引玉,引出更多、更精彩的奇思妙文,以“飨”读者。
关于浮动按钮的实现思路不少,多是采取多图片重叠显示来实现。这种方法代码量多,实现起来较繁琐。因为,一个按钮还好,如果有十个按钮呢?一个按钮三个图片,十个就要三十个图片,可不是闹着玩的。
我的思路是:
舍弃CommandButton控件,每个按钮用4条Line控件和一个Label控件替代。4条Line围住Label的边缘,调入窗体时,置显示属性为False,并将左、上直线的颜色设为白色,右、下直线的颜色设为黑色。当鼠标移到Label上时,4条Line的显示属性置True;当鼠标离开按钮时,将4条Line的显示属性设置为False。这样在视觉上就完全得到立体浮动的效果。另外,VB的Line控件还支持直线倾斜,以此类推,完全可以做出更加美观的倾斜按钮。篇幅所限,下面仅给出一个按钮实现浮动效果的源代码。
Option Explicit
Private Sub Form_Load()
注释:初始Form与Label
Form1.Caption = “浮动按钮"
Form1.KeyPreview = False
label1.Caption = “确定"
注释:初始4条Line的显示属性为False
Line1.Visible = False
Line2.Visible = False
Line3.Visible = False
Line4.Visible = False
注释:初始4条Line的颜色
Line1.BorderColor = &HE0E0E0
Line2.BorderColor = &HE0E0E0
Line3.BorderColor = &H808080
Line4.BorderColor = &H808080
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
注释:鼠标指针在窗体上(不在按钮上)时,置4条Line的显示属性为False
Line1.Visible = False
Line2.Visible = False
Line3.Visible = False
Line4.Visible = False
End Sub
Private Sub label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
注释:鼠标指针在按钮上时,置4条Line的显示属性为True
Line1.Visible = True
Line2.Visible = True
Line3.Visible = True
Line4.Visible = True
End Sub
(浙江黄岩职技校96计算机 中专 王建跃 )
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:25:51 | 显示全部楼层
VB中防止将重复项目添加到列表框控件中
作者:谭翁
---- Visual Basic 的 列 表 框 控 件 中 包 含 项 目 的 列 表, 本 文 介 绍 如 何 检 查 列 表 中 项 目 是 否 已 经 存 在, 以 及 如 何 将 新 的 项 目 添 加 到 列 表 框 控 件 中。

使 用SendMessage 函 数 搜 寻 重 复 的 项 目
---- 在Visual Basic 中 开 发 应 用 程 序 时, 可 以 使 用 列 表 框 控 件 来 创 建 一 个 项 目 的 列 表。 要 将 新 的 项 目 添 加 到 列 表 中, 可 以 使 用AddItem 方 法, 该 方 法 不 能 自 动 地 报 告 在 列 表 框 控 件 中 是 否 有 重 复 的 信 息 存 在, 所 以 必 须 在 将 新 项 目 添 加 到 列 表 之 前 首 先 检 查 一 下。

---- 可 以 通 过 使 用Windows 应 用 程 序 编 程 接 口(API) 的SendMessage 函 数 来 在 列 表 框 控 件 中 搜 寻 指 定 的 项 目, 它 函 数 允 许 向 操 作 系 统 中 发 送 消 息。 在 本 文 的 例 子 里, 我 们 让SendMessage 函 数 往 列 表 框 控 件 中 执 行 一 个LB_FINDSTRING 消 息。

---- LB_FINDSTRING 消 息 允 许 在 一 个 列 表 框 控 件 中 搜 索 同 目 标 字 符 串 相 匹 配 的 项 目。 该 消 息 的 第 一 个 参 数 是 希 望 进 行 的 搜 索 类 型, 须 将 该 值 设 为0, 表 示 从 列 表 框 控 件 中 的 第 一 个 项 目 开 始 搜 索。 第 二 个 参 数 是 一 个NULL 结 束 的 字 符 串, 它 是 实 际 希 望 搜 索 的 项 目。

---- 如 果 该LB_FINDSTRING 消 息 返 回 值-1, 则 表 明 在 列 表 框 控 件 中 没 有 找 到 目 标 字 符 串, 此 时 可 以 使 用AddItem 方 法 来 将 新 的 项 目 添 加 到 列 表 框 控 件 中。 如 果 该 项 目 已 经 在 列 表 中 存 在, 则 可 以 简 单 地 显 示 一 个 信 息 框 或 是 执 行 一 些 其 它 的 过 程, 来 通 知 用 户 一 个 重 复 的 项 目 已 经 在 列 表 框 控 件 中 存 在。

样 例 程 序
---- 该 程 序 显 示 了 如 何 确 定 在 一 个 列 表 框 控 件 中 是 否 已 经 包 含 了 一 个 要 添 加 到 控 件 中 的 项 目。

---- 1. 在Visual Basic 中 开 始 一 个 新 的 工 程, 采 用 缺 省 的 方 法 建 立Form1。
---- 2. 将 如 下 常 量 和 声 明 语 句 添 加 到Form1 的 通 用 声 明 部 分 中( 注 意 该 声 明 语 句 需 要 被 书 写 在 一 行 内):
---- Private Declare Function SendMessageFind Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As String) As Long
---- Const WM_USER = &H400
---- Const LB_ERR = (-1)
---- Const LB_FINDSTRING = &H18F

---- 3. 将 如 下 代 码 添 加 到Form1 的Form_Load 事 件 中:

Private Sub Form_Load()
List1.AddItem "Item #1"
List1.AddItem "Item #2"
List1.AddItem "Item #3"
List1.AddItem "Item #4"
End Sub

---- 4. 在Form1 上 添 加 一 个 文 本 框 控 件, 采 用 缺 省 的 方 法 建 立Text1。
---- 5. 在Form1 上 添 加 一 个 列 表 框 控 件, 采 用 缺 省 的 方 法 建 立List1。
---- 6. 在Form1 上 添 加 一 个 命 令 按 钮 控 件, 采 用 缺 省 的 方 法 建 立Command1, 将 起Caption 属 性 设 置 为“ 重 复”。
---- 7. 将 如 下 代 码 添 加 到Command1 的 单 击 事 件 中:

Private Sub Command1_Click()
CheckForDupes
End Sub

---- 8. 创 建 一 个 新 的 名 为CheckForDupes 的 函 数, 将 如 下 代 码 添 加 到 该 函 数 中:

Sub CheckForDupes()
Dim Ret As Long
Dim A As String
A = Text1.TEXT
Ret = SendMessageFind(List1.hwnd, LB_FINDSTRING, 0, (A))
If Ret = LB_ERR Then
List1.AddItem Text1.TEXT
Else
List1.ListIndex = Ret
MsgBox " 重 复 项 目 - 不 能 被 添 加 到 列 表 框 中", 16, " 错 误"
End If
End Sub

---- 按 下F5 键 来 执 行 本 程 序。 在 列 表 框 控 件 中 有5 个 项 目。 在 文 本 框 控 件 中 键 入 一 个 新 的 项 目, 单 击 重 复 命 令 按 钮。 程 序 将 在 列 表 框 控 件 中 搜 索 刚 刚 键 入 到 文 本 框 控 件 中 的 项 目。 如 果 该 项 目 未 被 找 到, 则 程 序 将 把 该 项 目 添 加 到 列 表 框 控 件 中。 相 反, 如 果 该 项 目 已 经 在 列 表 框 中 存 在 了, 则 将 显 示 出 一 个 信 息 框 以 通 知 项 目 已 经 存 在。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:26:45 | 显示全部楼层
Visual Basic 中文本框处理技巧集萃
刘强
    在Visual Basic中,文本框(TextBox)是最常用的控件,熟练运用文本框是开发出高质量的应用程序的基础。笔者在从事应用程序开发中,摸索出有关文本框的应用技巧,写出来与VB爱好者共享。
1、设置只读文本框。
    有些时候在窗口显示一段信息,但又不希望用户去改变它,怎样实现文本的只读呢?首先,我们可以利用标签框( label )的只读属性,以标签来代替文本框以实现只读属性,但也可以用小程序实现真正的文本框的只读。
        Sub Text1_KeyPress (keyascii As Integer)
        keyascii = 0
        End Sub
    或者也可以用sendkey方法使文本框失去焦点,如以下程序:
        Sub Text1_KeyDown (KeyCode As Integer, Shift As Integer)
        SendKeys "{tab}"
        End Sub
2、限定文本框的输入内容和格式。
    以下程序可以实现限定文本框只能输入数字:
        Sub Text1_KeyPress (keyascii As Integer)
        If keyascii < 48 Or keyascii > 57 Then
        Beep
        Beep
        johny@nease.net
        keyascii = 0
        End If
        End Sub
    若想限定文本框输入格式,可以使用VB的FORMAT函数,也可以使用专业版的屏蔽控件(Masked Edit),通过设定屏蔽控件的Mask属性可以对文本框的输入格式作精确控制。
 
3、为TextBox 创建快捷键。
    VB规定,添加在窗体上的控件均在其Tabindex 属性中记载其加载顺序,程序运行时焦点按Tabindex 属性规定的顺序在控件间跳转。而为了简化操作,可VB中为任何具有 caption的属性的控制创建快捷键,这通过caption 属性中在想作为快捷键的字母前加&号实现。但有一个问题值得注意,而类似文本框这样的控件无 caption 这样的属性,这时可将标签与文本框同时使用。为 lable创建快捷键,标签 Tabindex 属性设置比文本框小1,又因为label 不能接收按点,焦点会自动跳至文本框。这相当于为文本框创建了快捷键。具体步骤如下:
    (1) 首先绘制标签,再绘制文本框。或随意绘制各种控制,将标签 Tabindex 属性设置比文本框小1
    (2) 在标签的caption 属性中使用“&”号设定快捷键
    这样就相当于为文本框设定了快捷键,当你按下标签框的快捷键时,焦点就会跳至文本框上。
 
4、在设计时实现文本框换行。
    对于文本框,在设计时properties 窗口不能输入换行符,但可以再程序执行时用代码来换行,即使用 ASCII字符的13和10,如下列小程序就可将两行文本放入文本框:
        Sub form_load( )
        NL=chr(13)+chr(10)
        text1.text=“my name is ”& NL & “ liu qiang”
        End sub
 
5、创建口令文本框。
    创建口令文本框可用设置属性的方法,也可以通过调用WINDOWS的API应用函数接口来实现。首先,文本框的属性 Passwordchar和maxlength 可用来设置口令框。其中 Passwordchar 指定文本框显示的字符,如指定“*”,则在文本框内显示“*”,Maxlength确定文本框中能输入几个字符。超过Maxlength以后,文本框发出警告声,不能接收更多的字符。若使用WINDOWS应用函数接口,可用GetWindowLong、SetWindowsLong和SendMessage等接口函数来实现,有兴趣的读者可查阅Windows API函数手册或VB的联机帮助文件,这里就不一一赘述了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:28:32 | 显示全部楼层
打印机技巧


用 API 打开打印对话框
使用通用对话框控件当然可以打开打印对话框, 不过要浪费更多的资源和增加了一个 OCX 部件。 而用 API 会高效。
声明:
Declare Function PRINTDLG Lib "comdlg32.dll" Alias _
"PrintDlgA" (pPrintdlg As PRINTDLG) As Long
Type PRINTDLG
lStructSize As Long
hwndOwner As Long
hDevMode As Long
hDevNames As Long
hdc As Long
flags As Long
nFromPage As Integer
nToPage As Integer
nMinPage As Integer
nMaxPage As Integer
nCopies As Integer
hInstance As Long
lCustData As Long
lpfnPrintHook As Long
lpfnSetupHook As Long
lpPrintTemplateName As String
lpSetupTemplateName As String
hPrintTemplate As Long
hSetupTemplate As Long
End Type
使用:
Private Sub Command1_Click()
Dim p As PRINTDLG
p.lStructSize = Len(p)
p.hwndOwner = Me.hWnd
p.nFromPage = 1
p.nToPage = 1
p.nMinPage = 1
p.nMaxPage = 1
p.nCopies = 1
x = PRINTDLG(p)
Printer.Print Text1.Text
End Sub
在打印字符串时自动换行
感谢 shijia 的代码测试。
其中 len1 为打印的宽度, Str 为打印的文本。
Do While Len(Str) > 0
str1 = Str
Do While len1 > 0 And Printer.TextWidth(str1) > len1
str1 = Left(str1, Len(str1) - 1)
Loop
Printer.Print str1 '打印
If Len(str1) = 0 Then Exit Do '不匹配
Str = Mid(Str, Len(Str1)+1) '截断!
Loop
让打印机只打印一行
在 Win95 下,只有在使用 EndDoc 或 NewPage 时,打印机才开始打印,而且每次都要换页。使用以下的方法,可以只打印一行,并且可以把打印机的控制字符也直接发到打印机。
注意:如果打印机无汉字库,不能输出中文。
Open "PRN" For Output As #1
Print #1, "一行"
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:30:01 | 显示全部楼层
改变 TreeView 的背景   

Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long

Private Declare Function GetWindowLong Lib "User32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long

Private Declare Function SetWindowLong Lib "User32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Const GWL_STYLE = -16&
Private Const TVM_SETBKCOLOR = 4381&
Private Const TVM_GETBKCOLOR = 4383&
Private Const TVS_HASLINES = 2&

Dim frmlastForm As Form

Private Sub Form_Load()
Dim nodX As Node
Set nodX = TreeView1.Nodes.Add(, , "R", "Root")
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "C1", "Child 1")
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "C2", "Child 2")
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "C3", "Child 3")
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "C4", "Child 4")
nodX.EnsureVisible
TreeView1.style = tvwTreelinesText ' Style 4.
TreeView1.BorderStyle = vbFixedSingle
End Sub

Private Sub Command1_Click()
Dim lngStyle As Long
Call SendMessage(TreeView1.hWnd, TVM_SETBKCOLOR, 0, ByVal RGB(255, 0, 0))
'改变背景到红色

lngStyle = GetWindowLong(TreeView1.hWnd, GWL_STYLE)
Call SetWindowLong(TreeView1.hWnd, GWL_STYLE, lngStyle - TVS_HASLINES)
Call SetWindowLong(TreeView1.hWnd, GWL_STYLE, lngStyle)
End Sub
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:30:39 | 显示全部楼层
建立可滚动的视区   
     
下面的范例演示如何建立可滚动的视区以滚动显示比视区大的图象
Private Sub HScroll1_Change()
Picture2.Left = -HScroll1.Value
End Sub

Private Sub VScroll1_Change()
Picture2.Top = -VScroll1.Value
End Sub

Private Sub Form_Resize()

With Picture1
.Height = Form1.Height
.Width = Form1.Width
End With

Picture1.Move 0, 0, ScaleWidth - VScroll1.Width, _
ScaleHeight - HScroll1.Height

Picture2.Move 0, 0

With HScroll1
.Top = Picture1.Height
.Left = 0
.Width = Picture1.Width
.Max = Picture2.Width - Picture1.Width
End With

With VScroll1
.Top = 0
.Left = Picture1.Width
.Height = Picture1.Height
.Max = Picture2.Height - Picture1.Height
End With

VScroll1.Visible = (Picture1.Height < Picture2.Height)
HScroll1.Visible = (Picture1.Width < Picture2.Width)

End Sub

Private Sub Form_Load()

Picture1.Move 0, 0, ScaleWidth - VScroll1.Width, _
ScaleHeight - HScroll1.Height

With Picture2
.AutoSize = True
.Picture = LoadPicture("d:\vbcode\examples\demos\banner.jpg")
.Move 0, 0
End With

With HScroll1
.Top = Picture1.Height
.Left = 0
.Width = Picture1.Width
End With

With VScroll1
.Top = 0
.Left = Picture1.Width
.Height = Picture1.Height
End With

HScroll1.Max = Picture2.Width - Picture1.Width
VScroll1.Max = Picture2.Height - Picture1.Height
' HScroll1.LargeChange = HScroll1.Max / 10
' VScroll1.LargeChange = VScroll1.Max / 10

VScroll1.Visible = (Picture1.Height < Picture2.Height)
HScroll1.Visible = (Picture1.Width < Picture2.Width)

End Sub
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:31:23 | 显示全部楼层
将程序从任务列表中隐藏   
将你的程序从Windows的系统任务列表中隐藏(即CTRL+ALT+DEL出来的框)


'复制以下代码到一模块中

Declarations
Public Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Public Declare Function GetCurrentProcess Lib "kernel32" () As Long
Public Declare Function RegisterServiceProcess Lib "kernel32" (ByVal dwProcessID As Long, ByVal dwType As Long) As Long
Public Const RSP_SIMPLE_SERVICE = 1
Public Const RSP_UNREGISTER_SERVICE = 0

'下面代码为隐藏
Public Sub MakeMeService()
Dim pid As Long
Dim reserv As Long
pid = GetCurrentProcessId()
regserv = RegisterServiceProcess(pid, RSP_SIMPLE_SERVICE)
End Sub

'恢复隐藏
Public UnMakeMeService()
Dim pid As Long
Dim reserv As Long
pid = GetCurrentProcessId()
regserv = RegisterServiceProcess(pid, RSP_UNREGISTER_SERVICE)
End Sub
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:32:08 | 显示全部楼层
禁止使用 Alt+F4 关闭窗口

Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long
Private Const MF_BYPOSITION = &H400&

Private Sub Form_Load()
Dim hwndMenu As Long
Dim c As Long
hwndMenu = GetSystemMenu(Me.hwnd, 0)

c = GetMenuItemCount(hwndMenu)

DeleteMenu hwndMenu, c - 1, MF_BYPOSITION

c = GetMenuItemCount(hwndMenu)
DeleteMenu hwndMenu, c - 1, MF_BYPOSITION

End Sub
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:33:11 | 显示全部楼层
取得和设置系统颜色   

取得和设置系统颜色
声明:
Public Const COLOR_SCROLLBAR = 0 '滚动条
Public Const COLOR_BACKGROUND = 1 '桌面背景
Public Const COLOR_ACTIVECAPTION = 2 '活动窗口标题
Public Const COLOR_INACTIVECAPTION = 3 '非活动窗口标题
Public Const COLOR_MENU = 4 '菜单
Public Const COLOR_WINDOW = 5 '窗口背景
Public Const COLOR_WINDOWFRAME = 6 '窗口框
Public Const COLOR_MENUTEXT = 7 '窗口文字
Public Const COLOR_WINDOWTEXT = 8 '3D 阴影 (Win95)
Public Const COLOR_CAPTIONTEXT = 9 '标题文字
Public Const COLOR_ACTIVEBORDER = 10 '活动窗口边框
Public Const COLOR_INACTIVEBORDER = 11 '非活动窗口边框
Public Const COLOR_APPWORKSPACE = 12 'MDI 窗口背景
Public Const COLOR_HIGHLIGHT = 13 '选择条背景
Public Const COLOR_HIGHLIGHTTEXT = 14 '选择条文字
Public Const COLOR_BTNFACE = 15 '按钮
Public Const COLOR_BTNSHADOW = 16 '3D 按钮阴影
Public Const COLOR_GRAYTEXT = 17 '灰度文字
Public Const COLOR_BTNTEXT = 18 '按钮文字
Public Const COLOR_INACTIVECAPTIONTEXT = 19 '非活动窗口文字
Public Const COLOR_BTNHIGHLIGHT = 20 '3D 选择按钮

Declare Function SetSysColors Lib "user32" Alias "SetSysColors" (ByVal nChanges As Long, lpSysColor As Long, lpColorValues As Long) As Long
Declare Function GetSysColor Lib "user32" Alias "GetSysColor" (ByVal nIndex As Long) As Long
使用:
Color=GetSysColors(COLOR_ACTIVECAPTION) '获得活动窗口标题颜色值

SetSysColors 1, COLOR_ACTIVECAPTION, RGB(255,0,0) '把活动窗口标题设置为红色
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-1-21 13:34:03 | 显示全部楼层
让窗体处于最前面
   
 
    应用SetWindowPos函数可以设置一个窗口的位置和状态,本例正是利用此函数来把一个窗体放在所有窗体之上,使之总是处于最前面。

  

  我们先来看看SetWindowPos函数的定义和参数:

  使用API函数之前必须先在程序中声明如下:
  Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

  其中各参数的意义如下表:

参数: 意义
hwnd Long,欲定位的窗口
hWndInsertAfter Long,窗口句柄。在窗口列表中,窗口hwnd会置于这个窗口句柄的后面
x,y Long,窗口新的x,y坐标
cx,cy Long,指定新的窗口宽度和高度
wFlags Long,包含了旗标的一个整数,是下列之一
返回值 Long,非零表示成功,零表示失败

  下面是部分wFlags参数和它们的意义:

参数  意义和使用方法  
SWP_DRAWFRAME  围绕窗口画一个框
SWP_HIDEWINDOW  隐藏窗口
SWP_NOACTIVATE  不激活窗口
SWP_NOMOVE  保持当前位置 (x和y设定将被忽略) &H2
SWP_NOREDRAW  窗口不自动重画
SWP_NOSIZE  保持当前大小 (cx和cy会被忽略) &H1
SWP_NOZORDER  保持窗口在列表的当前位置 (hWndInsertAfter将被忽略)
SWP_SHOWWINDOW 显示窗口 &H40
SWP_FRAMECHANGED 强迫一条WM_NCCALCSIZE消息进入窗口,即使窗口的大小没有改变

  函数的使用很简单,我们只须在Form_Load中加入如下语句即可:

  retValue = SetWindowPos(Me.hwnd, HWND_TOPMOST, Me.CurrentX, Me.CurrentY, 300, 300, SWP_SHOWWINDOW)

  这样窗体就能保持在所有窗体的前面了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2021-4-12 02:54

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表