以下文章以 http://download.csdn.net/detail/91program/7588393 中的工程为基础,这也是我写此文章时一步一步建立的 Silverlight 工程。
1 使用 Microsoft Expression Blend 3 创建一个 Silverlight for Windows Embedded Application 工程,放一个按键控件在窗体上,命名按键然后保存。由于 Microsoft Expression Blend 3 现在只支持生成 C# 的代码,对我们没有什么用,所以我们只用其中的 XAML 文件。
2 VS2008 新建:智能设备->Win32 智能设备项目,选拔一个支持 Silverlight 的SDK。
3 文件 SilverlightHelloWorld.cpp 中,只保留如下代码,其它删除:
// SilverlightHelloWorld.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "SilverlightHelloWorld.h"
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
return 0;
}
4 新增加 4 个空文件,内容后面补,分别是:
App.cpp
App.h
MainPage.cpp
MainPage.h
5 增加文件 XRPack.rules,文件的内容如下:
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioToolFile
Name="XRPack Tool"
Version="8.00"
>
<Rules>
<CustomBuildRule
Name="XRPack Tool"
DisplayName="XRPack Tool"
CommandLine=""$(VSInstallDir)VC\VCWizards\WindowsEmbeddedSilverlightTools\XRPack.exe" "/Root=$(ProjectDir)" "/IntermediateFiles=$(OutDir)" "@$(InputPath)""
Outputs="$(InputName)Generated.h $(InputName)Generated.rc2"
FileExtensions="*.xrpack"
ExecutionDescription="Generating RC2 file."
>
<Properties>
</Properties>
</CustomBuildRule>
</Rules>
</VisualStudioToolFile>
6 将 XRPack.rules 增加到工程文件 SilverlightHelloWorld.vcproj 中,修改了两个地方,修改后的内容如下:
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="SilverlightHelloWorld"
ProjectGUID="{6DDF8C53-109B-4FC3-90B2-DD270ACA3A2C}"
RootNamespace="SilverlightHelloWorld"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="HSW_T9_SDK (ARMv4I)"
/>
</Platforms>
<ToolFiles>
<ToolFile
RelativePath=".\XRPack.rules"
/>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|HSW_T9_SDK (ARMv4I)"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="XRPack Tool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
......
7 新增文件 SilverlightHelloWorld.xrpack,其内容如下:
# This file is used to generate the rc2 file and baml resources
# Uncomment /C to force xrpack to perform a clean build every time
# /C
# Verbosity can be a value between 1 and 10
/Verbosity=3
/NoResourceCompile
"/TargetRC=WinEmbeddedHelloWorldGenerated.rc2"
"/TargetHeader=WinEmbeddedHelloWorldGenerated.h"
"/Project=..\WinEmbeddedHelloWorld\WinEmbeddedHelloWorld.csproj"
8 修改 stdafx.h ,增加以下内容:
// Xaml Runtime Header Files
#include <XamlRuntime.h>
#include <XRDelegate.h>
#include <XRPtr.h>
#include <XRCustomControl.h>
// IUnknown
extern "C" const GUID __declspec(selectany)IID_IUnknown = __uuidof(IUnknown);
// Resource type for XAML files
#define RT_XAML L"XAML"
// Application headers
#include "App.h"
#include "resource.h"
9 将 SilverlightHelloWorld.xrpack 文件增加到工程中
这样才能自动生成 WinEmbeddedHelloWorldGenerated.rc2 和 WinEmbeddedHelloWorldGenerated.h 文件
10 WinMain() 函数的实现代码如下
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
App AppInstance;
HRESULT hr = AppInstance.Initialize(hInstance);
if(SUCCEEDED(hr))
{
hr = AppInstance.Run();
}
return AppInstance.GetWinMainResultCode();
}
11 编译,是可以成功的,但还需要根据 XAML 文件的内容来修改 MailPage.cpp 和 MailPage.h。
MailPage.h
#pragma once
// <UserControl x:Class="SilverlightClock.MainPage">
class __declspec(uuid("{1756acb7-63be-4a4b-97cf-edc048541e75}")) MainPage
: public XRCustomUserControlImpl<MainPage>
{
QI_IDENTITY_MAPPING(MainPage, XRCustomUserControlImpl)
public:
static HRESULT GetXamlSource(__in XRXamlSource* pXamlSource)
{
HRESULT hr = E_INVALIDARG;
if (pXamlSource)
{
pXamlSource->SetResource (App::GetHInstance(), IDR_SILVERLIGHTCLOCK_MAINPAGE);
hr = S_OK;
}
return hr;
}
static HRESULT Register()
{
return XRCustomUserControlImpl<MainPage>::Register (__uuidof(MainPage), L"MainPage", L"clr-namespace:SilverlightClock");
}
#pragma region GeneratedCode
// ============================================================================
// WARNING: DO NOT EDIT THIS ALWAYS-GENERATED CODE
// ============================================================================
HRESULT OnLoaded(__in IXRDependencyObject* pRoot);
HRESULT InitializeComponent();
IXRGridPtr m_pLayoutRoot; // Grid x:Name="LayoutRoot" ...
IXRButtonBasePtr m_MyBtn;
IXRDelegate<XRMouseButtonEventArgs> *m_clickDelegate;
// ============================================================================
// WARNING: DO NOT EDIT THIS ALWAYS-GENERATED CODE
// ============================================================================
#pragma endregion GeneratedCode
};
MailPage.cpp
#include "stdafx.h"
#include "SilverlightHelloGenerated.h"
#include "MainPage.h"
#include "App.h"
#include "resource.h"
#define TEST_BTN_CLICK_PROCESS 1
#if TEST_BTN_CLICK_PROCESS
class BtnEventHandler
{
public:
HRESULT OnClick(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
{
MessageBox(NULL,TEXT("Click!"),TEXT("Silverlight for Hello World!!!"),MB_OK);
return S_OK;
}
};
#endif
// ============================================================================
// OnLoaded
//
// Description: Calls InitializeComponent to bind member variables to named
// elements, and attach event handlers specified in XAML
//
// Parameters: pRoot - The root dependency object.
// ============================================================================
HRESULT MainPage::OnLoaded(__in IXRDependencyObject* pRoot)
{
UNREFERENCED_PARAMETER(pRoot);
HRESULT hr = InitializeComponent();
return hr;
} // OnLoaded
#pragma region GeneratedCode
// ============================================================================
// WARNING: DO NOT EDIT THIS ALWAYS-GENERATED CODE
// ============================================================================
HRESULT MainPage::InitializeComponent()
{
HRESULT hr = E_FAIL;
m_clickDelegate = NULL;
FindName(L"LayoutRoot", &m_pLayoutRoot);
#if TEST_BTN_CLICK_PROCESS
{
HRESULT retCode = 0;
BtnEventHandler handler;
if(FAILED(retCode = FindName(TEXT("HelloWorldBtn"), &m_MyBtn)))
return -1;
/*
指向委托对象的指针并不是一个智能指针(smart pointer),我们需要显式释放它:clickDelegate->Release();
现在未释放!!!可以仿 OnLoaded 中 AddLoadedEventHandler 的实现方式。
*/
if(FAILED(retCode = CreateDelegate(&handler,&BtnEventHandler::OnClick,&m_clickDelegate)))
return -1;
if(FAILED(retCode = m_MyBtn->AddClickEventHandler(m_clickDelegate)))
return -1;
}
#endif
if (m_pLayoutRoot && m_MyBtn)
{
hr = S_OK;
}
return hr;
}
// ============================================================================
// WARNING: DO NOT EDIT THIS ALWAYS-GENERATED CODE
// ============================================================================
#pragma endregion GeneratedCode
12 App.cpp 和 App.h 的代码如下:
App.h
#pragma once
#include <XamlRuntime.h>
//
// This function pointer type is used to declare a table of
// registration functions in App.cpp
//
typedef HRESULT (*PFN_XRCUC_REGISTER)();
//
// This is the main application class.
//
class App
{
public:
//
// Intialize member variables that cannot fail initialization in the constructor.
//
App():
m_bInitialized(FALSE),
m_nResult(0)
{
}
//
// Destructor
//
~App() {}
// Intialize the XamlRuntime API, a VisualHost, and initialize the application
HRESULT Initialize(HINSTANCE hInstance);
// Create the VisualHost.
HRESULT CreateHost(XRWindowCreateParams* pCreateParams);
// Run the application until the message pump exits.
HRESULT Run();
// Register the UserControls implemented in this module
HRESULT RegisterUserControls();
// Get the host window creation parameters
HRESULT GetWindowParameters(XRWindowCreateParams* pWindowParameters);
// Get the result code to be returned from WinMain
int GetWinMainResultCode();
// Set the result code to be returned from WinMain
void SetWinMainResultCode(int nResult);
// Get the application HINSTANCE
static HINSTANCE GetHInstance();
// Exit the application
HRESULT Exit();
// OnStartup is called after the visual host is created
// and before the message loop is entered
HRESULT OnStartup();
// OnExit is called after the message pump is exited
// and before the visual host, and IXRApplication are destroyed.
HRESULT OnExit();
// Register the resource dictionary for this application
HRESULT InitializeComponent();
// Gets the visual host for this application
static HRESULT GetVisualHost(IXRVisualHost** ppHost);
// Gets IXRApplication for this class
static HRESULT GetApplication(IXRApplication ** ppApp);
private:
// Sets the visual host for this application
static void SetVisualHost(IXRVisualHost* pHost);
// Sets IXRApplication for this class
static void SetApplication(IXRVisualHost* pApp);
protected:
// member variables
BOOL m_bInitialized; // Initialization succeeded
int m_nResult; // WinMain result code
// static member variables
static HINSTANCE m_hInstance; // The HINSTANCE of this process
// 为指向运行 SilverLight 应用程序的单体对象,此对象用来加载管理分析 XAML 文件。
static IXRApplicationPtr m_pApplication; // IXRApplication for this process
// 指向 Windows(HWND) 容器对象对象树,以便在运行时用 C++ 或 XAML 创建的对象处理相应事件消息,并显示或隐藏其 XAML 或 C++ 类创建的窗口。
static IXRVisualHostPtr m_pVisualHost; // IXRVisualHost for this process
};
// ============================================================================
// Initialize
//
// Description: Intialize the XamlRuntime API, and the XRApplication and then
// create a visual host.
//
// Parameters: hInstance - The HINSTANCE from WinMain
// ============================================================================
inline HRESULT App::Initialize(HINSTANCE hInstance)
{
HRESULT hr = E_FAIL;
// 创建主窗口并让 SE 管理它的内容
XRWindowCreateParams WindowParameters = {0};
m_hInstance = hInstance;
// Public API exported from XamlRumtime.dll. Initialize the system.
BOOL m_bInitialized = XamlRuntimeInitialize();
// Create IXRApplication instance
if (m_bInitialized)
{
// Public API exported from XR.dll. Obtain a reference to the XRApplication object singleton.
hr = GetXRApplicationInstance(&m_pApplication);
}
if (SUCCEEDED(hr))
{
// Add this module for the XamlRuntime to use when automatically resolving Image Source URIs as presented in XAML.
hr = m_pApplication->AddResourceModule(m_hInstance);
}
if (SUCCEEDED(hr))
{
hr = RegisterUserControls();
}
if (SUCCEEDED(hr))
{
hr = InitializeComponent();
}
if (SUCCEEDED(hr))
{
hr = GetWindowParameters(&WindowParameters);
}
if (SUCCEEDED(hr))
{
hr = CreateHost(&WindowParameters);
}
if (SUCCEEDED(hr))
{
hr = OnStartup();
}
return hr;
} // Initialize
// ============================================================================
// Run
//
// Description: Run the application until the message pump exits.
// ============================================================================
inline HRESULT App::Run()
{
HRESULT hr = E_FAIL;
UINT uiExitCode = 0;
if (m_pVisualHost != NULL)
{
// save the exit code for WinMain
hr = m_pVisualHost->StartDialog(&uiExitCode);
SetWinMainResultCode(uiExitCode);
}
// Allow user to cleanup resources.
OnExit();
//
// XamlRuntime interfaces must be released in the
// following order: IXRVisualHost, IXRApplication.
// After these interfaces are released the runtime
// can be uninitialized.
//
// First release IXRVisualHost
m_pVisualHost = NULL;
// Second release IXRApplication
m_pApplication = NULL;
// If XamlRuntime was initialized, uninitialize it
if (m_bInitialized)
{
m_bInitialized = FALSE;
XamlRuntimeUninitialize();
}
m_hInstance=NULL;
return hr;
} // Run
// ============================================================================
// GetWinMainResultCode
//
// Description: Get the result code to be returned from WinMain
// ============================================================================
inline int App::GetWinMainResultCode()
{
return m_nResult;
} // GetWinMainResultCode
// ============================================================================
// SetWinMainResultCode
//
// Description: Set the result code to be returned from WinMain
//
// Parameters: nResult - The result code to be returned from WinMain
// ============================================================================
inline void App::SetWinMainResultCode(int nResult)
{
m_nResult = nResult;
} // SetWinMainResultCode
// ============================================================================
// GetHInstance
//
// Description: Get the application HINSTANCE
// ============================================================================
inline HINSTANCE App::GetHInstance()
{
return m_hInstance;
} // GetHInstance
// ============================================================================
// Exit
//
// Description: Exit the application
// ============================================================================
inline HRESULT App::Exit()
{
HRESULT hr = E_FAIL;
if (NULL != m_pVisualHost)
{
hr = m_pVisualHost->EndDialog(0);
}
return hr;
} // Exit
// ============================================================================
// GetVisualHost
//
// Gets the visual host for this application
// ============================================================================
inline HRESULT App::GetVisualHost(IXRVisualHost ** ppHost)
{
if (!ppHost)
return E_INVALIDARG;
if (m_pVisualHost)
{
*ppHost = m_pVisualHost;
(*ppHost)->AddRef();
return S_OK;
}
return E_FAIL;
}
// ============================================================================
// SetVisualHost
//
// Sets the visual host for this application
// ============================================================================
inline void App::SetVisualHost(IXRVisualHost* pHost)
{
// Smart pointer automatically calls AddRef
m_pVisualHost = pHost;
}
// ============================================================================
// GetApplication
//
// Gets IXRApplication for this class
// ============================================================================
inline HRESULT App::GetApplication(IXRApplication ** ppApp)
{
HRESULT hr = E_FAIL;
if (!ppApp)
return E_INVALIDARG;
if (m_pApplication)
{
*ppApp = m_pApplication;
(*ppApp)->AddRef();
hr = S_OK;
}
return hr;
}
// ============================================================================
// SetApplication
//
// Sets IXRApplication for this class
// ============================================================================
inline void App::SetApplication(IXRVisualHost* pApp)
{
// Smart pointer automatically calls AddRef
m_pApplication = pApp;
}
App.cpp
#include "stdafx.h"
#include "SilverlightHelloGenerated.h"
#include "App.h"
#include "MainPage.h"
// The MAX_LOADSTRING constant needs to be equal to or greater
// than the length of the string referenced by IDS_APP_TITLE
#define MAX_LOADSTRING 100
// ============================================================================
// Static class member instantiation.
// ============================================================================
HINSTANCE App::m_hInstance; // HINSTANCE of this process
IXRApplicationPtr App::m_pApplication; // IXRApplication for this process
IXRVisualHostPtr App::m_pVisualHost; // IXRVisualHost for this process
// ============================================================================
// InitializeComponent
//
// Description: Load the Application resource dictionary if one exists.
// ============================================================================
HRESULT App::InitializeComponent()
{
XRXamlSource appXaml(GetHInstance(), IDR_SILVERLIGHTCLOCK_APP);
HRESULT hr = m_pApplication->LoadResourceDictionary(&appXaml,NULL);
return hr;
} // InitializeComponent
// ============================================================================
// GetWindowParameters
//
// Description: Set the window creation parameters for this application.
//
// Parameters: pWindowParameters - Window creation parameters.
// ============================================================================
HRESULT App::GetWindowParameters(XRWindowCreateParams* pWindowParameters)
{
static WCHAR szTitle[MAX_LOADSTRING]; // title bar text
HRESULT hr = E_INVALIDARG;
if (pWindowParameters)
{
pWindowParameters->Style = WS_VISIBLE;
pWindowParameters->ExStyle = WS_EX_TOPMOST;
// Set the title bar text
LoadString(m_hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
pWindowParameters->pTitle = szTitle;
// Set window position
pWindowParameters->Left = 0;
pWindowParameters->Top = 0;
// TODO: To specify a window size for the visual host set Width and Height
// If Width and Height are zero the Width and Height specified in the
// XAML are used
//pWindowParameters->Width = GetSystemMetrics(SM_CXSCREEN);
//pWindowParameters->Height = GetSystemMetrics(SM_CYSCREEN);
hr = S_OK;
}
return hr;
} // GetWindowParameters
// ============================================================================
// OnStartup
//
// Description: OnStartup is called after the visual host is created.
// and before the message loop is entered.
// ============================================================================
HRESULT App::OnStartup()
{
HRESULT hr = S_OK;
IXRFrameworkElementPtr pRoot;
hr = m_pVisualHost->GetRootElement(&pRoot);
if (SUCCEEDED(hr))
{
// TODO: Add one time initialization code here.
}
return hr;
} // OnStartup
// ============================================================================
// OnExit
//
// Description: OnExit is called after the message pump is exited
// and before the visual host, and IXRApplication are destroyed.
// ============================================================================
HRESULT App::OnExit()
{
// TODO: Add one-time cleanup code here.
return S_OK;
} // OnExit
// ============================================================================
// CreateHost
//
// Description: Create the visual host.
//
// Parameters: pCreateParams - The parameters used for creating the
// visual host's window
// ============================================================================
HRESULT App::CreateHost(XRWindowCreateParams* pCreateParams)
{
XRPtr<IXRCustomUserControl> pControl;
HRESULT hr = E_FAIL;
hr = m_pApplication->CreateObject(__uuidof(MainPage),&pControl);
if (SUCCEEDED(hr))
{
hr = m_pApplication->CreateHostFromElementTree(pControl, pCreateParams, &m_pVisualHost);
}
return hr;
}
#pragma region RegisterUserControls Generated Code
// ============================================================================
// RegisterUserControls
//
// Description: Register all XRCustomUserControl implemenations here.
//
// WARNING: DO NOT EDIT THIS ALWAYS-GENERATED FUNCTION
// ============================================================================
HRESULT App::RegisterUserControls()
{
HRESULT hr = S_OK;
static PFN_XRCUC_REGISTER pfn[] =
{
&MainPage::Register,
};
for (int i=0; i<_countof(pfn) && SUCCEEDED(hr); i++)
{
hr = pfn[i]();
if (FAILED(hr))
{
RETAILMSG(1,(L"RegisterUserControls failed."));
}
}
return hr;
} // RegisterUserControls
// ============================================================================
// WARNING: DO NOT EDIT THIS ALWAYS-GENERATED FUNCTION
// ============================================================================
#pragma endregion RegisterUserControls Generated Code
13 编译、运行,失败了!程序没有加载起来。一般来说,没有加载成功是因为 XMAL 解析失败,或资源没有加载成功。需要进一步分析是什么具体的原因?
调试代码发现,如下函数在加载资源时报错: hr = -2147023082 {找不到映像文件中指定的资源名。}
HRESULT App::InitializeComponent()
{
XRXamlSource appXaml(GetHInstance(), IDR_SILVERLIGHTCLOCK_APP);
HRESULT hr = m_pApplication->LoadResourceDictionary(&appXaml,NULL);
return hr;
} // InitializeComponent
解决方法:
将资源文件 SilverlightHelloWorld.rc 中的 SilverlightHelloWorld.rc2 替换成 SilverlightHelloGenerated.rc2,共两处。
14 编译、运行,可以看到想要的界面。点击按键,会弹出一个对话框。
OK,到此新建 WinCE 下 Silverlight 工程的整个过程算是结束了,是不是有些复杂?
呵呵...,个人的感觉也是,挺复杂的。