;运行效果
;win32汇编环境,窗口程序使用树形视图示例二
;得到树形视图控件Treeview的全路径字符串,这里的方法是由子项向父项挨个找的算法找齐路径
;直接抄进RadAsm可编译运行。重要部分加备注。
;下面为asm文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include comctl32.inc
includelib user32.lib
includelib kernel32.lib
includelib comctl32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
;Equ 等值定义
;ICO_MAIN equ 1000 ;图标
IDC_TV equ 1001 ;树形视图控件标识符
ButtonID equ 1002
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.DATA
ClassName db "SimpleWinClass",0
AppName db "窗口程序的模版",0
szFileIocn db "Main.ico",0
szSTClassName db "static",0 ;静态控件类名
szSTCaption db "树形视图示例二:",0
szTVClassName db "SysTreeView32",0 ;树形视图控件类名
szButtonClassName db "button",0 ;按钮类名
szButtonTitle db "得到被选中的项的路径",0
szShow1 db "魏国",0
szShow11 db "武将",0
szShow111 db "张辽",0
szShow112 db "曹仁",0
szShow113 db "夏侯渊",0
szShow12 db "文臣",0
szShow121 db "荀彧",0
szShow122 db "司马懿",0
szShow123 db "郭嘉",0
szShow2 db "蜀国",0
szShow3 db "吴国",0
szMsg db "提示",0
szFMR db "取得的IP地址是 %d.%d.%d.%d",0
szFuHao01 db "\",0
.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
h_Trv01 HWND ? ;树形视图控件句柄
hButton HWND ?
h_IconList01 dd ? ;图像列表控件句柄
h_icon01 dd ?
h_icon02 dd ?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.CODE
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, eax
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadImage,hInstance,addr szFileIocn,IMAGE_ICON,0,0,LR_LOADFROMFILE
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL, ADDR ClassName,ADDR AppName,WS_OVERLAPPEDWINDOW,100,100,260,470, NULL,NULL,hInst, NULL
mov hwnd,eax
invoke ShowWindow, hwnd,CmdShow
invoke UpdateWindow, hwnd
.while TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.break .if (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.endw
mov eax,msg.wParam
ret
WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL @tvs01:TV_INSERTSTRUCT ;根项的结构
LOCAL @h01:HTREEITEM ;根项的句柄
LOCAL @tvs011:TV_INSERTSTRUCT
LOCAL @h011:HTREEITEM
LOCAL @tvs0111:TV_INSERTSTRUCT
LOCAL @tvs0112:TV_INSERTSTRUCT
LOCAL @tvs0113:TV_INSERTSTRUCT
LOCAL @tvs012:TV_INSERTSTRUCT
LOCAL @h012:HTREEITEM
LOCAL @tvs0121:TV_INSERTSTRUCT
LOCAL @tvs0122:TV_INSERTSTRUCT
LOCAL @tvs0123:TV_INSERTSTRUCT
LOCAL @tvs02:TV_INSERTSTRUCT
LOCAL @tvs03:TV_INSERTSTRUCT
LOCAL @GetTvs:TVITEM ;定义一个要保存的当前选定项的 TVITEM 结构
LOCAL @szBuffer[256]:byte
LOCAL @szCurrentBuffer[256]:byte ;当前项字符串用的数组
LOCAL @szPareBuffer[256]:byte ;父项字符串用的数组
LOCAL @szAllBuffer[256]:byte ;要显示全部路径字符串的数组
LOCAL @Cheshi[256]:byte ;中转用字符串数组
LOCAL @hCurrent ;当前选定项的句柄
LOCAL @hPare ;父项的句柄
.if uMsg == WM_CREATE
invoke CreateWindowEx,NULL,ADDR szSTClassName,ADDR szSTCaption, WS_CHILD + WS_VISIBLE,20, 15, 150, 30,hWnd,NULL,NULL,NULL ;创建静态控件,用来显示文本
invoke CreateWindowEx,NULL,ADDR szTVClassName,NULL, WS_CHILDWINDOW+WS_VISIBLE+TVS_LINESATROOT + TVS_HASLINES + TVS_HASBUTTONS + WS_BORDER + WS_TABSTOP,20,50,200,300,hWnd,IDC_TV,NULL,NULL ;创建树形视图控件
mov h_Trv01,eax
invoke CreateWindowEx,NULL,ADDR szButtonClassName,ADDR szButtonTitle, WS_TABSTOP OR WS_VISIBLE OR WS_CHILD OR BS_DEFPUSHBUTTON ,35,380,180,25,hWnd,ButtonID,NULL,NULL ;创建按钮控件
mov hButton,eax
;开始前需要给控件绑定图像列表,即使不显示图像,只显示文本
invoke ImageList_Create,32,32,ILC_MASK + ILC_COLORDDB,0,0 ;创建图像列表,32是图标的像素32*32,ILC_MASK是让图像四周的多余部分透明化,ILC_COLORDDB是尽量保留原图清晰度
mov h_IconList01,eax ;保存句柄留后面用
invoke LoadIcon,NULL,IDI_APPLICATION ;得到默认应用程序图标的句柄
invoke ImageList_AddIcon,h_IconList01,eax ;eax是上面得到的句柄,本函数让这个图标添加入图像列表里面
mov h_icon01,eax ;保存图标在列表中的索引值
;invoke GetDlgItem,hWnd,IDC_TRV1
;mov h_Trv01,eax
invoke SendMessage,hWnd,TVM_SETIMAGELIST,TVSIL_NORMAL,h_Trv01 ;给树形视图控件绑上图像列表,就是点开和不点开时的图标样式
mov @tvs01.hParent,TVI_ROOT ;添加"魏国"字样,TVI_ROOT是指其为根项
mov @tvs01.item._mask,TVIF_TEXT ;将item的TVIF_TEXT值设好,即说明这个项是使用文本显示的
lea eax,offset szShow1 ;把字符串szShow1的地址给eax
mov @tvs01.item.pszText,eax ;eax是前面的字符串地址
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs01 ;发送TVM_INSERTITEM消息添加这一项,其返回值就是这一项的句柄
mov @h01,eax ;保存句柄,后面跟在它身后的子项,需使用这个作为父项句柄
mov ebx,@h01 ;开始添加"武将"字样
mov @tvs011.hParent,ebx ;hParent的意思是指定父项的句柄,就是说后面点击展开的是子项,它需要前面的父项的句柄
mov @tvs011.item._mask,TVIF_TEXT
lea eax,offset szShow11
mov @tvs011.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs011
mov @h011,eax
mov ebx,@h011 ;开始添加"张辽"字样
mov @tvs0111.hParent,ebx
mov @tvs0111.item._mask,TVIF_TEXT
lea eax,offset szShow111
mov @tvs0111.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs0111
mov ebx,@h011 ;开始添加"曹仁"字样
mov @tvs0112.hParent,ebx
mov @tvs0112.item._mask,TVIF_TEXT
lea eax,offset szShow112
mov @tvs0112.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs0112
mov ebx,@h011 ;开始添加"夏侯渊"字样
mov @tvs0113.hParent,ebx
mov @tvs0113.item._mask,TVIF_TEXT
lea eax,offset szShow113
mov @tvs0113.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs0113
mov ebx,@h01 ;开始添加"文臣"字样
mov @tvs012.hParent,ebx
mov @tvs012.item._mask,TVIF_TEXT
lea eax,offset szShow12
mov @tvs012.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs012
mov @h012,eax
mov ebx,@h012 ;开始添加"荀彧"字样
mov @tvs0121.hParent,ebx
mov @tvs0121.item._mask,TVIF_TEXT
lea eax,offset szShow121
mov @tvs0121.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs0121
mov ebx,@h012 ;开始添加"司马懿"字样
mov @tvs0122.hParent,ebx
mov @tvs0122.item._mask,TVIF_TEXT
lea eax,offset szShow122
mov @tvs0122.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs0122
mov ebx,@h012 ;开始添加"郭嘉"字样
mov @tvs0123.hParent,ebx
mov @tvs0123.item._mask,TVIF_TEXT
lea eax,offset szShow123
mov @tvs0123.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs0123
mov @tvs02.hParent,TVI_ROOT ;开始添加"蜀国"字样
mov @tvs02.item._mask,TVIF_TEXT
lea eax,offset szShow2
mov @tvs02.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs02
mov @tvs03.hParent,TVI_ROOT ;开始添加"吴国"字样
mov @tvs03.item._mask,TVIF_TEXT
lea eax,offset szShow3
mov @tvs03.item.pszText,eax
invoke SendMessage,h_Trv01,TVM_INSERTITEM,0,addr @tvs03
.elseif uMsg == WM_COMMAND
mov eax,wParam
.if ax == ButtonID
invoke SendMessage,h_Trv01,TVM_GETNEXTITEM,TVGN_CARET,0
mov @hCurrent,eax
mov eax,@hCurrent
mov @GetTvs.hItem,eax ;将句柄赋值给要保存的 @GetTvs 变量的 hItem
mov @GetTvs._mask,TVIF_TEXT ;指定掩码成员为 TVIF_TEXT ,就是要取得其字符串的意思
lea eax,@szCurrentBuffer ;把空的字符串数组地址给eax
mov @GetTvs.pszText,eax ;让 @GetTvs 变量的 pszText 成员指向上面的字符串数组
mov @GetTvs.cchTextMax,256
invoke SendMessage,h_Trv01,TVM_GETITEM,0,addr @GetTvs ;发送 TVM_GETITEM 消息给控件,让它把所选项的数据填到变量 @GetTvs 里去
invoke lstrcpy,addr @szAllBuffer,addr @szCurrentBuffer
.while TRUE
invoke SendMessage,h_Trv01,TVM_GETNEXTITEM,TVGN_PARENT,@hCurrent ;得到当前项的父项的句柄
mov @hPare,eax
invoke RtlZeroMemory,addr @GetTvs,sizeof @GetTvs ;清空结构变量@GetTvs
invoke RtlZeroMemory,addr @szPareBuffer,sizeof @szPareBuffer ;清空用来保存父项字符串的数组
mov eax,@hPare ;开始得到父项字符串
mov @GetTvs.hItem,eax
mov @GetTvs._mask,TVIF_TEXT
lea eax,@szPareBuffer
mov @GetTvs.pszText,eax
mov @GetTvs.cchTextMax,256
invoke SendMessage,h_Trv01,TVM_GETITEM,0,addr @GetTvs ;得到父项字符串结束
.break .if @hPare == 0 ;如果父句柄为0,说明前面没有父项了,即到根项了,则跳出
invoke lstrcpy,addr @Cheshi,addr @szAllBuffer ;把前面保存的要显示的全路径字符串保存到中转字符数组去
invoke RtlZeroMemory,addr @szAllBuffer,sizeof @szAllBuffer ;把全路径字符串清空
invoke lstrcpy,addr @szAllBuffer,addr @szPareBuffer ;把父项字符串复制到全路径字符串数组去
invoke lstrcat,addr @szAllBuffer,addr szFuHao01 ;把 \ 符号添加在全路径字符串后面,之所以用这个,是要显示文件夹时常用这个
invoke lstrcat,addr @szAllBuffer,addr @Cheshi ;把中转字符数组里的字符串添加在全路径字符串后面。
mov eax,@hPare
mov @hCurrent,eax
.endw
invoke MessageBox,hWnd,addr @szAllBuffer,addr szMsg,MB_OK
.endif
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start