以下以罗云琳《Win32汇编程序设计》第18章odbc例子为例;在RadASM中导入该项目,并为该项目略添加功能;
一 masm32 项目导入radasm
先看一下radasm示例项目的结构如下;
新建工程,masm编译器,工程类型Win32;
没有模板;
不创建任何文件;
这是向导的最后一步;
可以右击文件夹单个导入文件;但是此种方式导入的文件不会复制到项目文件夹下;
重新再来;点击向导界面的 导入 按钮,在导入对话框中选择路径,并对文件做如下选择;
导入以后的情况如下;但是此时构建会出现rc不编译;
重新再来;把odbc.rc也选为主文件;
这下导入后基本可以了;虽然不知为何asm文件跑到Resources文件夹,不过可编译运行;
二 关于 - undefined keyword or key name
至于原程序中的#include <resource.h>,把它注释了;编译出现,
error RC2104 : undefined keyword or key name: WS_CHILD
类似错误时,打开radasm自带的resource.h,把WS_CHILD等常量定义拷贝到.rc中即可;
三 为odbc示例添加小功能
这是原来程序的运行界面;
下面增加一个小功能,修改资源文件,添加一个按钮和灰色文本框,点击 浏览 按钮,执行一条预先赋值的SQL;
并且需要在主asm文件中添加对应的常量定义和代码;下面是执行效果;
下面给出主asm文件和资源文件代码;其他文件和原程序同;
odbcaddr7.rc
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //#include <resource.h> //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #define DS_MODALFRAME 0x80L #define WS_POPUP 0x80000000L #define WS_VISIBLE 0x10000000L #define WS_CAPTION 0x00C00000L #define WS_SYSMENU 0x00080000L #define WS_THICKFRAME 0x00040000L #define ES_AUTOHSCROLL 0x0080L #define WS_BORDER 0x00800000L #define WS_TABSTOP 0x00010000L #define WS_DISABLED 0x08000000L #define BS_DEFPUSHBUTTON 0x00000001L #define WS_CHILD 0x40000000L #define ICO_MAIN 1000 #define DLG_MAIN 2000 #define IDC_CONN_STR 2001 #define IDC_CONN 2002 #define IDC_DISCONN 2003 #define IDC_SQL 2004 #define IDC_EXEC 2005 #define IDC_LIST 2006 #define IDC_INFO 2007 #define IDC_COMMIT 2008 #define IDC_ROLLBACK 2009 #define IDC_LIULAN 2010 #define IDC_SQLll 2011 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ICO_MAIN icon "Main.ico" //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DLG_MAIN DIALOG 51, 78, 465, 237 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "ODBC数据库操作例子" FONT 9, "宋体" { EDITTEXT IDC_CONN_STR, 65, 5, 290, 12, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP PUSHBUTTON "连接(&C)", IDC_CONN, 359, 4, 50, 14 PUSHBUTTON "断开(&D)", IDC_DISCONN, 412, 4, 50, 14, WS_DISABLED | WS_TABSTOP EDITTEXT IDC_SQLll, 125, 22, 261, 12, ES_AUTOHSCROLL | WS_DISABLED | WS_BORDER | WS_TABSTOP DEFPUSHBUTTON "浏览(&L)", IDC_LIULAN, 65, 21, 50, 14, BS_DEFPUSHBUTTON | WS_TABSTOP EDITTEXT IDC_SQL, 40, 62, 261, 12, ES_AUTOHSCROLL | WS_DISABLED | WS_BORDER | WS_TABSTOP DEFPUSHBUTTON "执行(&E)", IDC_EXEC, 306, 61, 50, 14, BS_DEFPUSHBUTTON | WS_DISABLED | WS_TABSTOP PUSHBUTTON "提交(&M)", IDC_COMMIT, 359, 61, 50, 14, WS_DISABLED | WS_TABSTOP PUSHBUTTON "回滚(&R)", IDC_ROLLBACK, 412, 61, 50, 14, WS_DISABLED | WS_TABSTOP CONTROL "", IDC_LIST, "SysListView32", 13 | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 2, 96, 460, 179 LTEXT "SQL语句", -1, 5, 64, 34, 8 LTEXT "ODBC连接字符串", -1, 5, 8, 60, 8 LTEXT "", IDC_INFO, 5, 78, 455, 18 } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
odbcaddr7.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Sample code for < Win32ASM Programming 2nd Edition> ; by 罗云彬, http://asm.yeah.net ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Odbc.asm ; 用Odbc操作数据库的例子 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 使用 nmake 或下列命令进行编译和链接: ; ml /c /coff Odbc.asm ; rc Odbc.rc ; Link /subsystem:windows Odbc.obj Odbc.res ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .386 .model flat, stdcall option casemap :none ; case sensitive ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 数据 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include comctl32.inc includelib comctl32.lib include odbc32.inc includelib odbc32.lib ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; equ 数据 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ICO_MAIN equ 1000 DLG_MAIN equ 2000 IDC_CONN_STR equ 2001 IDC_CONN equ 2002 IDC_DISCONN equ 2003 IDC_SQL equ 2004 IDC_EXEC equ 2005 IDC_LIST equ 2006 IDC_INFO equ 2007 IDC_COMMIT equ 2008 IDC_ROLLBACK equ 2009 IDC_LIULAN equ 2010 IDC_SQLll equ 2011 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 数据段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .data hInstance dd hWinMain dd ;对话框句柄 hListView dd ;列表框句柄 hEnv dd ;ODBC环境句柄 hConn dd ;ODBC连接句柄 szConnString db 1024 dup () ;ODBC连接字符串 szFullString db 1024 dup () ;连接后返回的全字符串 szSQL db 1024 dup () ;输入的准备执行的SQL语句 .const szDefConnStr db "Driver={Microsoft Access Driver (*.mdb)};dbq=test.mdb",0 szErrConn db '无法连接到数据库!',0 szOkCaption db '成功连接到数据库,完整的连接字符串如下:',0 szErrDDL db 'DDL/DCL 语句已成功执行。',0 szErrDML db 'DML 语句已成功执行,Insert/Update/Delete的行数:%d。',0 szErrDQL db '查询语句已经成功执行,得到的结果集如下:',0 sqlliulan db 'select * from addr',0 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 代码段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .code include _ListView.asm include _RecordSet.asm ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 执行SQL语句 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _Execute proc local @dwTemp,@dwErrCode local @szSQLState[8]:byte,@szMsg[SQL_MAX_MESSAGE_LENGTH]:byte local @dwRecordCols,@dwResultRows local @szName[128]:byte,@dwNameSize,@dwType,@dwSize,@dwSize1,@dwNullable local @stRs:ODBC_RS,@hStmt invoke SetDlgItemText,hWinMain,IDC_INFO,NULL invoke ShowWindow,hListView,SW_HIDE invoke _ListViewClear,hListView invoke SQLAllocHandle,SQL_HANDLE_STMT,hConn,addr @hStmt .if ax != SQL_SUCCESS && ax != SQL_SUCCESS_WITH_INFO ret .endif invoke SQLSetStmtAttr,@hStmt,SQL_ATTR_CURSOR_TYPE,SQL_CURSOR_STATIC,0 ;******************************************************************** ; 执行 SQL 语句 ;******************************************************************** invoke lstrlen,addr szSQL invoke SQLExecDirect,@hStmt,addr szSQL,eax .if ax != SQL_SUCCESS && ax != SQL_SUCCESS_WITH_INFO && ax != SQL_NO_DATA mov @szMsg,0 invoke SQLGetDiagRec,SQL_HANDLE_STMT,@hStmt,1,\ addr @szSQLState,addr @dwErrCode,addr @szMsg,\ sizeof @szMsg,addr @dwTemp invoke SetDlgItemText,hWinMain,IDC_INFO,addr @szMsg jmp _FreeStmt .endif ;******************************************************************** ; 语句执行成功,如果是DML语句,则显示语句影响的行数 ;******************************************************************** invoke SQLNumResultCols,@hStmt,addr @dwRecordCols and @dwRecordCols,0ffffh .if ! @dwRecordCols invoke SQLRowCount,@hStmt,addr @dwResultRows .if @dwResultRows == -1 ;DDL或DCL语句 invoke SetDlgItemText,hWinMain,IDC_INFO,addr szErrDDL .else ;DML语句 invoke wsprintf,addr @szMsg,addr szErrDML,@dwResultRows invoke SetDlgItemText,hWinMain,IDC_INFO,addr @szMsg .endif jmp _FreeStmt .endif ;******************************************************************** ; 如果是Select语句,则根据结果集初始化ListView的标题,以便显示 ;******************************************************************** invoke SetDlgItemText,hWinMain,IDC_INFO,addr szErrDQL invoke ShowWindow,hListView,SW_SHOW xor ebx,ebx .while ebx < @dwRecordCols inc ebx invoke SQLDescribeCol,@hStmt,ebx,\ addr @szName,sizeof @szName,addr @dwNameSize,\ addr @dwType,addr @dwSize,addr @dwSize1,addr @dwNullable mov eax,@dwSize ;列宽度=字符数*8象素 mov ecx,8 mul ecx .if eax > 300 ;最大不超过300象素 mov eax,300 .endif .if eax < 40 ;最小不小于40象素 mov eax,40 .endif lea ecx,@szName ;将列名称插入列表框 invoke _ListViewAddColumn,hListView,ebx,eax,ecx .endw ;******************************************************************** ; 将结果集填写到ListView中 ;******************************************************************** invoke _RsOpen,addr @stRs,@hStmt xor esi,esi .while TRUE invoke _RsMoveNext,addr @stRs .break .if eax invoke _ListViewSetItem,hListView,esi,-1,0 ;插入新的一行 mov esi,eax xor ebx,ebx ;循环显示一行中的所有列 .while ebx < @dwRecordCols invoke _RsGetField,addr @stRs,ebx .if eax invoke _ListViewSetItem,hListView,esi,ebx,eax .endif inc ebx .endw inc esi ;行号加1 .endw invoke _RsClose,addr @stRs invoke SQLCloseCursor,@hStmt ;******************************************************************** _FreeStmt: invoke SQLFreeHandle,SQL_HANDLE_STMT,@hStmt ret _Execute endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 断开到数据库的连接 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _DisConnect proc .if hConn invoke SQLEndTran,SQL_HANDLE_DBC,hConn,SQL_COMMIT invoke SQLDisconnect,hConn invoke SQLFreeHandle,SQL_HANDLE_DBC,hConn .endif .if hEnv invoke SQLFreeHandle,SQL_HANDLE_ENV,hEnv .endif xor eax,eax mov hConn,eax mov hEnv,eax invoke SetDlgItemText,hWinMain,IDC_INFO,NULL invoke SetDlgItemText,hWinMain,IDC_SQL,NULL invoke ShowWindow,hListView,SW_HIDE invoke GetDlgItem,hWinMain,IDC_CONN_STR invoke EnableWindow,eax,TRUE invoke GetDlgItem,hWinMain,IDC_CONN invoke EnableWindow,eax,TRUE invoke GetDlgItem,hWinMain,IDC_SQL invoke EnableWindow,eax,FALSE invoke GetDlgItem,hWinMain,IDC_DISCONN invoke EnableWindow,eax,FALSE invoke GetDlgItem,hWinMain,IDC_COMMIT invoke EnableWindow,eax,FALSE invoke GetDlgItem,hWinMain,IDC_ROLLBACK invoke EnableWindow,eax,FALSE ret _DisConnect endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 连接到数据库 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _Connect proc local @dwTemp invoke GetDlgItem,hWinMain,IDC_CONN_STR invoke EnableWindow,eax,FALSE invoke GetDlgItem,hWinMain,IDC_CONN invoke EnableWindow,eax,FALSE ;******************************************************************** ; 申请环境句柄和连接句柄 ;******************************************************************** invoke SQLAllocHandle,SQL_HANDLE_ENV,SQL_NULL_HANDLE,addr hEnv .if ax != SQL_SUCCESS && ax != SQL_SUCCESS_WITH_INFO jmp _Error .endif invoke SQLSetEnvAttr,hEnv,SQL_ATTR_ODBC_VERSION,SQL_OV_ODBC3,0 .if ax != SQL_SUCCESS && ax != SQL_SUCCESS_WITH_INFO jmp _Error .endif invoke SQLAllocHandle,SQL_HANDLE_DBC,hEnv,addr hConn .if ax != SQL_SUCCESS && ax != SQL_SUCCESS_WITH_INFO jmp _Error .endif invoke SQLSetConnectAttr,hConn,SQL_ATTR_AUTOCOMMIT,SQL_AUTOCOMMIT_OFF,0 ;******************************************************************** ; 连接到数据库 ;******************************************************************** invoke lstrlen,addr szConnString mov ecx,eax invoke SQLDriverConnect,hConn,hWinMain,addr szConnString,ecx,\ addr szFullString,sizeof szFullString,addr @dwTemp,SQL_DRIVER_COMPLETE .if ax == SQL_SUCCESS || ax == SQL_SUCCESS_WITH_INFO invoke MessageBox,hWinMain,addr szFullString,addr szOkCaption,MB_OK invoke GetDlgItem,hWinMain,IDC_DISCONN invoke EnableWindow,eax,TRUE invoke GetDlgItem,hWinMain,IDC_COMMIT invoke EnableWindow,eax,TRUE invoke GetDlgItem,hWinMain,IDC_ROLLBACK invoke EnableWindow,eax,TRUE invoke GetDlgItem,hWinMain,IDC_SQL push eax invoke EnableWindow,eax,TRUE pop eax invoke SetFocus,eax .else _Error: invoke MessageBox,hWinMain,addr szErrConn,NULL,MB_ICONSTOP or MB_OK invoke _DisConnect .endif ret _Connect endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 主窗口程序 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam local @stWsa:WSADATA mov eax,wMsg .if eax == WM_COMMAND mov eax,wParam ;******************************************************************** ; 输入连接字符串后才激活“连接”按钮 ;******************************************************************** .if ax == IDC_CONN_STR invoke GetDlgItemText,hWnd,IDC_CONN_STR,addr szConnString,sizeof szConnString invoke GetDlgItem,hWnd,IDC_CONN .if szConnString invoke EnableWindow,eax,TRUE .else invoke EnableWindow,eax,FALSE .endif ;******************************************************************** ; 输入SQL语句后才激活“执行”按钮 ;******************************************************************** .elseif ax == IDC_SQL invoke GetDlgItemText,hWnd,IDC_SQL,addr szSQL,sizeof szSQL invoke GetDlgItem,hWnd,IDC_EXEC .if szSQL invoke EnableWindow,eax,TRUE .else invoke EnableWindow,eax,FALSE .endif ;******************************************************************** ; 连接、断开连接、执行按钮的处理 ;******************************************************************** .elseif ax == IDC_CONN invoke _Connect .elseif ax == IDC_DISCONN invoke _DisConnect .elseif ax == IDC_EXEC invoke _Execute invoke SendDlgItemMessage,hWnd,IDC_SQL,EM_SETSEL,0,-1 .elseif ax == IDC_COMMIT invoke SQLEndTran,SQL_HANDLE_DBC,hConn,SQL_COMMIT .elseif ax == IDC_ROLLBACK invoke SQLEndTran,SQL_HANDLE_DBC,hConn,SQL_ROLLBACK .elseif ax == IDC_LIULAN invoke GetDlgItemText,hWnd,IDC_SQLll,addr szSQL,sizeof szSQL invoke _Execute .endif ;******************************************************************** .elseif eax == WM_INITDIALOG push hWnd pop hWinMain invoke LoadIcon,hInstance,ICO_MAIN invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax invoke GetDlgItem,hWnd,IDC_LIST mov hListView,eax invoke SendMessage,hListView,LVM_SETEXTENDEDLISTVIEWSTYLE,\ 0,LVS_EX_GRIDLINES or LVS_EX_FULLROWSELECT invoke ShowWindow,hListView,SW_HIDE invoke SendDlgItemMessage,hWnd,IDC_CONN_STR,EM_SETLIMITTEXT,1024,0 invoke SendDlgItemMessage,hWnd,IDC_SQL,EM_SETLIMITTEXT,1024,0 invoke SetDlgItemText,hWnd,IDC_CONN_STR,addr szDefConnStr invoke SetDlgItemText,hWnd,IDC_SQLll,addr sqlliulan ;******************************************************************** .elseif eax == WM_CLOSE .if ! hEnv && !hConn invoke EndDialog,hWinMain,NULL .endif ;******************************************************************** .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgMain endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 程序开始 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> start: invoke InitCommonControls invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,eax,DLG_MAIN,NULL,offset _ProcDlgMain,0 invoke ExitProcess,NULL ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end start
工程下载:
http://pan.baidu.com/s/1o7OEMc6
odbcaddr7.rar
- 顶
- 0
- 踩
- 0