前面几篇文章中都没有使用到菜单,对话框等资源,这次就演练如何在应用程序中加入这些资源。我们就以将VC6.0默认生成的Win32程序移植为32位汇编为例。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
首先用VC6.0生成一个默认Win32版的Hello,World程序,将Hello.rc,demo.ico,small.ico都拷贝到项目目录下,去掉VC6.0相关的部分,最后Hello.rc修改如下:
//MicrosoftVisualC++generatedresourcescript.
//
#include"resource.h"

#defineIDR_MAINFRAME128
#defineIDD_DEMO_DIALOG102
#defineIDD_ABOUTBOX103
#defineIDS_APP_TITLE103

#defineIDM_ABOUT104
#defineIDM_EXIT105
#defineIDS_HELLO106
#defineIDI_DEMO107
#defineIDI_SMALL108
#defineIDC_DEMO109

#defineIDC_MYICON2
#defineIDC_STATIC-1

/////////////////////////////////////////////////////////////////////////////
//
//Icon
//
//IconwithlowestIDvalueplacedfirsttoensureapplicationicon
//remainsconsistentonallsystems.

IDI_DEMOICONDISCARDABLE"demo.ICO"
IDI_SMALLICONDISCARDABLE"SMALL.ICO"
/////////////////////////////////////////////////////////////////////////////
//
//Menu
//
IDC_DEMOMENUDISCARDABLE
BEGIN
POPUP"&File"
BEGIN
MENUITEM"E&xit",IDM_EXIT
END
POPUP"&Help"
BEGIN
MENUITEM"&About
",IDM_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
//Accelerator
//
IDC_DEMOACCELERATORSMOVEABLEPURE
BEGIN
"?",IDM_ABOUT,ASCII,ALT
"/",IDM_ABOUT,ASCII,ALT
END
/////////////////////////////////////////////////////////////////////////////
//
//Dialog
//
IDD_ABOUTBOXDIALOGDISCARDABLE22,17,230,75
STYLEDS_MODALFRAME|WS_CAPTION|WS_SYSMENU
CAPTION"About"
FONT8,"System"
BEGIN
ICONIDI_DEMO,IDC_MYICON,14,9,16,16
LTEXT"HelloApp1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
LTEXT"Copyright(C)2008",IDC_STATIC,49,20,119,8
DEFPUSHBUTTON"OK",IDOK,195,6,30,11,WS_GROUP
END

/////////////////////////////////////////////////////////////////////////////
//
//StringTable
//

STRINGTABLEDISCARDABLE
BEGIN
IDC_DEMO"DEMO"
IDS_APP_TITLE"demo"
IDS_HELLO"HelloWorld!"
END
/////////////////////////////////////////////////////////////////////////////
然后创建一个MakFile文件,内容如下:
NAME=Hello
OBJS=$(NAME).obj
RES=$(NAME).res

$(NAME).exe:$(OBJS)$(RES)
Link/SUBSYSTEM:WINDOWS$(OBJS)$(RES)
$(RES):$(NAME).rc
rc$(NAME).rc
.asm.obj:
ml/c/coff$(NAME).asm
最后仿照VC++代码编写汇编代码如下:
.386
.modelflat,stdcall
optioncasemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Include文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>includewindows.inc
includegdi32.inc
includelibgdi32.lib
includeuser32.inc
includelibuser32.lib
includekernel32.inc
includelibkernel32.lib


IDR_MAINFRAMEequ128
IDD_DEMO_DIALOGequ102
IDD_ABOUTBOXequ103
IDS_APP_TITLEequ103
IDM_ABOUTequ104
IDM_EXITequ105
IDS_HELLOequ106
IDI_DEMOequ107
IDI_SMALLequ108
IDC_DEMOequ109
IDC_MYICONequ2
IDC_STATICequ-1

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstancedd?;应用程序句柄
hWinMaindd?;窗口句柄
szCaptionMaindb1024dup(?)
szTextdb1024dup(?)

.const
szClassNamedb'MyClass',0;窗口类名称

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;About对话框处理函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Aboutprocusesebxediesi,hDlg,uMsg,wParam,lParam
moveax,uMsg
.ifeax==WM_COMMAND
moveax,wParam
movzxeax,ax
.ifeax==IDOK
invokeEndDialog,hDlg,eax
;invokeMessageBox,NULL,addrszText,addrszCaptionMain,MB_OK
.endif
.elseifeax==WM_INITDIALOG
moveax,1
ret
.endif
xoreax,eax;这句非常重要,清零eax,相当于返回false
ret
_Aboutendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_ProcWinMainprocusesebxediesihWnd,uMsg,wParam,lParam;让汇编器保持子程序中使用到的寄存器的正确性
local@stPs:PAINTSTRUCT
local@stRect:RECT
[email protected]

