This is the html version of the file http://myiecs.iecs.fcu.edu.tw/upload/paper_uni/912pdf/910230.pdf.
Google automatically generates html versions of documents as we crawl the web.
Page 1
逢 甲 大 學
資訊工程學系專題報告
◎◎◎PDA點餐系統◎◎◎
◎◎◎◎◎◎◎◎◎◎◎◎
涂 允 勝 (四甲)
學
生: 黃 振 註 (四甲)
黃 川 泰 (四甲)
指 導 教 授 : 黃 秋 煌
中華民國九十二年四月
I
Page 2
逢
甲
大
學
資
訊
工
程
學
系
專
題
報
告
P
D
A
點
餐
系
統
91
II
Page 3
III
Page 4
目錄
第一章、 緒論..............................................3
1.1、 動機.............................................3
1.2、 目標.............................................4
1.3、 系統簡介.........................................5
第二章、 背景..............................................6
2.1、硬體環境..........................................6
2.2、系統開發軟體......................................6
2.2.1 Visual Basic 6.0..............................6
2.2.2 Microsoft eMbedded Visual Basic 3.0...........6
2.2.3 資料庫的介紹..................................7
2.3、Winsock 介紹......................................17
2.3.1 建立 Server 端................................18
2.3.2 建立 Client 端................................19
2.4、無線網路介紹.....................................19
第三章、 系統架構.........................................22
3.0、資料正規劃與關連式資料庫說明.....................22
3.0.1、資料正規劃.....................................22
3.0.2、關連式資料庫...................................33
Page 5
1
3.1、系統架構.........................................36
3.1.1、Sever 端........................................37
3.1.2、Client 端......................................39
3.2、資料流程圖.......................................41
第四章、 系統實作.........................................43
4.1 Server 端.........................................43
4.1.1
Menu 資料庫..................................43
4.1.2
櫃檯的接收..................................55
4.2
Client 端.........................................62
第五章、 系統使用手冊.....................................75
5.1 PDA 點餐系統的建構.................................75
5.1.1
Server 端的建構..............................75
5.1.2
Client 端的建構..............................78
5.2 Server 端..........................................78
5.2.1 主畫面.......................................78
5.2.2
Menu........................................80
5.2.3
櫃臺........................................86
5.3 Client 端.........................................90
第六章、 結論與心得......................................107
Page 6
2
參考資料................................................113
附錄 A、.................................................115
附錄 B、.................................................146
附錄 C、.................................................185
Page 7
3
第一章、 緒論
1.1、動機
網路改變電腦的使用(LAN -> WAN ->Internet -> Wireless)。
檢視電腦帶給人們或社會最大的應用時,我們發現資料的溝通型
態,往往會帶來不僅電腦應用效益的改變,甚至社會工作型態與生活
方式的改變。當只有單一電腦時,在強大的運算功能或是資料庫管理
系統,也僅可以在定點為少數人所用,因此隨著區域網路的發展,電
腦成為企業組組織的工作的利器。然而網際網路更是將全世界的電腦
連接起來的大功臣,讓不管身在何處的人們,只要透過連上網際網
路,便可以與世界各地的電腦做溝通與資料交換。網路的連結其功效
便開始大大改變了工作方式,群組的工作溝通更加方便與有效率了,
人們的溝通互動不受地理的限制,生活與工作的模式也因網路可有所
改變。
無線上網環境逐漸成熟促成了行動商務
隨著無線上網的日益普及,無線通訊是網際網路另一波的革命浪
潮,擺脫了以往必須在定點上網的限制,無線上網讓工作與生活更具
Page 8
4
機動性,工作的進展將不再受制於時空環境設備的限制。在競爭日趨
激烈的數位時代裡,工作的即時性將越來越重要,速度與時間將成為
企業競爭的重要關鍵。行動工作的發展大致可分為以個人行動工作與
企業行動商務兩個發展主軸,輕薄短小結合無線通訊的 PDA 具有可攜
性與電腦的資料處理能力,帶動了所謂的「行動商務」發展。成為許
多企業下一波 e 化的重點。許多軟硬體資訊大廠的投入,都相繼宣布
投入行動商務服務的行列,宣告了行動商務的時代已經到來。
1.2、目標
目前大部分的餐廳仍是以傳統書面方式及定點式系統點餐,如果
餐廳的佔地較廣或正值用餐尖峰時間,則需花費較多的人力與時間往
返,而降低了服務的效率。為了解決此問題,打造無線行動點餐的環
境,提昇營運效率和服務品質。透過無線點餐系統達到即時、快速、
無紙化的點餐品質。無線點餐系統的行動性、可攜帶性帶來極大的便
利。透過 PDA 點餐系統,侍者點餐時只需要以畫面點選的方式,即時
記下客人的需求,經過確認後,透過無線網路將顧客所點的餐點傳送
到廚房與櫃檯。這當中,節省下侍者從餐桌走到廚房遞單、再移動至
櫃檯紀錄的時間,也縮短了顧客等候的時間。PDA 點餐系統是藉由行
動終端設備:PDA、PC 與無線網路設備,來達到工作人員可即時地進
Page 9
5
行點餐工作,再經由無線通訊方式傳輸至廚房;同時櫃台收銀區亦會
收到交易訊息,不需要額外的書面帳單的傳送、也不需要再將帳單重
新輸入,卻能讓多人同時分享資訊,可確實有效地提昇工作效率。特
別是在高峰時間,這套系統減少了不少人力與時間的支出,也降低了
點單錯誤的機率。而且,在客人的眼中,這套系統更留下了積極經營
的正面印象。
1.3、系統簡介
顧客的餐點經由無線區域網路設備,包含侍者手中的PDA、server
端的 PC、無線 AP、無線網路卡,將顧客的點餐傳送至廚房、櫃臺。
當顧客決定餐點的同時,廚師就可開始準備顧客已點用的餐點,不但
可節省時間快速上菜,提高顧客滿意度,還可降低點餐的錯誤,間接
降低時才成本,因為將菜單選項資訊電子化,透過侍者點選後加以確
認的方式,記錄顧客的需求,便減少了流程中因錯認侍者字跡、導致
廚房出單錯誤的機率。
Page 10
6
第二章、 背景
2.1、硬體環境
本組測試的硬體環境包含:
桌上型 PC 一組:作業系統 Windows2000、CPU800Mz、RAM512Mb。
PDA 一台:Ipaq3600、作業系統 Windows CE、CPU206Mz、RAM32Mb、
PDA 傳輸座。
無線網路:無線 AP、無線網卡 for PC and PDA。
2.2、系統開發軟體
2.2.1 Visual Basic 6.0
在 1965 年,大學教授 John G. Kemeny 以及 Thomas E. Kurtz 就已經
提出交談式學習程式語言的概念,為了這樣的需求,他們把當時最流
行的程式語言 Fortran 加以簡化,並且加入一些特點,創造出 Basic。
而隨著技術的演進,程式語言也由最基本的文字輸出輸入,演變成圖
形化的操作介面。於是微軟在 1991 年發表了 Visual Basic 1.0,提
供給 Windows 程式設計者另外一個選擇。如今的 Visual Basic 6.0
除了承襲了易學易用的特點之外,也新增了多媒體、資料庫、ActiveX
元件開發、Internet 程式開發等。
Page 11
7
2.2.2 Microsoft eMbedded Visual Basic 3.0
此程式語言專門針對開發 PDA 軟體而設計,eMbedded Visual Tools
可分為 eMbedded Visual Basic 3.0 以及 eMbedded Visual C++ 3.0。
本小組是採用 eMbedded Visual Basic 3.0 來設計 PDA 上的 Client
應用程式。eMbedded Visual Basic 3.0 可選擇要編寫 OS 程式或 Win
CE 程式。不僅可以藉由程式產生的 PDA 模擬器來測試軟體,也可直
接在 PDA 測試。編寫完的程式,可製作成一般安裝檔給其他相同系統
的 PDA 使用。
2.2.3 資料庫的介紹
2.2.3.1 資料庫基本概念
依資料結構的不同.資料庫可以被分類為關聯式.階層式.網狀式.
物件導向式等.而這些分類中又以關聯式資料庫最為大多數人所使用.
所謂的關聯式資料庫就是一種表格式(二維表格)的資料結構.依據資
料表的關聯(兩資料表間的一個連結)來做存取的動作.例如:當刪除
某一個客戶.資料庫可以依關聯找到客戶的訂單.一併刪除。
我們可以透過ADO.DAO.等資料控制項來操作.存取資料庫.同時.
類似一般控制像物件.對這些資料庫存取物件.仍可以適當地加入程
式碼.以增強其功能.我僅就資料庫結構的基本觀念與 SQL 指令的運
用加以探討.希望讀者對研讀更深入的資料庫課題會更有幫助。
Page 12
8
2.2.3.2 資料庫結構
資料庫的組織結構由上而下依序欄位(Field).紀錄(Record).資
料表(Table)而組成資料庫(Database).如表單所提菜單的資料庫中.
菜單的菜名,價格…等都屬於”欄位”.每道菜的欄位集合叫做一
筆”紀錄”.將這些同結構的紀錄集合起來.可以組成一個”資料
表”.一個或多個相關資料表又構成一個”資料庫”.而資料庫管理
系統(DBMS).便是用來管理資料庫的軟體.如 MS-SQL.Sybase.Oracle
等皆屬之。
(a) 欄位
每個欄位都會有個代表其欄位意義的名稱,在同一個資料表中,
欄位名稱是不可以重複的,欄位也會定義不同的資料型態,以便
存放各種資料。
(b) 紀錄
紀錄由多個欄位組成,如菜單的 table,每個紀錄就是一道菜,價
格及菜名就是其欄位,而每一道菜的紀錄就是由菜名和價格組
成。
(c) 資料表
資料表就是由相同的結構定義所組成,通常來表示某種分類如菜
單這個 table 就是一個資料表。
Page 13
9
2.2.3.3 開放資料庫連結協定(ODBC)
當我們要新增一筆資料至資料庫時.不同資料庫對於此一新增資料動
作的使用語法可能都不相同.但是在這種情形下.是否就意味著我們
必須針對不同的資料庫撰寫相對應的程式碼呢?
事實上.寫程式並沒有這麼麻煩.透過開放資料庫連結協定
(ODBC.Open Database Connectivity)當作我們存取資料庫的介面.
就可以輕易的存取不同資料庫.ODBC 是一種程式的”介面”.它讓應
用程式可以透過它存取支援”結構化查詢語言”(SQL)的資料庫資料.
當然.這樣的方便.必須透過 ODBC 驅動程式達成.也就是資料庫廠商
必須提供支援作業系統的ODBC驅動程式.舉例來說.如果我們以VB搭
配 Access 開發一個進銷存管理系統.突然有一天.我們想改用 MS-SQL
資料庫(例如資料量大到 Access 無法負荷或者速度的考量).透過
ODBC 的驅動程式.我們可以簡單幾個操作步驟將整個系統轉移.而不
必重新開發.這便是使用 ODBC 的特異功能.它將不同資料庫資料存取
的責任.都封裝到相對應的驅動程式.也就是說.ODBC只提供應用程式
與資料庫之間連結的介面.而它實際上如何處理(也就是實作).並不
需要程式設計者煩惱.因為.它是執行階段由資料庫那一端實作的.就
好像使用 Word 列印時.只要安裝.指定列印機的驅動程式這麼簡單
接下來.我們概要說明 ODBC 的架構.ODBC 包含應用程式.驅動程式管
Page 14
10
理者.驅動程式.資料來源四個構成要素。
[1]應用程式 (Application)
主要負責執行一個行程.選擇要連結的”資料來源”.傳遞 SQL 敘述
(透過呼叫 ODBC 函數).取得傳回結果.處理錯誤.交易確認與取消及
中斷連結資料來源。
[2]驅動程式管理者 (Driver Manager)
驅動程式管理者主要工作是將應用程式的 ODBC 函數呼叫傳遞到正確
的驅動程式.它也可以直接處理幾個 ODBC 函數呼叫及基本的錯誤檢
查.驅動程式管理者另一個重要的工作就是載入.載出驅動程式.前述
的應用程式.則只負責載入.載出驅動程式管理者。
[3]驅動程式 (Driver)
驅動程式用來實作 ODBC 函數.因此.當應用程式呼叫存取不同資料庫
的 ODBC 函數時.也需有不同的驅動程式來實作這些函數(功能).傳遞
SQL 指令的要求.或者傳回查詢結果給應用程式。
事實上.驅動程式最重要的功能之一.就是把應用程式接收的 SQL 指
令(透過 ODBC函數呼叫)轉換為指定資料庫看得懂的SQL命令.並傳遞
給相對應的資料來源。
[4]資料來源 (Data Sources)
資料來源可以是檔案.DBMS 的資料庫等.其主要目的是匯集應用程式
Page 15
11
存取資料庫所需的全部資訊(包括驅動程式名稱.IP 位置等).它也可
以是作業系統或網路平台上的一個資料庫管理系統。
我們針對 WIND0WS98 的 ODBC 資源設定解說吧。
首先點選 Windows 視窗下的[ 開始>設定>控制台>ODBC 資料來源
(ODBC Data Source) ].以便進入”ODBC 資料來源管理員(ODBC Data
Source Administrator)”視窗 (如下圖)
(圖 2-1)
在進入 ODBC 資料來源管理員視窗後.視窗中有三種與資料來源有關
的標籤頁可供設定”資料來源名稱”.分述如下:
[a]使用者資料來源名稱 (User DSN)
設定在這個標籤頁的資料來源只能提供給本機電腦使用.並糗只有目
Page 16
12
前的使用者才可以使用。
系統資料來源名稱 (System DSN)
設定在這個標籤頁的資料來源只能提供給本機電腦使用.不果只要是
在這個系統上或是其他具有存取權限的使用者都可以使用此資料來
源。
[c]檔案資料來源名稱 (File DSN)
設定在這個標籤頁的資料來源可以被安裝同一個驅動程式的所有使
用者使用.此種資料來源並不限定某一個使用者身上或某一個本機電
腦上.檔案資料來源並不以資料來源紀錄我們所設定的資料來源.而
是以檔案名稱紀錄。
前述三種資料來源.雖然使用對象不同.但設定的方式幾乎是一樣的.
因此.我們直接以”使用者的資料來源名稱”頁籤設定.說明如何新
增.刪除與修改聯結 MDB 格式資料庫檔案的資料來源.分述如下:
(一)新增資料來源名稱 (User DSN)
要在”使用者資料來源”名稱頁籤建立 MDB 格式資料庫檔案的連
結。其步驟如下:
步驟一:
再使用者資料來源名稱的標籤頁下點選”新增”鈕.進入”建立資料
來源(Create New Data Source)”視窗 (如下圖)
Page 17
13
(圖 2-2)
在進入”建立新資料來源”視窗後.選擇驅動程式名稱
為”Microsoft Access Driver (*.mdb)”.按”完成”鈕進入”ODBC
Microsoft Access 設定”視窗。
步驟二:
在”ODBC Microsoft Access 設定”視窗中.輸入資料來源名稱(名稱
可自訂.假設我們輸入 MyExDSN)並且選取要存取資料庫來源.要設定
資料庫來源.只要點選”選取(Select)”鈕.於蹦現出的”選取資料
庫”視窗.選擇所要的資料庫檔案(假設我們選擇範例光碟所附的
Data.mdb檔.並請確定此檔以複製到硬碟以及唯讀屬性已去除).完成
後按”確定(OK)”鈕返回 ODBC Microsoft Access 設定視窗 (如下
圖)
Page 18
14
(圖 2-3)
步驟三:
在”ODBC Microsoft Access 設定”視窗下點選”確定(OK)”鈕後.
回到”ODBC 資料來源管理員(ODBC Data Source Adminstrator)”視
窗.此時.在使用者資料來源的列表中.便會發現新增的資料來源名
稱.”db1”.已將顯示在使用者資料來源列表上了。
(二)移除資料來源名稱
當我們要刪除資料來源列表中.已存在的資料來源名稱.只要在 ODBC
資料來源管理員視窗內.選擇所要刪除的資料來源名稱.再點選”移
除(Remove)”鈕即可。
(三)變更資料來源名稱內容
要變更資料來源列表中已存在的資料來源.只需要在 ODBC 資料來源
Page 19
15
管理員視窗內.選擇要變更內容的資料來源.再點選”設定
(Configure)”鈕.就會回到新增時看到”ODBC Microsoft Access 設
定”視窗 (如上圖).與新增相同.包括資料來源名稱.資料庫與其他
選項都可以重新設定.完成後按”確定”鈕返回”ODBC資料來源管理
員”視窗。
2.2.3.4 SQL
結構化查詢語言(Structured Query Language)是一種對資料庫查
詢,存取與管理的標準語言,它使用一些簡單的音文字母句子組合
起來,相單簡單而且彈性高.SQL 既然是一種資料庫使用的語言,它
便會有一些規則.限制,比較糟糕的是,並非所有的資料庫管理系
統,都使用一模一樣的 SQL 指令.因此,要對資了庫下達某些叫特殊
的指令時,應該先參考資料庫技術手冊,了解它是否支援我們下達
的指令,或者該如何將指令修改為該資料庫接受的格式
以下是 SQL 的示範。
所需材料的 table
Page 20
16
(圖 2-4)
素材的 table
(圖 2-5)
我所使用的 SQL 敘述是用 join。
SQL 敘述:
select 所須材料.菜名,素材.素材名,素材.種類 From 所須材料,素
Page 21
17
材 where 所須材料.材料 = 素材.素材名
結果:
(圖 2-6)
2.3、Winsock 介紹
Socket 是一個網路的終點,結合了 IP 位址和通訊埠號碼。Socket 這
個字被用做一個隱喻,因為 socket 內所含的資訊可以直接插入目的
地電腦上被要求的處理程序中。Socket 可以用來識別 Intetnet 上任
何地方所執行的應用程式。
Page 22
18
Berkeley Socket(SBD Socket),是一個網路城市介面的名稱,已經
廣泛的被應用在 UNIX 中,作為 TCP/IP 的通訊工具。BSD Socket API
也可以運用在視窗上,稱為 Windows Sockets,或稱為 WinSock,
WinSock 包含了許多功能,以 Windows 為基礎的應用程式設計,Socket
是 Interner 程式設計可以做到的最低階方式。
Winsock Control 運作原理
程式設計師可以用 Winsock Control 元件,讓程式透過 TCP/IP 或紅
外線傳輸(IrDA)來傳遞資料。這個元件使用方式如下:
2.3.1 建立 Server 端
2.3.1.1 決定程式要當作 Server 端或 Client 端。假設要建立一個
TCP/IP 的 Server 端程式,先把 Winsock Control 元件的 Protocal
屬性設定成 sckTCPProtocal,並且把 Server 程式所要接受資料的
port 指定給 LocalPort 屬性。在設定好這些屬性之後,就可以呼叫
Listen 等待連接。
2.3.1.2 當有 Client 程式要連結到 Server 端的時候,Server 端的
Winsock Control 元件會產生 ConnectionRequest 這個事件,以
Accpet 來接受 Client 端的連線要求。
2.3.1.3 連線完成後,Winsock Control 的 State 屬性會被設定成
sckConnected,這時候就可以開始傳送資料。
Page 23
19
2.3.1.4 當資料傳到 Server 時,Winsock Control 元件,會產生
DataArrival 事件,通知程式有資料送達。如果要接受資料,使用
GetData 來接受該資料。
2.3.1.5 如果要使用 Winsock Control 元件傳送資料的話,使用
SendData,資料就會傳送至 RemoteHostIP 以及 RemotePort 這兩個屬
性所指定的地方。在傳送資料的過程中,會產生 SendProgress 事件,
傳送完畢之後,會產生 SendComplete 事件。
2.3.1.6 當要結束連線的時候,使用 Close 來中斷連線。連線中斷之
後,產生 Close 事件。
2.3.1.7 如果在上述過程中發生錯誤,Winsock Control 會產生 Error
事件,可將錯誤處理的程式碼放在此處。
2.3.2 建立 Client 程式
2.3.2.1 要建立用戶端程式,首先要設定好 RemoteHost 以及
RemotePort 屬性,並使用 Connect 來向 Server 要求連線。
2.3.2.2 連線建立之後,程式就可以使用 SendData 以及 GetData 來
傳遞或接收資料。
2.4、無線網路介紹
Page 24
20
隨著 IEEE802.11b 標準的制定,無線傳輸的速率最快可達到 11M
bps,加上主要網路設備廠商相繼投入,使得無線區域網路已漸漸受
到重視,大家都希望能透過無線網路連結原本有線區域網路,以增加
使用者的移動性及減少不必要的佈線需求。透過無線的方式雖然增加
了不少便利性,但是大家關心的是這種無線上網的方式是否容易管
理、擴充性如何及最重要的網路安全議題。
在無線區域網路的安全議題上面,主要包括處理的控制及資料傳
輸的隱密性兩個議題。在處理的控制方面是要讓只有授權的使用者能
處理重要的資料。隱密性則是要確保資料正確傳輸且不被竊取。由於
無線網路是使用 radio wave 方式在大氣中傳遞資料,所以架設無線
網路就好似到處裝設 Ethernet Ports,由於並沒有方向性或特定目
標,因此資料的保密性就成為很關鍵的重點。
一般無線區域網路要解決安全問題,通常是使用 SSIDs(service
set identifiers)及 WEP(wired equivalent privacy)。SSIDs 是在
插有無線網卡的終端設備上設定名稱,依此來判定處理的權限,而負
責接收並與一般區域網路連結的 Access Point 則會廣播其本身的
SSID,而這種 SSID 的安全性往往不足。而 WEP 方式是可以設定在傳
輸資料是以加密的方式進行,互相通訊的雙方使用相同的 key 及演算
Page 25
21
法,key 的管理就顯得格外重要。IEEE802.11b 標準定義兩種型式的
認證,open 及 shared key。Open key 是透過未加密的方式傳送 key
來認證,而 shared key 則是由 Access Point 先傳送一個封包給終端
設備,在由終端設備依照正確的 WEP key 來加密並回傳給 Access
Point,假如 key 值正確即通過認證。也有產品直接以網卡上的 MAC
位址直接做認證。
但目前方式也有些潛在威脅:由於 WEP 或 MAC 是與終端設備結
合,故需防止設備遺失或遭竊,若發生必須要能即時通知管理者,以
進行資料及靜態 key 值的修改並通知所有的接取設備;而 EP 認證方
式是單方向由 access point 對使用者來認證,有心人事可利用非授
權的 access point 來阻絕提供使用者服務。另外,WEP 是對每封包
加以封裝而非加以授權,駭客可能破壞資料封包。
Page 26
22
第三章、 系統架構
3.0 資料庫的正規劃與關連式資料庫的說明
3.0.1 資料正規化
何謂正規化
將表格細分成多個更小的表格,直到每個表格只描述一種事實為
止,這一連串的調整過程就稱為資料正規化(Normalization)。
3.0.1.1 目的
正規化的目的何在?簡單的說就是要將資料的重覆性降至最低
(避免資料重複的狀況發生)。倘若在不同的表格中都有學生的姓名
時,一旦有個學生改名了,則必須同步更改多個表格的內容;修改的
過程中若稍有遺漏,有些資料沒更正,就會發生不一致的狀況。因此,
避免資料重複是相當重要的。
3.0.1.2 步驟
第一正規化(First Normal Form,簡稱 1NF。由 E. F. Codd 提出)
第二正規化(Second Normal Form,簡稱 2NF。由 E. F. Codd 提出)
第三正規化(Third Normal Form,簡稱 3NF。由 E. F. Codd 提出)
Boyce/Codd 正規化(Boyce/Codd Normal Form,簡稱 BCNF。由 R. F.
Boyce 與 E. F. Codd 共同提出)
第四正規化(Fourth Normal Form,簡稱 4NF。由 R. Fagin 提出)
Page 27
23
第五正規化(Fifth Normal Form,簡稱 5NF。由 R. Fagin 提出)
3.0.1.3 實例探討
假設我們將要設計一個成績單郵寄列印系統,需要學號、地址、
郵遞區號、學科代碼與各科成績等資料,而初步搜集到的原始資料如
下表所示:
Stu_no City ZIP
Subject_no, Score
75312 台中市 400
(S5302, 89), (S5345, 90),
(S8005, 78), (S3581, 80),
(M1201, 65), (M5251, 95)
75524 高雄市 800 (S5302, 88)
75302 高雄縣 830
(S5302, 98), (S5345, 90),
(S3581, 84), (M5251, 85)
(表 3-1)
接下來,我們將依序探討 1NF, 2NF 與 3NF 的過程。
1. 第一正規化(First Normal Form)
條件
第一正規化的表格最重要的是能滿足「每個欄位只能含有一個值」這
個條件。
正規化
Page 28
24
原始表格:
Stu_no City ZIP
Subject_no, Score
75312 台中市 400
(S5302, 89), (S5345, 90),
(S8005, 78), (S3581, 80),
(M1201, 65), (M5251, 95)
75524 高雄市 800 (S5302, 88)
75302 高雄縣 830
(S5302, 98), (S5345, 90),
(S3581, 84), (M5251, 85)
(表 3-2)
在正規化之後,我們將表格命名為 A:
《A》
Stu_no City ZIP Subject_no Score
75312 台中市 400
S5302
89
75312 台中市 400
S5345
90
75312 台中市 400
S8005
78
75312 台中市 400
S3581
80
75312 台中市 400
M1201
65
Page 29
25
75312 台中市 400
M5251
95
75524 高雄市 800
S5302
88
75302 高雄縣 830
S5302
98
75302 高雄縣 830
S5345
90
75302 高雄縣 830
S3581
84
75302 高雄縣 830
M5251
85
(表 3-3)
結果討論
在同一學生只能選修同科目一次的條件下,「Stu_no」加上
「Subject_no」可以做為 A 的主鍵(Primary key)。我們以下圖來
說明主鍵與其他欄位之間在功能上的相依關係(Functional
Dependency):
(圖 3-1)
在 A 之中係以(Stu_no, Subject_no)為 Primary key,但從上圖
看來,有三項「功能相依」關係是錯誤的(如紅線所示),City 與 ZIP
的值與 Subject_no 絲毫無關。
Page 30
26
在這樣的架構下,將產生下列問題:
1. 無法單獨新增一筆學生資料。因為 Subject_no 是 Primary
key 之一,不能為空值(Null);因此,一個未修習任何課程學
生的資料,將無法寫入 A。
2. 無法單獨刪除一筆成績資料。如果我們打算刪除(75524,
S5302)這筆資料的話,該生的地址資料也將一併消失。
3. 需要同步異動的資料太多。假如 75312 這個學生搬家了,那麼
我們得異動其中的 6 筆紀錄。
2. 第二正規化(Second Normal Form)
條件
一個表格必須滿意第一正規化的條件,並且非主鍵的欄位都要對主鍵
有「完全地功能性相依(Fully Functional Dependency)」關係,才
能算是達到第二正規化。
正規化
已合乎 1NF 的表格 A:
Stu_no City ZIP Subject_no Score
75312 台中市 400
S5302
89
75312 台中市 400
S5345
90
Page 31
27
75312 台中市 400
S8005
78
75312 台中市 400
S3581
80
75312 台中市 400
M1201
65
75312 台中市 400
M5251
95
75524 高雄市 800
S5302
88
75302 高雄縣 830
S5302
98
75302 高雄縣 830
S5345
90
75302 高雄縣 830
S3581
84
75302 高雄縣 830
M5251
85
(表 3-4)
在正規化之後,我們將表格 A 一分為二,並分別命名為 B1 與 B2:
《B1》
Stu_no City ZIP
75312 台中市 400
75524 高雄市 800
75302 高雄縣 830
《B2》
Stu_no Subject_no Score
75312
S5302 89
75312
S5345 90
75312
S8005 78
75312
S3581 80
Page 32
28
75312
M1201 65
75312
M5251 95
75524
S5302 88
75302
S5302 98
75302
S5345 90
75302
S3581 84
75302
M5251 85
(表 3-5)
結果探討
在經過 2NF 之後,先前的「無法單獨新增一筆學生資料」與「無法
單獨刪除一筆成績資料」的問題都解決了。我們再看看 B1 與 B2 各
欄位和主鍵之間在功能上的相依關係(Functional Dependency):
(圖 3-2)
Page 33
29
(圖 3-3)
在一個表格中,如果某一欄位值可決定其他欄位值;而這些欄位中又
存在某一欄位可以決定剩餘欄位的值,稱為「遞移相依性(Transitive
Dependency)」。若有此一情況發生,在異動資料時,可能會造成其他
資料不一致的現象。
在 B1 之中便有「遞移相依性」關係存在:B1.Stu_no -> B1.City 且
B1.City -> B1.ZIP 。
在這樣的架構下,將產生下列問題:
1. 無法單獨新增一筆縣市資料。因為 Stu_no 是 Primary key,
不能為空值(Null);因此,若無任何學生居住的某個縣市,其
郵遞區號資料將無法被事先建立。
2. 無法單獨刪除一筆學生資料。如果我們打算刪除 75524 這筆資
料的話,該生所在的高雄市郵遞區號資料也將一併消失。
3. 仍有需要同步異動的資料。假如台中市的郵遞區號修改了,且
住在該地區的學生又不只一位時,那麼我們又得異動多筆紀錄
了。
Page 34
30
3. 第三正規化(Third Normal Form)
條件
一個表格必須滿意第二正規化的條件,並且消除「遞移相依」現象,
意即非主鍵的欄位之間沒有「完全地功能性相依」關係,才能算是達
到第三正規化。
正規化
已合乎 2NF 的表格 B1:
Stu_no City ZIP
75312 台中市 400
75524 高雄市 800
75302 高雄縣 830
(表 3-6)
在正規化之後,我們將表格 B1 再度一分為二,並分別命名為 C1 與
C2:
C1》
Stu_no City
《C2》
City ZIP
Page 35
31
75312 台中市
75524 高雄市
75302 高雄縣
台中市 400
高雄市 800
高雄縣 830
(表 3-7)
結果探討
在經過 3NF 之後,先前的「無法單獨新增一筆縣市資料」與「無法
單獨刪除一筆學生資料」的問題都解決了,需要同步異動大量資料的
情況似乎也不復存在了。我們再以表格與欄位間的相依關係來看看正
規化的結果:
《C1》
Stu_no City
75312 台中市
75524 高雄市
75302 高雄縣
《C2》
City ZIP
台中市 400
高雄市 800
高雄縣 830
《B2》
Stu_no Subject_no Score
75312
S5302 89
75312
S5345 90
75312
S8005 78
75312
S3581 80
75312
M1201 65
75312
M5251 95
Page 36
32
75524
S5302 88
75302
S5302 98
75302
S5345 90
75302
S3581 84
75302
M5251 85
(表 3-8)
(圖 3-4)
(圖 3-5)
(圖 3-6)
Page 37
33
一般表格進行至第三正規化時,多半沒有什麼狀況了;倘若仍有異常
狀況發生,則需繼續進行 Boyce-Codd 及第四、第五種正規化格式,
但實務上不常發生。
Boyce-Codd 正規化
將多個候選鍵中挑出一個決定因子作為主鍵。
4NF
去除多值相依性。
5NF
克服合併相依性。
正規化只是建立資料表的原則,而非鐵律。切莫因為過度正規化,
反而導致資料存取的效率下降。有時在優先考量執行效率的前提下,
我們還必須做適當的反正規化(Denormalize)。
(以上資料來源 http://chensh.loxa.edu.tw/php/B_2.php)
3.0.2 關聯式資料庫
3.0.2.1 資料
在日常生活中,我們會面對許多不同型態的資料,如親朋好
友的通訊資料、個人行程計畫等等。為了保存這些資料,我們會
自定一些規則,將它們有組織地記錄在紙張或電腦上,以便將來
取用。我們用這樣的方法長期保存資料,就算是一種「資料庫」。
Page 38
34
3.0.2.2 資料模型
前面提到,我們會自定一些資料記錄的規則,將資料庫以固定的
架構來組成;而用來表示資料庫如何組成的架構,稱為資料模型。
關於資料模型的理論不少,其中最為著名的是「關聯式資料模型」
(relational model of data),這是 E. F. Codd 博士(數學家,
IBM 的研究人員)於 1970 年在「A Relational Model of Data for
Large Shared Data Banks」這篇論文中所提出的。
這項理論隨後不斷地被討論與修正,到 1980 年前後開始有「關
連式」的資料庫產品上市;自此之後,資料庫方面的發展與研究
幾乎都是「關連式」的天下了。
3.0.2.3 關聯式資料庫
什麼樣的資料庫系統才是「關連式」的呢?簡單地說,「關連式系
統」就是:
1. 使用者看到的都是表格。
2. 使用者可使用的運算子,都是從舊表格中產生新表格。這些
運算子至少包括 RESTRICT(SELECT)、PROJECT 與 JOIN。
換句話說,「關連式系統」的特徵就是其利用表格來呈現資料,然
後將表格視為集合來進行處理。當要操作資料時,便是針對表格
Page 39
35
去執行以集合理論為基礎的數學運算,而其執行結果還是表格。
表格
下圖是一個「表格」(table),其中縱向的稱為「行」(column),
或是稱為「欄」(field),存放著相同性質的資料。橫向的稱為
「列」(row),或是「記錄」(record),裡頭包含許多不同性質
的資料項目。這個表格有 4 欄 3 列。
(圖 3-7)
圖中黑色名詞與紅色名詞的意義相近,雖然在大多數的場合它們
也被視為同義詞,但後者的定義較為嚴謹,才是符合數學理論的
正式名稱。
3.0.2.4 運算
關連式資料模型是以數學的集合理論為基礎,Codd 博士定義了
八個運算子(operator),用來對關聯式資料模型做數學運算。運
算後的結果會再度成為一個資料表(relations in, relations
Page 40
36
out),而且這個資料表也能再度進行運算。透過這樣不斷地運算,
便可導出所需的結果來。這八個運算子之中,前四個是傳統的集
合運算(union, intersection, difference, and Cartesian
product),後四個則是特殊的關聯式運算(restrict, project,
join, and divide)。
(圖 3-8)
舉個例子來看,從通訊錄中取出所有性別為「女性」的資料列,
Page 41
37
這就是「restrict」運算;若取出「姓名」與「電話」這兩欄的
所有資料,則屬於「project」運算。
(資料來源 http://chensh.loxa.edu.tw/php/B_2.php)
3.1、系統架構
系統基本架構包含:資料庫、Server 端與 Client 端(PDA),(圖 3-9)
可說明這三大主體的連結。Server 負責連結資料庫與 Client,並存
取資料庫裡的資料。Client 端,透過 Server 來讀取 Menu,作為讓顧
客點菜使用,顧客點好的菜單,Client 端送出命令給 Server,Server
接收之後傳送到櫃臺與廚房,讓廚房人員收到哪一桌,點了什麼菜,
由此資訊開始廚房的作業。
Page 42
38
(圖 3-9)
3.1.1 Server 端
Server 端,分為兩個最主要的部分,Menu 跟 Menu 的接收部分。
Server 端還負責確認使用者登入,判斷是否是存在的使用者,
Menu 的部分,採用 Microsoft Access 建立,包含幾個資料表:
pass 資料表:使用者的名稱與密碼。
VIP 資料表:顧客姓名、聯絡電話與優待折數。
素材資料表:各餐點所需的基本材料。
餐點資料表:包含各種餐點的單品名稱、價格。
Menu 的接收部分,主要是負責接受 Client 傳送的點餐資料。將所送
達的點餐資料,顯示給廚房人員觀看,讓廚房人員知道哪一桌,點了
Page 43
39
什麼菜色。
3.1.2、Client 端資料流程圖
(圖 3-10)
Page 44
40
(圖 3-10)顯示出結帳的資料流程圖,先決定欲結帳的桌次,讀取該
桌次的資料,所點的餐點明細、金額。決定折扣與否,確定之後,將
此消費記錄存入。
(圖 3-11)為一般人工作業、辦自動化點餐作業與自動化點餐作
業的比較圖。其中有幾點主要的差別。
1. 人工作業所有的動作,包含點餐、菜單的紀錄與遞送,都透過人
力來完成。
2. 辦自動化點餐作業,點餐與菜單的紀錄由人力完成,而菜單的傳
遞,則透過電腦傳輸。可節省往返廚房與櫃臺的時間。
3. 全自動化點餐作業,點餐、菜單的紀錄與傳遞、都透過電腦來傳
遞資料,服務生只需要做確認即可。不需要來回往返廚房、櫃臺,
尤其佔地較廣的餐廳,可以藉此省下更多的時間成本。
Page 45
41
(圖 3-11)(摘錄自”電腦科技雜誌”)
3.2、資料流程圖
(圖 3-12)為 Menu 的資料流程圖,作業功能說明:
1. 進入 Menu 頁之後,會先顯示出各餐點的資料,經由使用者動作,
Page 46
42
可進入 Menu 的新增、編輯、刪除、修改或者離開該頁面。
(圖 3-12)
Page 47
43
第四章、 系統實作
4.1 Server 端
4.1.1 Menu 資料庫
資料庫的是用關聯式資料庫,關聯式資料庫主要有下面幾個原則
(資料來源 http://www.dyu.edu.tw/~msung/OfficeAuto/Access/
Ref_Integrity.htm )
1.
在資料庫中形成關聯的兩個資料表格中之間的維護關
係,Access 藉由設定永久性關聯來達成。
2.
可將所有分散的資料整合在一起﹐應用於查詢、印表、統
計等工作上
3.
資料庫關聯圖視窗主要用來建立、檢視、及修改各資料表
間的永久性關聯。
資料庫有正規化, 正規化就是在資料庫內,相同的資料可由不同
的方式儲存。資料庫表格的設計會影響到未來資料管理、更新、
使用上的效率。正規化就是確保資料庫效率所發展的技巧。以一
步步正規化組織之檔案資料以設計資料庫之方法,可以克服在
update、insert、delete 時可能發生之問題。我是用 2NF 的方
式去做的,以下是我的資料庫格式。
Schema
Page 48
44
Table 1
帳號密碼表(pass)
欄位 欄位名稱
資料型態
Null 額外資訊
ID User Varchar
No 主鍵
PWD Password
Varchar
No
===========================================================
Table 2
菜單
欄位 欄位名稱
資料型態
Null 額外資訊
Name
菜名
Varchar
No
主鍵/排序
Price 單價 Int No
===========================================================
Table 3
訂單
欄位 欄位名稱
資料型態
Null 額外資訊
Name 菜名 Varchar
No
Amount 數量 Int
No
Page 49
45
Table 4
材料
欄位 欄位名稱
資料型態
Null 額外資訊
Name 素材名 Varchar
No 主鍵
Kind 種類 Varchar
No
Amount 數量 Int
No
Table 5
所需材料
欄位 欄位名稱
資料型態
Null 額外資訊
MenuName 菜名
Varchar No
主鍵
Name 素材名 Varchar
No
===========================================================
Table 6
套餐
Page 50
46
欄位 欄位名稱
資料型態
Null 額外資訊
Num 編碼 Int No
Name 菜名 Varchar
No 主鍵
Price 價格 Int No
===========================================================
Table7
點心
欄位 欄位名稱
資料型態
Null 額外資訊
Num 編碼 Int No
Name 菜名 Varchar
No 主鍵
Price 價格 Int No
===========================================================
Table 8
湯類
欄位 欄位名稱
資料型態
Null 額外資訊
Num 編碼 Int No
Name 菜名 Varchar
No 主鍵
Page 51
47
Price 價格 Int No
Table 9
菜單種類
欄位 欄位名稱
資料型態
Null 額外資訊
Name
菜名
Varchar
No
主鍵/排序
Kind 種類 Varchar
No
===========================================================
Table 10
顧客資料(vip)
欄位 欄位名稱
資料型態
Null 額外資訊
Name
菜名
Varchar
No
主鍵/排序
Price 單價 Int No
我是使用 2NF 但不是 3NF,因為我不能單獨對一表格的單一資料作處
理及新增刪除等動作(因為資料有「遞移相依性(Transitive
Dependency)」) 。
2NF 有啥缺點?請看下一段程式碼那是一個新增菜單的程式碼
新增程式碼:
Page 52
48
Private Sub cmdAdd_Click()
Dim kind As String
Dim num As Integer
Dim rmsg As String
If textadd1.Text = "" Or textadd2.Text = "" Or textkind1.Text
= "" Or Text3.Text = "" Or Text4.Text = "" Then
Beep
rmsg = MsgBox("請輸入要菜名及價格", vbOKOnly, "訊息")
Exit Sub
End If //確定新增菜的資料都有輸入
Set cc3 = New ADODB.Connection //以下皆為打開菜單種類資料流
的動作
Set rr3 = New ADODB.Recordset
cc3.ConnectionString = "dsn=db1"
cc3.Open
rr3.Open "菜單種類", cc3, adOpenStatic, adLockOptimistic
rr3.AddNew
//新增菜單在菜單種類上
rr3!菜名 = textadd1.Text
rr3!kind = textkind1.Text
Page 53
49
rr3.Update
kind = textkind1.Text
rs.AddNew //新增菜單在菜單上
rs!菜名 = textadd1.Text
rs!kind = textkind1.Text
rs!價格 = CLng(textadd2.Text)
Set cn0 = New ADODB.Connection
Set rs0 = New ADODB.Recordset
cn0.ConnectionString = "dsn=db1"
cn0.Open
rs0.Open "所須材料", cn0, adOpenStatic, adLockOptimistic//
以下皆為打開所需材料資料流的動作
rs0.AddNew //新增所需材料
rs0!菜名 = textadd1.Text
rs0!材料 = Text3.Text
rs0.AddNew
rs0!菜名 = textadd1.Text
rs0!材料 = Text4.Text
rs0.Update
Page 54
50
Set cn1 = New ADODB.Connection //以下皆為打開各個種類菜單
的資料流動作
Set rs1 = New ADODB.Recordset
cn1.ConnectionString = "dsn=db1"
cn1.Open
rs1.Open kind, cn1, adOpenStatic, adLockOptimistic
rs1.MoveLast
num = rs1!編碼
num = num + 1
rs1.AddNew //新增菜在各類菜單
rs1!編碼 = num
rs1!菜名 = textadd1.Text
rs1!價格 = textadd2.Text
rs1.Update
Set cc2 = New ADODB.Connection
Set rr2 = New ADODB.Recordset
cc2.ConnectionString = "dsn=db1"
cc2.Open
rr2.Open "訂單", cc2, adOpenStatic, adLockOptimistic
Page 55
51
rr2.AddNew
rr2!菜名 = textadd1.Text
rr2!數量 = "0"
rr2.Update
End Sub
以下是執行結果當我新增一筆菜單時我的 table 會有很多變動
如我新增一筆菜單像是海陸大餐
(圖 4-1)
Page 56
52
結果有 4 個 table 增加此菜
(圖 4-2)
(圖 4-3)
(圖 4-4)
Page 57
53
(圖 4-5)
可以注意到我的程式碼中有很多的動作都是在打開 table 的動作,
因為我用 2NF 的正規化,並沒有用到 3NF。這樣再做一個動作就必須
做很大的同步處理我沒用 3NF 的正規化的原因是因為我當初想要做
各各表單的 show 出表現而以並沒想想到要做的資料處理簡便,這是
我當初所沒想到的,而且每個表單的都有相關性。
做完這個資料庫的時候讓我知道下一次要做資料庫至少要做到3NF,
要不然會有很多的時間及系統資源都在做同步處理,而且在程式
debug 時就不會太麻煩,因為我在寫這個程式時最麻煩的就是再新增
及修改菜單時所花費的處理錯誤的時間上, 如果用 3NF 的話我想會
對程式的撰寫方面姐化很多,因為只要把每個動作做的沒問題就好,
Page 58
54
不需要對各個表單做檢查。
4.1.2 櫃檯
Server 端,採用 Visual Basic 6.0 編寫。在這個功能選
項底下,有一個建立新專案選項,選取之後,建立一個一般執行檔專
案,會自動產生一個新的 Project,並產生一個 Form1(圖 4-6)。
(圖 4-6)
在(圖 4-6)Form1 的畫面,可以再增加許多 Objects,如 Command
Buttom 或 Label,選取某一個物件,例如選取 Command Button 之後,
可由畫面右下角的屬性欄,建立修改該物件的資料。例如這個Command
Button 的顏色、字體、Caption、外框大小、畫面的位置之類的基本
設定。如(圖 4-7)
Page 59
55
(圖 4-7)
雙擊 Command Button,會出現另外一個新的視窗,Project-Form1
(程式碼)的視窗,可在這個視窗編寫程式碼來執行所要求的動作,而
一般而言,會將這個物件預設成 private 物件,僅供這個 Form 使用,
如(圖 4-8)所示。
Page 60
56
(圖 4-8)
新增一個表單,在(圖 4-6)的視窗,畫面右邊的部分,有一個專案
-Project 欄位,此欄位底下的表單上按右鍵,新增另外一個新的表
單,可選取一般表單,或是系統提供的特殊表單。例如選擇一個登入
對話方塊,就可以產生出一個使用者登入的對話方塊,如(圖 4-8)所
顯示。
Page 61
57
(圖 4-8)
而這個表單的好處在於,VB 6.0 會自動初始所需的基本程式碼,並
在程式碼中給予相關的說明。只需在之中,填入適當的程式碼,例如
使用者資料的連結、呼叫,判斷使用者資料輸入之後的動作。如(圖
4-9)所顯示
Page 62
58
(圖 4-9)
而 Menu 資料的讀取,與 Client 的資料接收,透過 Server 來運
作。採用網路連結的方式,在此,採用 Winsock 來實作。Winsock 負
責接收 Client 資料,此系統預設的 port 為 7577,而 IP 位址則是網
卡的 IP 位址。為什麼此系統還要有 port 跟 IP 位址呢?因為一個運用
到網路連結的程式,若沒指定其目的 IP,發送端無法決定資料的傳
送地點,如此一來,資料根本無法送達目的。而 port 只是給予一個”
通道”,例如一般 FTP port 為 21,POP3 port 為 110,Web port 為
80,如果 port 錯誤了,即使 IP 位址正確,資料還是無法傳送。採用
Winsock,Port 的指定由程式設計者指定,而 IP 位址會由 Winsock
決定,可以是一般網卡的 IP 位址,或是無線網路卡的 IP 位址。
Page 63
59
Client 端,在登入畫面,必須輸入正確的 IP 位址與 port,不然
無法連線到 Server,Server 端並不會顯示出連線狀態,連線是否成
功,由 Client 端來判定,若連線成功了,Client 會出現”連線開啟”
的訊息,若連線失敗,則出現連線失敗的錯誤訊息。Server 端只負
責接收 Client 端發出的命令,並顯示出接收到的資料。
(圖 4-10)包含幾個主要部分,第一個部分為 Menu 的顯示,這段
程式碼,會自動讀取此點餐系統設定的 ODBC 來源,按照順序顯示出
該餐點的名稱,餐點種類,與該餐點的價格。
以下為菜單顯示的程式碼片段:
Private Sub DataGrid1_Click()
End Sub
Private Sub Form_load()
Dim mysqo As String
mysqo = "select μa3a.μa¥W ,μa3a.Kind ,μa3a.»uRa From μa3a
order by μa3a.Kind asc"
Winsock1.Protocol = sckTCPProtocol
Winsock1.LocalPort = 7577
Page 64
60
Winsock1.Listen
Set cn3 = New ADODB.Connection
Set rs3 = New ADODB.Recordset
cn3.ConnectionString = "dsn=db1"
cn3.Open
rs3.Open mysqo, cn3, adOpenStatic, adLockOptimistic
Set DataGrid1.DataSource = rs3
End Sub
結果如下所示:
(圖 4-10)
Page 65
61
第二個部分在顯示出接收到的菜單,顯示順序包含餐點順序、桌
次、菜名、價格,會對每一次收到的菜單做排序,結果如下:
(圖 4-11)
(圖 4-11)畫面 1 的部分為利用 PDA 模擬器傳送的結果,由於模擬器
本身無法顯示中文字碼所以在顯現的時候,會出現??。
(圖 4-11)畫面 2 的部分是直接透過 PDA 傳送資料,在此顯現的資料
即可正常顯示。而 PDA 共傳送兩次資料,所以第二次收到的資料,點
餐順序還是由 1 開始排序。
4.2 Client(PDA)端
在系統實作方面 ﹐PDA 跟 SERVER 端的連結傳輸部分 ﹐我們使
用 WinSock 來撰寫程式 。
Page 66
62
WinSock 簡介 ﹕Winsock 是在 1991 年於美國加州的一次會議
中 ﹐由 JSB 公司的 Marting Hall 所提出的 。Windows Sockets 不
是指任何具有實體的程式或軟體,而是指一套公開的,在 MS Windows
下發展網路程式的應用程式介面(Application
ProgrammingInterface,API)。
(索引 ﹕
http://www.cis.nctu.edu.tw/~is82232/NetProg/program5.html#A
)
WinSock 的觀念 ﹕WinSock 應用程式對電腦使用者提供資訊服
務,它們讓使用者快速又容易的在電腦之間傳送資訊,在 WinSock 的
網路模型中,網路系統只單純的依 WinSock 應用程式的要求收送資
料,這些資料對 WinSock 應用程式而言是有意義的,對網路系統而言
就沒有,當 WinSock 應用程式送出一段具有特定長度、格式和意義的
資訊,網路系統可將這份資料任意地分割,然後在另一端重組回來,
它可能會將資料當作一串位元組,並要求應用程式在收到後將它們重
組回來,這些資料的處理方式會依所要求的傳輸服務而有不同,但無
論在何種情況,網路系統在傳送資料時都不會理會它的內容或意義 。
(索引 ﹕
http://www.mi.chu.edu.tw/~ta87859/WinSock/WinSock-2.htm)
Page 67
63
Winsock 的 I/O 模式共分為以下三種:
1、Blocking Mode
2、Nonblocking Mode
3、Asynchronous Mode
以下分別介紹:
Blocking Mode:在此模式下的函式呼叫後,會等到函式作用完
成之後才會返回函式呼叫點。函式作用可能需要等待某個時機才能完
成,而這個時機不一定會在該函式呼叫時就會出現。函式呼叫可能馬
上就能完成,也可能要經過一段相當長的時間。舉例,在阻攔模式下
用 recv() 接收遠端傳來的資料,你不能控制遠端程式傳資料過來的
時機,資料可能一下就丟過來,也有可能要等很久才會送過來。
Nonblocking Mode:在此模式下的函式呼叫,函式作用不管有沒
有完成,會馬上返回函式呼叫點。不像 blocking mode 下需要等待
函式完全作用完成後才會返回;在此模式下,目前等不到成熟的時
機,可以先做其它的事,回頭再來呼叫函式。舉例,在此模式下利用
recv() 去接收遠端傳來的資料。程式呼叫 recv() 接收資料,但是
因為網路塞車,資料無法及時傳來,所以這次的呼叫收不到任何的訊
息。程式返回呼叫點之後,告訴程式有關資料尚未收到的訊息。知道
Page 68
64
目前還有資料尚未收到,程式可以先做其它的事情,回頭再來呼叫
recv() 收其它的資料。
Asynchronous Mode:在此模式下,事件的發生是由某個判斷事
件發生的機制去通知應用程式,而應用程式依照該事件的性質坐不同
的處理。舉例,以此模式的 socket 接收遠端傳來的資料,傳送期間
不管經過了多少波折,資料送來了,由系統通知程式資料送達的訊
息。這時程式就可以去呼叫 recv() 函式接收資料。在此模式下,把
判斷函式呼叫的時機的責任交給系統(WinSock.DLL)。
(索引﹕
http://www.cis.nctu.edu.tw/~is82232/NetProg/program5.html#A
)
在使用 WinSock 物件方面十分的順利 ﹐因為在我們參考的書籍
(附錄中)裡面有提到滿多有關的使用方式 ﹐讓我們受益良多 。
PDA 程式範例 ﹕
Private Sub cmdConnect_Click()
WinSock1.Protocol = sckTCPProtocol
WinSock1.RemoteHost = txtRemortHost.Text
WinSock1.RemotePort = txtRemortPort.Text
Page 69
65
WinSock1.Connect
lblStatus.Caption = "連線開啟"
//*成功開啟連線才會出現 ﹐無法開啟會產生錯誤 。 處理方式在操
作簡介有作介紹 。*//
If WinSock1.State sckConnected Then
lblStatus.Caption = CStr(GetState(WinSock1))
Exit Sub
End If
cmdConnect.Enabled = False
cmdClose.Enabled = True
End Sub
//*此段程式是在開啟 WinSock 物件和 SERVER 端的連結 。*//
Private Sub cmdClose_Click()
Page 70
66
WinSock1.Close
WinSock1.LocalPort = 0
cmdConnect.Enabled = True
cmdClose.Enabled = False
lblStatus.Caption = "連線關閉"
End Sub
//*這段程式碼是關閉連線部分。*//
接下來 PDA 的重頭戲就在菜單資料庫的顯示 ﹐在參考許許多多
的書籍以及尋找網路上的資料 ﹐我們決定使用 GridCtrl 這項工具 ﹐
它可以把資料庫的內容讀取之後秀出在它的介面上 ﹐剛好對於我們
菜單的顯示有莫大的幫助 ﹐可以免除為了菜色的排版而大費周章 ﹐
不僅節省功夫而且效果非常的好 。
秀出菜單資料的主要程式碼 ﹕
Private Sub DisplayDataToGrid(tablename As String)
Dim rs As ADOCE.Recordset
Dim intCount As Integer
Dim strData As String
Page 71
67
Dim intCol As Integer
Dim intCounter As Integer
grdItems.Rows = 0
grdItems.AddItem ("餐點" + vbTab + "價格")
intCounter = 0
intCol = 0
For intCol = 0 To 1
grdItems.Col = intCol
grdItems.Row = intCounter
grdItems.CellFontSize = 10
Next
If connOpen = True Then
Set rs = CreateObject("ADOCE.Recordset.3.0")
On Error Resume Next
Page 72
68
rs.Open "select * from " & tablename, conn,
adOpenForwardOnly, adLockReadOnly
rs.MoveFirst
Do While Not rs.EOF
strData = CStr(rs(1).Value) + vbTab + CStr(rs(2).Value)
grdItems.AddItem strData
intCounter = intCounter + 1
For intCol = 0 To 1
grdItems.Col = intCol
grdItems.Row = intCounter
grdItems.CellFontSize = 10
Next
rs.MoveNext
Page 73
69
Loop
rs.Close
Set rs = Nothing
On Error GoTo 0
End If
grdItems.TopRow = 0
grdItems.ColWidth(0) = 2000
grdItems.ColWidth(1) = 1000
connClose
End Sub
//*這段程式碼是將資料庫內的資料依序讀出。*//
對於資料庫是否存在 ﹐有個別的測試程式存在 。
Page 74
70
測試程式 ﹕
Private Function DBExists(strFileName As String) As Boolean
If FileSystem1.Dir(strFileName) "" Then
DBExists = True
Else
DBExists = False
End If
End Function
如果存在將會將 DBExists 值傳回 ﹐根據不同的值 ﹐會有不同
的資訊顯示在 PDA 下方的 LABEL 上 。 (於操作介面說明有介紹。)
在點餐的方面 ﹐使用點擊方式來點餐 ﹐用指標來指定每一個欄
位的餐點 、價格 ﹐將依序排入 ARRAY 中 ﹐為的是可以將點餐的東
西秀到點餐清單的 LABEL 上 ﹐使用這方式可以準確的紀錄每一筆點
餐的菜色 、價格 ﹐使得在點餐確認作業上可以更精確更快速的進行
。
刪除的主要程式碼 ﹕
上略
Page 75
71
temp = MsgBox("你確定要刪除:" & ItemName1.Caption, vbOKCancel,
"刪除餐點")
If temp = vbCancel Then
Exit Sub
End If
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 1
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
lngTotalMoney = lngTotalMoney -
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo - 1
lblBuyCount.Caption = intTotalSelectItemNo
End If
Page 76
72
MoveDate intCurrentItemNo
下略
MoveDate 函式的主要程式碼 ﹕
Private Sub MoveDate(ItemNo As Integer)
Dim intTemp
For intTemp = ItemNo To intTotalItem
strItemName(intTemp) = strItemName(intTemp + 1)
intItemMoney(intTemp) = intItemMoney(intTemp + 1)
intItemCheck(intTemp) = intItemCheck(intTemp + 1)
Next
strItemName(intTotalItem + 1) = ""
intItemMoney(intTotalItem + 1) = ""
intItemCheck(intTotalItem + 1) = 0
ClearList
Page 77
73
DisplayListData intCurrentPageNo
End Sub
在點餐清單上 ﹐我們使用 LABEL 將每一筆菜色 、價格條列出
來 ﹐也提供一個 CHECK BOX 來作標記使用 ﹐使用方法在操作介面說
明有解說 ﹐本來可以將每樣菜色都堆疊在一起 ﹐例如 ﹕牛排 5客 ﹐
這類的方法 ﹐但是考慮到刪除的時候 ﹐如果刪除 5 筆中的 1 筆 ﹐
就必須多個數字鍵輸入 ﹐為了求畫面的整齊 、清爽 ﹐所以我們將
每一筆資料都是個別的分開 ﹐不把相同的菜色累加在一起 ﹐在這方
面應該算是創意部分的不同 ﹐也許有更好的處理方式 ﹐有待我們去
發掘。
Page 78
74
第五章、 系統使用手冊
5.1 PDA 點餐系統的建構
5.1.1Server 端的建構
安裝 Server 端主程式,執行 PDA 點餐系統.exe 檔,會自動解壓縮並
產生”C:\Program Files\PDAShopping\”這個目錄,
設定 ODBC 資料來源,[開始]->[設定]->[控制台]->[系統管理工
具]->[資料來源(ODBC)]
進入系統的[控制台]選項。(如圖 5-1)
(圖 5-1)
選取[控制台]中的[系統管理工具]。如(圖 5-2)
Page 79
75
(圖 5-2)
選取[系統管理工具]中的[資料來源(ODBC)]選項。如(圖 5-3)
(圖 5-3)
新增一個資料來源。如圖(5-4)
Page 80
76
(圖 5-4)
選取 Driver do Microsoft Access(*.mdb),(圖 5-5),完成之後
(圖 5-5)
(圖 5-6)選取資料檔來源,輸入資料來源名稱”db1”
(圖 5-6)
選取資料庫名稱,位於 C:\Program Files\PDAShopping\db1.mdb
按下確定,即可設定此程式所使用的資料庫來源。如(圖 5-7)
Page 81
77
(圖 5-7)
5.1.2 Client 端的建構
將光碟放入光碟機中,選取 CD1 資料夾,雙擊 Setup 執行檔,即
可安裝 PDA 的 Client 端程式於 PDA 上。
5.2 Server 端
5.2.1 主畫面
(圖 5-8)
Page 82
78
執行主程式之後,會出現此視窗(圖 5-8),選取,可進入 PDA
點餐系統,或者選擇結束此系統。進入系統時,必須先做使用
者登入的動作(圖 5-9),
(圖 5-9)
輸入使用者名稱與密碼,若資料正確,即可登入主功能頁(圖 5-10)
。若使用者名稱輸入錯誤,會出現”sorry no this user”的錯誤訊
息,並結束此程式。若使用者名稱正確,密碼輸入錯誤,會出
現”password error”錯誤訊息,可再重新輸入密碼,或選擇取消,
離開程式。
主功能頁:
Page 83
79
(圖 5-10)
主功能頁包含,以及兩大功能。
5.2.2 MENU
選擇之後,可進入 Menu 的畫面
Page 84
80
(圖 5-11)
此頁面(圖 5-11)會顯示出 Menu 的資料。可進而對此 Menu 做,
,,。
(一) 首先是新增
初始畫面
Page 85
81
(圖 5-12)
按下的結果
Page 86
82
(圖 5-13)
(二)刪除
執行結果
Page 87
83
(圖 5-14)
按下的執行結果
Page 88
84
(圖 5-15)
(三)修改
初始畫面
(圖 5-16)
注意(圖 5-16)表格中的箭頭是說要改的資料
按下後
執行結果
Page 89
85
(圖 5-17)
5.2.3 櫃檯
在主功能頁(圖 5-10),選取之後,可進入櫃檯系統(圖 5-18)。
Page 90
86
(圖 5-18)
(圖 5-18)畫面中分為兩個顯示的部分,其中第一個部分,是顯示 Menu
的資料。第二個部分,顯示接收的菜單。
點選,會出現下圖(圖 5-19)。
Page 91
87
(圖 5-19)
此頁面會顯示出目前各餐點所需的基本素材。
選取,會出現下圖(圖 5-20)。
Page 92
88
(圖 5-20)
統計目前已點過的所有餐點。
Page 93
89
5.3 Client 端的操作說明
(圖 5-21)
連線區的起始畫面 ﹐伺服器 IP 和連接阜可以配合 SERVER 端更
改 ﹐桌號也可以依照不同的餐桌來做修訂 ﹐在沒有連線成功的畫面
時 ﹐下方有 LABEL 顯示連線狀態 “尚未連線” ﹐最下方的資料庫
準備就緒 ﹐是測試菜單的資料庫連結是否成功 ﹐成功則會顯現出
“資料庫準備就緒” 。 而在此畫面有 TABSTRIP 用來顯示三個大選
單 ﹐分別是 “連線區” 、”選擇餐點” 、”點餐清單” 。
將此頁擺在第一頁面 ﹐是為了方面服務生在點餐前可以確認一
些細節部分 ﹐例如 ﹕伺服器 IP 、連接阜 、是否有修改 ﹐隨著店
家喜好這些部分都是可以更改 ﹐以方便為主 。
Page 94
90
桌號的確認十分重要 ﹐為了要給顧客更快速的服務 ﹐桌號千萬
不能夠錯誤 ﹐不然就沒辦法達到使用 PDA 點餐的用意 。
連線狀況 、資料庫連結狀況 ﹐都必須在開店的時候就準備好 ﹐
必要的時候也可以測試一下連線情形 。
當確認工作完成 ﹐也就可以正式連線 ﹐準備讓客人點餐的作業
了 。
點擊 ”連線” 按鈕 ﹐連線成功的畫面 。
(圖 5-22)
連線失敗 。
Page 95
91
(圖 5-23)
如果連線失敗的話 ﹐就必須檢查 SERVER 端是否有開啟 ﹐或者
IP 、連接阜是否有誤 。
如在這些部分出了問題 ﹐可以在 SERVER 端更改 ﹐或者在 PDA
上直接輸入也是允許的 ﹐但是必須注意一點 ﹐不管是更改哪一邊的
IP 、連接阜 ﹐都必須將每一台機器都做確認 ﹐或者統一好 IP 位
址 ﹐再把程式做成安裝檔 ﹐重新安裝到 PDA 裡面 。
Page 96
92
(圖 5-24)
如果是資料庫沒有準備好的話 ﹐下方會出現資料庫無法載入 ﹐
就要檢查 PDA 內部的資料夾 ﹐當作成安裝檔的時候會產生一個
Shopping 的資料夾在檔案總管內( 當然因為安裝檔個人喜好有不同
的名字 ) ﹐在此資料夾內必須放入菜單的資料庫 ﹐而 PDA 讀取資料
庫的格式為 .cdb 檔 ﹐確認內部有一個 menu.cdb 檔 ﹐如果沒有就
必須將資料庫轉檔 ﹐轉檔的方式為 ﹕把 PDA 接在電腦上 ﹐必須要
有 ACTIVESYNC ﹐必須達到同步的效果 ﹐然後把檔案貼到新產生的
PDA 槽內 ﹐就會自動做轉換的動作了 ﹐如果要將 menu.cdb 檔拿出
PDA 槽 ﹐又會自動轉換成 mdb 檔 ﹐所以在這邊可以 ACTIVESYNC 的
選項內 ﹐選擇從 PDA 移出檔案時不轉換 ﹐就可以拿出 *.cdb 檔案
Page 97
93
了 。
(圖 5-25)
在 ACTIVESYNC 下的功能使用 ﹐可以選擇檔案如何轉換 ﹐請選擇檔
案轉換內的轉換設定鍵 。
Page 98
94
(圖 5-26)
進入之後選擇 Pocket Access 在點選編輯按鍵 。
(圖 5-27)
可選擇轉換或者不轉換 ﹐為了將*.cdb 檔案拿出,所以選擇不轉換 。
Page 99
95
(圖 5-28)
這樣就大功告成 ﹐而*.cdb 檔案就可以被 EVB 用做讀取的功用 。
接下來確定桌號後就可以進入選擇餐點 。
點擊 ’選擇餐點’
(圖 5-29)
Page 100
96
中間的部分為 DATAGRID ﹐是為了要將資料庫內的菜單秀出 。進入成
功後 ﹐點擊 ’請選擇餐點分類’的右方 box ﹐出現選項 。
(圖 5-30)
有三種餐點可以選擇 ﹐套餐 、湯類 、點心 。
選擇套餐 。
Page 101
97
(圖 5-31)
選擇了套餐之後 ﹐下方的 DATAGRID 就把資料庫內的套餐內容顯示出
來 。
點選湯類 、點心 ﹐也有一樣的效果 。
在這個畫面下可以點擊餐點下的選項 ﹐而點擊價格下面的表單 ﹐也
有跟點擊餐點下面選項相同的功能 ﹐都是點選一次欄位中的菜色 。
可以點選菜色的數量上限為 60 道菜色 。
超過數量上限的錯誤。
Page 102
98
(圖 5-32)
開始點餐 。
Page 103
99
(圖 5-33)
點選成功之後會在下方出現加入餐點為什麼菜色 ﹐在點選餐點之
後 ﹐可以到點餐清單確認 。
(圖 5-34)
確認無誤 ﹐點選成功 。
可以在右方的 CHECK BOX 點擊 ﹐來清查所點選的菜色 、數量是否正
確 。 此項功能可用可不用 ﹐目的是要標記住正確的餐點 ﹐方便做
點餐確認的工作 ﹐ 點選之後不會影響到任何作業 。
Page 104
100
(圖 5-35)
刪除某一樣錯誤的菜色,點擊兩次餐點名稱 。 例如 ﹕牛排 。
Page 105
101
(圖 5-36)
選擇 OK ﹐刪除牛排 。 選擇 Cancel 則不會更改點餐清單 。
(圖 5-37)
牛排成功刪除 。
如果全部都要重新點過 ﹐則使用清除清單 。
Page 106
102
(圖 5-38)
清除清單後 ﹐將會把點餐清單內的資料初始化 。
返回選擇餐點 ﹐繼續點餐 。 當點選菜色超過 8 樣 ﹐則使用↑↓鍵
來檢查其他頁數的菜色 。
Page 107
103
(圖 5-39)
下一頁
Page 108
104
(圖 5-40)
在上下頁的時候 ﹐所有功能都可以使用 ﹐例如 ﹕CHECK BOX 、刪
除 等功能都能夠運作 。
選擇傳送菜單 ﹐則會將所選擇的菜單送到櫃檯的 SERVER 端 。
當連線有問題 ﹐沒辦法傳送時會出現的錯誤 。
(圖 5-41)
傳送成功的時候 ﹐下方會出現傳送成功的字樣 。
Page 109
105
(圖 5-42)
而在 SERVER 端就會出現接受到菜單的訊息 。
Page 110
106
第六章、 結論與心得
涂允勝:
PDA 程式撰寫心得感想與困難突破 ﹕
時下 PDA 的應用範圍十分廣泛 ﹐所以在撰寫程式的時候就有滿
多種的語言可以選擇 ﹐而我們這一組選擇使用 VB 來編寫 PDA 的點餐
系統 ﹐所以我們整個架構都是由 VB 語言組成的 ﹐再使用 VB 語言寫
程式的時候可以感覺到 VB 是一個滿友善的語言 ﹐不僅僅是語法使用
方式或者是操作介面 ﹐可以非常快速的上手 。 雖然 VB 是一個簡易
上手的語言 ﹐但是它的功能也是非常強大的 。
在撰寫方面首先遇到的麻煩就屬於整個系統的架構了 ﹐因為是
PDA 點餐 ﹐勢必使用 PDA 的是服務生或者是顧客 ﹐所以在這方面的
考量 ﹐要把介面設計成便利性最高 ﹐卻又不落於簡陋 ﹐所以菜單
方面的呈現 ﹐則使用 Grid 的方式表現 ﹐使得系統能夠直接讀取出
菜單的種類 、樣式 ﹐不過在這邊 PDA 讀取的資料庫模式是讀取 .cdb
檔 ﹐而我們製作的資料庫則是 .mdb 檔 ﹐在這邊就必須要有轉檔的
動作 ﹐不然 PDA 將無法讀取出正確的資料庫內容 。
之後則是秀出菜單之後的點選方式 ﹐採用的是單擊一次 ”菜
名” 或者是 “價格” ﹐單擊之後會將資料存入陣列中 ﹐之後在秀
在點菜清單區 ﹐而點菜的最多數量為 60 ﹐超過則會顯示出 "選購
Page 111
107
商品超過 60 項!" ﹐然後沒有辦法在繼續增加餐點 ﹐單擊一次為點
一樣菜色 。
接下來是點菜清單區 ﹐在點菜清單區可以清楚的看出共點了幾
道菜 、多少錢 ﹐一個 Page 顯示 8 道菜 ﹐有 Page-Up 跟 Page-Down
可以提供換頁 ﹐還有 Check Box 來做為標記確認的餐點 ﹐純粹幫
助餐點的計量 、確認等工作 ﹐如果想要刪除某一道菜色 ﹐則在菜
名上連擊兩次 ﹐則會出現刪除訊息 ﹐在選擇是否要刪除 ﹐刪除之
後的欄位由下往上遞補 。 然後就是傳輸了 ﹐在傳輸的方面 ﹐點下
傳送菜單的按鈕 ﹐就會將點菜清單全部的資料送往 SERVER 端 ﹐然
後 PDA 上的資料則會清除 ﹐而桌號的更改則在連線區有桌號的 TEXT
BOX ﹐在欄位內填入正確的桌號即可 。 如果要清除掉所有的菜單 ﹐
則按下清除菜單的按鈕則會將所有點菜的資料刪除 ﹐並不會送到
SERVER 端 。
遭遇到的困難大多屬於對 VB 這語言的不熟悉 ﹐沒有辦法靈活運
用各項功能 ﹐以至於在程式上會有些許拖泥帶水的感覺 ﹐如果能夠
更熟悉各功能的細節 、以及使用方式 ﹐會使得在程式表現上有更俐
落的感覺 。
Page 112
108
黃振註:
最近兩三年來,無線網路環境越來越發達,硬體成本的降低,軟
體的支援性越來越高。如何有效的利用硬體設備,來降低成本支出,
也是本組所要研究的問題。
PDA 雖然耳熟能詳,但是功能為何,直到真正接觸之前,還是一
頭霧水,在設計此 PDA 點餐系統之前,甚至於不知道 PDA 還有分 OS
系統與 Win CE 系統。而之所以會選擇編寫 Win CE 系統的 PDA 點餐系
統,因 Win CE 的功能性較強,尤其是與 PC 做資料連結、資料傳輸的
部分,比較適用於現在的 Windows 系統。而 PDA 硬體的架設,也是逐
步測試,由 PDA 與 PC 的同步開始,一步一步的設定。
由於程式設計之初,就決定要利用無線網路的傳輸,所以在無線
網路環境的架設,是我們一開始遇到的問題,何謂無線網路,無線網
路的 protocal 要怎麼設定,無線網路卡的安裝、測試。市面上有關
此的書籍寫的不怎麼齊全,雖然在概念上都具備了,不過在於硬體實
際架設,真正使用的硬體,與書上的又不盡相同。只好從網路上尋找
資料,畢竟新的資訊,新的產品,最快取得相關資料的方式,就是藉
由網路。而 PDAorDIE 此網站,不僅是一個介紹網站,裡面的討論區
對我而言,如獲至寶一般的,可以藉由使用者的討論、分享。來找到
我要的解答。
Page 113
109
而 Server 端的程式,在於 Database 的讀取,與 PDA 資料的接收,
如何正確的表現出來,Server 與 Client 的連結方式,要如何設定、
編寫,是此部分所遭遇最大的問題。
另外在無線網路測試的部分,在 Winsock 建立之後,單機測試都
可以運作,但是運用到無線網路的時候,卻無法連線,問題在於無線
網路卡的安裝,安裝 PC 的無線網卡時,PC 原本的網卡卻掛掉了,推
測可能是硬體相衝所導致。另外 PDA 的無線網卡,甚至連驅動程式都
沒有,安裝完驅動程式之後,PDA 的網路設定又測試了幾天,最後,
終於可以正常連線。
Page 114
110
黃川泰:
其實vip資料的 Database是很簡單的,因為他沒有牽涉到其他
的表單,所以只要對此表單做資料處理就好了,不需要做其他的資料
連結,所有的資料控自都是非常的簡單而起單一的,不需要考慮太多,
但是如果遇到表單的控制與其他的表單有關聯時怎麼辦,情況會變的
非常複雜.
我們可以看看 menu 的修改的程式碼對您顯示出來程式的撰寫方
面會變的多複雜.
相信各位都有看到我的程式碼,為啥一個資料的新增刪除及修改
要做那麼多動作?必須要做那麼多的資料連結?
因為 Database的修改困難程度在於Database的各表單的關係是
否複雜,我們就以菜單來說吧!我們可以從 E-R 圖來看,一個菜單的修
改會影響到他的 3 個子表單及一個相關表單,所以單就資料流的搜尋
及指定是很簡單的,但是如果要修改一個大的相關表單是需要比較大
的功夫的
我們可以拿 ADD 這個指令來看,只是一個很簡單的資料增加的指
令,但是為啥要作那麼多的動作,因為一筆菜的增加必須要有相關素
材的連結以及其他種類菜單資料的連結(PDA 的轉檔方便所以必須多
分菜單種類出來)所以變的很複雜.
Page 115
111
我們可以拿 vip 修改的程式來看,他不需要做任何其他的資料連
結,因為他只需要做他本身的資料修改就可以完成他所有的動作,相
對於菜單的修改就不一樣因為他有許多的相關資料跟他有關,所以一
但改了一筆資料就必須改其他許多地方.
Page 116
112
參考資料
[1]David M. Kroenke, DataBase Processing, Fundamentals, Design
and Implementation, 8/e, Prentice-Hall, Inc. Programming, May
2002
[2]江意華,Visual Basic 6 完美經典,金禾資訊,Basic,April 2002
[3]鍾俊仁編譯,許建志校閱, Guy Eddon, Henry Eddon 原著,
Microsoft Visual Basic 6.0 元件程式設計開發指南(Programming
Components with Microsoft Visual Basic 6.0), Basic,華彩軟體,
Nov. 1999
[4]李永隆, 深入 PDA 程式設計 無線網路、硬體控制、主從式資料庫,
電腦程式語言,文魁資訊股份有限公司,April 2002
[5]賴禹丞,Pocket PC 專案開發範本,Basic(電腦程式語言),作業系
統,金禾資訊, April 2002
[6]季延平譯, Gary B. Shelly, Thomas J. Cashman, Haryy J.
Rosenblatt 著,系統分析與設計(System Analysis and design),系
統分析,東華書局,Nov. 1999
網站
小雄資訊服務中心 http://infoserv.com.tw/
Page 117
113
PDAorDie http://www.pdaordie.com/
Google http://www.google.com/intl/zh-TW/
專題報告 http://www.cdic.gov.tw/research4.jsp
Page 118
114
附錄
A.Server 端
經理介面
Form load 程式碼:
Private Sub form_load()
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
Dim mysqq As String
mysqq = "select 菜單.菜名 ,菜單.Kind ,菜單.價格 From 菜單
order by 菜單.Kind asc"
cn.ConnectionString = "dsn=db1"//取得資料集
cn.CursorLocation = adUseClient
cn.Open
rs.Open mysqq, cn, adOpenStatic, adLockOptimistic
Set DataGrid1.DataSource = rs //datagrid1 取得資料集
Text5.Text = rs!kind
Text1.Text = rs!菜名
Text2.Text = rs!價格
End Sub
Page 119
115
搜尋程式碼:
Private Sub cmdfind_click()
Dim i As Integer
Dim ret As Integer
If textfind1.Text = "" Then
Beep
rmsg = MsgBox("", vbOKOnly, "°TR§")
Exit Sub
End If
rs.MoveFirst
rs.Find "請輸入搜尋值='" & textfind1.Text & "訊息'"
If rs.EOF = True Then
rs.MoveFirst
Beep
rmsg = MsgBox("沒此菜", vbOKOnly, "訊息")
Exit Sub
End If
Page 120
116
i = rs! »
textfind2.Text = i
Text6.Text = rs!kind
Text5.Text = rs!kind
Text1.Text = rs!菜名
Text2.Text = rs!價格
End Sub
第一筆程式碼:
Private Sub cmdFirst_Click()
rs.MoveFirst
Text5.Text = rs!kind
Text1.Text = rs!菜名
Text2.Text = rs!價格
End Sub
最後一筆程式碼:
Page 121
117
Private Sub cmdLast_Click()
rs.MoveLast
Text5.Text = rs!kind
Text1.Text = rs!菜名
Text2.Text = rs!價格
End Sub
下一筆程式碼:
Private Sub cmdNext_Click()
rs.MoveNext
If rs.EOF = True Then
rs.MoveLast
End If
Text5.Text = rs!kind
Text1.Text = rs!菜名
Text2.Text = rs!價格
End Sub
Page 122
118
上一筆程式碼:
Private Sub cmdup_Click()
rs.MovePrevious
If rs.BOF = True Then
rs.MoveFirst
End If
Text5.Text = rs!kind
Text1.Text = rs!菜名
Text2.Text = rs!價格
End Sub
新增程式碼:
Private Sub cmdAdd_Click()
Dim kind As String
Dim num As Integer
Dim rmsg As String
Page 123
119
If textadd1.Text = "" Or textadd2.Text = "" Or textkind1.Text
= "" Or Text3.Text = "" Or Text4.Text = "" Then
Beep
rmsg = MsgBox("請輸入要菜名及價格", vbOKOnly, "訊息")
Exit Sub
End If //確定新增菜的資料都有輸入
Set cc3 = New ADODB.Connection //以下皆為打開菜單種類資料流
的動作
Set rr3 = New ADODB.Recordset
cc3.ConnectionString = "dsn=db1"
cc3.Open
rr3.Open "菜單種類", cc3, adOpenStatic, adLockOptimistic
rr3.AddNew
//新增菜單在菜單種類上
rr3!菜名 = textadd1.Text
rr3!kind = textkind1.Text
rr3.Update
kind = textkind1.Text
rs.AddNew //新增菜單在菜單上
rs!菜名 = textadd1.Text
Page 124
120
rs!kind = textkind1.Text
rs!價格 = CLng(textadd2.Text)
Set cn0 = New ADODB.Connection
Set rs0 = New ADODB.Recordset
cn0.ConnectionString = "dsn=db1"
cn0.Open
rs0.Open "所須材料", cn0, adOpenStatic, adLockOptimistic//
以下皆為打開所需材料資料流的動作
rs0.AddNew //新增所需材料
rs0!菜名 = textadd1.Text
rs0!材料 = Text3.Text
rs0.AddNew
rs0!菜名 = textadd1.Text
rs0!材料 = Text4.Text
rs0.Update
Set cn1 = New ADODB.Connection //以下皆為打開各個種類菜單
的資料流動作
Set rs1 = New ADODB.Recordset
cn1.ConnectionString = "dsn=db1"
Page 125
121
cn1.Open
rs1.Open kind, cn1, adOpenStatic, adLockOptimistic
rs1.MoveLast
num = rs1!編碼
num = num + 1
rs1.AddNew //新增菜在各類菜單
rs1!編碼 = num
rs1!菜名 = textadd1.Text
rs1!價格 = textadd2.Text
rs1.Update
Set cc2 = New ADODB.Connection
Set rr2 = New ADODB.Recordset
cc2.ConnectionString = "dsn=db1"
cc2.Open
rr2.Open "訂單", cc2, adOpenStatic, adLockOptimistic
rr2.AddNew
rr2!菜名 = textadd1.Text
rr2!數量 = "0"
rr2.Update
Page 126
122
End Sub
刪除程式碼
Private Sub cmdDelete_Click()
Dim ret As Integer
Dim m_name As String
Dim k_name As String
Set cc3 = New ADODB.Connection
Set rr3 = New ADODB.Recordset
cc3.ConnectionString = "dsn=db1"
cc3.Open
rr3.Open "菜單種類", cc3, adOpenStatic, adLockOptimistic//
打開”菜單種類”資料流
Set cn0 = New ADODB.Connection
Set rs0 = New ADODB.Recordset
cn0.ConnectionString = "dsn=db1"
cn0.Open
rs0.Open "所須材料", cn0, adOpenStatic, adLockOptimistic//
打開”所須材料”的資料流
Set cc2 = New ADODB.Connection
Page 127
123
Set rr2 = New ADODB.Recordset
cc2.ConnectionString = "dsn=db1"
cc2.Open
rr2.Open "訂單", cc2, adOpenStatic, adLockOptimistic//打開”
訂單”的資料流
Beep
ret = MsgBox("是否真的要刪除此菜:[" & rs!菜名 & "]", vbYesNo,
"確認刪除")
If ret = vbYes Then
m_name = rs!菜名
k_name = rs!kind
rs0.Find "菜名='" & rs!菜名 & "'"//下三行是做各資料流的搜
尋動作
rr3.Find "菜名='" & rs!菜名 & "'"
rr2.Find "菜名='" & rs!菜名 & "'"
rr2.Delete //以下為訂單及所需材料及菜單種類及菜單的刪除
If rr2.EOF = True Then
rr2.MoveLast
End If
Page 128
124
rr3.Delete
If rr3.EOF = True Then
rr3.MoveLast
End If
rs0.Delete
rs0.MoveNext
rs0.Delete
If rs0.EOF = True Then
rs0.MoveLast
End If
rs.Delete
rs.MoveNext
If rs.EOF = True Then
rs.MoveLast
End If
Set cc = New ADODB.Connection //以下是取得各套餐的資料
Page 129
125
流及刪除動作
Set rr = New ADODB.Recordset
cc.ConnectionString = "dsn=db1"
cc.Open
rr.Open k_name, cc, adOpenStatic, adLockOptimistic
rr.Find "菜名='" & m_name & "'"
rr.Delete
rr.MoveNext
If rr.EOF = True Then
rr.MoveLast
End If
Else
Exit Sub
End If
End Sub
修改程式碼:
Private Sub cmdEdit_Click()
Dim ret As Integer
Dim menu As String
Page 130
126
Dim kind1 As String
kind1 = Text5.Text
Set cn1 = New ADODB.Connection///打開各種菜單的資料流
Set rs1 = New ADODB.Recordset
cn1.ConnectionString = "dsn=db1"
cn1.Open
rs1.Open kind1, cn1, adOpenStatic, adLockOptimistic
Set cc3 = New ADODB.Connection //打開菜單種類的資料流
Set rr3 = New ADODB.Recordset
cc3.ConnectionString = "dsn=db1"
cc3.Open
rr3.Open "菜單種類", cc3, adOpenStatic, adLockOptimistic
Set cn0 = New ADODB.Connection ///打開所需材料的資料流
Set rs0 = New ADODB.Recordset
cn0.ConnectionString = "dsn=db1"
Page 131
127
cn0.Open
rs0.Open "所須材料", cn0, adOpenStatic, adLockOptimistic
m_name = rs!菜名
If Text5.Text = rs!kind Then
If Text1.Text = "" Or Text2.Text = "" Then
Beep
ret = MsgBox("請輸入要改的菜名及價格", vbOKOnly, "訊
息")
Exit Sub
End If
rs1.MoveFirst
rs0.MoveFirst
rr3.MoveFirst
rs0.Find "菜名='" & rs!菜名 & "'" //下三行是做各資料流
的搜尋動作
Page 132
128
rs1.Find "菜名='" & rs!菜名 & "'"
rr3.Find "菜名='" & rs!菜名 & "'"
rs.Update "菜名", Text1.Text //以下是各資料流的修改
動作
rs.Update "價格", CLng(Text2.Text)
rs.Update "Kind", Text5.Text
rs1.Update "菜名", Text1.Text
rs1.Update "價格", CLng(Text2.Text)
rs0.Update "菜名", Text1.Text
rs0.MoveNext
rs0.Update "菜名", Text1.Text
rr3.Update "菜名", Text1.Text
rr3.Update "Kind", Text5.Text
Else
Beep
Page 133
129
ret = MsgBox("請確定種類", vbOKOnly, "訊息")
Exit Sub
End If
End Sub
櫃臺介面
Form load 程式碼:
Login 程式碼:
Private cn2 As ADODB.Connection
Private rs2 As ADODB.Recordset
Private Sub Form_load()
Set cn2 = New ADODB.Connection
Set rs2 = New ADODB.Recordset
cn2.ConnectionString = "dsn=db1"
cn2.CursorLocation = adUseClient
cn2.Open
Page 134
130
rs2.Open "pass", cn2, adOpenStatic, adLockOptimistic
End Sub
Private Sub cmdOK_Click()
Dim ps As String
ps = Text2.Text
rs2.MoveFirst
rs2.Find "User='" & Text1.Text & "'"
If rs2.EOF = True Then
Beep
ret = MsgBox("sorry no this user")
rs2.MoveFirst
End
End If
If rs2!Password = ps Then
Unload Me
Form7.Show
Else
Beep
ret = MsgBox("password error")
Page 135
131
End If
End Sub
Private Sub cmdch_click()
End
End Sub
Kitchen 程式碼:
Private cn3 As ADODB.Connection
Private rs3 As ADODB.Recordset
Private cn5 As ADODB.Connection
Private rs5 As ADODB.Recordset
Private Sub cmdEdit_Click()
Form5.Show
End Sub
Private Sub cmdseeinfo_Click()
Forminfo.Show
End Sub
Page 136
132
Private Sub cmdseesin_Click()
訂單.Show
End Sub
Private Sub cmdtest_Click()
Dim strData As String
Dim m_name As String
Dim tmp As String
Dim i As Integer
m_nane = ""
Dim nFn1 As Long
nFn1 = FreeFile
Open cppPath & "test.txt" For Input As #nFn1
While Not EOF(nFn1)
Input #nFn1, tmp
If tmp = "2" Then
Text2.Text = "interp"
Exit Sub
Page 137
133
End If
Text1.Text = Text1.Text & tmp
Wend
End Sub
Private Sub Form_load()
Dim mysqo As String
mysqo = "select 菜單.菜名 ,菜單.Kind ,菜單.價格 From 菜單
order by 菜單.Kind asc"
Winsock1.Protocol = sckTCPProtocol
Winsock1.LocalPort = 7577
Winsock1.Listen
Set cn3 = New ADODB.Connection
Set rs3 = New ADODB.Recordset
cn3.ConnectionString = "dsn=db1"
cn3.Open
rs3.Open mysqo, cn3, adOpenStatic, adLockOptimistic
Set DataGrid1.DataSource = rs3
End Sub
Page 138
134
Private Sub cmdref_Click()
Dim mysqo As String
mysqo = "select 菜單.菜名 ,菜單.Kind ,菜單.價格 From 菜單
order by 菜單.Kind asc"
Set cn3 = New ADODB.Connection
Set rs3 = New ADODB.Recordset
cn3.ConnectionString = "dsn=db1"
cn3.Open
rs3.Open mysqo, cn3, adOpenStatic, adLockOptimistic
Set DataGrid1.DataSource = rs3
End Sub
Private Sub cmdor_click()
Dim cn1 As ADODB.Connection
Dim rs1 As ADODB.Recordset
Dim criteria As String
Dim int1 As Integer
Set cn1 = New ADODB.Connection
Set rs1 = New ADODB.Recordset
int1 = 0
Page 139
135
cn1.ConnectionString = "dsn=db1"
cn1.Open
rs1.Open "訂單", cn1, adOpenStatic, adLockOptimistic
criteria = rs3!菜名
rs1.Find "菜名='" & criteria & "'"
int1 = rs1!數量
int1 = int1 + 1
rs1!數量 = int1
rs1.Update
rs1.MoveFirst
End Sub
Private Sub Winsock1_ConnectionRequest(ByVal requestID As
Long)
Winsock1.Close
Winsock1.Accept requestID
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim strData As String
Winsock1.GetData strData
Page 140
136
test.Text = test.Text + strData
End Sub
所需材料程式碼:
Private cn4 As ADODB.Connection
Private rs4 As ADODB.Recordset
Private rs5 As ADODB.Recordset
Private cn5 As ADODB.Connection
Private Sub cmdneed_Click()
Dim mysql As String
mysql = "select 所需材料.菜名,素材.素材名,素材.種類 From 所
需材料,素材 where 所需材料.材料 = 素材.素材名 order by 所需
材料.菜名 desc"
Set cn4 = New ADODB.Connection
Set rs4 = New ADODB.Recordset
cn4.ConnectionString = "dsn=db1"
cn4.Open
rs4.Open mysql, cn4, adOpenStatic
Page 141
137
Set DataGrid1.DataSource = rs4
End Sub
Private Sub Form_load()
Dim mysql As String
mysql = "select 所需材料.菜名,素材.素材名,素材.種類 From 所
需材料,素材 where 所需材料.材料 = 素材.素材名 order by 所需
材料.菜名 desc"
Set cn4 = New ADODB.Connection
Set rs4 = New ADODB.Recordset
cn4.ConnectionString = "dsn=db1"
cn4.Open
rs4.Open mysql, cn4, adOpenStatic
Set DataGrid1.DataSource = rs4
End Sub
Private Sub cmd_click()
Set cn5 = New ADODB.Connection
Set rs5 = New ADODB.Recordset
Page 142
138
cn5.ConnectionString = "dsn=db1"
cn5.Open
rs5.Open "素材", cn5, adOpenStatic
Set DataGrid1.DataSource = rs5
End Sub
Private Sub cmdone_click()
Dim mysql As String
Dim i_name As String
i_name = Text1.Text
mysql = "select 所需材料.菜名,素材.素材名,素材.種類 From 所
需材料,素材 where 所需材料.材料 = 素材.素材名 order by 所需
材料.菜名 desc"
Set cn5 = New ADODB.Connection
Set rs5 = New ADODB.Recordset
cn5.ConnectionString = "dsn=db1"
cn5.Open
rs5.Open mysql, cn5, adOpenStatic
Set DataGrid1.DataSource = rs5
Page 143
139
End Sub
VIP
Form load 程式碼:
Private Sub form_load()
Set cnvip = New ADODB.Connection
Set rsvip = New ADODB.Recordset
Dim myvip As String
myvip = "select vip.姓名 ,vip.電話 From vip order by vip.
姓名 asc"
cnvip.ConnectionString = "dsn=db1"
cnvip.CursorLocation = adUseClient
cnvip.Open
rsvip.Open myvip, cnvip, adOpenStatic, adLockOptimistic
Set DataGrid1.DataSource = rsvip
Text4.Text = rsvip!姓名
Page 144
140
Text5.Text = rsvip!電話
End Sub
新增程式碼
Private Sub cmdAdd_Click()
If Text1.Text = "" Or Text2.Text = "" Then
Beep
rmsg = MsgBox("請輸入資料", vbOKOnly, "訊息")
Exit Sub
End If
rsvip.AddNew
rsvip!姓名 = Text1.Text
rsvip!電話 = Text2.Text
rsvip.Update
End Sub
Page 145
141
刪除程式碼
Private Sub cmddel_Click()
Dim ret As String
Beep
ret = MsgBox("是否真的要刪除此顧客:[" & rsvip!姓名 & "]",
vbYesNo, "確認刪除")
If ret = vbYes Then
rsvip.Delete
rsvip.MoveNext
If rsvip.EOF = True Then
rsvip.MoveLast
End If
Else
Exit Sub
End If
End Sub
Page 146
142
修改程式碼
Private Sub cmdEdit_Click()
If Text4.Text = "" Or Text5.Text = "" Then
Beep
rmsg = MsgBox("請輸入要改的資料", vbOKOnly, "訊息")
Exit Sub
End If
rsvip.Update "姓名", Text4.Text
rsvip.Update "電話", Text5.Text
End Sub
第一筆程式碼
Private Sub cmdFirst_Click()
rsvip.MoveFirst
Text4.Text = rsvip!姓名
Page 147
143
Text5.Text = rsvip!電話
End Sub
最後一筆程式碼
Private Sub cmdLast_Click()
rsvip.MoveLast
Text4.Text = rsvip!姓名
Text5.Text = rsvip!電話
End Sub
下一筆程式碼
Private Sub cmdNext_Click()
rsvip.MoveNext
If rsvip.EOF = True Then
rsvip.MoveLast
End If
Text4.Text = rsvip!姓名
Page 148
144
Text5.Text = rsvip!電話
End Sub
上一筆程式碼
Private Sub cmdup_Click()
rsvip.MovePrevious
If rsvip.BOF = True Then
rsvip.MoveFirst
End If
Text4.Text = rsvip!姓名
Text5.Text = rsvip!電話
End Sub
Page 149
145
B.Client 端
程式碼的解說 ﹕
Option Explicit
Dim conn As ADOCE.Connection
Dim DBFilename As String
Dim strTableName As String
Dim intTotalItem As Integer
Dim strItemName(60) As String
Dim intItemMoney(60) As Integer
Dim intItemCheck(60) As Integer
Dim intCurrentItemNo As Integer
Dim intCurrentPageNo As Integer
Dim intTotalPageNo As Integer
Page 150
146
Dim lngTotalMoney As Long
Dim intTotalSelectItemNo As Integer
Dim strShopFilename As String
Dim FoodCounter As Integer
/*將所需要的變數做定義
Private Sub cmdClose_Click()
WinSock1.Close
WinSock1.LocalPort = 0
cmdConnect.Enabled = True
cmdClose.Enabled = False
lblStatus.Caption = "連線關閉"
End Sub
/*離線按鈕的設定
Page 151
147
Private Sub cmdConnect_Click()
WinSock1.Protocol = sckTCPProtocol
WinSock1.RemoteHost = txtRemortHost.Text
WinSock1.RemotePort = txtRemortPort.Text
WinSock1.Connect
lblStatus.Caption = "連線開啟"
If WinSock1.State sckConnected Then
lblStatus.Caption = CStr(GetState(WinSock1))
Exit Sub
End If
cmdConnect.Enabled = False
cmdClose.Enabled = True
Page 152
148
End Sub
/*連線按鈕點擊之後產生的後續動作
Private Sub cmdTrains_Click()
If WinSock1.State sckConnected Then
lblStatus.Caption = CStr(GetState(WinSock1))
Exit Sub
End If
FoodCounter = 0
Dim strOrder As String
Dim i As Integer
For i = 1 To 60 Step 1
If intItemMoney(i) = "" Then Exit For
FoodCounter = FoodCounter + 1
strOrder = CStr(FoodCounter) + " : " + txtTable.Text + " : "
+ strItemName(i) + " : " + intItemMoney(i) + " 元 " + vbCrLf
WinSock1.SendData strOrder
Page 153
149
Next i
Dim intTemp As Integer
For intTemp = 1 To 60
strItemName(intTemp) = ""
intItemMoney(intTemp) = ""
intItemCheck(intTemp) = 0
Next
intTotalItem = 0
intCurrentItemNo = 1
intCurrentPageNo = 1
lngTotalMoney = 0
intTotalSelectItemNo = 0
lblBuyCount.Caption = intTotalSelectItemNo
lblShopMoney.Caption = lngTotalMoney
lblTotalCount.Caption = intTotalItem
Page 154
150
lblMessage.Caption = "傳送成功"
ClearList
DisplayListData intCurrentPageNo
End Sub
/*傳送菜單按鈕 ﹐傳什麼資料以及成功之後的後續動作 。
Private Sub Form_Load()
Dim strPath As String
strPath = App.Path
If strPath = "\" Then
strPath = ""
End If
DBFilename = strPath & "\menu.cdb"
Page 155
151
If DBExists(DBFilename) = True Then
lblMessage.Caption = "資料庫準備就緒"
Else
lblMessage.Caption = "資料庫無法載入"
End If
fraItems.Left = TabStrip1.ClientLeft
fraItems.Top = TabStrip1.ClientTop
fraItems.Width = TabStrip1.ClientWidth
fraItems.Height = TabStrip1.ClientHeight
fraList.Left = TabStrip1.ClientLeft
fraList.Top = TabStrip1.ClientTop
fraList.Width = TabStrip1.ClientWidth
fraList.Height = TabStrip1.ClientHeight
fraList.Visible = False
fraItems.Visible = True
Page 156
152
intTotalItem = 0
intCurrentItemNo = 1
intCurrentPageNo = 1
lngTotalMoney = 0
intTotalSelectItemNo = 0
Dim intTemp As Integer
For intTemp = 1 To 60
intItemCheck(intTemp) = 0
Next
End Sub
/*測試資料庫是否存在 。
Page 157
153
Private Sub cboItems_Click()
Dim strTemp As String
strTemp = cboItems.Text
Select Case strTemp
Case "套餐"
strTableName = "套餐"
Case "湯類"
strTableName = "湯類"
Case "點心"
strTableName = "點心"
End Select
If strTableName "" Then
DisplayDataToGrid strTableName
Page 158
154
End If
grdItems.Row = 0
End Sub
/*選擇餐點的種類 ﹐以及選了之後 CALL 另外的 SUB 來秀 。
Private Sub TabStrip1_Click()
Select Case TabStrip1.SelectedItem.Key
Case "SelectItems" '選擇餐點
fraList.Visible = False
fraItems.Visible = True
fraConnect.Visible = False
Case "ListItems" '點餐清單
fraList.Visible = True
fraItems.Visible = False
fraConnect.Visible = False
DisplayListData (intCurrentPageNo)
Page 159
155
Case "Connect" '連線區
fraList.Visible = False
fraItems.Visible = False
fraConnect.Visible = True
End Select
End Sub
/*TABSTRIP 的功能設定 ﹐三個選項 。
Private Function DBExists(strFileName As String) As Boolean
If FileSystem1.Dir(strFileName) "" Then
DBExists = True
Else
DBExists = False
End If
End Function
Page 160
156
Function connOpen() As Boolean
On Error Resume Next
connOpen = True
If conn Is Nothing Then
Set conn = CreateObject("ADOCE.Connection.3.0")
conn.Open DBFilename
If conn.Errors.Count > 0 Then
MsgBox "errors in connOpen", vbOKOnly
connOpen = False
End If
End If
On Error GoTo 0
End Function
Sub connClose()
On Error Resume Next
conn.Close
Set conn = Nothing
Page 161
157
On Error GoTo 0
End Sub
/*打開資料庫
Private Sub DisplayDataToGrid(tablename As String)
Dim rs As ADOCE.Recordset
Dim intCount As Integer
Dim strData As String
Dim intCol As Integer
Dim intCounter As Integer
grdItems.Rows = 0
grdItems.AddItem ("商品" + vbTab + "價格")
intCounter = 0
intCol = 0
For intCol = 0 To 1
grdItems.Col = intCol
grdItems.Row = intCounter
grdItems.CellFontSize = 10
Next
Page 162
158
If connOpen = True Then
Set rs = CreateObject("ADOCE.Recordset.3.0")
On Error Resume Next
rs.Open "select * from " & tablename, conn,
adOpenForwardOnly, adLockReadOnly
rs.MoveFirst
Do While Not rs.EOF
strData = CStr(rs(1).Value) + vbTab + CStr(rs(2).Value)
grdItems.AddItem strData
intCounter = intCounter + 1
For intCol = 0 To 1
grdItems.Col = intCol
grdItems.Row = intCounter
grdItems.CellFontSize = 10
Next
rs.MoveNext
Loop
rs.Close
Page 163
159
Set rs = Nothing
On Error GoTo 0
End If
grdItems.TopRow = 0
grdItems.ColWidth(0) = 2000
grdItems.ColWidth(1) = 1000
connClose
End Sub
Private Sub grdItems_Click()
If grdItems.RowSel = 0 Then
Exit Sub
ElseIf grdItems.Clip = "" Then
Exit Sub
End If
If intTotalItem > 60 Then
lblMessage.Caption = "選購商品超過 60 項!"
Page 164
160
Exit Sub
End If
intTotalItem = intTotalItem + 1
strItemName(intTotalItem) =
grdItems.TextMatrix(grdItems.RowSel, 0)
intItemMoney(intTotalItem) =
grdItems.TextMatrix(grdItems.RowSel, 1)
lngTotalMoney = lngTotalMoney +
grdItems.TextMatrix(grdItems.RowSel, 1)
lblShopMoney.Caption = lngTotalMoney
lblMessage.Caption = "加入商品:" &
grdItems.TextMatrix(grdItems.RowSel, 0)
lblTotalCount.Caption = intTotalItem
intTotalPageNo = ((lblTotalCount - 1) \ 8) + 1
End Sub
/*秀出表單的方式
Private Sub DisplayListData(PageNo As Integer)
Page 165
161
ItemName1.Caption = strItemName((PageNo - 1) * 8 + 1)
ItemName2.Caption = strItemName((PageNo - 1) * 8 + 2)
ItemName3.Caption = strItemName((PageNo - 1) * 8 + 3)
ItemName4.Caption = strItemName((PageNo - 1) * 8 + 4)
ItemName5.Caption = strItemName((PageNo - 1) * 8 + 5)
ItemName6.Caption = strItemName((PageNo - 1) * 8 + 6)
ItemName7.Caption = strItemName((PageNo - 1) * 8 + 7)
ItemName8.Caption = strItemName((PageNo - 1) * 8 + 8)
ItemMoney1.Caption = intItemMoney((PageNo - 1) * 8 + 1)
ItemMoney2.Caption = intItemMoney((PageNo - 1) * 8 + 2)
ItemMoney3.Caption = intItemMoney((PageNo - 1) * 8 + 3)
ItemMoney4.Caption = intItemMoney((PageNo - 1) * 8 + 4)
ItemMoney5.Caption = intItemMoney((PageNo - 1) * 8 + 5)
ItemMoney6.Caption = intItemMoney((PageNo - 1) * 8 + 6)
ItemMoney7.Caption = intItemMoney((PageNo - 1) * 8 + 7)
ItemMoney8.Caption = intItemMoney((PageNo - 1) * 8 + 8)
ItemCheck1.Value = intItemCheck((PageNo - 1) * 8 + 1)
Page 166
162
ItemCheck2.Value = intItemCheck((PageNo - 1) * 8 + 2)
ItemCheck3.Value = intItemCheck((PageNo - 1) * 8 + 3)
ItemCheck4.Value = intItemCheck((PageNo - 1) * 8 + 4)
ItemCheck5.Value = intItemCheck((PageNo - 1) * 8 + 5)
ItemCheck6.Value = intItemCheck((PageNo - 1) * 8 + 6)
ItemCheck7.Value = intItemCheck((PageNo - 1) * 8 + 7)
ItemCheck8.Value = intItemCheck((PageNo - 1) * 8 + 8)
End Sub
/*秀出點菜清單的方式
Private Sub cmdPageDown_Click()
Dim temp
temp = intTotalSelectItemNo
If intCurrentPageNo >= intTotalPageNo Then
Exit Sub
End If
intCurrentPageNo = intCurrentPageNo + 1
Page 167
163
DisplayListData intCurrentPageNo
intTotalSelectItemNo = temp
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
/*下一頁的表現方式
Private Sub cmdPageUp_Click()
Dim temp
temp = intTotalSelectItemNo
If intCurrentPageNo = 1 Then
Exit Sub
End If
intCurrentPageNo = intCurrentPageNo - 1
DisplayListData intCurrentPageNo
intTotalSelectItemNo = temp
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
Page 168
164
/*上一頁的表現方式
Private Sub ClearList()
ItemName1.Caption = ""
ItemName2.Caption = ""
ItemName3.Caption = ""
ItemName4.Caption = ""
ItemName5.Caption = ""
ItemName6.Caption = ""
ItemName7.Caption = ""
ItemName8.Caption = ""
ItemMoney1.Caption = ""
ItemMoney2.Caption = ""
ItemMoney3.Caption = ""
ItemMoney4.Caption = ""
ItemMoney5.Caption = ""
ItemMoney6.Caption = ""
ItemMoney7.Caption = ""
Page 169
165
ItemMoney8.Caption = ""
End Sub
/*清除畫面上的資料
Private Sub MoveDate(ItemNo As Integer)
Dim intTemp
For intTemp = ItemNo To intTotalItem
strItemName(intTemp) = strItemName(intTemp + 1)
intItemMoney(intTemp) = intItemMoney(intTemp + 1)
intItemCheck(intTemp) = intItemCheck(intTemp + 1)
Next
strItemName(intTotalItem + 1) = ""
intItemMoney(intTotalItem + 1) = ""
intItemCheck(intTotalItem + 1) = 0
ClearList
DisplayListData intCurrentPageNo
Page 170
166
End Sub
Private Sub ItemName1_DblClick()
Dim temp
temp = MsgBox("你確定要刪除:" & ItemName1.Caption, vbOKCancel,
"刪除商品")
If temp = vbCancel Then
Exit Sub
End If
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 1
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
lngTotalMoney = lngTotalMoney -
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo - 1
Page 171
167
lblBuyCount.Caption = intTotalSelectItemNo
End If
MoveDate intCurrentItemNo
End Sub
/*刪除點菜資料的方式 ﹐第一欄位到第八欄位都是一樣 。
Private Sub ItemName2_DblClick()
Dim temp
temp = MsgBox("你確定要刪除:" & ItemName2.Caption, vbOKCancel,
"刪除商品")
If temp = vbCancel Then
Exit Sub
End If
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 2
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
Page 172
168
lngTotalMoney = lngTotalMoney -
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo - 1
lblBuyCount.Caption = intTotalSelectItemNo
End If
MoveDate intCurrentItemNo
End Sub
Private Sub ItemName3_DblClick()
Dim temp
temp = MsgBox("你確定要刪除:" & ItemName3.Caption, vbOKCancel,
"刪除商品")
If temp = vbCancel Then
Exit Sub
Page 173
169
End If
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 3
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
lngTotalMoney = lngTotalMoney -
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo - 1
lblBuyCount.Caption = intTotalSelectItemNo
End If
MoveDate intCurrentItemNo
End Sub
Page 174
170
Private Sub ItemName4_DblClick()
Dim temp
temp = MsgBox("你確定要刪除:" & ItemName4.Caption, vbOKCancel,
"刪除商品")
If temp = vbCancel Then
Exit Sub
End If
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 4
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
lngTotalMoney = lngTotalMoney -
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo - 1
Page 175
171
lblBuyCount.Caption = intTotalSelectItemNo
End If
MoveDate intCurrentItemNo
End Sub
Private Sub ItemName5_DblClick()
Dim temp
temp = MsgBox("你確定要刪除:" & ItemName5.Caption, vbOKCancel,
"刪除商品")
If temp = vbCancel Then
Exit Sub
End If
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 5
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
lngTotalMoney = lngTotalMoney -
Page 176
172
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo - 1
lblBuyCount.Caption = intTotalSelectItemNo
End If
MoveDate intCurrentItemNo
End Sub
Private Sub ItemName6_DblClick()
Dim temp
temp = MsgBox("你確定要刪除:" & ItemName6.Caption, vbOKCancel,
"刪除商品")
If temp = vbCancel Then
Exit Sub
End If
Page 177
173
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 6
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
lngTotalMoney = lngTotalMoney -
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo - 1
lblBuyCount.Caption = intTotalSelectItemNo
End If
MoveDate intCurrentItemNo
End Sub
Private Sub ItemName7_DblClick()
Dim temp
temp = MsgBox("你確定要刪除:" & ItemName7.Caption, vbOKCancel,
"刪除商品")
Page 178
174
If temp = vbCancel Then
Exit Sub
End If
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 7
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
lngTotalMoney = lngTotalMoney -
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo - 1
lblBuyCount.Caption = intTotalSelectItemNo
End If
MoveDate intCurrentItemNo
Page 179
175
End Sub
Private Sub ItemName8_DblClick()
Dim temp
temp = MsgBox("你確定要刪除:" & ItemName8.Caption, vbOKCancel,
"刪除商品")
If temp = vbCancel Then
Exit Sub
End If
intCurrentItemNo = (intCurrentPageNo - 1) * 8 + 8
intTotalItem = intTotalItem - 1
lblTotalCount.Caption = intTotalItem
lngTotalMoney = lngTotalMoney -
intItemMoney(intCurrentItemNo)
lblShopMoney.Caption = lngTotalMoney
If intItemCheck(intCurrentItemNo) = 1 Then
Page 180
176
intTotalSelectItemNo = intTotalSelectItemNo - 1
lblBuyCount.Caption = intTotalSelectItemNo
End If
MoveDate intCurrentItemNo
End Sub
Private Sub ItemCheck1_Click()
If ((intCurrentPageNo - 1) * 8 + 1) > intTotalItem Then
ItemCheck1.Value = 0
Exit Sub
End If
intItemCheck((intCurrentPageNo - 1) * 8 + 1) = ItemCheck1.Value
If ItemCheck1.Value = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo + 1
Else
intTotalSelectItemNo = intTotalSelectItemNo - 1
Page 181
177
End If
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
/*標記欄位 1-8
Private Sub ItemCheck2_Click()
If ((intCurrentPageNo - 1) * 8 + 2) > intTotalItem Then
ItemCheck2.Value = 0
Exit Sub
End If
intItemCheck((intCurrentPageNo - 1) * 8 + 2) = ItemCheck2.Value
If ItemCheck2.Value = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo + 1
Else
intTotalSelectItemNo = intTotalSelectItemNo - 1
End If
lblBuyCount.Caption = intTotalSelectItemNo
Page 182
178
End Sub
Private Sub ItemCheck3_Click()
If ((intCurrentPageNo - 1) * 8 + 3) > intTotalItem Then
ItemCheck3.Value = 0
Exit Sub
End If
intItemCheck((intCurrentPageNo - 1) * 8 + 3) = ItemCheck3.Value
If ItemCheck3.Value = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo + 1
Else
intTotalSelectItemNo = intTotalSelectItemNo - 1
End If
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
Private Sub ItemCheck4_Click()
Page 183
179
If ((intCurrentPageNo - 1) * 8 + 4) > intTotalItem Then
ItemCheck4.Value = False
Exit Sub
End If
intItemCheck((intCurrentPageNo - 1) * 8 + 4) = ItemCheck4.Value
If ItemCheck4.Value = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo + 1
Else
intTotalSelectItemNo = intTotalSelectItemNo - 1
End If
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
Private Sub ItemCheck5_Click()
If ((intCurrentPageNo - 1) * 8 + 5) > intTotalItem Then
ItemCheck5.Value = 0
Exit Sub
Page 184
180
End If
intItemCheck((intCurrentPageNo - 1) * 8 + 5) = ItemCheck5.Value
If ItemCheck5.Value = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo + 1
Else
intTotalSelectItemNo = intTotalSelectItemNo - 1
End If
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
Private Sub ItemCheck6_Click()
If ((intCurrentPageNo - 1) * 8 + 6) > intTotalItem Then
ItemCheck6.Value = 0
Exit Sub
End If
intItemCheck((intCurrentPageNo - 1) * 8 + 6) = ItemCheck6.Value
Page 185
181
If ItemCheck6.Value = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo + 1
Else
intTotalSelectItemNo = intTotalSelectItemNo - 1
End If
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
Private Sub ItemCheck7_Click()
If ((intCurrentPageNo - 1) * 8 + 7) > intTotalItem Then
ItemCheck7.Value = False
Exit Sub
End If
intItemCheck((intCurrentPageNo - 1) * 8 + 7) = ItemCheck7.Value
If ItemCheck7.Value = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo + 1
Else
Page 186
182
intTotalSelectItemNo = intTotalSelectItemNo - 1
End If
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
Private Sub ItemCheck8_Click()
If ((intCurrentPageNo - 1) * 8 + 8) > intTotalItem Then
ItemCheck8.Value = False
Exit Sub
End If
intItemCheck((intCurrentPageNo - 1) * 8 + 8) = ItemCheck8.Value
If ItemCheck8.Value = 1 Then
intTotalSelectItemNo = intTotalSelectItemNo + 1
Else
intTotalSelectItemNo = intTotalSelectItemNo - 1
Page 187
183
End If
lblBuyCount.Caption = intTotalSelectItemNo
End Sub
Private Sub cmdClear_Click()
Dim intTemp As Integer
For intTemp = 1 To 60
strItemName(intTemp) = ""
intItemMoney(intTemp) = ""
intItemCheck(intTemp) = 0
Next
intTotalItem = 0
intCurrentItemNo = 1
intCurrentPageNo = 1
lngTotalMoney = 0
intTotalSelectItemNo = 0
Page 188
184
lblBuyCount.Caption = intTotalSelectItemNo
lblShopMoney.Caption = lngTotalMoney
lblTotalCount.Caption = intTotalItem
lblMessage.Caption = ""
ClearList
DisplayListData intCurrentPageNo
End Sub
/*將所有資料清除
Private Sub Form_OKClick()
App.End
End Sub
/*程式結束
Page 189
185
C.介紹如何將模擬器程式製作成安裝檔 ﹐將其安裝到 PDA 上 。
使用 EVB 寫出來的程式要安裝到 PDA 內部 ﹐變成內部執行程
式必須要將程式碼做成安裝檔 ﹐首先將程式打開 ﹐在 FILE 選項內 ﹐
有個 Make *****.vb 的指令 ﹐
做出來的 vb 檔案等等會用到 ﹐所以先放在明顯的地方 ﹐如桌面等
等 。 接下來就是製作安裝檔 ﹐在 Tools 內的 Remote Tools 下的
Application Install Wizard 。
Page 190
186
點擊進入 。
確定進入下一步 。
所指定的位置必須為該程式的*.ebp 檔案所在位置 。 確認後進行下
一步 。
Page 191
187
這個檔案就是一開始製作的 vb 檔 ﹐在這邊要把它載入 。
接下來就是選擇位置放置製作的安裝檔案 。
Page 192
188
這個功能是選擇支援哪種電腦 。
如果程式內使用到任何資源 ﹐都要把它載入 。
Page 193
189
是否有任何附加檔案 。
接下來就是對這安裝檔的敘述 。
Page 194
190
接下來按下 Create Install 就開始製作安裝檔 。
這就是做出來的全部安裝檔 ﹐如果要安裝 ﹐請進入 CD1 的資料夾 。
點擊 Setup 就會將程式安裝到 PDA 中 。
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment