WIN32汇编语言教程:第08章 通用对话框 · 8.3 浏览目录对话框(2)

       Alloc                 IMalloc_Alloc                 ?
       Realloc               IMalloc_Realloc               ?
       Free                  IMalloc_Free                  ?
       GetSize               IMalloc_GetSize               ?
       DidAlloc              IMalloc_DidAlloc              ?
       HeapMinimize          IMalloc_HeapMinimize          ?
IMalloc ends
;#####################################################################
                      .data  ?
_BrowseFolderTmp        dd   ?
;#####################################################################
                      .const
_szDirInfo            db     '请选择目录:',0
 
                      .code
;#####################################################################
; 弹出选择目录的对话框
;#####################################################################
_BrowseFolderCallBack  proc   hWnd,uMsg,lParam,lpData
                       local  @szBuffer[260]:byte
 
       mov            eax,uMsg
       .if            eax == BFFM_INITIALIZED
                       invoke SendMessage,hWnd,BFFM_SETSELECTION,\
                       TRUE,_BrowseFolderTmp
       .elseif        eax == BFFM_SELCHANGED
                       invoke  SHGetPathFromIDList,lParam,addr @szBuffer
                       invoke  SendMessage,hWnd,BFFM_SETSTATUSTEXT,\
                              0,addr @szBuffer
       .endif
       xor            eax,eax
       ret
 
_BrowseFolderCallBack  endp
;#####################################################################
_BrowseFolder      proc      _hWnd,_lpszBuffer
                   local     @stBrowseInfo:BROWSEINFO
                   local     @stMalloc
                   local     @pidlParent,@dwReturn
 
                   pushad
 
;********************************************************************
; 初始化COM库
;********************************************************************
               invoke  CoInitialize,NULL
               invoke  SHGetMalloc,addr @stMalloc
               .if     eax == E_FAIL
                        mov  @dwReturn,FALSE
                        jmp  @F
               .endif   
               invoke   RtlZeroMemory,addr @stBrowseInfo,sizeof @stBrowseInfo
;********************************************************************
; SHBrowseForFolder 选择一个目录,把不含路径的目录名放入
; stBrowseInfo.pszDisplayName 中,SHGetPathFromIDList 把
; stBrowseInfo.pszDisplayName 转换成含全部路径的目录名
;********************************************************************
               push    _hWnd
               pop     @stBrowseInfo.hwndOwner
               push    _lpszBuffer
               pop     _BrowseFolderTmp
               mov     @stBrowseInfo.lpfn,offset _BrowseFolderCallBack
               mov     @stBrowseInfo.lpszTitle,offset _szDirInfo
               mov     @stBrowseInfo.ulFlags,\
                        BIF_RETURNONLYFSDIRS or BIF_STATUSTEXT
               invoke  SHBrowseForFolder,addr @stBrowseInfo
               mov     @pidlParent,eax
               .if     eax != NULL
                        invoke SHGetPathFromIDList,eax,_lpszBuffer
                        mov  eax,TRUE
               .else
                        mov  eax,FALSE
               .endif
               mov     @dwReturn,eax
;********************************************************************
; 释放COM库
;********************************************************************
               mov     eax,@stMalloc
               mov     eax,[eax]
               invoke  (IMalloc PTR [eax]).Free,@stMalloc,@pidlParent 
               mov     eax,@stMalloc
               mov     eax,[eax]
               invoke  (IMalloc PTR [eax]).Release,@stMalloc
 
               @@:
               invoke  CoUninitialize
               popad
               mov     eax,@dwReturn
               ret
 
_BrowseFolder  endp
;#####################################################################

8.3.2 使用浏览目录对话框

浏览目录对话框的实现分为两个部分:初始化部分和对话框功能部分。

1. 初始化COM库

浏览目录对话框要用到COM接口,所以必须首先调用CoInitialize函数来初始化COM库并调用SHGetMalloc函数来获取一个IMalloc类型的接口,这个接口实际上是一个内存块,中间包含各种COM功能模块的入口地址。在对话框返回的时候,再调用接口中的Free模块释放接口,并调用CoUninitialize函数释放COM库。

COM编程是一个很大的课题,有关COM组件中的IUnknown接口和IMalloc接口等工作机理的内容本身就是一个比较深奥的问题,这不是本书所要涉及的内容,读者可以不必深入研究_BrowseFolder.asm文件中关于这两种接口的定义,只要将定义部分和代码中初始化和释放COM库的代码直接拿过来用就是了,这也是本书将这个模块单独放入一个文件的原因。如果读者对COM编程的内容感兴趣,可以访问http://here.is/cominasm(可能需要使用代理服务器访问),这是一个讨论如何用Win32汇编编写COM程序的站点。

COM库的相关函数包含在ole32.dll中,所以源程序中必须包含下列语句:

include    ole32.inc
includelib ole32.lib

2. 显示对话框

显示对话框的功能函数包含在Shell32.dll中,所以在源程序的头部也应该有下列包含语句:

include      shell32.inc
includelib   shell32.lib

显示对话框的功能由SHBrowseForFolder函数实现,函数的用法是:

invoke       SHBrowseForFolder,lpbi
mov          lpItemIDList,eax         ;返回一个ITEMIDLIST结构指针

参数lpbi指向一个包含对话框初始化数据的BROWSEINFO结构:

BROWSEINFO STRUCT
 HwndOwner            dd ?     ;对话框的父窗口
 PidlRoot             dd ?     ;用来表示起始目录的ITEMIDLIST目录
 PszDisplayName       dd ?     ;用来接收用户选择目录的缓冲区
 LpszTitle            dd ?     ;对话框中的用户定义文字
 ulFlags             dd ?     ;标志
 lpfn                dd ?     ;回调函数地址
 lParam               dd ?     ;传给回调函数的参数
 iImage               dd ?     ;用来接收选中目录的图像
BROWSEINFO ENDS

上页:第08章 通用对话框 · 8.3 浏览目录对话框(1) 下页:第08章 通用对话框 · 8.3 浏览目录对话框(3)

第08章 通用对话框

版权所有 © 中山市飞娥软件工作室 证书:粤ICP备09170368号