⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 008.txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 4 页
字号:
; IUnknown 接口定义

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

externdef IID_IUnknown:IID 

LPUNKNOWN typedef DWORD

LPPUNKNOWN   typedef ptr LPUNKNOWN

 

IUnknown_QueryInterfaceProto  typedef proto :DWORD, :DWORD, :DWORD

IUnknown_AddRefProto   typedef proto :DWORD 

IUnknown_ReleaseProto typedef proto :DWORD

IUnknown_QueryInterface typedef ptr IUnknown_QueryInterfaceProto

IUnknown_AddRef typedef ptr IUnknown_AddRefProto

IUnknown_Release   typedef ptr IUnknown_ReleaseProto

  

IUnknown struct DWORD

  QueryInterface IUnknown_QueryInterface ?

  AddRef IUnknown_AddRef ?

  Release   IUnknown_Release   ?

IUnknown ends

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

;IMalloc 接口定义

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

externdef IID_IMalloc:IID   

LPMALLOC   typedef DWORD

LPPMALLOC typedef ptr LPMALLOC

 

IMalloc_AllocProto   typedef proto :DWORD, :DWORD

IMalloc_ReallocProto   typedef proto :DWORD, :DWORD,:DWORD

IMalloc_FreeProto typedef proto :DWORD, :DWORD

IMalloc_GetSizeProto   typedef proto :DWORD, :DWORD

IMalloc_DidAllocProto typedef proto :DWORD, :DWORD

IMalloc_HeapMinimizeProto typedef proto :DWORD

 

IMalloc_Alloc typedef ptr IMalloc_AllocProto

IMalloc_Realloc typedef ptr IMalloc_ReallocProto

IMalloc_Free   typedef ptr IMalloc_FreeProto

IMalloc_GetSize typedef ptr IMalloc_GetSizeProto

IMalloc_DidAlloc   typedef ptr IMalloc_DidAllocProto

IMalloc_HeapMinimize   typedef ptr IMalloc_HeapMinimizeProto

 

IMalloc struct DWORD

  QueryInterface IUnknown_QueryInterface   ?

  AddRef IUnknown_AddRef   ?

  Release   IUnknown_Release ?

        


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
        


8.3 浏览目录对话框(3)


结构的各个重要字段说明如下。

● lpszTitle——对话框中的自定义文字,如例子中显示的是“请选择目录”。

● lpfn——回调函数的地址。

● ulFlags——用来定义对话框类型的标志,下面是一些重要的标志:

■ BIF_BROWSEFORPRINTER——对话框中只能选择打印机。

■ BIF_BROWSEINCLUDEFILES——同时显示目录中的文件。

■ BIF_RETURNONLYFSDIRS——只返回文件系统中的目录。

■ BIF_STATUSTEXT——对话框中显示一个状态栏。

■ BIF_EDITBOX——显示一个编辑框供用户手工输入目录。

■ BIF_VALIDATE——显示编辑框的时候检测用户输入目录的合法性。

3. 对话框的回调函数

当函数执行后,将显示对话框,当对话框初始化以及每当用户选择不同的目录的时候,函数调用lpfn指定的回调函数,回调函数的参数有4个,分别是父窗口句柄hWnd、消息类型uMsg、消息参数lParam和自定义数据lpData,回调函数的语法如下:

_BrowseFolderCallBack proc hWnd,uMsg,lParam,lpData

 

  mov   eax,uMsg

  .if   eax == BFFM_INITIALIZED

...

  .elseif  eax == BFFM_SELCHANGED

...

  .endif

  xor   eax,eax

  ret

 

_BrowseFolderCallBack endp

回调函数可能收到的消息有3种:

● BFFM_INITIALIZED——在对话框初始化的时候收到。

● BFFM_SELCHANGED——在用户选择了一个目录的时候收到,这时lParam参数指向一个表示当前被选择目录的ITEMIDLIST结构。

● BFFM_VALIDATEFAILED——用户输入了一个不合法的目录名。

在回调函数中,程序可以根据情况向对话框发送控制消息,当收到BFFM_SELCHANGED消息时,可以根据选择情况决定是否允许用户单击对话框中的“确定”按钮,通过发送BFFM_ENABLEOK 消息可以控制“确定”按钮的状态:

invoke  SendMessage,hWnd, BFFM_ENABLEOK,0,TRUE  ;允许“确定”按钮

invoke  SendMessage,hWnd, BFFM_ENABLEOK,0,FALSE ;灰化“确定”按钮

程序也可以通过发送BFFM_SETSELECTION消息来设定目录:

invoke  SendMessage,hWnd,BFFM_SETSELECTION,TRUE,lpPath 

如果消息的wParam参数为TRUE,则目录用lParam参数指定的字符串表示;如果wParam为FALSE,则目录用lParam指定的ITEMIDLIST结构表示。由于用字符串表示比较方便,所以例子程序在收到初始化消息的时候用上面的语句设置初始目录。

调用SHBrowseForFolder函数的时候,通过BROWSEINFO结构的pidlRoot字段也可以设置初始目录,但设置ITEMIDLIST结构比较麻烦,所以一般不使用这种方法。

另外,在回调函数中可以通过BFFM_SETSTATUSTEXT消息设置状态栏的文字,对话框的状态栏并不是指一般窗口底部的状态栏,而是指自定义文字下面的那一行文字,在图8.6中就是显示被选择目录名的地方,使用BFFM_SETSTATUSTEXT消息的格式是:

invoke  SendMessage,hWnd,BFFM_SETSTATUSTEXT,0,lpsz

例子程序中,回调函数每次在收到用户选择目录的BFFM_SELCHANGED消息后,在状态栏中显示目录的名称。

4. 获取返回的目录

当SHBrowseForFolder返回的时候,如果用户单击的是“取消”按钮,那么函数的返回值是0,否则的话,函数返回一个指向ITEMIDLIST结构的指针,对于这个结构可以不必去深究,因为使用SHGetPathFromIDList函数可以很方便地将它转换成目录字符串:

invoke  SHGetPathFromIDList,lpItemIDList,addr szPath

函数执行后,szPath中就是字符串格式的用户选择的目录名称了。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -