说起工具栏我们都不会陌生为了方便起见,首先看一下图:标示的地方就是工具栏,好像是一个一个的位图文件组成的一样,其实那就是位图组成的,只不过是一组连续在一起的位图(而且是windows自己定义好的,我们只管拿来使用就行了)。
对于工具栏的实现我大概分为如下几步:
菜单 | IDR_MENU1 |
图标 | IDI_ICON1 |
字符串表 | STRINGTABLE |
改变工具栏大小 | _Resize |
消息处理过程 | _ProcWinMain |
窗口模板 | 主函数
_WinMain |
下面来看一下编写资源文件的时候遇见的问题及心得体会:这次编写资源文件依然用的是ResEdit工具,还记得在编写状态栏的时候创建资源文件的时候创建的是一个对话框,然后在对话框中实现的状态栏,但是工具栏则不能在对话中发挥其所有功能,如果在对话框中使用工具栏则有一些工具栏的高级功能无法实现,因为当工具栏向父窗口发送WM_NOTIFY消息时,父窗口必须根据消息处理情况返回TRUE或FALSE,然后工具栏会根据,父窗口的不同返回值做出不同的动作,因此,如果没有返回值那么工具栏就无法完成正确的动作,然而对话框过程的返回值只会用来通知“对话框管理器”是否处理了相关消息,返回值并不会被对话框管理器返回到工具栏子窗口(工具栏也是一个子窗口)去,所以对话框中无法使用工具栏的高级功能(可以添加删除按钮),但是如果只是为了使用工具栏的按钮当做菜单快捷按钮的话可以使用对画框,因为此时只需要处理WM_COMMAND消息,此消息并不需要返回值。如果看罗云斌老师的资源文件的时候你会发现,资源文件里面其实也包含对话框文件,但是并没有使用,我感觉可以去掉(我写的时候就没写。。懒。。),此外关于资源文件就没有什么问题了。下面看一下资源文件代码:
// Generated by ResEdit 1.6.6
// Copyright (C) 2006-2015
// http://www.resedit.net
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
//
// Menu resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDR_MENU1 MENU
{
POPUP "文件(&F)"
{
MENUITEM "新文件(N)...", IDM_NEW
MENUITEM "开文件(&O)...", IDM_OPEN
MENUITEM "保存文件(&S)", IDM_SAVE
MENUITEM SEPARATOR
MENUITEM "页面设置(&A)", IDM_PAGESETUP
MENUITEM "打印(&P)", IDM_PRINT
MENUITEM SEPARATOR
MENUITEM "退出(&X)", IDM_EXIT
}
POPUP "编辑(&E)"
{
MENUITEM "剪切(&U)", IDM_CUT
MENUITEM "拷贝(&C)", IDM_COPY
MENUITEM "粘贴(&P)", IDM_PASTE
MENUITEM SEPARATOR
MENUITEM "查找字符串(&S)", IDM_FIND
MENUITEM "替换字符串(&R)", IDM_REPLACE
}
POPUP "帮助(&H)"
{
MENUITEM "帮助(&H)", IDM_HELP
}
}
//
// String Table resources
//
LANGUAGE 1023, 63
STRINGTABLE
{
IDM_NEW "新建文件"
IDM_OPEN "打开文件"
IDM_SAVE "保存文件"
IDM_PAGESETUP "页面设置"
IDM_PRINT "打印"
IDM_COPY "拷贝"
IDM_CUT "剪切"
IDM_PASTE "粘贴"
IDM_FIND "查找"
IDM_REPLACE "替换"
IDM_HELP "帮助"
}
//
// Icon resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDI_ICON1 ICON "F:\\ResEdit-win32\\23\\icon8.ico"
下面来看一下在编写实现工具栏的时候遇见的一些疑问及心得:
说实话在刚看到实现工具栏的字符提示功能和定制工具栏功能时,感觉太陌生了,好多的结构体,还有一些新的用法,当时头就大了,等你把每一个结构体每一个API函数搞懂以后再回过头来看一下,其实程序还是很简单的,只不过新的知识不少,其它的还是老生常谈的内容。在子函数_Resize中是为了改变工具栏的大小,然后在调节编辑区域的大小,改变工具栏的大小只需要向工具栏发送TB_AUTOSIZE消息就可以了,它会自动调节工具栏的大小,改变了工具栏的大小,也要适当的调整编辑区的大小,这个需要自己来实现,依然要涉及到GetClientRect和GetWindowRect这两个计算大小就要出现的烦人的函数(我在写状态栏的时候也仔细介绍过,还写了一篇关于这两个函数的博客,虽然不好理解,容易忘,但是多看看,多写写画画,还是可以理解记忆的),这个问题不再多说。
下面就是怎样在工具栏中显示提示字符串了,关于这个问题,我参考了一下书籍,当要显示工具提示信息时,工具提示控件(当创建工具栏的时候风格里包含TBSTYLE_TOOLTIPS的时候,CreateToolbarEx函数会自动创建一个工具提示控件Tool Tip 并为工具栏上的每个按钮注册提示文本,当鼠标指针移动到按钮上停留片刻的时候,工具栏提示信息会自动显示出来)向父窗口发送TTN_NEEDTEXT通知码(这个通知码是放在NMHDR结构中的,并且windows为每一个需要附带其他数据的WM_NOTIFY消息定义的不同的结构中都包含一个NMHDR结构),父窗口将需要显示的提示字符放在TOOLTIPTEXT结构中并返回以后,工具提示控件就会把它显示出来,首先将字符串包含在资源中,这时将TOOLTIPTEXT结构的hInst字段设置为字符串ID,其他字段保持为NULL,工具提示控件会自己使用LoadString函数装入字符串(这只使用的一中比较简便的方法,因为字符串ID和菜单的命令ID为一样的(一一对应)并且在NMHDR结构中的idFrom字段中返回了命令ID)如下代码:
.elseif eax == WM_NOTIFY ;判断如果为工具栏发送的消息WM_NOTIFY
mov ebx,lParam ;将WM_NOTIFY消息的lParam 地址传递给ebx
.if [ebx + NMHDR.code] == TTN_NEEDTEXT ;判断通知码是否为lParam指向的 TOOLTIPTEXT结构中的NMHDR结构中的.code元素
assume ebx:ptr TOOLTIPTEXT ;将ebx设定为结构TOOLTIPTEXT的指针
mov eax,[ebx].hdr.idFrom ;将命令ID传递到eax
mov [ebx].lpszText,eax ;把命令ID传递给TOOLTIPTEXT结构的lpszText 字段
push hInstance ;将包含字符串资源的模块句柄压栈
pop [ebx].hInst ;将包含字符串资源的模块句柄出栈并传递给 TOOLTIPTEXT结构中的hInst字段
assume ebx:nothing ;取消开始的设定
上面就是显示提示字符的功能代码涉及到的一些陌生的结构,详细介绍一下.
下面就来介绍另一个比较有意思的功能:定制工具栏
什么叫定制工具栏?其实就是可以自定义的添加删除已经定义好的按钮(我自己的理解),说到定制工具栏那么首先应该想到的就是在用CreateToolbarEX函数创建工具栏的时候需要指定CCS_ADJUSTABLE风格(就如同窗口风格一样只不过是工具栏专属的风格),为了实现双击工具栏的空白处可以弹出一个可以添加自定义按钮的“自定义工具栏”,首先就需要知道通知码(包含在特定的结构体中)TBN_QUERYINSERT,TBN_QUERYDELETE,TBN_GETBUTTONINFO,从字面的意思就可以知道什么意思(英文),说道这几个通知码以及实现的功能,就需要知道另一个新的结构TBNOTIFY(具体内容看下面介绍),有一个问题就是怎么一会是这个结构一会又变成那个结构了(其实我自己感觉这样考虑比较好:对于那个NMHDR结构中在每个指定的结构中都会存在,而且NMHDR结构中的.code
通知码才是关键,首先判断通知码是什么,然后再根据不同的通知码指向不同的功能结构体,然后再做其它操作,这样理解就很容易理解了),下面就是怎么将在自定义窗口中将已经定义的按钮全部显示出来了:当通知码TBN_GETBUTTONINFO时,需要用到的结构体就是TBNOTIFY,看下面代码:
.elseif [ebx + NMHDR.code] == TBN_GETBUTTONINFO ;判断通知码是否为
TBN_GETBUTTONINFO
assume ebx:ptr TBNOTIFY ;如果通知码是上面的,那么设置ebx为结构 TBNOTIFY的指针
mov eax,[ebx].item ;将TBNOTIFY结构的Item字段传递给eax
.if eax < NUM_BUTTONS ;比较按钮的索引值与NUM_BUTTONS的值(也就是16)
mov ecx,sizeof TBBUTTON ;将TBBUTTTON结构的长度传递给ecx
mul ecx ;eax=eax*ecx
add eax,offset stToolbar ;eax就是下一个按钮内容的地址
invoke RtlMoveMemory,addr [ebx].tbButton,eax,sizeof TBBUTTON ;将以eax未开始地址的一段内
存 中的内容拷贝到[ebx].tbButton字段中
invoke LoadString,hInstance,[ebx].tbButton.idCommand,addr @szBuffer,sizeof @szBuffer ;将TBBUTTON结构中的idCommand字段拷贝到缓冲区@szBuffer中
lea eax,@szBuffer ;将缓冲区@szBuffer的内容传递给eax
mov [ebx].pszText,eax ;将eax的内容传递给TBNOTIFY结构的
pszText字段(及按钮的提示字符串)
invoke lstrlen,addr @szBuffer ;测量缓冲区的大小
mov [ebx].cchText,eax ;将缓冲区的大小(在eax中存放)传递给TNNOTIFY结
构的cchText字段
assume ebx:nothing
;取消设定(和开头的assume语句对应)
mov eax,TRUE ;返回TRUE
ret ;返回调用处
至此自定义工具栏的功能得以实现,一共出现了3个新的结构体在这里。下面看一下程序源代码:
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include comctl32.inc
includelib comctl32.lib
IDI_ICON1 equ 101
IDR_MENU1 equ 102
IDM_NEW equ 40000
IDM_OPEN equ 40001
IDM_SAVE equ 40002
IDM_PAGESETUP equ 40003
IDM_PRINT equ 40004
IDM_COPY equ 40005
IDM_CUT equ 40006
IDM_PASTE equ 40007
IDM_FIND equ 40008
IDM_REPLACE equ 40009
IDM_HELP equ 40010
IDM_EXIT equ 40011
ID_TOOLBAR equ 1
ID_EDIT equ 2
.data?
hInstance dd ?
hWinMain dd ?
hMenu dd ?
hWinToolbar dd ?
hWinEdit dd ?
.const
szClass db ‘EDIT‘,0
szClassName db ‘ToolbarExample‘,0
szCaptionMain db ‘工具栏示例‘,0
szCaption db ‘命令消息‘,0
szFormat db ‘收到 WM_COMMAND 消息,命令ID:%d‘,0
stToolbar equ this byte
TBBUTTON <STD_FILENEW,IDM_NEW,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <STD_FILEOPEN,IDM_OPEN,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <STD_FILESAVE,IDM_SAVE,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
TBBUTTON <STD_PRINTPRE,IDM_PAGESETUP,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <STD_PRINT,IDM_PRINT,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
TBBUTTON <STD_COPY,IDM_COPY,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <STD_CUT,IDM_CUT,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <STD_PASTE,IDM_PASTE,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
TBBUTTON <STD_FIND,IDM_FIND,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <STD_REPLACE,IDM_REPLACE,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
TBBUTTON <STD_HELP,IDM_HELP,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
NUM_BUTTONS equ 16
.code
_Resize proc
LOCAL @stRect:RECT,@stRect1:RECT
invoke SendMessage,hWinToolbar,TB_AUTOSIZE,0,0
invoke GetClientRect,hWinMain,addr @stRect
invoke GetWindowRect,hWinToolbar,addr @stRect1
mov eax,@stRect1.bottom
sub eax,@stRect1.top
mov ecx,@stRect.bottom
sub ecx,eax
invoke MoveWindow,hWinEdit,0,eax,@stRect.right,ecx,TRUE
ret
_Resize endp
_ProcWinMain proc uses ebx edi esi hWnd ,uMsg,wParam,lParam
LOCAL @szBuffer[128]:byte
mov eax,uMsg
.if eax == WM_CLOSE
invoke PostMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.elseif eax == WM_CREATE
mov eax,hWnd
mov hWinMain,eax
invoke CreateWindowEx,WS_EX_CLIENTEDGE,addr szClass,NULL,WS_CHILD or WS_VISIBLE or ES_MULTILINE or\
ES_WANTRETURN or WS_VSCROLL or ES_AUTOHSCROLL,0,0,0,0,hWnd,ID_EDIT,hInstance,NULL
mov hWinEdit,eax
invoke CreateToolbarEx,hWinMain,WS_VISIBLE or WS_CHILD or TBSTYLE_FLAT or TBSTYLE_TOOLTIPS or\
CCS_ADJUSTABLE,ID_TOOLBAR,0,HINST_COMMCTRL,IDB_STD_SMALL_COLOR,offset stToolbar,\
NUM_BUTTONS,0,0,0,0,sizeof TBBUTTON
mov hWinToolbar,eax
call _Resize ;注意此处作者用的是Call而并非是invoke
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax == IDM_EXIT
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
.elseif ax != ID_EDIT
invoke wsprintf,addr @szBuffer,addr szFormat,wParam
invoke MessageBox,hWnd,addr @szBuffer,addr szCaption,MB_OK or MB_ICONINFORMATION
.endif
.elseif eax == WM_SIZE
call _Resize
.elseif eax == WM_NOTIFY
mov ebx,lParam
.if [ebx + NMHDR.code] == TTN_NEEDTEXT
assume ebx:ptr TOOLTIPTEXT
mov eax,[ebx].hdr.idFrom
mov [ebx].lpszText,eax
push hInstance
pop [ebx].hInst
assume ebx:nothing
.elseif ([ebx + NMHDR.code] == TBN_QUERYINSERT) || ([ebx + NMHDR.code] == TBN_QUERYDELETE)
mov eax,TRUE
ret
.elseif [ebx + NMHDR.code] == TBN_GETBUTTONINFO
assume ebx:ptr TBNOTIFY
mov eax,[ebx].iItem
.if eax < NUM_BUTTONS
mov ecx,sizeof TBBUTTON
mul ecx
add eax,offset stToolbar
invoke RtlMoveMemory,addr [ebx].tbButton,eax,sizeof TBBUTTON
invoke LoadString,hInstance,[ebx].tbButton.idCommand,addr @szBuffer,sizeof @szBuffer
lea eax,@szBuffer
mov [ebx].pszText,eax
invoke lstrlen,addr @szBuffer
mov [ebx].cchText,eax
assume ebx:nothing
mov eax,TRUE
ret
.endif
.endif
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
_ProcWinMain endp
_WinMain proc
local @stWndClass:WNDCLASSEX
local @stMsg:MSG
invoke
InitCommonControls
invoke
GetModuleHandle,NULL
mov hInstance,eax
invoke
LoadMenu,hInstance,IDR_MENU1
mov hMenu,eax
invoke
RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
invoke
LoadIcon,hInstance,IDI_ICON1
mov @stWndClass.hIcon,eax
mov @stWndClass.hIconSm,eax
invoke
LoadCursor,0,IDC_ARROW
mov @stWndClass.hCursor,eax
push hInstance
pop @stWndClass.hInstance
mov @stWndClass.cbSize,sizeof WNDCLASSEX
mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
mov @stWndClass.lpfnWndProc,offset _ProcWinMain
mov @stWndClass.hbrBackground,COLOR_BTNFACE+1
mov @stWndClass.lpszClassName,offset szClassName
invoke
RegisterClassEx,addr @stWndClass
invoke
CreateWindowEx,NULL,\
offset szClassName,offset szCaptionMain,\
WS_OVERLAPPEDWINDOW,\
CW_USEDEFAULT,CW_USEDEFAULT,700,500,\
NULL,hMenu,hInstance,NULL
mov hWinMain,eax
invoke
ShowWindow,hWinMain,SW_SHOWNORMAL
invoke
UpdateWindow,hWinMain
.while
TRUE
invoke
GetMessage,addr @stMsg,NULL,0,0
.break
.if eax == 0
invoke
TranslateMessage,addr @stMsg
invoke
DispatchMessage,addr @stMsg
.endw
ret
_WinMain endp
start:
call _WinMain
invoke
ExitProcess,NULL
end start
下面来介绍一下新的结构体和一些陌生的的API函数:
TBBUTTON STRUCT
iBitmap DWORD ? ;按钮使用的位图编号
idCommand DWORD ? ;按钮按下时在WM_COMMAND中使用的ID
fsState BYTE ? ;按钮的状态
fsStyle BYTE ? ;按钮的风格
_wPadl WORD ? ;
dwData DWORD ? ;自定义数据
iString DWORD ? ;按钮字符串索引
TBBUTTON ENDS
- iBitmap
-
按钮图像的从零开始的索引。
- idCommand
-
命令标识符相关的按钮。这个标识符中使用WM_COMMAND消息当按钮选择。
- fsState
-
按钮状态标志。它可以结合下表中列出的值。状态 描述
TBSTATE_CHECKED
按钮有TBSTYLE_CHECKED风格和被按下。
TBSTATE_ELLIPSES
按钮显示省略号(…)如果文本不符合大小的按钮。这种风格是独一无二的Windows CE嵌入。
TBSTATE_ENABLED
按钮接受用户输入。一个按钮没有这个国家不接受用户输入,并暗了下来。
TBSTATE_HIDDEN
按钮是不可见的,不能接收用户的输入。
TBSTATE_HIGHLIGHTED
突出显示的按钮。
TBSTATE_INDETERMINATE
这个按钮是暗了下来。
TBSTATE_PRESSED
这个按钮被按下。
TBSTATE_WRAP
后面的按钮有一个换行符。按钮也必须TBSTATE_ENABLED状态。
- fsStyle
-
按钮的风格。它可以是一个按钮样式的组合中列出的值控制方式.
- dwData
-
指定一个应用程序定义的值。
- iString
-
按钮的从零开始的索引的字符串。
TBADDBITMAP STRUCT
hInst DWORD ? ;包含位图的模块实例句柄
nID DWORD ? ;位图的资源ID
TBADDBITMAP ENDS
hInst
-
处理模块实例可执行文件,它包含一个位图资源。您可以将系统定义的位图按钮添加到列表通过指定HINST_COMMCTRL hInst成员和成员以下值之一的国家免疫日。价值 描述
IDB_STD_LARGE_COLOR
增加大,颜色标准的位图。
IDB_STD_SMALL_COLOR
添加小,颜色标准的位图。
IDB_VIEW_LARGE_COLOR
增加大,颜色查看位图。
IDB_VIEW_SMALL_COLOR
添加小,颜色查看位图。
- nID
-
位图资源的资源标识符包含按钮图像。如果hInst为空,该参数必须包含按钮图像位图的句柄。Windows CE头文件嵌入提供以下值作为标准和查看位图索引。
价值 描述
STD_COPY
指定复制图像。
STD_CUT
指定的图像。
STD_DELETE
指定删除图片。
STD_FILENEW
指定新文件的图像。
STD_FILEOPEN
指定打开的文件的图像。
STD_FILESAVE
指定保存文件的图像。
STD_FIND
指定找到图像。
STD_HELP
指定图像的帮助。
STD_PASTE
指定了粘贴图片。
STD_PRINT
指定打印图像。
STD_PRINTPRE
指定打印预览图像。
STD_PROPERTIES
指定属性的形象。
STD_REDOW
指定了重做形象。
STD_REPLACE
指定替代的形象。
STD_UNDO
指定了复原图像。
VIEW_DETAILS
指定视图细节图像。
VIEW_LARGEICONS
指定视图大图标形象。
VIEW_LIST
指定视图列表图片。
VIEW_SMALLICONS
指定视图小图标形象。
VIEW_SORTDATE
指定按日期排序的图像。
VIEW_SORTNAME
指定图像的名字。
VIEW_SORTSIZE
指定按大小排序的图像。
VIEW_SORTTYPE
指定排序类型的形象。
TOOLTIPTEXT STRUCT
hdr NMHDR <> ;头部位置是一个NMHDR结构
lpszText DWORD ? ; 工具提示字符串指针
szText BYTE 80 dup (?) ;工具提示字符串缓冲区
hInst DWORD ? ;包含字符串资源的模块句柄
uFlags DWORD ? ;标志
TOOLTIPTEXT ENDS
TBNOTIFY STRUCT
hdr NMHDR <> ;头部也是一个NMHDR结构
iTem DWORD ? ;按钮的位置索引
tbButton TBBUTTON <> ;包含按钮信息的TBBUTTON结构
cchText DWORD ? ;pszText中字符串的长度
pszText DWORD ? ;按钮的说明字符串
TBNOTIFY ENDS
下面看一下陌生的API函数
RtlMoveMemory()
功能:
从指定内存中复制内存至另一内存里.简称:复制内存,与CopyMemory相同
原型:
VOID RtlMoveMemory(
VOID UNALIGNED *Destination,
const VOID UNALIGNED *Source,
SIZE_T Length
);
参数:
Destination :指向移动目的地址的指针。
Source :指向要复制的内存地址的指针。
Length :指定要复制的字节数。
返回值:无
LoadString()
功能:
从
资源 里加载字符串资源到CString对象里。
原型:
WINUSERAPI int WINAPI LoadStringA(
__in_opt HINSTANCE hInstance,
__in UINT uID,
__out_ecount(cchBufferMax) LPSTR lpBuffer,
__in int nBufferMax);
参数:
参数1: hInstance是应用程序实例句柄。
参数2: uID是资源中的字符串编号。
参数3: lpBuffer是接收从资源里拷贝字符串出来的缓冲区。
参数4: nBufferMax是指明缓冲的大小。
返回值:
如果函数成功,返回值是TCHARs复制到缓冲区的数量,不包括终止NULL字符
CraeteToolbarEx()
功能:
这个函数创建一个工具栏窗口,并将指定的按钮添加到工具栏。
原型:
HWND CreateToolbarEx(
HWND hwnd,
DWORD ws,
UINT wID,
int nBitmaps,
HINSTANCE hBMInst,
UINT wBMID,
LPCTBBUTTON lpButtons,
int iNumButtons,
int dxButton,
int dyButton,
int dxBitmap,
int dyBitmap,
UINT uStructSize
);
参数:
hwnd
工具栏的父窗口句柄。
ws
在指定窗口工具栏风格。该参数必须指定至少WS_CHILD风格。
wID
工具栏的控制标识符。
nBitmaps
的按钮图像中包含指定的位图hBMInst wBMID。
hBMInst
处理模块实例包含位图资源的可执行文件。
wBMID
位图资源的资源标识符。如果hBMInst为空,该参数必须是一个有效的位图句柄。
lpButtons
长指向数组的指针TBBUTTON结构包含按钮添加到工具栏的信息。
iNumButtons
按钮添加到工具栏的数量。
dxButton
指定宽度,以像素为单位,按钮添加到工具栏。
dyButton
指定高度,以像素为单位的按钮添加到工具栏。
dxBitmap
指定宽度,以像素为单位,按钮添加到工具栏中的按钮图像。
dyBitmap
指定高度,以像素为单位的图像添加到工具栏中的按钮的按钮。
uStructSize
无符号整数包含TBBUTTON结构的大小。
返回值:
工具栏显示成功的窗口句柄。零表示失败
Lstrlen()
功能:
该函数返回指定字符串的字节长度(ANSI版)或字符长度(双字节标准版);其中不包括终止NULL字符。
原型:
int lstrlen(LPCTSTR lpString);
参数:
lpString:指向以NULL为终止符的字符串。
返回值:
指定字符串中字节(ANSI版)或字符(双字节标准版)的长度。