moveax,uMsg
;*************************************************************
.ifeax==WM_PAINT
invokeBeginPaint,hWnd,[email protected]
mov@hDc,eax

invokeGetClientRect,hWnd,[email protected]
invokeDrawText,@hDc,addrszText,-1,/;长度设置为-1,表示输出的字符串以'/0'结尾,且由函数自动计算出其长度
[email protected],/
DT_SINGLELINEorDT_CENTERorDT_VCENTER
invokeEndPaint,hWnd,[email protected]
;*************************************************************
.elseifeax==WM_COMMAND
moveax,wParam
movzxeax,ax
.ifeax==IDM_EXIT
invokeDestroyWindow,hWinMain
invokePostQuitMessage,NULL
.elseifeax==IDM_ABOUT
invokeDialogBoxParam,hInstance,IDD_ABOUTBOX,hWnd,_About,NULL
.endif

;*************************************************************
.elseifeax==WM_CLOSE
invokeDestroyWindow,hWinMain
invokePostQuitMessage,NULL
;*************************************************************
.else
invokeDefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
;*************************************************************
xoreax,eax;eax寄存器清零
ret

_ProcWinMainendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;WinMain函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_WinMainproc
local@stWndClass:WNDCLASSEX
local@stMsg:MSG

invokeGetModuleHandle,NULL;获取应用程序句柄,这在VC里是通过操作系统传递进来的,但是汇编中需要自己去获取
movhInstance,eax;获取到的应用程序句柄在eax中
invokeRtlZeroMemory,[email protected],[email protected];清零
;*************************************************************
;注册窗口类
;*************************************************************
invokeLoadCursor,0,IDC_ARROW;加载光标
mov@stWndClass.hCursor,eax
invokeLoadIcon,hInstance,offsetIDI_DEMO
mov@stWndClass.hIcon,eax
invokeLoadString,hInstance,IDS_APP_TITLE,addrszCaptionMain,sizeofszCaptionMain
invokeLoadString,hInstance,IDS_HELLO,addrszText,sizeofszText
pushhInstance
pop@stWndClass.hInstance
mov@stWndClass.cbSize,sizeofWNDCLASSEX
mov@stWndClass.style,CS_HREDRAWorCS_VREDRAW

mov@stWndClass.lpfnWndProc,offset_ProcWinMain;设置窗口处理函数
;invokeGetStockObject,WHITE_BRUSH
;[email protected],eax
mov@stWndClass.hbrBackground,COLOR_WINDOW+1
mov@stWndClass.lpszClassName,offsetszClassName
mov@stWndClass.lpszMenuName,offsetIDC_DEMO
invokeRegisterClassEx,[email protected];注册窗口类
;*************************************************************
;建立并显示窗口
;*************************************************************
invokeCreateWindowEx,WS_EX_CLIENTEDGE,offsetszClassName,addrszCaptionMain,/
WS_OVERLAPPEDWINDOW,/
100,100,600,400,/
NULL,NULL,hInstance,NULL;创建窗口,发出一个WM_CREATE消息
movhWinMain,eax;保存窗口句柄
invokeShowWindow,hWinMain,SW_SHOWNORMAL;显示窗口
invokeUpdateWindow,hWinMain;发出一个WM_PAINT消息
;*************************************************************
;第一种消息循环,使用GetMessage,同步的
;*************************************************************
;.whileTRUE
;invokeGetMessage,[email protected],NULL,0,0
;.break.ifeax==0;stMsg为0,即收到WM_QUIT消息时退出
;invokeTranslateMessage,[email protected]
;invokeDispatchMessage,[email protected]
;.endw
;*************************************************************
;另一种消息循环,使用PeekMessage,异步的
;*************************************************************
.whileTRUE
invokePeekMessage,[email protected],NULL,0,0,PM_REMOVE
.ifeax!=0
[email protected]==WM_QUIT
invokeTranslateMessage,[email protected]
invokeDispatchMessage,[email protected]
.else
;空闲时间,可以做其他处理工作
.endif
.endw
ret
_WinMainendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;程序入口点
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
call_WinMain
invokeExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
endstart
nmake编译后运行如下图:
