?? odbc-c5.htm
字號:
pop lvi.lParam
invoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi
mov lvi.imask,LVIF_TEXT
inc lvi.iSubItem
mov lvi.pszText,offset TheSurname
invoke SendMessage,hList,LVM_SETITEM, 0,addr lvi
inc lvi.iSubItem
mov lvi.pszText,offset TelNo
invoke SendMessage,hList,LVM_SETITEM, 0,addr lvi
inc row
.else
.break
.endif
.endw
ret
FillData endp
RunQuery proc hDlg:DWORD
invoke ShowWindow, hList, SW_SHOW
invoke SendMessage, hList, LVM_DELETEALLITEMS,0,0
invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLExecDirect, hStmt, addr SQLStatement, sizeof SQLStatement
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke FillData
.else
invoke ShowWindow, hList, SW_HIDE
invoke MessageBox,hDlg,addr ExecuteFail, addr AppName, MB_OK+MB_ICONERROR
.endif
invoke SQLCloseCursor, hStmt
invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt
.else
invoke ShowWindow, hList, SW_HIDE
invoke MessageBox,hDlg,addr AllocStmtFail, addr AppName, MB_OK+MB_ICONERROR
.endif
ret
RunQuery endp
QueryProc proc hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
.if uMsg==WM_CLOSE
invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt
invoke EndDialog, hDlg,0
.elseif uMsg==WM_INITDIALOG
invoke ShowWindow, hList, SW_SHOW
invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke lstrcpy, addr Conn, addr SQLStatement
invoke lstrcat, addr Conn, addr WhereStatement
invoke SQLBindParameter,hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,25,0, addr SearchName,25,addr StrLen
invoke SQLPrepare, hStmt, addr Conn, sizeof Conn
.else
invoke ShowWindow, hList, SW_HIDE
invoke MessageBox,hDlg,addr AllocStmtFail, addr AppName, MB_OK+MB_ICONERROR
invoke EndDialog, hDlg,0
.endif
.elseif uMsg==WM_COMMAND
mov eax, wParam
shr eax,16
.if ax==BN_CLICKED
mov eax,wParam
.if ax==IDC_OK
invoke GetDlgItemText, hDlg, IDC_NAME, addr SearchName, 25
.if ax==0
invoke MessageBox, hDlg,addr NoData, addr AppName, MB_OK+MB_ICONERROR
invoke GetDlgItem, hDlg, IDC_NAME
invoke SetFocus, eax
.else
invoke lstrlen,addr SearchName
mov StrLen,eax
invoke SendMessage, hList, LVM_DELETEALLITEMS,0,0
invoke SQLExecute, hStmt
invoke FillData
invoke SQLCloseCursor, hStmt
.endif
.else
invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt
invoke EndDialog, hDlg,0
.endif
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
QueryProc endp
end start</b></font>
</pre>
<h4><font face="Tahoma" color="#FFFFCC">分析</font></h4>
<pre><b><font face="Tahoma" color="#33CCCC">start:
invoke GetModuleHandle, NULL
mov hInstance,eax
call GetProgramPath</font></b></pre>
<p><font face="Tahoma" size="-1">當程序開始時,將獲得實例句柄并獲得所在路徑.默認情況下數據庫 test.mdb應與程序處于同一文件夾. </font><br>
</p>
<pre><font face="Tahoma"><b><font color="#33CCCC">GetProgramPath proc
invoke GetModuleFileName, NULL,addr ProgPath,sizeof ProgPath
std
mov edi,offset ProgPath
add edi,sizeof ProgPath-1
mov al,"\"
mov ecx,sizeof ProgPath
repne scasb
cld
mov byte ptr [edi+2],0
ret
GetProgramPath endp</font></b></font> </pre>
<p><font face="Tahoma" size="-1">GetProgramPath調用GetModuleFileName來獲得程序的全路徑名.接著在路徑中查找最后一個"\"符",通過將文件名的第一個字符置為0獲得(truncate)" 文件名. 因此我們在ProgPath中獲得了程序的路徑名.</font></p>
<p><font face="Tahoma" size="-1">然后程序將用<font color="#FFFFCC"><b>DialogBoxParam</b></font>顯示主對話框.當主對話框第一次被載入時,它將獲得菜單句柄和listview control句柄.接下來在listview control中插入三列(因為我們已經知道結果集將包含三列.因為是我們先建的表.)</font></p>
<p><font face="Tahoma" size="-1">現在,它就等待用戶的動作了.如果用戶在菜單中選擇"connect",將會調用<font color="#FFFFCC"><b>ODBCConnect</b></font>函數.</font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC">ODBCConnect proc hDlg:DWORD
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_NULL_HANDLE, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">它做的第一件事是調用<font color="#FFFFCC"><b>SQLAllocHandle</b></font>來分配一個環境句柄.</font><b><font color="#33CCCC"><br>
</font></b></font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> invoke SQLSetEnvAttr, hEnv,SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3,0
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">獲得環境句柄后,程序調用<font color="#FFFFCC"><b>SQLSetEnvAttr</b></font>來表示將要使用ODBC 3.x的語法.</font><b><font color="#33CCCC"><br>
</font></b></font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> invoke SQLAllocHandle, SQL_HANDLE_DBC, hEnv, addr hConn
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">如果一切順利,程序將通過調用<font color="#FFFFCC"><b>SQLAllocHandle</b></font>獲得連接句柄來實現連接.</font><b><font color="#33CCCC"><br>
</font></b></font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> invoke lstrcpy,addr ConnectString,addr strConnect
invoke lstrcat,addr ConnectString, addr ProgPath
invoke lstrcat, addr ConnectString,addr DBName</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">接著填寫連接字符串.完整的連接字符串將被用在<b><font color="#33CCCC">ConnectionString</font></b><br>
</font></font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> invoke SQLDriverConnect, hConn, hDlg, addr ConnectString, sizeof ConnectString, addr Conn, sizeof Conn,addr StrLen, SQL_DRIVER_COMPLETE
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SwitchMenuState,TRUE
invoke MessageBox,hDlg, addr Conn,addr ConnectCaption,MB_OK+MB_ICONINFORMATION</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">當連接字符串完成,程序將調用<font color="#FFFFCC"><b>SQLDriverConnect</b></font>來通過MS Access ODBC 驅動程序連接test.mdb數據庫.如果文件test.mdb不存在,ODBC driver將提示用戶輸入該文件的位置,因為我們已經設定了<font color="#CCFFCC"><b>SQL_DRIVER_COMPLETE</b></font>標志.當<font color="#CCFFCC"><b>SQLDriverConnect</b></font>成功返回時, <font color="#CCFFCC"><b>Conn</b></font> 被填入由ODBC驅動程序創建的完整連接字符串.我們通過一個message box來將其顯示給用戶. <font color="#CCFFCC"><b>SwitchMenuState</b></font>是一個單純切換菜單選項可用的函數.</font></font></p>
<p><font face="Tahoma" size="-1">現在,到數據庫的連接已經建立并被打開,并一直保持打開狀態直到用戶選擇關閉. </font></p>
<p><font face="Tahoma" size="-1">當用戶選擇了"View All Records"命令,
對話框過程將調用<font face="Tahoma" size="-1"><b><font color="#33CCCC">RunQuery.</font></b>函數
<br>
</font></font></p><font face="Tahoma" size="-1">
<pre><font face="Tahoma" size="+0"><b>
<font color="#33CCCC">RunQuery proc hDlg:DWORD
invoke ShowWindow, hList, SW_SHOW
invoke SendMessage, hList, LVM_DELETEALLITEMS,0,0</font></b></font></pre>
<p><font face="Tahoma" size="-1">由于listview control在創建時是不可見的,現在我們把它顯示出來.還有 要把其中的所有元素(如果有的話)刪掉.</font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC" size="+0"> invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">接下來,程序將獲得一個語句句柄.</font></font><br>
</p></font>
<pre><font face="Tahoma" size="+0"><b><font color="#33CCCC"> invoke SQLExecDirect, hStmt, addr SQLStatement, sizeof SQLStatement
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">通過<font color="#FFFFCC"> <b>SQLExecDirect</b></font>執行已準備好的SQL語句.我這里選擇<font color="#FFFFCC"><b>SQLExecDirect</b></font>
的原因是只須執行一次.</font><b><font color="#33CCCC"><br>
</font></b></font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> invoke FillData</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">執行SQL語句后,將返回一個結果集.我們使用<font color="#FFFFCC"> <b>FillData</b></font>函數來從結果集中解出數據并將其放入listview control中.</font></font></p>
<pre><font face="Tahoma"><font face="Tahoma"><b><font color="#33CCCC">FillData proc
LOCAL lvi:LV_ITEM
LOCAL row:DWORD
invoke SQLBindCol, hStmt,1,SQL_C_CHAR, addr TheName, sizeof TheName,addr NameLength
invoke SQLBindCol, hStmt,2,SQL_C_CHAR, addr TheSurname, sizeof TheSurname,addr SurnameLength
invoke SQLBindCol, hStmt,3,SQL_C_CHAR, addr TelNo, sizeof TelNo,addr TelNoLength</font></b></font></font></pre>
<p><font face="Tahoma"><font face="Tahoma" size="-1">現在,結果集被返回.我們要綁定結果集的所有三列到我們提供的緩沖區中.這是調用<font color="#FFFFCC"><b>SQLBindCol</b></font>來實現的.注意我們要對每一列分別調用.并且我們并不需要綁定所有的列:只要綁定要獲得數據的列就行了. </font><font face="Tahoma"><b><br>
</b></font></font></p>
<pre><font face="Tahoma"><font face="Tahoma"><b><font color="#33CCCC"> mov row,0
.while TRUE
mov byte ptr ds:[TheName],0
mov byte ptr ds:[TheSurname],0
mov byte ptr ds:[TelNo],0</font></b></font></font></pre>
<p><font face="Tahoma"><font face="Tahoma" size="-1">當列中沒有數據時,我們初始化緩沖區為NULLs.更好的方法是用<font color="#FFFFCC"><b>SQLBindCol</b></font>指定的變量中數據的長度.在我們的例子中,我們可以檢查<font color="#CCFFCC"><b>NameLength</b></font>,
<font color="#CCFFCC"> <b>SurnameLength</b></font>和<font color="#CCFFCC"><b>TelNoLength</b></font>中的值的確切長度.</font><font face="Tahoma"><b>
</b></font></font></p>
<pre><font face="Tahoma"><font face="Tahoma"><b><font color="#33CCCC"> invoke SQLFetch, hStmt
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
mov lvi.imask,LVIF_TEXT+LVIF_PARAM
push row
pop lvi.iItem
mov lvi.iSubItem,0
mov lvi.pszText, offset TheName
push row
pop lvi.lParam
invoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi</font></b></font><font size="-1" color="#33CCCC"> </font><font color="#33CCCC"><b> </b></font></font></pre>
<p><font face="Tahoma"><font size="-1">其它都很簡單了.調用<font color="#FFFFCC"><b>SQLFetch
</b></font>來獲得結果集的一行,并將其存入listview control的緩沖區中.當沒有更多的行供檢索時(已到達文件尾), <font color="#FFFFCC"><b>SQLFetch</b></font>返回<font color="#CCFFCC"><b>SQL_NO_DATA</b></font>并且程序跳出循環.</font></font><font face="Tahoma"><b><font color="#33CCCC">
</font></b></font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> invoke SQLCloseCursor, hStmt
invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">當完成對結果集的操作時,調用<font color="#FFFFCC"><b>SQLCloseCursor</b></font>關閉結果集并調用<font color="#FFFFCC"><b>SQLFreeHandle</b></font>釋放語句句柄.</font><font face="Tahoma" size="-1"><font color="#33CCCC"><br>
</font></font><font color="#33CCCC" face="Tahoma" size="-1"><br>
</font><font face="Tahoma" size="-1">當用戶選擇"Query"命令,程序顯示另一個對話框供用戶輸入要查詢的名字.</font></font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> .elseif uMsg==WM_INITDIALOG
invoke ShowWindow, hList, SW_SHOW
invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke lstrcpy, addr Conn, addr SQLStatement
invoke lstrcat, addr Conn, addr WhereStatement
invoke SQLBindParameter,hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,25,0, addr SearchName,25,addr StrLen
invoke SQLPrepare, hStmt, addr Conn, sizeof Conn</font></b></font></pre>
<p><font face="Tahoma" size="-1">對話框做的第一件事是顯示listview control.接下來分配一個語句句柄以創建SQL語句.這個SQL語句有一個"where"子句及一個參數標志符"?".
完整的SQL語句是:</font></p>
<blockquote>
<p><font face="Tahoma" color="#ffffcc" size="-1"><b>select * from main where name=?</b></font></p>
</blockquote>
<p><font size="-1" face="Tahoma">接著程序調用<font color="#FFFFCC"><b>SQLBindParameter</b></font>
來建立參數標志符與緩沖區<font color="#CCFFCC"><b>SearchName</b></font>的連接,這樣當SQL語句被執行時,ODBC驅動程序就可從<font color="#CCFFCC"><b>SearchName</b></font>中獲得需要的字符串.接下來,程序調用<font color="#FFFFCC"><b>SQLPrepare</b></font>來編譯SQL語句.
這樣我們只要準備/編譯SQL語句一次就可多次使用.因為SQL語句已被編譯過,接下來的執行過程會快一些.</font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> .if ax==IDC_OK
invoke GetDlgItemText, hDlg, IDC_NAME, addr SearchName, 25
.if ax==0
invoke MessageBox, hDlg,addr NoData, addr AppName, MB_OK+MB_ICONERROR
invoke GetDlgItem, hDlg, IDC_NAME
invoke SetFocus, eax
.else</font></b></font></pre>
<p><font face="Tahoma"><font size="-1">當用戶在編輯框(edit control)中填入了一些名字并按下回車鍵, 程序將獲得編輯框中的文本并檢查是否是空字符串.如果是,則顯示一個message box并將鍵盤焦點設在編輯框上,提示用戶輸入名字.<br>
</font><b> </b></font></p>
<pre><font face="Tahoma"><b><font color="#33CCCC"> invoke lstrlen,addr SearchName
mov StrLen,eax
invoke SendMessage, hList, LVM_DELETEALLITEMS,0,0
invoke SQLExecute, hStmt
invoke FillData
invoke SQLCloseCursor, hStmt</font></b></font></pre>
<p><font face="Tahoma" size="-1">如果編輯框中已有字符串,程序會獲得它的長度并將其放入<font color="#CCFFCC"><b>StrLen</b></font>中供ODBC驅動程序使用(記住我們已將StrLen的地址傳送給了<font color="#FFFFCC"><b>SQLBindParameter</b></font>).
接下來程序使用獲得的語句句柄調用<font color="#FFFFCC"><b>SQLExecute</b></font>執行已準備好的SQL語句.當<font color="#FFFFCC"><b>
SQLExecute</b></font>返回時,程序調用FillData在listview control顯示結果.因為我們不會再用到結果集,調用<font color="#FFFFCC"><b>SQLCloseCursor</b></font>來關閉它.</font></p>
<p align="center"><b><font face="Tahoma" size="-1"><a href="odbc-c4.htm">[<<]</a>
<a href="odbc-index.html">[index]</a> <a href="odbc-index.html">[>>]</a></font></b></p>
<hr>
<p align="center"><font face="Tahoma" size="-1"><b>[<a href="http://win32asm.cjb.net">Iczelion's
Win32 Assembly Homepage</a>]</b></font></p>
<p align="center"><b><font face="Tahoma" size="-1">[The Chinese Portion Is Translated By <a href="mailto:hw1979@263.net">Orochi</a> ,2000.8.24]</font></b></p>
<p> </p>
<p> </p>
</body>
</html>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -