Khởi động ứng dụng Silverlight (XAML) trên Windows Embedded CE 7.0

Trong môi trường Windows Embedded CE 7.0, quy trình khởi động của một ứng dụng Silverlight (dựa trên XAML) tuân theo một chuỗi lời gọi nhất định, được minh họa qua stack trace sau:

SWEClock.exe!MainPage::OnLoaded(IXRDependencyObject* pRoot = 0x00047840) Line: 37, Offset: 0x24 C++  
SWEClock.exe!XRCustomUserControlImpl<MainPage,IXRCustomUserControl>::Create(IXRDependencyObject* pExistingDependencyObject = 0x0004782c, IXRDependencyObject** ppNewDp = 0x0003fbf4) Line: 568, Offset: 0x188 C++  
 0x40158c30   
 0x40158e98   
 0x4015c850   
>SWEClock.exe!IXRApplication::CreateObject<IXRCustomUserControl>(_GUID& riid = {...}, IXRCustomUserControl** ppObject = 0x0003fcb0) Line: 3112, Offset: 0x3c   C++  
SWEClock.exe!App::CreateHost(XRWindowCreateParams* pCreateParams = 0x0003fd00) Line: 112, Offset: 0x54  C++  
SWEClock.exe!App::Initialize(HINSTANCE__* hInstance = 0x064c005e) Line: 146, Offset: 0x148  C++  
SWEClock.exe!WinMain(HINSTANCE__* hInstance = 0x064c005e, HINSTANCE__* __formal = 0x00000000, wchar_t* __formal = 0x0003fe88, int __formal = 0x00000005) Line: 32, Offset: 0x6c C++  
SWEClock.exe!WinMainCRTStartupHelpANCE__* hInstaner(HINSTce = 0x00000054, HINSTANCE__* hInstancePrev = 0x00000000, unsigned short* lpszCmdLine = 0x00000000, int nCmdShow = 0x00070005) Line: 71, Offset: 0x40  C  

Sau khi thư viện phân tích XAML được gọi, luồng điều khiển quay trở lại mã ứng dụng thông qua hàm OnLoaded(). Điều này có nghĩa là tên hàm OnLoaded() là cố định và không thể thay đổi.

Các định nghĩa liên quan:

  • IXRApplication::CreateObject được định nghĩa trong x:\Program Files\Windows CE Tools\SDKs\HSW_T9_SDK\Include\Armv4i\xamlruntime.h
  • XRCustomUserControlImpl<MainPage,IXRCustomUserControl>::Create được định nghĩa trong x:\Program Files\Windows CE Tools\SDKs\HSW_T9_SDK\Include\Armv4i\xrcustomcontrol.h

Trong MainPage::OnLoaded(), quá trình phân tích file XAML chính thức bắt đầu. Dựa trên nội dung file XAML, các biến phần tử tương ứng được khai báo. Để biết thư viện XAML hỗ trợ những phần tử nào, bạn có thể tham khảo file header x:\Program Files\Windows CE Tools\SDKs\HSW_T9_SDK\Include\Armv4i\xrptr.h, phần cuối có chứa các định nghĩa tương tự như sau:

 1 #define XR_SMARTPTR(x) typedef XRPtr< x > x##Ptr  
 2   
 3 XR_SMARTPTR(IXRArcSegment);  
 4 XR_SMARTPTR(IXRBeginStoryboard);  
 5 XR_SMARTPTR(IXRBezierSegment);  
 6 XR_SMARTPTR(IXRBitmapCache);  
 7 XR_SMARTPTR(IXRBitmapImage);  
 8 XR_SMARTPTR(IXRBorder);  
 9 XR_SMARTPTR(IXRBrush);  
10 XR_SMARTPTR(IXRCanvas);  

Bạn cũng có thể gán sự kiện cho các phần tử, ví dụ như sự kiện tải (loaded), nhấp chuột (click), v.v. Thông thường, nếu form cần xử lý đặc biệt khi tải, bạn sẽ định nghĩa sự kiện tải và hoàn thành các công việc chuẩn bị trong hàm xử lý sự kiện.

(1) Xử lý sự kiện Layout Loaded

Giả sử Canvas là phần tử gốc (Root Element), bạn có thể định nghĩa như sau: IXRCanvasPtr m_pLayoutRoot;

 1 FindName(L"LayoutRoot", &m_pLayoutRoot);  
 2 if (m_pLayoutRoot)  
 3 {  
 4     m_pLayoutRoot->AddLoadedEventHandler(CreateDelegate(this, &MainPage::Canvas_Loaded));  
 5 }  
 6   
 7 // ============================================================================  
 8 //  Canvas_Loaded  
 9 //   
10 //  Description: Event handler implementation  
11 //  Lưu ý: Sự kiện Loaded="Canvas_Loaded" trong XAML không bắt buộc phải khớp với tên hàm này. Bạn có thể đổi thành Loaded="Canvas_Loaded_2" và chương trình vẫn chạy bình thường.  
12 //  Parameters:  pSender - Dependency object gây ra sự kiện.  
13 //               pArgs - Đối số của sự kiện.  
14 // ============================================================================  
15 HRESULT MainPage::Canvas_Loaded (IXRDependencyObject* pSender, XRRoutedEventArgs* pArgs)  
16 {  
17     // Xử lý logic tại đây  
18 }  

(2) Thêm xử lý sự kiện nút bấm

Bạn có thể truy cập vào nút bấm thông qua thuộc tính Name được khai báo trong Expression Blend (XAML) hoặc chỉnh sửa trực tiếp file XAML. Sử dụng kiểu phần tử XAML được định nghĩa trong file x:\Program Files\Windows CE Tools\SDKs\HSW_T9_SDK\Include\Armv4i\xrptr.h, ví dụ:

 1 IXRButtonBasePtr MyBtn;  
 2 if (FAILED(retCode=root->FindName(TEXT("MyButton"), &MyBtn)))  
 3     return -1;  

Để nhận thông báo khi người dùng nhấp vào nút, bạn cần cung cấp một delegate (khái niệm quen thuộc với lập trình viên C#). Trong C++, delegate ở đây là một con trỏ trỏ tới phương thức của một thể hiện (instance) của lớp C++ với prototype được xác định trước.

Bạn có thể khai báo một lớp C++ đơn giản trong file .cpp và triển khai delegate cho sự kiện nhấp chuột:

 1 class BtnEventHandler  
 2 {  
 3 public:  
 4     HRESULT OnClick(IXRDependencyObject* source, XRMouseButtonEventArgs* args)  
 5     {  
 6         MessageBox(NULL, TEXT("Click!"), TEXT("Silverlight for Windows Embedded test"), MB_OK);  
 7         return S_OK;  
 8     }  
 9 };  

Khi nút được nhấp, event handler chỉ đơn giản hiển thị một hộp thoại thông báo. Như bạn thấy, event handler có hai tham số: một con trỏ tới đối tượng gây ra sự kiện (nút bấm) và một con trỏ tới cấu trúc chứa tham số sự kiện.

Để kết nối event handler với nút bấm, bạn cần tạo một đối tượng delegate:

 1 BtnEventHandler handler;  
 2 IXRDelegate<XRMouseButtonEventArgs>* clickDelegate;  
 3 if (FAILED(retCode=CreateDelegate(&handler, &BtnEventHandler::OnClick, &clickDelegate)))  
 4     return -1;  
 5 if (FAILED(retCode=MyBtn->AddClickEventHandler(clickDelegate)))  
 6     return -1;  

Sau đó, event handler đã được gắn vào nút. Bây giờ chỉ cần chờ người dùng nhấp vào nút để hiển thị UI.

Lưu ý rằng con trỏ tới đối tượng delegate không phải là smart pointer, vì vậy bạn cần giải phóng nó một cách tường minh:

1 clickDelegate->Release();  

Thẻ: Windows Embedded CE Silverlight XAML C++ Event Handling

Đăng vào ngày 6 tháng 7 lúc 21:02