2009-04-16

MessageBox显示自定义图标

  主要是用到了API函数MessageBoxIndirect,代码如下所示:


LOCAL loMessageBox
loMessageBox = CREATEOBJECT("MessageBox")
? loMessageBox.ShowMessageBox("看到MessageBox显示自定义图标了吗?", ;
128 + 4, "提示信息", 16)

*---------------------------------------------------
*- MessageBox类
*---------------------------------------------------
DEFINE CLASS MessageBox AS Custom

#DEFINE HEAP_ZERO_MEMORY 0x00000008

#DEFINE DONT_RESOLVE_DLL_REFERENCES 1
#DEFINE LOAD_LIBRARY_AS_DATAFILE 2
#DEFINE LOAD_WITH_ALTERED_SEARCH_PATH 3

#DEFINE MB_ICONHAND 0x10
#DEFINE MB_ICONQUESTION 0x20
#DEFINE MB_ICONEXCLAMATION 0x30
#DEFINE MB_ICONASTERISK 0x40

#DEFINE MB_USERICON 0x80
#DEFINE MB_ICONWARNING MB_ICONEXCLAMATION
#DEFINE MB_ICONERROR MB_ICONHAND
#DEFINE MB_ICONINFORMATION MB_ICONASTERISK
#DEFINE MB_ICONSTOP MB_ICONHAND

#DEFINE MB_OK 0x0
#DEFINE MB_OKCANCEL 0x1
#DEFINE MB_ABORTRETRYIGNORE 0x2
#DEFINE MB_YESNOCANCEL 0x3
#DEFINE MB_YESNO 0x4
#DEFINE MB_RETRYCANCEL 0x5

#DEFINE MB_DEFBUTTON1 0x0
#DEFINE MB_DEFBUTTON2 0x100
#DEFINE MB_DEFBUTTON3 0x200
#DEFINE MB_DEFBUTTON4 0x300

#DEFINE MB_APPLMODAL 0x0
#DEFINE MB_SYSTEMMODAL 0x1000
#DEFINE MB_TASKMODAL 0x2000

#DEFINE MB_HELP 0x4000
#DEFINE MB_SETFOREGROUND 0x10000
#DEFINE MB_DEFAULT_DESKTOP_ONLY 0x20000
#DEFINE MB_TOPMOST 0x40000
#DEFINE MB_RIGHT 0x80000
#DEFINE MB_RTLREADING 0x100000
#DEFINE MB_SERVICE_NOTIFICATION 0x200000

#DEFINE MB_TYPEMASK 0xF
#DEFINE MB_ICONMASK 0xF0
#DEFINE MB_DEFMASK 0xF00
#DEFINE MB_MODEMASK 0x3000
#DEFINE MB_NOFOCUS 0x8000
#DEFINE MB_MISCMASK 0xC000

#DEFINE IDOK 1
#DEFINE IDCANCEL 2
#DEFINE IDABORT 3
#DEFINE IDRETRY 4
#DEFINE IDIGNORE 5
#DEFINE IDYES 6
#DEFINE IDNO 7

*#DEFINE MB_OK 0
*#DEFINE MB_OKCANCEL 1
*#DEFINE MB_ICONHAND 16
*#DEFINE MB_ICONQUESTION 32
*#DEFINE MB_ICONEXCLAMATION 48
*#DEFINE MB_ICONASTERISK 64
*#DEFINE MB_ICONMASK 240

PROTECTED hResource

PROCEDURE Init
LOCAL lcResourceFile
lcResourceFile = ADDBS(GETENV("windir")) + "SYSTEM32\Shell32.DLL"
THIS.DeclareDlls()
THIS.hResource = LoadLibraryEx(lcResourceFile, 0, ;
LOAD_LIBRARY_AS_DATAFILE)
ENDPROC

PROTECTED PROCEDURE DeclareDlls
DECLARE INTEGER LoadLibraryEx IN KERNEL32 ;
STRING lpLibFileName, ;
INTEGER hFile, ;
INTEGER dwFlags
DECLARE INTEGER FreeLibrary IN KERNEL32 ;
INTEGER hLibModule
DECLARE INTEGER HeapCreate IN KERNEL32 ;
INTEGER flOptions, ;
INTEGER dwInitialSize, ;
INTEGER dwMaximumSize
DECLARE INTEGER HeapAlloc IN KERNEL32 ;
INTEGER hHeap, ;
INTEGER dwFlags, ;
INTEGER dwBytes
DECLARE RtlMoveMemory IN KERNEL32 ;
INTEGER Destination, ;
STRING @Source, ;
INTEGER nLength
DECLARE INTEGER MessageBeep IN USER32 ;
INTEGER wType
DECLARE INTEGER MessageBoxIndirect IN USER32 ;
STRING @lpMsgBoxParams
ENDPROC

PROTECTED PROCEDURE ClearDlls
CLEAR DLLS "LoadLibraryEx", "FreeLibrary", ;
"HeapCreate", "HeapAlloc", "RtlMoveMemory", ;
"MessageBeep", "MessageBoxIndirect"
ENDPROC

PROCEDURE ShowMessageBox
LPARAMETERS tuMessage, tnStyle, tcCaption, tnIconIndex, tnSoundIndex
LOCAL lnReturnValue, lcMsgBoxParams, lnMessageHeap, lnMessageAddress, ;
lnCaptionHeap, lnCaptionAddress, lnSoundIndex
IF TYPE("tuMessage") <> "C"
tuMessage = TRANSFORM(tuMessage)
ENDIF
IF TYPE("tnStyle") <> "N"
tnStyle = 0
ENDIF
IF TYPE("tcCaption") <> "C"
tcCaption = _SCREEN.Caption
ENDIF
IF TYPE("tnIconIndex") <> "N"
tnIconIndex = 0
ENDIF
IF TYPE("tnSoundIndex") <> "N"
tnSoundIndex = 0
ENDIF
lnReturnValue = -1
lcMsgBoxParams = ""
lnMessageHeap = 0
lnMessageAddress = 0
lnCaptionAddress = 0
lnCaptionHeap = 0
tuMessage = IIF(ASC(RIGHT(tuMessage, 1)) = 0, tuMessage, ;
tuMessage + CHR(0))
tcCaption = IIF(ASC(RIGHT(tcCaption, 1)) = 0, tcCaption, ;
tcCaption + CHR(0))
lnMessageHeap = HeapCreate(0, LEN(tuMessage), 0)
lnMessageAddress = HeapAlloc(lnMessageHeap, HEAP_ZERO_MEMORY, ;
LEN(tuMessage))
= RtlMoveMemory(lnMessageAddress, @tuMessage, LEN(tuMessage))
lnCaptionHeap = HeapCreate(0, LEN(tcCaption), 0)
lnCaptionAddress = HeapAlloc(lnCaptionHeap, HEAP_ZERO_MEMORY, ;
LEN(tcCaption))
= RtlMoveMemory(lnCaptionAddress, @tcCaption, LEN(tcCaption))
lnSoundIndex = 0
DO CASE
CASE BITAND(tnStyle, BITNOT(MB_ICONMASK)) <> tnStyle
lnSoundIndex = MB_ICONMASK
CASE BITAND(tnStyle, BITNOT(MB_ICONASTERISK)) <> tnStyle
lnSoundIndex = MB_ICONASTERISK
CASE BITAND(tnStyle, BITNOT(MB_ICONEXCLAMATION)) <> tnStyle
lnSoundIndex = MB_ICONEXCLAMATION
CASE BITAND(tnStyle, BITNOT(MB_ICONQUESTION)) <> tnStyle
lnSoundIndex = MB_ICONQUESTION
CASE BITAND(tnStyle, BITNOT(MB_ICONHAND)) <> tnStyle
lnSoundIndex = MB_ICONHAND
CASE BITAND(tnStyle, BITNOT(MB_OKCANCEL)) <> tnStyle
lnSoundIndex = MB_OKCANCEL
ENDCASE
IF BITAND(tnStyle, BITNOT(MB_USERICON)) <> tnStyle
lnSoundIndex = tnSoundIndex
ENDIF
lcMsgBoxParams = BINTOC(40, "4RS") + ;
BINTOC(_SCREEN.HWnd, "4RS") + ;
BINTOC(THIS.hResource, "4RS") + ;
BINTOC(lnMessageAddress, "4RS") + ;
BINTOC(lnCaptionAddress, "4RS") + ;
BINTOC(tnStyle, "4RS") + ;
BINTOC(tnIconIndex, "4RS") + ;
BINTOC(0, "4RS") + ;
BINTOC(0, "4RS") + ;
BINTOC(VAL(SYS(3004)), "4RS")
= MessageBeep(lnSoundIndex)
lnReturnValue = MessageBoxIndirect(@lcMsgBoxParams)
RETURN lnReturnValue
ENDPROC

PROCEDURE Destroy
= FreeLibrary(THIS.hResource)
THIS.ClearDlls()
ENDPROC

ENDDEFINE


  效果图:


  上面的代码用到了WINDOWS\SYSTEM32目录下的SHELL32.DLL文件,ShowMessageBox方法中的tnIconIndex参数即是SHELL32.DLL文件中图标的顺序号。其实完全可以自行创建一个包含图标的纯资源DLL文件。
  例如,在D盘下创建一个文件夹ResourceDll,然后将rc.exe、rcdll.dll、cvtres.exe、link.exe、mspdb50.dll这些文件(可以在http://www.masm32.com/masmdl.htm下载m32v10r.zip,解压后运行安装程序安装MASM32开发工具包,然后在安装目录下可以找到这些文件)放到ResourceDll文件夹下,然后在ResourceDll下创建Resource文件夹,将DLL中要包含的图标放到该目录下,然后在该目录下创建资源文件Resource.RC,内容大致如此:

  1 ICON "360.ico"
  2 ICON "aptana.ico"
  3 ICON "close.ico"
  4 ICON "connect.ico"
  5 ICON "delete.ico"

然后打开命令提示窗口,切换到D:\ResourceDll目录下,依次执行下面的命令:

  rc.exe /v resource/resource.rc
  cvtres.exe /machine:ix86 resource/resource.res
  link.exe /SUBSYSTEM:WINDOWS /DLL /NOENTRY resource/resource.res

就可以得到Resource.DLL文件了,然后我们可以像调用SHELL32.DLL那样使用Resource.DLL中的图标了。

没有评论: