Các điều khiển trong ứng dụng đồ họa

Một phần của tài liệu TÌM HIỂU và NGHIÊN cứu kỹ THUẬTPHÁT TRIỂN ỨNG DỤNG TRÊN MÔITRƯỜNG SYMBIAN OS (Trang 116)

2 Hướng nghiên cứu và giới hạn đề tài

5.5.3 Các điều khiển trong ứng dụng đồ họa

Như các hệ điều hành khác, trong ứng dụng giao diện đồ họa, Symbian cũng cung cấp nhiều kiểu hộp điều khiển khác nhau để tạo giao tiếp giữa người dùng và

ứng dụng: dialog box, button, list box, editor, ... Các điều khiển này thường được khai báo trong các file tài nguyên. Symbian cung cấp nhiều lớp khác nhau để quản lý các loại điều khiển này và tất cả chúng đều kế thừa từ lớp CCoeControl.

KHOA CNTT –

ĐH KHTN

• Xây dựng file tài nguyên

Vì biên dịch file tài nguyên bắt đầu bằng tiền xử lý C, nên file tài nguyên có cấu trúc và sử dụng kiểu như chương trình C.

- Các kiểu dữ liệu dùng trong file tài nguyên: BYTE (1 byte), WORD (2 byte), LONG (4 byte), DOUBLE (thực 8 byte), TEXT (chuỗi kết thúc bằng null), LTEXT (chuỗi Unicode có chứa chiều dài), BUF (chuỗi Unicode), BUF8 (chuỗi ký tự 8 bit), LINK và LLINK (ID của tài nguyên khác 16 và 32 bit), SRLINK (ID tài nguyên do nó định nghĩa). Symbian cũng cho phép chúng ta tự định nghĩa kiểu dữ

liệu riêng có cấu trúc như sau:

STRUCT struct-name [BYTE|WORD] {struct-member-list} Với: struct-name: Tên kiểu dữ liệu có cấu trúc viết chữ hoa.

BYTE|WORD: tham số tùy chọn dùng với STRUCT có chiều dài thay

đổi, chỉ có ý nghĩa khi STRUCT này được dùng làm thành viên của một STRUCT khác.

Struct-member-list: danh sách các thành viên, phân cách nhau bởi dấu phẩy và chứa trong cặp dấu ngoặc kép {}. Các thành viên này có kiểu dữ liệu là cấp sẵn hoặc là STRUCT và có thểđặt giá trị mặc định cho nó.

- Khai báo tài nguyên: Có tất cả 5 loại khai báo, ngoài STRUCT nhưở trên 4 loại còn lại là NAME, RESOURCE, ENUM và CHARACTER_SET.

Khai báo Ý nghĩa

CHARACTER_SET Định nghĩa bộ ký tự cho chuỗi trong file tài nguyên ENUM Liệt kê các giá trị

NAME Tên cho nhóm tài nguyên, định danh cho 1 file tài nguyên nên phải được khai báo trước tiên

RESOURCE Khai báo loại tài nguyên

STRUCT Khai báo dữ liệu có cấu trúc riêng B5.1 Các khai báo trong file tài nguyên

KHOA CNTT –

ĐH KHTN

Một file tài nguyên có thể chứa 4095 khai báo tài nguyên. RESOURCE là khai báo quan trọng nhất trong file tài nguyên, cấu trúc như sau:

RESOURCE struct-name [id] {member-list}

Với: struct-name: Tên kiểu dữ liệu STRUCT đã khai báo trước , thường nằm trong file tài nguyên .rh.

id: định danh cho tài nguyên dưới dạng chữ thường, định danh được

định nghĩa trong file .rsg ở dạng chữ hoa với khai báo #define.

member-list: danh sách các thành viên, phân cách nhau bởi dấu phẩy và chứa trong cặp dấu ngoặc kép {}.

Ví dụ: Khai báo tài nguyên menu chuẩn trong file uikon.rh STRUCT MENU_PANE { STRUCT item[]; LLINK extension=0; } STRUCT MENU_ITEM { LONG command=0; LLINK cascade=0; LONG flags=0; LTEXT txt; LTEXT extratxt= “”; LTEXT bmpfile=“”; WORD bmpid=0xffff; WORD bmpmask=0xffff; LLINK extension=0; }

KHOA CNTT –

ĐH KHTN

và khai báo menu trong ứng dụng HelloWorld: RESOURCE MENU_PANE r_hello_menu

{ items = { MENU_ITEM { command = EHelloCmd; txt = “Item”; } MENU_ITEM { command = EeikCmdExit; txt = “Close”; } }; }

5.6 Quy ước đặt tên và xây dựng thư mục dự án trong Symbian

Như mọi hệ thống, Symbian sử dụng quy ước đặt tên để xác định những gì quan trọng. Các quy ước này làm cho việc lập trình và đọc mã nguồn dễ hơn.

5.6.1 Tên lớp

Symbian sử dụng các quy ước đặt tên sau để xác định đặc tính cơ bản của một lớp:

• Lớp T: lớp đơn giản (tựa như typedef) thường sử dụng cho số integer, kiểu Boolean và các cấu trúc đơn giản khác. Nó không có constructor và destructor và có thểđược lưu trên stack. Ví dụ: TInt, TBool, TPoint,...

KHOA CNTT –

ĐH KHTN

• Lớp C: Lớp có constructor và destructor và tất cả đều là dẫn xuất từ CBase. Các đối tượng được tạo bằng new và luôn được lưu trữ trên heap. Ví dụ: CConsoleBase, CActive,...

• Lớp R: Lớp R thường là đại diện, được uỷ quyền bởi một đối tượng khác (thường là một server chạy trong một tiểu trình khác). Đối tượng lớp R thường có một hàm khởi tạo và một hàm kết thúc. Nó có thểđược lưu trên heap. Ví dụ: RFile, RTimer, RWindow,...

• Lớp M: Lớp ảo (abstract) giống như interface trong Java, nó chỉ bao gồm các phương thức ảo rỗng và không có dữ liệu. Ví dụ: MGraphicsDeviceMap, MGameViewCmdHandler,...

Việc phân biệt giữa T, C và R lớp là rất quan trọng, nó ảnh hưởng tới việc giải phóng bộ nhớ khi sử dụng.

5.6.2 Tên dữ liệu

Tương tự, Symbian cũng dùng chữ cái đầu để phân biệt các loại dữ liệu:

• Hằng liệt kê (Enumerated constant): Bắt đầu với ký tự E, nó đại diện cho một giá trị hằng trong một dãy liệt kê. Nó có thể là một phần của lớp T. Ví dụ: (ETrue, EFalse) của TBool hay EMonday là một thành phần của TDayOfWeek.

• Hằng (constant): Bắt đầu với ký tự K, thường được dùng trong các khai báo #define hay các giá trị hằng do Symbian quy định. Ví dụ: KMaxFileName hay KErrNone.

• Biến thành phần (member variable): Bắt đầu với chữ cái i (instance), được dùng khi sử dụng các biến động là thành viên của một lớp. Đây là quy ước quan trọng, dùng cho việc hủy vùng nhớ trên heap. Ví dụ: iDevice, iX, …

• Tham số (argument): Bắt đầu bằng chữ a (argument), được dùng khi các biến làm tham số. Ví dụ: aDevice, aX, …

• Macro: Không có quy ước đặc biệt. Tất cả đều viết hoa và dùng dấu gạch dưới để phân tách từ. Ví dụ: IMPORT_C, _TEST_INVARIANT, _ASSERT_ALWAYS, v.v…

KHOA CNTT –

ĐH KHTN

• Biến tự động (automatic): chữ cái đầu nên viết thường. Biến toàn cục (global): nên viết hoa chữ cái đầu nhưng để tránh nhầm lẫn nên bắt đầu tên bằng chữ cái “g”. Tuy nhiên trên Symbian không khuyến khích dùng biến toàn cục.

5.6.3 Tên hàm

Tên hàm bắt đầu bằng ký tự hoa. Khác với 2 trường hợp trên, quy ước đặt tên hàm lại dựa trên ký tự cuối cùng:

• Hàm không thể “ngắt” an toàn (non-leaving function): Ví dụ: Draw() hay Intersects().

• Hàm “ngắt” an toàn (leaving function): Kết thúc bằng ký tự L. Hàm này thường được dùng để xử lý các trường hợp hay gặp lỗi. Ví dụ: DrawL() hay RunL().

• Hàm LC: Kết thúc với cặp ký tự LC. Các hàm này khai báo một đối tượng mới, đặt nó lên cleanup stack và ngắt an toàn khi gặp lỗi. Ví dụ: AllocLC(), CreateLC(), OpenLC() hay NewLC().

• Các hàm Get và Set: trong trường hợp đơn giản thường là các hàm thành viên của một lớp. Set dùng cho việc xác lập giá trị cho một biến thành viên của lớp. Get được dùng cho các hàm sẽ trả về giá trị trên tham số. Khi hàm có giá trị trả về

thì thường không dùng Get.

Ví dụ: SetThing(aData); GetThing(aData); nhưng iData = Thing(); Khi các hàm này truy xuất hay ghi lên các tài nguyên hay thực hiện các thao tác có thể gây ra lỗi thì chúng sẽ sử dụng các hàm có thoát an toàn. Chúng cũng là các hàm L.

5.6.4 Cấu trúc thư mục dự án

Tuy không bắt buộc nhưng Symbian khuyến khích lập trình viên xây dựng thư

mục dự án ứng dụng thành các thư mục con với chức năng riêng biệt. Thông thường thư mục dự án có cấu trúc như sau:

• Thư mục dự án: chứa các file dự án .mmp, bld.inf, file tài nguyên .rss. Thư

mục này cũng sẽ lưu trữ các file thông tin cụ thể cho chương trình dùng với các IDE. Thư mục này thường được đặt tên là: group.

KHOA CNTT –

ĐH KHTN

• Thư mục các file header: chứa các file khai báo cho file tài nguyên và các file mã nguồn. Thư mục này thường có tên là: inc.

• Thư mục mã nguồn: chứa các file cài đặt các lớp chương trình. Thư mục này thường có tên là: src.

• Thư mục dữ liệu: chứa dữ liệu cần cho chương trình ứng dụng và có tên là data.

• Thư mục thông tin ứng dụng: chứa file tài nguyên .rss để tạo file .aif và các hình ảnh, tài nguyên phục vụ cho ứng dụng. Tậo hợp các hình này được lưu trữ

trong một file .mbm (multi bitmap). Thư mục này có tên là aif.

• Thư mục cài đặt: chứa các file .pkg, các thành phần cài đặt bổ sung cho ứng dụng. Thư mục này thường có tên là: install.

• Thư mục chương trình: lưu trữ file cài đặt .sis. Thường nó được gộp với thư

mục install. Thư mục này có tên là release.

Tuy nhiên các dự án thường chỉ gồm các thư mục: group, inc và src.

5.7 Xây dựng ứng dụng độc lập thiết bị

Lập trình độc lập thiết bị và môi trường hệ thống luôn là chủ đề được quan tâm. Các lập trình viên luôn cố gắng viết các chương trình có thể chạy trên nhiều hệ

thống thiết bị khác nhau. Và đối với lập trình trên Symbian, độc lập thiết bị vẫn rất

được chú ý. Tuy nhiên như đã nói ở chương 1, Symbian chỉ hỗ trợ phần hệ thống còn phần giao diện thì do các nhà sản xuất điện thoại cung cấp dựa trên các dòng chuẩn nên trong một ứng dụng giao diện đồ họa thì phần engine xử lý bên dưới rõ ràng là đã độc lập thiết bị còn phần giao diện đồ họa GUI thì rất khác nhau phụ

thuộc dòng thiết bị mà ứng dụng đó hoạt động. Nói cách khác phần giao diện của

ứng dụng là phụ thuộc thiết bị. Vì vậy việc lập trình độc lập thiết bị trên Symbian là một việc hầu như không làm được.

Các lập trình viên biết rõ điều này nhưng họ vẫn mong muốn xây dựng một chương trình mà có thể hoạt động trên các nền hệ thống khác nhau mà ít phải chỉnh sửa lại chương trình nhất.

KHOA CNTT –

ĐH KHTN

Với một ứng dụng, muốn chạy được trên các nền hệ thống Symbian khác nhau như Series 60, Series 80 hay UIQ thì phải viết 3 chương trình có mã nguồn khác nhau. Tuy nhiên các chương trình này có phần kiến trúc ứng dụng APPARC bao gồm phần ứng dụng (application) và phần tài liệu (document) là tương đối giống nhau, phần engine xử lý các công việc bên dưới vẫn có thể dùng chung. Chúng chỉ

khác nhau phần AppUI xử lý giao diện. Dựa vào điều này, các phương pháp khác nhau đã được đề xuất để có thể tận dụng phần mã chung, xây dựng các chương trình chạy trên nhiều hệ thống nền khác nhau với chọn lựa phần AppUI thích hợp.

• Chép các file và chỉnh chúng cho phù hợp nền hệ thống: Đây là phương pháp thô sơ nhất. Các file chứa phần AppUI khác nhau giữa các nền hệ thống sẽ được thay thếđể biên dịch cho phù hợp với thiết bị đích. Phần ứng dụng (application) có thể giữ nguyên nhưng với một vài ứng dụng thì phần tài liệu (document) phải chỉnh sửa đôi chút.

• Sử dụng các macro: Điểm thuận lợi của phương pháp này là nhanh và dễ dùng nếu sự khác nhau giữa phần mã các chương trình là nhỏ. Nhưng khi ứng dụng phức tạp thì phương pháp này sẽ mang lại nhiều vấn đề, khó có thể duy trì các macro như

vậy.

Ví dụ:

#ifdef UIQ_CODE

// Do something UIQ specific

# define APPUI_PARENT_CLASS CQikAppUi #elif CKON_CODE

// Do something CKON-specific

# define APPUI_PARENT_CLASS CEikAppUi

#endif class CMyAppUi: public APPUI_PARENT_CLASS class CMyAppUi: public APPUI_PARENT_CLASS

Phương pháp này thường được dùng để áp dụng cho các ứng dụng có phần đặc tả riêng cho loại điện thoại. Ví dụ, cùng dùng Series 60 nhưng có một số chức năng

KHOA CNTT –

ĐH KHTN

trên Siemens SX1 sử dụng khác Nokia 6600. Sử dụng các macro với đặc tả thiết bị

sẽ giúp chúng ta có một chương trình nhưng có thể chạy trên cả SX1 và N6600.

• Kế thừa: Phương pháp này dựa trên việc sử dụng lớp AppUI cho các nền hệ

thống kế thừa từ một lớp AppUI cơ sở. Mới nhìn, đây có vẻ là giải pháp hoàn hảo, lại tận dụng những thành tựu của lập trình hướng đối tượng.

// Base class with common commands class CBaseAppUI: public CEikAppUi {

public:

void ConstructL(); ~CBaseAppUi(); protected:

void HandleCommandL(TInt aCommand); protected:

void CmdGoToPageL(); protected:

TInt iPage; // Current page

TInt iZoom; // Current zoom factor };

void CBaseAppUi::HandleCommandL(TInt aCommand) { switch (aCommand) { case EEikCmdHelpAbout: AboutDialog::RunDlgLD(); break; case EBaseCmdGoToPage: CmdGoToPageL(); break; // etc. } } void CBaseAppUi::CmdGoToPageL() {

TInt newPage = iPage;

if (GoToPageDialog::RunDlgLD(newPage, iDocument->NumPages()) {

if (iPage != newPage) ChangePageL(newPage); }

KHOA CNTT –

ĐH KHTN

Cài đặt cho UIQ:

// Base class with common commands class CUIQAppUI: public CBaseAppUi {

public:

void ConstructL(); ~CUIQAppUi(); public:

void HandleCommandL(TInt aCommand); private:

void CmdDeleteFileL(); // etc.

};

void CPdfUIQAppUi::HandleCommandL(TInt aCommand) { switch (aCommand) { case EPdfCmdDeleteFile: CmdDeleteFileL(); break; // etc.

default: CPdfAppUi::HandleCommandL(aCommand) break; }

}

Nhưng hướng tiếp cận này gặp một số vấn đề:

- Thứ nhất, với kiến trúc hệ thống Avkon (cho nền hệ thống Series 60) thì không chỉ lớp AppUI mà lớp AppView cũng phụ thuộc hệ thống bởi lớp AppView kế thừa từ lớp CAknView thay vì trực tiếp kế thừa lớp CCoeControl như các hệ

thống khác (Qikon và Ckon). Do đó không thể sử dụng giải pháp này với ứng dụng Avkon.

- Thứ hai, với kế thừa thì phải có lớp cơ sở chung. Nhưng không giống như ví dụ trên, CEikAppUI không phải là lớp cơ sở mà các lớp AppUI của ứng dụng trên các hệ thống khác nhau. Bởi vì chỉ có lớp AppUI trên Ckon (Series 80/Nokia 9200 Series) là kế thừa trực tiếp từ lớp CEikAppUI, còn trên Qikon (UIQ) kế thừa từ

CQikAppUI, trên Avkon kế thừa từ CAknAppUI hay từ CAknViewAppUI. Do đó việc kế thừa gần như là không thể, nếu được việc này cũng rất khó khăn.

KHOA CNTT –

ĐH KHTN

• Dùng lớp điều khiển: Sử dụng một lớp Controller để cài đặt tất cả các chức năng của lớp AppUI mà có thể dùng chung cho nhiều hệ thống. Lớp AppUI vẫn tồn tại nhưng nó chỉ chứa phần cài đặt các chức năng phụ thuộc hệ thống. Lớp Controller này không kế thừa từ lớp Eikon chính nào nhờđó nó không chỉđược các lớp AppUI sử dụng mà các lớp khác cũng có thể sử dụng nó. Giải pháp sử dụng lớp Controller tỏ ra hữu hiệu hơn giải pháp kế thừa. Nhưng cũng như vấn đề mà giải pháp kế thừa gặp phải là với hệ thống Avkon thì lớp AppView kế thừa từ lớp CAknAppView thay vì CCoeControl nghĩa là chúng ta phải dùng một lớp phụ thuộc thiết bị (AppView) với một lớp độc lập thiết bị (Controller). Giải pháp tầm thường là tạo các lớp AppView khác nhau cho các hệ thống. Giải pháp tốt hơn cho vấn đề

này là dùng một interface để cài đặt phần AppView, lớp Control điều khiển khung tham khảo interface này. Lúc này lớp AppView của ứng dụng Qikon và Ckon kế

thừa từ lớp CCoeControl và interface này còn lớp AppView trên Avkon kế thừa lớp CAknView và interface này.

class MBaseAppViewControllerInterface {

public:

virtual void DrawNewPage() const = 0; // Other abstract methods

};

class CBaseController: public CBase {

public:

void SetPageView(MPdfAppViewControllerInterface* aAppView); // etc.

private:

MBasePageViewControllerInterface* iAppView; // etc.

KHOA CNTT –

ĐH KHTN

Cài đặt lớp AppView cho UIQ:

CUIQAppView : public CCoeControl, publicCBaseAppViewControllerInterface

{ public:

// Constructing and destructing public:

void DrawNewPage() const; // etc.

};

Cài đặt lớp AppView cho Series 60: CS60AppView : public CAknAppView,

public MBaseAppViewControllerInterface {

public:

// Constructing and destructing public:

void DrawNewPage() const; // etc.

};

Giải pháp này đã giải quyết được vấn đề cơ bản trong việc xây dựng ứng dụng

đa nền và cấu trúc thư mục chương trình được xây dựng như sau: <Thư mục chương trình>

UI : Phần độc lập nền hệ thống Series60 :

aif, data, group, release

UI : Mã UI phụ thuộc kiến trúc AVKON Series 80 :

aif, data, group, release

UI: Mã phụ thuộc kiến trúc CKON UIQ

aif, data, group, release

KHOA CNTT –

ĐH KHTN

CHƯƠNG 6

KIM LI, BIÊN DCH VÀ TRIN KHAI

NG DNG SYMBIAN

Giả lập điện thoại Symbian trên PC Cấu trúc thư mục Emulator

Vị trí file biên dịch và file ứng dụng Các đặc tính của một Emulator Kiểm lỗi (debug)

Kiểm lỗi trên Emulator

Kiểm lỗi trên điện thoại Symbian

Với IDE CodeWarrior Professional Edittion hay OEM Edittion Với chương trình GDB

Một số mã lỗi thông dụng trong Symbian Biên dịch chương trình

Các loại biên dịch

Biên dịch cho Emulator Biên dịch cho WINC

Biên dịch cho điện thoại Symbian Biên dịch ứng dụng đồ họa

File AIF

Biên dịch với các công cụ biên dịch Biên dịch với IDE

Sơđồ biên dịch ứng dụng cho điện thoại Symbian Triển khai ứng dụng

Cấu trúc file điều khiển đóng gói .pkg Quá trình triển khai ứng dụng

KHOA CNTT –

ĐH KHTN

6.1 Giả lập điện thoại Symbian trên PC

Một phần của tài liệu TÌM HIỂU và NGHIÊN cứu kỹ THUẬTPHÁT TRIỂN ỨNG DỤNG TRÊN MÔITRƯỜNG SYMBIAN OS (Trang 116)

Tải bản đầy đủ (PDF)

(190 trang)