VB6中用Win32 API创建工具栏:解决按钮文本重复问题
解决VB6中Win32 API工具栏按钮文本重复问题
问题原因
出现第二个按钮文本重复的核心原因有两个:
- TBBUTTON结构体定义错误:如果结构体的成员顺序、大小与Win32官方定义不符,会导致传递给
TB_ADDBUTTONSA的参数错位,使得iString(文本索引)未被正确设置。 - 字符串传递方式错误:直接传递字符串字面量给
TB_ADDSTRINGA时,VB6会将字符串临时分配在栈上,SendMessage返回后栈内存被回收,工具栏控件后续读取时会获取到无效内容,导致文本索引指向错误。
修正后的代码
首先确保结构体定义正确,然后调整字符串传递和索引获取逻辑:
'Form1 Option Explicit ' 严格按照Win32 API定义TBBUTTON结构体 Private Type TBBUTTON iBitmap As Long idCommand As Long fsState As Byte fsStyle As Byte bReserved(1) As Byte ' 保留字节,占2个Byte dwData As Long iString As Long End Type Private Type TBADDBITMAP hInst As Long nID As Long End Type Private hWndTb As Long Private tbb As TBBUTTON Private tbab As TBADDBITMAP Private Const WS_EX_CLIENTEDGE As Long = &H200& Private Const WS_CHILD As Long = &H40000000 Private Const WS_VISIBLE As Long = &H10000000 Private Const TBSTYLE_TOOLTIPS As Long = &H80 Private Const TBSTYLE_BUTTON As Long = &H0 Private Const TBSTATE_ENABLED As Long = &H4 Private Const HINST_COMMCTRL As Long = (-1) Private Const IDB_STD_SMALL_COLOR As Long = &H1 Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Const TB_BUTTONSTRUCTSIZE As Long = &H402 Private Const TB_ADDBITMAP As Long = &H407 Private Const TB_ADDSTRINGA As Long = &H403 Private Const TB_ADDBUTTONSA As Long = &H408 Private Const TB_AUTOSIZE As Long = &H410 Private Sub Form_Load() Dim strText1 As String, strText2 As String Dim txtIdx1 As Long, txtIdx2 As Long Show ' 创建工具栏窗口 hWndTb = CreateWindowEx(WS_EX_CLIENTEDGE, "ToolbarWindow32", "", WS_CHILD Or WS_VISIBLE Or TBSTYLE_TOOLTIPS, 0, 0, 100, 100, Me.hwnd, 1001, App.hInstance, ByVal 0&) ' 设置按钮结构体大小(必须与定义的TBBUTTON大小一致) SendMessage hWndTb, TB_BUTTONSTRUCTSIZE, Len(tbb), 0 ' 添加标准小图标位图 tbab.hInst = HINST_COMMCTRL tbab.nID = IDB_STD_SMALL_COLOR SendMessage hWndTb, TB_ADDBITMAP, 0, ByVal VarPtr(tbab) ' 准备NULL结尾的ANSI字符串,使用变量确保内存有效 strText1 = "Text1" & vbNullChar strText2 = "Text2" & vbNullChar ' 添加字符串并获取返回的索引(避免手动设置索引出错) txtIdx1 = SendMessage(hWndTb, TB_ADDSTRINGA, 0, ByVal StrPtr(strText1)) txtIdx2 = SendMessage(hWndTb, TB_ADDSTRINGA, 0, ByVal StrPtr(strText2)) ' 添加第一个按钮 With tbb .iBitmap = 0 .idCommand = 101 .fsState = TBSTATE_ENABLED .fsStyle = TBSTYLE_BUTTON .iString = txtIdx1 .dwData = 0 End With SendMessage hWndTb, TB_ADDBUTTONSA, 1, ByVal VarPtr(tbb) ' 添加第二个按钮 With tbb .iBitmap = 1 .idCommand = 102 .fsState = TBSTATE_ENABLED .fsStyle = TBSTYLE_BUTTON .iString = txtIdx2 .dwData = 0 End With SendMessage hWndTb, TB_ADDBUTTONSA, 1, ByVal VarPtr(tbb) Form_Resize End Sub Private Sub Form_Resize() SendMessage hWndTb, TB_AUTOSIZE, 0, 0 End Sub
关键修正点
- 结构体定义:严格对齐Win32的
TBBUTTON结构,包含bReserved保留字节,确保成员顺序和大小正确,避免参数传递错位。 - 字符串传递:使用字符串变量并追加
vbNullChar生成标准NULL结尾的ANSI字符串,通过StrPtr传递字符串地址,保证内存有效性。 - 索引获取:捕获
TB_ADDSTRINGA的返回值作为文本索引,而非手动硬编码0/1,确保索引与实际添加的字符串一一对应。
内容的提问来源于stack exchange,提问作者Carlos Domingo
相关产品推荐
相关产品推荐

