【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2282|回复: 3

[转]windows8开发简易教程(上)

[复制链接]
发表于 2012-8-3 12:23:30 | 显示全部楼层 |阅读模式
软件开发者真是闲不下来的命,技术更新太快,这不,微软这位大哥又高举windows8闪亮登场了,关于win8的战略意义,时代背景,偶这样的小人物在这里就不多说了,google上这类文章不胜枚举,作为开发者,在这个系列里会从技术角度去一探win8的一些特性和风采。

       说到为什么写win8方向博客,原因有二:
       第一,最近在抽时间看MSDN提供的windows8 app开发文档,内容不少,个人觉得还是边看边总结效果会比较好,所以有了写windows8 App开发这个系列的打算,而这个系列后续所有的文章都会是基于MSDN文章的内容外加上自己的一些理解和尝试。
       第二,对自己的耐心没有十分的信心,光看不写,说不定研究个两天就不想再弄了,写博客公开了,至少有读者监督,可以加强一定持续性,拒绝TJ。


       也想声明下,本人绝对不是MS的拥簇,没有看了Metro UI就惊为天人,当然心里也不抵触,同时本人也非赶时髦之人(ios从未涉足,android只略微了解),想一窥win8也不过是一个偶然的念头使然,总觉得但凡这些大牛公司推出的新技术新框架,都会有值得我们这些开发者推敲和学习的地方,既然移动领域自己已经错过了ios和android,这次好歹在win8上留下点印迹。


       Ok,windows8 App开发系列,今天开始起航,希望大家多多捧场,一起研究,一起分享。
      最后,以一张Metro风格的桌面作为结尾吧!
 楼主| 发表于 2012-8-3 12:24:55 | 显示全部楼层
开发平台与开发框架preview
相信大家对windows8 都拭目以待吧,那么先把windows8 开发平台和开发框架分享给大家。
2012-5-20 09:29:28 上传
下载附件 (159.77 KB)





      win8 App开发主要分成两部分,desktop app和metro app。右边蓝色的部分就是desktop app的部分,也是从win7延续过来没有发生变动的部分,前段在论坛上经常看到有人说在win8中不再支持MFC,ATL等,这些绝对是谣言,以前桌面开发支持的,win8桌面程序也都支持,所以搞MFC,Com,ATL等开发的不用觉得是世界末日,地球还是绕着太阳转着呢。


     重点是绿色的部分,Metro风格App的开发平台,这是win8中全新的架构,让我们一层层来看吧。
     底层是windows内核,往上是windows Runtime层,你可以把WinRT理解为升级版的Windows API,比如它提供了更易使用的Metro UI的API,比如异步编程的全面支持,比如对多种开发语言交互的支持等等,可以说是微软继.Net之后的又一重要框架。它是由C++实现的,所以性能应该会有优势。


     从WinRT上方的几部分可以看出,win8支持3种方式开发Metro App,第一种是Html+CSS+JS,第二种是XAML+C++,第三种是XAML+C#.Net或VB.Net。对Javascript的支持,绝对是Web前端开发者的福音,至少UI这部分的开发几乎是无缝就能上手的,JS也终于走出浏览器这个沙盒,开始支持开发native app了,从Win8也对JS提供支持可以看出目前JS有多火,曾经小看或轻视这门语言的人该醒醒了。而C++开发者也可以走第二条路,而且从XAML设计UI和WinRT提供的UI接口来看,易用性和扩展性绝对要比桌面时代C/C++开发UI要强很多。第三种.Net的开发方式,让原来.Net的开发者也可以无缝过渡到Win8的Metro App开发上。所以,不管是Web开发者,C++开发者,还是.Net开发者进军Win8 Metro App开发的路都是走的通的。从技术上来看,虽然支持三种开发形式,但最后其实还是映射到WinRT这个沙盒中,所以性能都不会差。


     也许还有人会问,那原来的Win32 API和Com API跟Metro App开发中就完全无关了吗?其实不然。因为有了WinRT API了,可以说大部分Win32和Com的API确实对Metro App开发不再有用,但是仍旧有一小部分API在WinRT中是没有被Cover到的,而这些应用仍旧是可以被使用的。据说在SDK代码头文件或者MSDN新的说明文档中都会指明各个API可以应用的范围(桌面或Metro或两者都支持)。其实.Net也是类似的,原来.Net Framework中的也是只有一部分API仍旧保留作为Metro App开发的API,只是.Net的这部分应该比Win32和Com中保留在Metro开发中能使用的要多的多了。


     如果让我来进行开发技术选型的话,我还是倾向逻辑层用C++实现封装成WinRT组件,Metro UI层用JS来做,基于WinRT的特性,JS调用WinRT组件的话几乎是无缝的,只是对Win8(IE10)中JS引擎的性能略有点担心。(呵呵,因为本人对.Net了解不多,所以暂不会考虑上面第三种开发方式)


     当然上面这些都只是初探Win8后自己的理解,可能多少有些偏颇,看到这里,大家对Win8这个开发框架有什么想法吗,疑问或指正也行,有的话别忘了留言分享下!
 楼主| 发表于 2012-8-3 13:04:38 | 显示全部楼层
通过上面的两章,我们对win8已经有个基本的了解,下面我们就开始谈谈具体的dll的封装和JS调用。
我们在Windows Runtime下(以下简称WinRT),可以用C++或C#或VB很方便的开发组件(dll),并且这些组件在用Javascript开发的Metro app中可以几乎无缝的被(javascript)调用。由于win8开发平台下,Javascript并不能访问原生的C++代码(虽然可以访问WinRT API),而实际开发中,经常会有一些既存的组件,或者需要用一些第三方库,这时就可以考虑把这些组件或希望利用的库包装成WinRT组件供UI层(JS)调用,
让我们来看一个具体的例子吧。以下代码在Beta版VS2011中可以编译运行。
  1. #pragma once
  2. #include <amp.h>
  3. #include <collection.h>

  4. namespace TestLib
  5. {
  6. public ref class WinRTComponent sealed
  7. {
  8. public:
  9. WinRTComponent();

  10. void SyncFunc(int number);
  11. Windows::Foundation::IAsyncOperationWithProgress<Windows::Foundation::Collections::IVector<int>^, double>^ AsyncFunc(int number);

  12. private:
  13. bool is_prime(int n);
  14. };
  15. }
复制代码
组件中类名为WinRTComponent,作为组件类,考虑到外部调用,声明为public,同时也声明为引用类型ref,它包含两个public方法,

SyncFunc方法为以同步调用方式计算出number值以下所有的质数,并返回结果

AsyncFunc方法为以异步调用方式计算出number以下所有的质数,并返回结果
  1. #include "pch.h"
  2. #include "WinRTComponent.h"
  3. using namespace TestLib;
  4. using namespace Platform;
  5. using namespace Concurrency;
  6. using namespace Platform::Collections;
  7. using namespace Windows::Foundation::Collections;
  8. using namespace Windows::Foundation;

  9. WinRTComponent::WinRTComponent()
  10. {
  11. }

  12. bool WinRTComponent::is_prime(int n)
  13. {
  14. if (n < 2)
  15. return false;
  16. for (int i = 2; i < n; ++i)
  17. {
  18. if ((n % i) == 0)
  19. return false;
  20. }
  21. return true;
  22. }

  23. void WinRTComponent::SyncFunc(int number)
  24. {
  25. auto primes = ref new Vector<int>();
  26. for (int i = 0; i < number; i++) {
  27. if (is_prime(i)) {
  28. primes->Append(i);
  29. }
  30. }
  31. }

  32. IAsyncOperationWithProgress<IVector<int>^, double>^ WinRTComponent::AsyncFunc(int number)
  33. {
  34. return create_async([this, number](progress_reporter<double> reporter)-> IVector<int>^ {
  35. auto primes = ref new Vector<int>();
  36. double progress = 0.0;
  37. double curProgress = 0.0;
  38. for (int i = 0; i < number; i++) {
  39. if (this->is_prime(i)) {
  40. primes->Append(i);
  41. }
  42. curProgress = 100.0 * i / number;
  43. if (curProgress > progress) {
  44. progress = curProgress;
  45. reporter.report(curProgress);
  46. }
  47. }
  48. reporter.report(100.0);
  49. return primes;
  50. });
  51. }
复制代码
AsyncFunc方法中,create_async函数是通过异步的方式创建一个异步调用,使计算在后台进行,而程序不会阻塞在质数统计的计算中。其中有个匿名函数Lambda表达式的使用,这是C++ 0x/11中支持的新特性。


另外,以上代码中ref,^等与传统C++不同的特性在本文中就不作说明了,在这个系列的其他文章中会有说明。


最后是javascript对以上组件dll的调用,代码如下:
  1. // 新建WinRTComponent对象
  2. var testlib = new TestLib.WinRTComponent();
  3. // 异步方法调用
  4. testlib.asyncFunc(1000).then(
  5. function (v) {
  6. // get result from v
  7. },
  8. function (error) {
  9. },
  10. function (p) {
  11. // get progress
  12. }
  13. );
  14. // 同步方法调用
  15. var vec = testlib.syncFunc(1000);
复制代码
异步方法调用后会立刻返回,在后台计算结束后会调用第一个回调函数,可以从参数v中取得计算结果。另外在计算中途,可以从最后一个回调函数中得到后台计算的进度。


总的来说,组件的封装和调用还是挺简单的,并不难掌握!
 楼主| 发表于 2012-8-3 13:15:44 | 显示全部楼层
我是从windows应用程序开发转变到Windows8 Metro App开发,这里很多人都是从windows phone 转变过来的,而对于我来说如果非要说最需要改变的观念有哪些,显而易见的Metro UI风格大家肯定都认同,而另外一个就是异步处理。
从win32早期几乎全盘的同步API,到后来.Net开始支持异步API,微软其实已经做出了API风格上的转变,但是晦涩的回调处理,异常,调试难度让大多数开发者对异步模型开发望而却步,同步处理的观念紧锁住了几乎绝大部分开发者的思想,试问在某些库宣称同时支持同步API和异步API后,包括我自己,又有多少开发者选择去尝试用异步API来构筑他们的应用程序呢?
      如果有公司宣称,“在我的平台上开发App,只要你的应用程序在UI线程上运行超过50ms就会被禁止,你必须把50ms以上的阻塞处理都搬到后台处理。”你可能觉得发表这样言论的人在做梦!但是,这正是windows8告诉我们开发Metro App必须遵循的规则。个人觉得,这个定义虽然会让我们在开发中多少感觉到一点别扭,但却会把windows程序UI操作的用户体验推上一个台阶。
进入正题,关于win8异步模型,让我们从Concurrency::task这个C++中支持异步API的类开始。
       先看一个例子:
  1. #include <ppltasks.h>
  2. #include <iostream>
  3. using namespace Concurrency;
  4. using namespace std;
  5. int main()
  6. {
  7.     task<int> t([]() {
  8.         return 10;
  9.     });
  10.     t.wait();
  11.     wcout << t.get() << endl;
  12.      return 0;
  13. }
复制代码
输出 10


       先解释下这段程序做了什么,task<int>定义了一个并行任务并设定会返回int型值,t的初始化用到了Lambda表达式,其中就涉及

到一个异步处理(return 10),wait()会等待异步处理结束,从get()方法能得到异步处理的返回值。这里主要用到了Concurrency::task这个

类。
在异步处理中,经常希望在一个异步操作结束后唤起另外一个异步处理。Concurrency::task也支持这种功能。
  1. #include <ppltasks.h>

  2. #include <iostream>

  3. using namespace Concurrency;


  4. using namespace std;


  5. int main()
  6. {
  7.     task<int> t([]() {

  8.         return 10;
  9.     });

  10.     auto ta =  t.then([](int n){ return n + 10;});

  11.     wcout << ta.get() << endl;

  12.      return 0;
  13. }

  14.         
复制代码
输出 20


        这里通过then()方法又加了一个异步处理,第一个return返回的10会作为第二个异步处理Lambda匿名函数的参数,get()方法得到

n+10的结果。在这里then方法返回的还是task<int>对象,所以如果后续还要追加其他任务可以这样写:

t.then([]{}).then([]{}).then([]{})..........
      
这里通过then()方法追加的延长任务(Continuation task)有Value-Based和Task-Based两种
  1. // Value-Based:
  2. t.then([](int n) {});
  3. // Task-Based:
  4. t.then([](task<int> preTask) {});
复制代码
两者的区别是: Value-Based类型的延长任务在前序任务被取消或发生异常时就不会被执行,而Task-Based类型延长任务则仍旧会被执行。


     怎么样,Concurrency::task的使用很简单吧。但是上面这些其实只是task类的一部分功能,还有很多其他功能,比如任务组合功能Concurrency::when_all,Concurrency::when_any,任务延时,任务取消等,本文只是作为一个引子,有兴趣的可以参考微软的MSDN,自己学习吧。
另外还想说明一点,Concurrency::task的API并不支持来自C++以外语言的调用,所以如果你想封装异步接口的组件供其他语言(JS,C#)调用,就不能使用Concurrency::task直接进行异步操作。针对这种情况Win8还提供了其他的API,我会在下一篇文章中进行说明。其实在前面写的文章中也有关于这方面的内容,JS调用C++组件的实例中就用到了异步处理。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 11:57

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表