不好意思,标题是为了让大仙们关注一下:同时也借助这个论坛的热度,希望能最快的得到解决方案。我先描述一下我在项目中遇到的这个问题的情况:
环境:windows 2003+VB6.0+SQL Server 2005.
项目产品结构是这样的,程序启动后有个主窗体,然后可以通过点击各种菜单在弹出各个子窗体(说穿了就是MS的word那样的东西,新建就会弹出一个非模态的窗体,这个窗体上的菜单是用MenuEditor+ToolBar做的,现在我们看来他是贼落后的架构,因为上述组件基本只能在design阶段来添加好各类菜单,不利于在插件里操作。)我现在的任务就是要重构这个结构,使得在插件里可以动态创建菜单和ToolBar的按钮。菜单的重构用一堆API结合subclass子类化技术已经搞定了,现在在搞ToolBar的过程中出现问题了。具体代码如下:
Dim lRetCode As Long
Dim tButton(0) As TBBUTTON
Dim bytCaption() As Byte
Dim strCaption As String
Dim lButtonCount As Long Dim oToolBar As MSComctlLib.ToolBar '取得form窗体上的ToolBar控件实例
Set oToolBar = GetFormToolBar(Me) 'ToolBarMsgHwnd函数就是一个获取ToolBar真正的窗体句柄(就是一个FindWindow语句)
lButtonCount = SendMessage(ToolBarMsgHwnd(oToolBar), TB_BUTTONCOUNT, 0, 0) With tButton(0)
.dwData = 0
.fsState = Enu_ToolButtonStateConst.TBSTATE_ENABLED
.fsStyle = Enu_ToolButtonStyleConst.BTNS_BUTTON
.idCommand = 10 ^ 3 + lButtonCount
bytCaption = "Button" & lButtonCount
strCaption = "Button" & lButtonCount
'这句有时有问题。
.iString = StrPtr(StrConv(strCaption, vbFromUnicode))
End With
'WM_USER+20=TB_ADDBUTTONS 添加一个按钮
lRetCode = SendMessage(ToolBarMsgHwnd(oToolBar), WM_USER + 20, 1, tButton(0)) 1、当ToolBar在Standard Exe工程里的时候,上面代码老正常了,没有问题!生成的按钮的文本也是“Button”+数字的形式
2、当ToolBar在ActiveX dll工程里的时候,就不正常了,按钮也能生成,但是其文本变成了这样的形式:36639386#1044C,不知道为啥?
3、当ToolBar传递到另外一个ActiveX DLL工程里的一个类里,然后这个类再把ToolBar传递到另外一个类,就会出现上面那句SendMessage的返回值为1(也就是消息发送成功了),但是ToolBar上却并没有增加按钮。上面罗罗嗦嗦的可能并不一定描述清楚了问题:下面用自然语言结构给大家描述一下:'/* MainForm.frmprivate sub command1_Click(...)
dim frmChild as new ChildForm
frmchild.show vbmodaless
end sub
'/* ChildForm.frm
private withevents m_oSubClassObject as TlSubClass.CSubClass
private objPlugInDelegate as PlugInDelegateprivate sub ChildForm_Load(...)
set m_oSubClassObject =new TLSubClass.CSubClass
'/* 把本窗体传进去进行子类化,并且对当前Form上的菜单及按钮进行元数据建立
m_oSubClassObject.HostForm=me
'/* 初始化插件代理
set objPlugInDelegate=CreateObject.... '/* 这里会创建一个插件实例
set objPlugIn=CreateObject("PlugInList.Item1")
objPlugIn.show objPlugInDelegate
end subprivate sub m_oSubClassObject_MenuBarClick(tool as string,bCancel as boolean)
objPlugInDelegate.FireMenuBarClick tool,bCancel
end sub'/* TlSubClass.CSubClass
private m_oHostForm as object
public property Let HostForm(frmParent as object)
set m_oHostForm=frmParent
'/* 子类化的代码及菜单按钮的元数据建立代码,这里就省略了。
end property
情况就是这样的,希望有人能帮上忙~~
而且个人感觉这个在不同情况下执行成功,但是结果却不一样,到底是MS问题了,还是我使用API的问题呢?希望大仙们解释一下~3ks
环境:windows 2003+VB6.0+SQL Server 2005.
项目产品结构是这样的,程序启动后有个主窗体,然后可以通过点击各种菜单在弹出各个子窗体(说穿了就是MS的word那样的东西,新建就会弹出一个非模态的窗体,这个窗体上的菜单是用MenuEditor+ToolBar做的,现在我们看来他是贼落后的架构,因为上述组件基本只能在design阶段来添加好各类菜单,不利于在插件里操作。)我现在的任务就是要重构这个结构,使得在插件里可以动态创建菜单和ToolBar的按钮。菜单的重构用一堆API结合subclass子类化技术已经搞定了,现在在搞ToolBar的过程中出现问题了。具体代码如下:
Dim lRetCode As Long
Dim tButton(0) As TBBUTTON
Dim bytCaption() As Byte
Dim strCaption As String
Dim lButtonCount As Long Dim oToolBar As MSComctlLib.ToolBar '取得form窗体上的ToolBar控件实例
Set oToolBar = GetFormToolBar(Me) 'ToolBarMsgHwnd函数就是一个获取ToolBar真正的窗体句柄(就是一个FindWindow语句)
lButtonCount = SendMessage(ToolBarMsgHwnd(oToolBar), TB_BUTTONCOUNT, 0, 0) With tButton(0)
.dwData = 0
.fsState = Enu_ToolButtonStateConst.TBSTATE_ENABLED
.fsStyle = Enu_ToolButtonStyleConst.BTNS_BUTTON
.idCommand = 10 ^ 3 + lButtonCount
bytCaption = "Button" & lButtonCount
strCaption = "Button" & lButtonCount
'这句有时有问题。
.iString = StrPtr(StrConv(strCaption, vbFromUnicode))
End With
'WM_USER+20=TB_ADDBUTTONS 添加一个按钮
lRetCode = SendMessage(ToolBarMsgHwnd(oToolBar), WM_USER + 20, 1, tButton(0)) 1、当ToolBar在Standard Exe工程里的时候,上面代码老正常了,没有问题!生成的按钮的文本也是“Button”+数字的形式
2、当ToolBar在ActiveX dll工程里的时候,就不正常了,按钮也能生成,但是其文本变成了这样的形式:36639386#1044C,不知道为啥?
3、当ToolBar传递到另外一个ActiveX DLL工程里的一个类里,然后这个类再把ToolBar传递到另外一个类,就会出现上面那句SendMessage的返回值为1(也就是消息发送成功了),但是ToolBar上却并没有增加按钮。上面罗罗嗦嗦的可能并不一定描述清楚了问题:下面用自然语言结构给大家描述一下:'/* MainForm.frmprivate sub command1_Click(...)
dim frmChild as new ChildForm
frmchild.show vbmodaless
end sub
'/* ChildForm.frm
private withevents m_oSubClassObject as TlSubClass.CSubClass
private objPlugInDelegate as PlugInDelegateprivate sub ChildForm_Load(...)
set m_oSubClassObject =new TLSubClass.CSubClass
'/* 把本窗体传进去进行子类化,并且对当前Form上的菜单及按钮进行元数据建立
m_oSubClassObject.HostForm=me
'/* 初始化插件代理
set objPlugInDelegate=CreateObject.... '/* 这里会创建一个插件实例
set objPlugIn=CreateObject("PlugInList.Item1")
objPlugIn.show objPlugInDelegate
end subprivate sub m_oSubClassObject_MenuBarClick(tool as string,bCancel as boolean)
objPlugInDelegate.FireMenuBarClick tool,bCancel
end sub'/* TlSubClass.CSubClass
private m_oHostForm as object
public property Let HostForm(frmParent as object)
set m_oHostForm=frmParent
'/* 子类化的代码及菜单按钮的元数据建立代码,这里就省略了。
end property
情况就是这样的,希望有人能帮上忙~~
而且个人感觉这个在不同情况下执行成功,但是结果却不一样,到底是MS问题了,还是我使用API的问题呢?希望大仙们解释一下~3ks
我是初步找到原因了,就是只要上述代码在ToolBar不可见时,执行是成功的,但是没效果。
现在重现此现象的条件是:
有个Form上面有个ToolBar,然后你把上面的那个创建按钮的代码放在Form_Load里执行就看不到添加的按钮。如果是放在按钮里执行(Form已经显示出来了),就可以。继续等待大虾。
可以在form_activate里面添加(定义一个变量作标识,已经添加了按钮就不再添加)
1、如果ToolBar上有下拉按钮,还没办法取得那个下拉按钮的句柄,所以也就没办法截获那个下拉后的菜单的点击消息,因此也就没办法向插件里抛事件。目前也只能重构到此程度了,看到vbAccelerator里的代码后,发现它的ToolBar全是自己重写的,那个下拉菜单也是自己创建的(CreatePopupMenu),然后在弹出时,进行HOOK,还是蛮麻烦的,所以放弃了那个方法。在此多谢各位的顶力帮助。
多此一举!还以为你有特殊需求呢。