Thursday, September 10, 2009

PDA 點餐系統

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 中 。

No comments: