-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
1886 lines (1407 loc) · 195 KB
/
atom.xml
File metadata and controls
1886 lines (1407 loc) · 195 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[blog.ponfius.com]]></title>
<link href="http://Ponf.github.io/atom.xml" rel="self"/>
<link href="http://Ponf.github.io/"/>
<updated>2015-06-23T16:55:47+03:00</updated>
<id>http://Ponf.github.io/</id>
<author>
<name><![CDATA[Filipp Panfilov]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Почему я выбрал стартап]]></title>
<link href="http://Ponf.github.io/blog/2015/06/why-startup/"/>
<updated>2015-06-23T12:42:45+03:00</updated>
<id>http://Ponf.github.io/blog/2015/06/why-startup</id>
<content type="html"><![CDATA[<p>Вот и прошел первый месяц моей работы на новом месте – в небольшом стартапе <strong>babystep.tv</strong>, и я хочу поделиться тем, что произошло за это время. Но с начала – почему я решил уйти с насиженного места в большой корпорации.</p>
<p><img src="http://Ponf.github.io/images/office.JPG"></p>
<h2>Работа в большой компании</h2>
<p>Сразу после окончания университета мне удалось попасть на работу в Mail.Ru, в команду мобильной почты. К этой компании можно относиться по-разному, но чего нельзя отрицать, так этого того, что у Mail.Ru очень высокий уровень экспертизы. За почти 3 года работы я застал два офиса (старый, с небольшими кабинетами, где было довольно тесно, и новый 27-этажный с огромными опенспейсами, старбаксом, и даже футбольным полем), получил просто невероятное количество опыта, а так же поменял свое направление с .NET платформы на iOS. И я с уверенностью могу сказать, что я работал в одной из самых сильных (если не самой сильной) команде iOS разработчиков в Москве. Вот основные плюсы работы в большой компании:</p>
<ul>
<li>Много возможностей для прокачивания себя в разных направлениях</li>
<li>Условия работы (ДМС-фрукты-тренажерный зал-свободная парковка)</li>
<li>Продукты, которыми пользуются миллионы людей ежедневно</li>
<li>Стабильность</li>
</ul>
<p>Вроде бы если все так круто, то почему же я ушел? Наверное основная причина в том, что в большой компании не чувствуется своя причастность к результату, нет какого-то признания, ответственность за продукт сильно размазана. Ну и вторая причина – в большой компании очень сложно расти вверх, так как должностей не так много, а конкуренция очень высокая.</p>
<p>Для многих людей эти причины вряд ли имеют какое-то значение. Если человек хочет спокойно работать и не париться на счет завтрашнего дня, то большая компания – отличный выбор. Это было не самое простое решение, но взвесив все плюсы и минусы я понял, что пока я молодой, у меня нет детей и ипотеки, надо выйти из зоны комфорта и реализовать свои амбиции.</p>
<p>Но и помимо этого, у меня есть <strong>мечта</strong>: я хочу жить в месте, где растут пальмы. Как вы понимаете, Москва не очень попадает под это требование :)</p>
<h2>Работа в стартапе</h2>
<h3>Первый день</h3>
<p>Конечно, после большой компании с фантастическим офисом у меня был шок. Он начался с самого утра, когда я пытался найти место для парковки, продолжился днем, когда я на кресле с колесиками привычным движением оттолкнулся от стола чтобы отъехать от него, а он внезапно улетел в другой конец комнаты, ну и завершился в 8 вечера, когда я понял, что кроме меня в офисе уже никого нет.</p>
<h3>Первая командировка</h3>
<p>Следующий шок был ровно через неделю, когда с утра CTO спросил, есть ли у меня открытая виза в США (она, к счастью, была), и что на следующий день мы утром вылетаем в Сан-Диего чтобы устроить там хакатон и подготовиться к софт-лончу. Сама поездка прошла очень круто, работали по 12-14 часов 7 дней в неделю, успевая утром поиграть в баскетбол, днем искупаться в океане, а вечером – поотмокать в джакузи. Единственное, что расстраивало – мысль, что скоро придется расстаться с моим белым мустангом с опускающейся крышей и вернуться в московские пробки и метро.</p>
<p><img src="http://Ponf.github.io/images/mustang.jpg"></p>
<h3>Первый релиз</h3>
<blockquote><p>“My dear, here we must run as fast as we can, just to stay in place. And if you wish to go anywhere you must run twice as fast as that.”</p><footer><strong>Lewis Carroll</strong> <cite>Alice in Wonderland</cite></footer></blockquote>
<p>Для стартапа очень важна скорость. Вообще она всегда важна, но в большой компании из-за сложности процессов скорость очень сильно падает. В стартапе получить нужный софт или новый макбук можно за несколько часов, в Mail.Ru это иногда занимало месяцы.</p>
<p>Чтобы лучше понять, вот несколько ключевых моментов за первый месяц работы:</p>
<ul>
<li>26 мая я вышел на работу</li>
<li>3 июня я уже был в Сан-Диего</li>
<li>5 июня выдал первую бета-версию нашего iOS приложения</li>
<li>15 июня babystep.tv 1.0 отправилась на ревью в AppStore</li>
</ul>
<p><img src="http://Ponf.github.io/images/startup.jpg"></p>
<p>Итого 3 недели для создания первой версии приложения с нуля. Конечно первая версия получилась довольно сырой, я успел сделать не все, что хотел, но больше, чем мы планировали на первый релиз. Изначально моя оценка была 3 месяца, но мы справились за 3 недели. <del>3 недели, Карл!!!</del></p>
<h2>Вместо заключения</h2>
<p>Многие наверное слышали крылатое выражение, что если человек найдет работу мечты, то ему больше ни одного дня не придется работать. Если в Mail.Ru я с первого дня понимал, что это не работа моей мечты, а скорее способ круто прокачать свои навыки, то babystep.tv имеет очень неплохие шансы стать такой работой для меня.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Apps в жизни]]></title>
<link href="http://Ponf.github.io/blog/2014/04/apps-v-zhizni/"/>
<updated>2014-04-10T22:42:17+04:00</updated>
<id>http://Ponf.github.io/blog/2014/04/apps-v-zhizni</id>
<content type="html"><![CDATA[<h2>Flashback</h2>
<p>Первый мой собственный сотовый телефон появился у меня году этак в 2003 и это был Siemens M55. Прекрасно помню, как я ходил по радио-рынкам, искал подходящие data-кабели для того, чтобы загрузить на него какие-нибудь простенькие java игры. Да, в те времена платформеры типа принца Персии были, пожалуй, пределом мечтаний.</p>
<p>С тех времен у меня сменилось множество гаджетов, и практически все они были либо смартфонами, либо коммуникаторами. Были одни из первых смартфонов Nokia – NGage QD, девайсы на Windows Mobile – Eten G500, и, наверное, мой самый любимый девайс – Nokia N82. Затем с Symbian я перешел на Android, а потом, быстро поняв, что это не моё, перешел на только появившийся Windows Phone. Ну и последний год я пользуюсь iPhone, и только теперь я понимаю, что телефон это не только звонилка+чатики+игры, а действительно незаменимый девайс в повседневной жизни.</p>
<!--more-->
<h2>Мобильные приложения</h2>
<p>Если посмотреть на мобильные приложения, то еще несколько лет назад они делились на 2 группы:</p>
<ul>
<li>бизнес-приложения (начиная почтой и заканчивая проприетарными приложениями, который использовались in-house)</li>
<li>убийцы времени (всевозможные мессенджеры и игры)</li>
</ul>
<p>То есть реально приложений, которые бы упрощали людям жизнь, практически не было.</p>
<p>Сейчас же появляется множество приложений для образования, работы (в том числе и узкоспециализированные), а самое главное – приложения для повседневной жизни. Я не буду писать про твиттеры и инстаграммы, это и так понятно :) Эти приложения можно смело отнести ко второй категории – убийцы времени. Намного интереснее посмотреть приложения, которые качественно улучшают жизнь. Например, сейчас когда я собираюсь в путешествие, я всегда скачиваю различные путеводители (Афиша Мир – один из любимых), схемы метро и прочие информационные приложения к себе на телефон и активно ими пользуюсь, не говоря о Google Maps. Я всегда смотрю по отзывам куда стоит сходить, а на что можно не тратить время, а придя в незнакомый ресторан/бар/кафе смотрю на Foursquare кто что из меню рекомендует.</p>
<p>Не так давно я воспользовался MNP и перешел с Мегафона на Билайн. Не могу сказать, что Билайн оправдал все мои надежды, но и речь сейчас не об этом. Речь о мобильном приложении Билайна для iOS. Будучи на Мегафоне, меня просто поразило, что мобильный оператор не может ни сделать нормальное приложение для телефона, ни сделать адаптивный дизайн сайта, который можно будет нормально смотреть с телефона. Получается какой-то сапожник без сапог. А приложение Билайна, напротив, меня очень приятно удивило, и теперь всё, что у Мегафона приходилось делать либо через веб (Сервис-Гид), либо отправляя старые-добрые SMS для управления услугами, я делаю в несколько касаний на телефоне. Единственное, что не очень нравится – детализацию нужно заказывать отдельно (хотя тоже через приложение), и она приходит на почту. В остальном к приложению никаких нареканий.</p>
<p>Или, например, интернет- и мобильный банкинг. Уже несколько лет являюсь клиентом Райффайзена, и единственное полезное что умеет их приложение – поиск ближайших банкоматов. Недавно я получил карточку Рокетбанка, где вообще вся работа с банком осуществляется через мобильное приложение, и это просто прекрасно. Не нужно ездить никуда в офис, не нужно висеть на линии у службы поддержки, слушиая какую-то унылую музыку, ожидая свободного оператора. Кроме это, у рокетбанка еще много и других, не менее интересных плюшек, но все плюсы и минусы я распишу через пару месяцев, когда пройдет начальный восторг, и найдется хотя бы один косяк :)</p>
<p>Также сейчас обретает моду целый зоопарк носимых девайсов – всевозможные умные часы, трекеры физической активности, и так далее. Несколько месяцев я пользовался Jawbone Up, затем он приказал долго жить. Но я не могу сказать, что эти гаджеты как-то сильно влияют на качество жизни – пока что это больше похоже на игрушки.</p>
<p>А какими приложениями пользуетесь вы?</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Кросс-платформенная разработка для Windows Phone и Windows 8]]></title>
<link href="http://Ponf.github.io/blog/2014/02/cross-platformennaya-razrabotka-dlya-windows-phone-i-windows-8/"/>
<updated>2014-02-01T00:50:11+04:00</updated>
<id>http://Ponf.github.io/blog/2014/02/cross-platformennaya-razrabotka-dlya-windows-phone-i-windows-8</id>
<content type="html"><![CDATA[<h2>Зачем переносить код, если и так все работает?</h2>
<p>Создавая любое приложение, разработчик, конечно же, хочет получить максимальную прибыль, и один из способов достижения этой цели – покрыть как можно большую аудиторию: для этого приложения локализуются, устраиваются рекламные кампании, и, конечно, переносятся на разные платформы. Существуют различные фреймворки для создания кроссплатформенных приложений, например, PhoneGap, приложения для которого разрабатываются на HTML5, или Xamarin – среда разработки приложений для iOS, Android, Windows Phone и Win8 на C#.</p>
<p>В рамках этой статьи мы рассмотрим, какие возможности для создания приложений с общим исходным кодом нам предлагает Microsoft.</p>
<!--more-->
<h2>Проблема: как минимизировать усилия при написании приложения на все платформы?</h2>
<p>Исторически сложилось так, что Windows Phone 7 появился рынке раньше, чем Windows 8, и в его основу лег тот же Windows CE, что был в Windows Mobile. Не обладаю инфромацией почему, но Microsoft закрыли возможность сторонним разработчикам писать Native приложения, но зато появилась возможность писать приложения на Silverlight, адаптированном для мобильных устройств, и разрабатывать игры на XNA. Windows Phone 7.5, помимо различных полезнейших вещей вроде фоновых агентов, принесла возможность разрабатывать приложения, совмещая технологии Silverlight и XNA.</p>
<p>Далее практически вместе с Windows 8 вышла новая версия мобильной операционной системы – Windows Phone 8. Основное отличие новой операционной системы – отказ от старого ядра Windows CE и переезд на то же ядро, что и в настольной операционной системе: Windows NT. Эти изменения конечно же затронули разработчиков, и теперь у нас появилась возможность разрабатывать приложения для Windows Phone еще и на C/C++.</p>
<p>Таким образом, перед разработчиками встал вопрос: как с минимальными усилиями поддерживать разработку приложения под Windows Phone и Windows 8?</p>
<h2>1. Использование PCL (Portable Class Library)</h2>
<p>Концепция PCL заключается в том, что по-большому счету, у обеих платформ (Windows Phone и Windows 8) пересекаются много пространств имен и они имеют много общих типов. Если ваш код, и библиотеки, которые в нем используются, используют только это подмножество .NET Framework, вы можете создать PCL, а потом прилинковать её к Windows Phone и Windows 8 проектам.</p>
<p>Когда вы выносите общий код в PCL, то можете заметить некоторые ограничения, в зависимости от платформ, которые вы выберите. Например, если вы хотите использовать механизм Tasks, который включает в себя поддержку ключевых слов async/await, то вашу библиотеку невозможно будет подключить к проекту для Windows Phone 7 приложений, т.к. в нем поддержка тасков отсутствует. Решается это с помощью установки Microsoft.Bcl.Async из NuGet.</p>
<p>Следующие 3 способа заключаются в том, что одни и те же файлы добавляются в проект для Windows Phone и Windows 8, разделяя функционал, недоступный на обеих платформах. Эти способы не являются взаимоисключающими, таким образом, их можно использовать совместно в одном проекте для тех или иных сценариев.</p>
<h2>2. Использование директив компилятора</h2>
<p>Первое – использование директив компилятора для скрытия участков кода, в зависимости от платформы, под которую компилируется приложение. По-умолчанию Windows Phone приложения определяются как WINDOWS_PHONE, и Windows 8 приложения, соответственно, как NETFX_CORE. Например, этот код подключает разные пространства имен в зависимости от платформы, под которую собираются приложения:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="cp">#if NETFX_CORE</span>
</span><span class='line'><span class="k">using</span> <span class="nn">Windows.UI.Xaml.Media.Imaging</span><span class="p">;</span>
</span><span class='line'><span class="cp">#else</span>
</span><span class='line'><span class="k">using</span> <span class="nn">System.Windows.Media.Imaging</span><span class="p">;</span>
</span><span class='line'><span class="cp">#endif</span>
</span></code></pre></td></tr></table></div></figure>
<p>Данный способ является наиболее простым в реализации, но код быстро становится неподдерживаемым, особенно если такой подход используется для больших кусков кода. Очень сложно определить, какой код является платформо-специфичным, а какой – общим.</p>
<h2>3. Использование наследования</h2>
<p>Одна из возможностей проще отделять платформо-зависимый код от платформо-независимого – использование наследования. Таким образом, общий код будет помещаться в базовый класс, а платформо-зависимый код – в классы-наследники.</p>
<p>В классы наследники будет попадать код по двум причинам: первое, если какая-то функциональность доступна только на одной платформе (например, отправка SMS). Второе – если какая-то функциональность должна быть по-разному устроена для разных платформ (например – API для работы с файлами). Такой код помещается также в подкласс, как в этом примере:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="k">public</span> <span class="k">abstract</span> <span class="k">class</span> <span class="nc">MainPageViewModel</span> <span class="p">:</span> <span class="n">NotifyBase</span><span class="p">,</span> <span class="n">IViewModel</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">protected</span> <span class="k">abstract</span> <span class="k">void</span> <span class="nf">DisplayPicture</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="k">public</span> <span class="k">class</span> <span class="nc">WinMainPageViewModel</span> <span class="p">:</span> <span class="n">MainPageViewModel</span><span class="p">,</span>
</span><span class='line'> <span class="n">ISupportsDesignTimeDataViaCode</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">DisplayPicture</span><span class="p">()</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="c1">// Имплементация отображения изображения</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<h2>4. Partial классы и методы</h2>
<p>Как альтернатива использованию наследования – использование Partial классов и методов. Partial классы изначально использовались для того, чтобы разработчики могли расширять функционал автоматически сгенерированных классов. Перегружая методы в отдельном partial классе, разработчик мог не бояться, что его работа исчезнет во время следующей генерации кода базового класса.</p>
<p>Такой же подход может быть использован для разделения общего кода, от платформозависимого. В данном примере, метод, находящийся в общем коде, вызывает метод находящийся в другом partial классе, который реализуется с учетом специфики платформы.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">DataSource</span> <span class="p">:</span> <span class="n">IDataSource</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">public</span> <span class="k">async</span> <span class="n">Task</span><span class="p"><</span><span class="n">IEnumerable</span><span class="p"><</span><span class="n">IFolder</span><span class="p">>></span> <span class="n">RetrieveFolders</span><span class="p">(</span><span class="n">IFolder</span> <span class="n">root</span><span class="p">)</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="c1">// Other logic</span>
</span><span class='line'> <span class="kt">var</span> <span class="n">folders</span> <span class="p">=</span> <span class="k">await</span> <span class="n">LoadFolders</span><span class="p">(</span><span class="n">root</span><span class="p">);</span>
</span><span class='line'> <span class="c1">// Other logic</span>
</span><span class='line'> <span class="k">return</span> <span class="n">folders</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">DataSource</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">private</span> <span class="k">async</span> <span class="n">Task</span><span class="p"><</span><span class="n">IEnumerable</span><span class="p"><</span><span class="n">IFolder</span><span class="p">>></span> <span class="n">LoadFolders</span><span class="p">(</span><span class="n">IFolder</span> <span class="n">root</span><span class="p">)</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="c1">//logic</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Примерно этот же подход можно использовать и для методов, но он накладывает некоторые ограничения (например, методы могут возвращать только void).
Когда вы пытаетесь решить, каким из этих способов переиспользования кода воспользоваться, очень полезно смотреть на API, предоставленное платформами. Некоторые из них, такие как акселерометр, очень похожи, другие, например, работа с файлами, могут здорово различаться не только в рамках отличий Windows Phone от Windows 8, но и в рамках отличий Windows Phone 7.5 от Windows Phone 8.</p>
<p>Существует отличный инструмент для этого: XAML Dialect Comparer Tool, почитать о котором и скачать можно по ссылке:
<a href="http://xamldialects.codeplex.com/">http://xamldialects.codeplex.com/</a></p>
<h2>5. Создание общих компонентов Windows Runtime.</h2>
<p>Компоненты Windows Runtime – компоненты, которые можно использовать для расширения функциональности поддерживаемых платформой языков. Используя Windows Runtime, поддерживаемый в Windows Phone 8 и Windows 8, вы можете создавать компоненты на одном языке программирования, а вызывать их в той среде, в которой выполняется ваше приложение. Такие компоненты создаются с помощью шаблона Windows Runtime Component в Visual Studio. На выходе вы получаете файл .winmd, который содержит также всю мета-информацию, необходимую чтобы этот компонент можно было внедрить в приложение, написанное на C#, C++, VB, JS.
Когда использовать Windows Runtime компоненты:</p>
<ul>
<li>Когда вам нужна производительность C++ : если ваше приложение совершает серьезные вычислительные операции, вам будет предпочтительнее писать код на C++ чтобы достичь максимальной производительности. Если ваше основное приложение, которое совершает эти рассчеты, написано на C# или VB, подключение такого компонента сделает ваше приложение значительно быстрее.</li>
<li>Возможность избежать ограничения языка: в целом, использование Windows Runtime компонентов – отличный способ расшарить общий код на все поддерживаемые платформы (например, которые не поддерживаются в PCL).</li>
<li>Использование Direct3D, Win32, COM API: Windows Phone 8 предоставляет native API для разработки «тяжелых» игр, прямого доступа к сети, или, например, к камере. Для использования этих API или managed кода вам необходимо написать обертку в виде Windows Runtime компонента, который будет реализовать нужный функционал.</li>
<li>Использование сторонних библиотек: еще недавно было весьма затруднительно использовать сторонние библиотеки, написанные на одном языке, при разработке приложения на другом. С использованием Windows Runtime вы можете взять стороннюю библиотеку, обернуть её в Windows Runtime компонент и вызывать её из Managed кода!</li>
</ul>
<h2>6. Переиспользование XAML</h2>
<p>Несмотря на похожий пользовательский интерфейс, одинаковый внешний вид и поведение многих контролов, бинарно XAML между Windows Phone и Windows 8 не совместим.</p>
<p>Пространства имен, префиксы и набор контролов также довольно здорово различаются, что не позволяет нам полностью переиспользовать XAML между приложениями под разные платформы.</p>
<p>И тем не менее, у разработчиков есть возможность создать UserControl, который можно будет использовать на обеих платформах.</p>
<h2>Что делать если есть приложение под одну платформу, и нужно написать под вторую?</h2>
<p>В этом случае я могу вам только пособолезновать ☺. А если серьезно, всё зависит от масштаба вашего приложения и заложенной в него архитектуры. Если приложение небольшое и при разработке использовался паттерн MVVM, то вынос общего кода не составит много проблем. Если же ваш проект уже здорово разросся: использует разные платформенные особенности и зависит от библиотек, которые есть только под одну из платформ, то перенос кода, если и возможен, будет осуществить значительно тяжелее.</p>
<p>Далее мы рассмотрим процесс создания приложения “с нуля”, сразу заточенное под перенос кода между платформами, и реализующее различные особенности платформ.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Материалы к моему докладу на]]></title>
<link href="http://Ponf.github.io/blog/2012/05/Materialy-k-moemu-dokladu-na-yamobile/"/>
<updated>2012-05-16T16:10:00+00:00</updated>
<id>http://Ponf.github.io/blog/2012/05/Materialy-k-moemu-dokladu-na-yamobile</id>
<content type="html"><![CDATA[<h2>Презентация:</h2>
<iframe src="http://www.slideshare.net/ponfius/slideshelf" width="615px" height="470px" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:none;" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe>
<p>Исходники: <a href="https://skydrive.live.com/redir.aspx?cid=a2567e038f37be43&amp;resid=A2567E038F37BE43!1260&amp;parid=A2567E038F37BE43!463">Примеры 1, 2 и 3</a>.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Немного о разработке под Win8]]></title>
<link href="http://Ponf.github.io/blog/2012/04/Nemnogo-o-razrabotke-pod-Win8/"/>
<updated>2012-04-01T18:58:00+00:00</updated>
<id>http://Ponf.github.io/blog/2012/04/Nemnogo-o-razrabotke-pod-Win8</id>
<content type="html"><![CDATA[<p>На прошлой неделе после твита <a href="https://twitter.com/#!/shwars">@shwars</a></p>
<p><img src="http://2.bp.blogspot.com/-fcsTfHDMTjA/T3SnoafGoZI/AAAAAAAAALo/ZhzPLTUT1uA/s1600/%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA.PNG"></p>
<p>под давлением совести было принято решение срочно сделать клиент для нашего проекта <strong>Imagine Cup</strong> для <strong>Windows 8</strong>. У меня уже был готов полностью работоспособный клиент под <strong>Windows Phone</strong>, так что это не должно было занять много времени. И действительно, суммарно я управился часов за 20. Под катом некоторые подробности о разработке в целом, использовании <strong>Bing Map SDK</strong> for Win8, <strong>Remote debugging</strong> и прочих моментах, с которыми я столкнулся.</p>
<!--more-->
<p></p>
<h2>0. Главная проблема</h2>
<p>Главная проблема, с которой я столкнулся – отсутствие библиотек. Хоть <strong>NuGet</strong> и работает отлично с <strong>VS11</strong>, но нет библиотек, к которым я так привык (например, мой любимый REST-клиент <strong>RestSharp</strong>), так что пришлось писать собственную имплементацию. Но не всё так плохо: постепенно появляются сборки библиотек по .NET 4.5, например обновление<strong> Json.NET</strong> вышло за пару дней до написания моего приложения :)</p>
<p><strong>Основной совет:</strong> будьте готовы к изобретению велосипедов.</p>
<h2>1. Metro Grid Application</h2>
<p>По-моему все люди, которые создают проект на основе <strong>Metro Grid</strong> больше времени тратят на попытку разобраться в верстке, нежели на написание кода. Что не удивительно: шаблон этот очень хорош, поддерживает всевозможные состояния (на весь экран, припаркованное и т.д.). Безусловно, это очень круто, но слишком сложно для восприятия. Но этот урок я прошел ещё на <strong>Win8 </strong>хакатоне, когда разрабатывал приложение для чтения газеты <strong>Коммерсантъ</strong>.</p>
<p><strong>Основной совет:</strong> если вас поджимают сроки, то лучше создавайте пустой проект. Если же нет – обязательно разберитесь в шаблоне<strong> Metro Grid Application</strong>.</p>
<h2>2. Bing Maps SDK для Windows 8</h2>
<p>Контрол карт пока что не входит в стандартную поставку <strong>Visual Studio 11</strong>, так что нужно устанавливать его отдельно. Из этого следует огромный <strong>FACEPALM</strong>, но об этом в следующем пункте. Подробнее о работе с контролом вы можете прочитать в <strong><a href="http://habrahabr.ru/post/139681/">статье</a> </strong>Игоря Сычева, я же расскажу о том, через что мне пришлось пройти, чтобы приложение заработало.Первое это то, что контрол <map> не может быть контейнером. То есть пушпины нужно добавлять через <strong>MapLayer</strong>. Ладно, не велика беда, идем дальше. Если у вас на странице несколько контролов карты, то <strong>MapLayer</strong> начинает сходить с ума и перестает понимать, к какой карте относится. Это уже меня довольно расстроило, на StackOverflow ответа не нашлось.Пришлось отказаться от этой концепции, продолжил дальше разработку. На странице деталей так же сделал карту, и теперь при переходе между страницами приложение начало падать. Причем не всегда, причину падения мне удалось диагностировать только в день выступления. На сколько я понял, если у вас на текущей карте не загрузился провайдер словаря карт (надпись <strong>(с) 2010 NAVTEQ</strong>) и вы перешли на другую страницу с картой – приложение падает. Опять же эта инфа не 100%, но другого объяснения я пока найти не смог.</p>
<p><strong>Основной совет:</strong> не забывайте, что <strong>Bing Maps SDK</strong> для <strong>WinRT </strong>пока что в стадии Beta.</p>
<h2>3. Remote Debugging</h2>
<p>В <strong>Visual Studio 11</strong>, как вы могли заметить, есть 3 вида отладки: на текущем устройстве, на симуляторе (<strong>не путать с эмулятором!</strong>) и на удаленной машине. Поскольку планшет я получил вечером перед выступлением, очень не хотелось ставить на него студию (кстати вышел отдельный квест) и прочий софт. Я попробовал сделал <strong>Install Package</strong> на рабочем компьютере и задеплоить его на планшете. Этот план провалился, так как на планшете не было сертификата разработчика (о чем мне услужливо подсказала консолька с логом). Планом “Б” был как раз <strong>Remote Debugging</strong>, но и с ним всё вышло совсем не так, как хотелось бы.Для того, чтобы задеплоить проект из студии на удаленную машину (в дальнейшем “жертва”), нужно чтобы они находились в одной сети, что вполне логично и удобно. В <strong>MSDN </strong>есть подробная <a href="http://msdn.microsoft.com/en-us/library/bt727f1t(v=vs.110"><strong>статья</strong></a>.aspx), описывающая как настроить оба устройства. При установке на жертву <strong>Remote Debugger</strong>, устанавливается и сертификат, который в будущем позволяет деплоить приложения, используя bat-файл.Я всё установил, настроил, компьютер практически сразу нашел жертву, я нажал кнопку <strong>F5</strong> и у меня на планшете появился <strong>Splash Screen</strong> моего приложения! Но счастье продолжалось не долго, кроме <strong>Splash Screen</strong> я так ничего и не увидел: приложение упало. Я немного поковырялся и понял, что проблема в отсутствии<strong> Bing SDK</strong> на жертве. Вспомнив обещание на каком-то из докладов по <strong>Win8</strong>, что все пакеты будут представлять из себя самодостаточные и независимые модули, я создал заново <strong>Install Package</strong> на компьютере, перекинул его на планшет и он отлично установился, найдя сертификат, установленный вместе с <strong>Remote Debugger</strong>.Но приложение снова ничего кроме <strong>Splash Screen</strong> мне не показало, поэтому я понял, что нужно ставить <strong>Bing SDK</strong> для <strong>WinRT</strong> на планшет.</p>
<p><strong>ОГРОМНОЕ СПАСИБО ЛЮДЯМ, КОТОРЫЕ СДЕЛАЛИ ЭТОТ SDK КАК РАСШИРЕНИЕ К СТУДИИ, А НЕ ОТДЕЛЬНЫЙ ИНСТАЛЛЯТОР!</strong></p>
<p><strong>Как вы поняли, время шло к утру, а мне нужно было ставить </strong>Visual Studio 2011** на планшет…</p>
<p><strong>Основной совет:</strong> <strong>Remote Debugging</strong> работает замечательно, но, боюсь, вам всё равно придется ставить студию на удаленную машину.</p>
<h2>4. Установка Visual Studio 11</h2>
<p>На планшет у меня студия встала попытки с 3 или 4, до этого <strong>Windows 8</strong> вываливалась в <strong>BSOD</strong>, что мне просто убило, так как на ноутбуке за месяц я так ни разу синий экран с грустным смайлом не увидел. Меня это довольно озадачило, но я вдруг заметил, что <strong>BSOD </strong>вылетает как только я касаюсь планшета. Собственно, виной всему оказался акселерометр/гироскоп. Если положение планшета не менять или заблокировать поворот экрана (не проверял, но вдруг поможет :) ), то студия устанавливается замечательно!</p>
<p><strong>Основной совет:</strong> Если ставите <strong>VS 2011</strong> на устройство с датчиками положения – лучше не шевелитесь :)</p>
<p>Несмотря на все проблемы, которые я нашел, разработка <strong>WinRT </strong>приложений мне очень понравилась. Думаю, разработчикам на <strong>Windows Phone</strong> не составит труда разобраться в нем и портировать свои приложения. Ну а вот что получилось у меня:</p>
<p><img src="http://4.bp.blogspot.com/-vb_Xiyxt504/T3ik4-OKVXI/AAAAAAAAALw/2ikwC4DraoM/s640/newScreen.png"></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Краткий обзор Windows 8 Consumer Preview]]></title>
<link href="http://Ponf.github.io/blog/2012/02/Kratkii-obzor-Windows-8-Consumer-Preview/"/>
<updated>2012-02-29T19:41:00+00:00</updated>
<id>http://Ponf.github.io/blog/2012/02/Kratkii-obzor-Windows-8-Consumer-Preview</id>
<content type="html"><![CDATA[<p>Как многие уже слышали, сегодня <strong>Microsoft</strong> на <strong>MWC</strong> представили <strong>Windows 8 Consumer Preview</strong>.</p>
<p>Вы можете скачать её совершенно бесплатно с сайта <strong>Microsoft</strong>: <a href="http://windows.microsoft.com/en-US/windows-8/iso">http://windows.microsoft.com/en-US/windows-8/iso</a></p>
<p><strong>Ключ</strong>: DNJXJ-7XBW8-2378T-X22TX-BKG7J</p>
<p>Для тех, у кого нет DVD-ROM, болванки или ещё чего-то, можно совершить установку с флешки с помощью этой утилиты: <a href="http://images2.store.microsoft.com/prod/clustera/framework/w7udt/1.0/en-us/Windows7-USB-DVD-tool.exe">http://images2.store.microsoft.com/prod/clustera/framework/w7udt/1.0/en-us/Windows7-USB-DVD-tool.exe</a>
Итак, первые ощущения.</p>
<!--more-->
<p></p>
<p><strong>Установка и запуск</strong>
У меня <strong>Windows 8</strong> ставилась примерно 15 минут (версия x64), с учетом ввода <strong>LiveID</strong> и прочего. Ставил я на соседний логический диск, рядом с <strong>Windows 7</strong>.
Первое, что бросилось в глаза – экран выбора операционной системы при загрузке. Я сначала не поверил своим глазам, но <strong>он стал красивым</strong>!
<img src="http://2.bp.blogspot.com/-A2H6JRGwjhM/T05zpyRRguI/AAAAAAAAAKc/QbRH1Sm4izg/s400/WP_000274.jpg"></p>
<p>Окно выбора системы</p>
<p>После входа в систему пользователь видит рабочий стол список установленных <strong>Metro</strong> приложений. А может и не только <strong>metro</strong>, т.к. у меня там появилась <strong>VS</strong> после установки.
<img src="http://3.bp.blogspot.com/-Bdjt1tMqG_c/T051kzrdUlI/AAAAAAAAAKk/L1JAqUeVcVE/s640/3.png"></p>
<p>Стартовый экран</p>
<p>Первым делом я поставил качаться <strong>VS11 Beta</strong> (не входит в комплект, в отличии от <strong>Developer Preview</strong>) и пошел смотреть на <strong>Windows Store</strong>. Могу сказать 2 вещи:</p>
<ul>
<li>Сделано довольно приятно, по аналогии с <strong>Windows Phone</strong>.</li>
<li><strong>Нужно писать программы! Срочно!</strong> В Store сейчас практически пусто и есть неплохой шанс подзаработать разработчикам.</li>
</ul>
<p>Хотя, конечно же, уже есть некоторые популярные программы. Например, Evernote:</p>
<p><img src="http://1.bp.blogspot.com/-ZlrxxyKPOQU/T053PcEYv2I/AAAAAAAAAKs/ljKOTNKbXsk/s640/180x150_O365_MidMarket_V2_Tryitfree_12_21_11.gif"></p>
<p>Или, известная игра <strong>Cut the Rope</strong> (подозреваю, что на HTML5 :) )</p>
<p><img src="http://3.bp.blogspot.com/-HLNSWxahcYI/T054EfLqNHI/AAAAAAAAAK0/LFL0bz0bYZg/s640/1.png"></p>
<p>Помимо интерфейса metro, в <strong>Win8</strong> присутствует и классический интерфейс. Если, конечно, классическим можно назвать интерфейс без кнопки “<strong>Пуск</strong>” :).</p>
<p><img src="http://3.bp.blogspot.com/-pP16kI_Zy2I/T055J1K8j_I/AAAAAAAAAK8/thn7qA2l6GI/s640/4.png"></p>
<p>Ну а <strong>Visual Studio 11</strong> встретила меня новым непривычным монохромным интерфейсом. Я ещё не смотрел разработку <strong>metro</strong> приложений, надеюсь, найдется время завтра.</p>
<p><img src="http://1.bp.blogspot.com/-CCvWnFcZXpM/T056rfsH7hI/AAAAAAAAALE/KuFR82Fbxv0/s640/5.png"></p>
<p>Из основных впечатлений:</p>
<ul>
<li>Смесь классического и metro интерфейсов смотрится пока что (после полутора часов использования) очень непривычно. Как отдельные сущности вроде бы уже стали привычны, но такая смесь пока что минимум непонятна. Например, долго искал кнопку выключения %).</li>
<li>Работает всё очень шустро, но не хватает тачскрина на ноутбуке. Без этого как-то теряется полнота ощущений от <strong>Metro</strong>, но выглядит всё равно очень круто.</li>
<li>Авторизация в системе по <strong>LiveID</strong> – авторизован на всех сервисах <strong>live.com</strong>. Довольно удобно.</li>
<li>Есть мнение, что новый дизайн <strong>Visual Studio</strong> ориентирован на дисплеи <strong>E-Ink</strong>))</li>
<li>Очень сложно найти привычные приложения вроде <strong>Paint</strong> и т.п. Нужно в боковой панели использовать поиск.</li>
</ul>
<p>Надеюсь найти ответы на все оставшиеся вопросы на <strong>Windows 8 Camp</strong>, проходящий в эту пятницу, 2 марта.
Если у вас нет возможности его посетить, присоединяйтесь к трансляции: <a href="http://www.microsoft.com/ru-ru/events/windows8camp/">http://www.microsoft.com/ru-ru/events/windows8camp/</a></p>
<p>P.S.: выключение находится на боковой панели во вкладке Settings (как связаны настройки с выключением??).</p>
<p>P.P.S.: Если будет планшет типа Asus Transformer с Win8 на борту и на нем будет запускаться студия – возьму безо всяких сомнений :).</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Все о Splash Screen в Windows Phone]]></title>
<link href="http://Ponf.github.io/blog/2012/02/Vse-o-Splash-Screen-v-Windows-Phone/"/>
<updated>2012-02-25T09:17:00+00:00</updated>
<id>http://Ponf.github.io/blog/2012/02/Vse-o-Splash-Screen-v-Windows-Phone</id>
<content type="html"><![CDATA[<p>Какое бы вы приложение не писали, даже самое простое, его запуск на телефоне будет занимать некоторое время, поэтому хорошей идеей будет показывать какой-нибудь Splash Screen во время загрузки. Существует несколько вариантов использования Splash Screen:</p>
<ul>
<li>Использовать изображение</li>
<li>Использовать анимированный Splash Screen</li>
<li>Не использовать Splash Screen</li>
</ul>
<p>Давайте поподробнее остановимся на каждом из этих пунктов.</p>
<!--more-->
<p></p>
<h3>Использование изображения </h3>
<p>При создании проекта в Visual Studio у вашего приложения уже есть Splash Screen по-умолчанию:</p>
<p><img src="http://1.bp.blogspot.com/-NPNjM2xI4Iw/T0nuhjRsEoI/AAAAAAAAAKM/Y6Eys9BCasA/s200/SplashScreenImage.jpg"></p>
<p>Для замены его на свой Splash Screen необходимо просто добавить в проект файл с именем SplashScreenImage.jpg (<strong>внимание</strong>: имя должно быть именно таким). Также у вашего Splash Screen разрешение должно быть 480х800px (480 пикселей в ширину и 800, соответственно, в высоту), и не забудьте указать в свойствах изображения Build Action: Content.</p>
<h3>Использование анимированного Splash Screen</h3>
<p>Если загрузка первой страницы вашего приложения занимает некоторое время (например, используются какие-то данные из Интернета), то создание анимированного экрана загрузки – так же хорошая идея. Итак, алгоритм работы будет следующий:</p>
<ul>
<li>При загрузке изображения показывается SplashScreenImage.jpg </li>
<li>После загрузки открывается <strong>MainPage</strong> с открытым <strong>Popup </strong>окном, развернутым на весь экран. Этот <strong>Popup</strong> может быть основан на вашем <strong>SplashScreenImage</strong> для создания наилучшего эффекта</li>
<li>Как только загрузка данных закончится – <strong>Popup</strong> закроется, и пользователь увидит содержимое <strong>MainPage</strong>.</li>
</ul>
<p>Как вы можете заметить, термин «анимированный Splash Screen» на самом деле не совсем верен: мы используем обычный статический экран заставки, а потом просто показываем пользователю страницу, похожую на экран заставки, тем временем выполняя в фоне какие-нибудь действия.</p>
<p>Для того чтобы наша загрузка выполнялась в отдельном потоке мы будем использовать класс <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx"><strong>BackgroundWorker</strong></a>. Этот класс позволяет делать какую-то работу в фоне, оставляя UI отзывчивым для пользователя. Также у нас будет возможность отслеживать состояние фонового процесса и убрать <strong>Popup </strong>при наступлении какого-нибудь события.</p>
<p>Для начала давайте создадим свой UserControl, для примера назовем его <strong>AnimatedSplashScreen</strong>.</p>
<p>Далее нам нужно добавить обработку <strong>Popup</strong> в MainPage.xaml.cs. Для этого добавим следующие пространства имен:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="k">using</span> <span class="nn">System.Threading</span><span class="p">;</span>
</span><span class='line'><span class="k">using</span> <span class="nn">System.Windows.Controls.Primitives</span><span class="p">;</span>
</span><span class='line'><span class="k">using</span> <span class="nn">System.ComponentModel</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>
<p>Теперь необходимо создать BackgroundWorker и наш Popup:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="n">BackgroundWorker</span> <span class="n">backroungWorker</span><span class="p">;</span>
</span><span class='line'><span class="n">Popup</span> <span class="n">myPopup</span><span class="p">;</span>
</span><span class='line'><span class="c1">// Constructor</span>
</span><span class='line'><span class="k">public</span> <span class="nf">MainPage</span><span class="p">()</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="n">InitializeComponent</span><span class="p">();</span>
</span><span class='line'> <span class="n">myPopup</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Popup</span><span class="p">()</span> <span class="p">{</span> <span class="n">IsOpen</span> <span class="p">=</span> <span class="k">true</span><span class="p">,</span> <span class="n">Child</span> <span class="p">=</span> <span class="k">new</span> <span class="n">AnimatedSplashScreen</span><span class="p">()</span> <span class="p">};</span>
</span><span class='line'> <span class="n">backroungWorker</span> <span class="p">=</span> <span class="k">new</span> <span class="n">BackgroundWorker</span><span class="p">();</span>
</span><span class='line'> <span class="n">RunBackgroundWorker</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">private</span> <span class="k">void</span> <span class="nf">RunBackgroundWorker</span><span class="p">()</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="n">backroungWorker</span><span class="p">.</span><span class="n">DoWork</span> <span class="p">+=</span> <span class="p">((</span><span class="n">s</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span> <span class="p">=></span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="n">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">5000</span><span class="p">);</span>
</span><span class='line'> <span class="p">});</span>
</span><span class='line'>
</span><span class='line'> <span class="n">backroungWorker</span><span class="p">.</span><span class="n">RunWorkerCompleted</span> <span class="p">+=</span> <span class="p">((</span><span class="n">s</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span> <span class="p">=&</span><span class="n">gt</span><span class="p">;</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="n">Dispatcher</span><span class="p">.</span><span class="n">BeginInvoke</span><span class="p">(()</span> <span class="p">=&</span><span class="n">gt</span><span class="p">;</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="n">myPopup</span><span class="p">.</span><span class="n">IsOpen</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">);</span>
</span><span class='line'> <span class="p">});</span>
</span><span class='line'> <span class="n">backroungWorker</span><span class="p">.</span><span class="n">RunWorkerAsync</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Что мы здесь делаем:</p>
<ul>
<li>Создаем <strong>Popup</strong>, по-умолчанию открытый, который содержит наш UserContol – <strong>AnimatedSplashScreen</strong>;</li>
<li>Создаем <strong>BackgroundWorker</strong>, который в фоне замораживает поток на 5000 мс.</li>
<li>Как только 5 секунд проходит, <strong>BackgroundWorker </strong>переходит в состояние <strong>RunWorkerCompleted </strong>и наш <strong>Popup </strong>закрывается.</li>
</ul>
<p>Основная логика есть, теперь давайте вернемся к содержимому нашего <strong>Popup</strong>. У себя в примере я использую изображение <strong>SplashScreenImage</strong>, <strong>TextBlock</strong> и <strong>PerformanceProgressBar</strong> из <strong><a href="http://silverlight.codeplex.com/releases/view/75888">WP7 Toolkit</a></strong>.</p>
<p>Для того чтобы немного оживить загрузку, я в <strong>Expression Blend</strong>создал анимацию мигания для текста:</p>
<p>Теперь осталось только добавить и запустить эту анимацию в конструкторе класса AnimatedSplashScreen:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="k">public</span> <span class="nf">AnimatedSplashScreen</span><span class="p">()</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="n">InitializeComponent</span><span class="p">();</span>
</span><span class='line'> <span class="n">Storyboard</span> <span class="n">Blinking</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">Resources</span><span class="p">[</span><span class="s">"Blinking"</span><span class="p">]</span> <span class="k">as</span> <span class="n">Storyboard</span><span class="p">;</span>
</span><span class='line'> <span class="n">Blinking</span><span class="p">.</span><span class="n">Begin</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Всё, наш анимированный <strong>Splash Screen</strong> готов! Запустив проект, мы увидим следующую картину:</p>
<p><img src="http://1.bp.blogspot.com/-2gjXoRFZl_E/T0n2-jZ0b5I/AAAAAAAAAKU/q0ggrmwHG4E/s320/screen.png"></p>
<p>Пример моего анимированного<strong> Splash Screen</strong> вы можете скачать по ссылке: <a href="https://skydrive.live.com/redir.aspx?cid=a2567e038f37be43&amp;resid=A2567E038F37BE43!512&amp;parid=A2567E038F37BE43!463">SkyDrive</a>.</p>
<p>В качестве альтернативы <strong>Popup</strong> можно использовать отдельную страницу, но тогда нужно предусмотреть чтобы при нажатии на кнопку <strong>Назад </strong>пользователь выходил из приложения, а не попадал снова на страницу загрузки. Это можно сделать, например, удалив страницу из стека навигации:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="n">NavigationService</span><span class="p">.</span><span class="n">CanGoBack</span> <span class="p">==</span> <span class="k">true</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="n">NavigationService</span><span class="p">.</span><span class="n">RemoveBackEntry</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<h3>Не использовать Splash Screen</h3>
<p>Для того чтобы убрать у вашего приложения экран заставки, достаточно просто удалить файл SplashScreenImage.jpg из вашего решения.</p>
<p>Итак, мы рассмотрели различные варианты создания Splash Screen в Windows Phone. Надеюсь, что эта статья оказалась для вас полезной :).</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Шпаргалка по сертификации приложения на WP7]]></title>
<link href="http://Ponf.github.io/blog/2011/12/Shpargalka-po-sertifikatcii-prilozheniia-na-WP7/"/>
<updated>2011-12-26T09:40:00+00:00</updated>
<id>http://Ponf.github.io/blog/2011/12/Shpargalka-po-sertifikatcii-prilozheniia-na-WP7</id>
<content type="html"><![CDATA[<p>Выкладываю давно обещанную шпаргалку по сертификации приложений на Windows Phone. Эта шпаргалка – краткое содержимое одной из моих прошлых <a href="http://mne.p0x.ru/2011/08/windows-phone-7.html">статей</a>.</p>
<p><img src="http://3.bp.blogspot.com/-a1neQybjK9U/Tvg_jvd_z0I/AAAAAAAAAJs/loz_YHZjVLo/s400/%25D0%25A1%25D0%25BD%25D0%25B8%25D0%25BC%25D0%25BE%25D0%25BA.PNG"></p>
<p>В этой шпаргалке я постарался поместить на одной странице все основные требования, на которые стоит обратить внимание при публикации приложения. Конечно же, поместить все требования на одной странице не представляется возможным, поэтому за более подробной информацией необходимо идти по ссылке: <a href="http://msdn.microsoft.com/en-us/library/hh184843.aspx">Application Certification Requirements for Windows Phone</a>.</p>
<p><a href="https://skydrive.live.com/redir.aspx?cid=a2567e038f37be43&amp;resid=A2567E038F37BE43!464&amp;parid=A2567E038F37BE43!463"><strong><span>Скачать</span></strong></a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Скрытые смайлы в Windows Phone]]></title>
<link href="http://Ponf.github.io/blog/2011/12/Skrytye-smaily-v-Windows-Phone/"/>
<updated>2011-12-23T11:13:00+00:00</updated>
<id>http://Ponf.github.io/blog/2011/12/Skrytye-smaily-v-Windows-Phone</id>
<content type="html"><![CDATA[<p>Кстати, а вы знали, что в Windows Phone есть скрытые смайлы? Достаточно отправить другу с Windows Phone какую-нибудь комбинацию, из представленных ниже, чтобы он получил забавную картинку :)</p>
<p><img src="http://4.bp.blogspot.com/-1i0pQW92DII/TvRh_NiGSFI/AAAAAAAAAJI/DsQa5b4nl08/s640/2678.Complete-1_thumb_1A1CA41C.png"></p>
<p>Вторая часть смайлов:</p>
<!--more-->
<p></p>
<p><img src="http://3.bp.blogspot.com/-64MqCZBms08/TvTF8Va_85I/AAAAAAAAAJU/GWUwe88353U/s1600/5226.emoticons2_lg_thumb_09D8E8AC.jpg"></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Как склеить несколько Texture2D / Howto merge few Texture2D]]></title>
<link href="http://Ponf.github.io/blog/2011/12/Kak-skleitj-neskoljko-Texture2D--Howto-merge-few-Texture2D/"/>
<updated>2011-12-16T14:19:00+00:00</updated>
<id>http://Ponf.github.io/blog/2011/12/Kak-skleitj-neskoljko-Texture2D–Howto-merge-few-Texture2D</id>
<content type="html"><![CDATA[<p>Решил попробовать написать этот пост и на русском, и на английском, так как очень долго гуглил о том как склеить несколько текстур формата Texture2D и сохранить результат, но не нашел ничего подходящего: либо метод не поддерживался в Windows Phone, либо меня не устраивала его производительность.</p>
<p><strong>Проблема</strong>
Есть несколько текстур с разными координатами, находящиеся на разных уровнях и никак друг с другом не связанные. Необходимо экспортировать это в фото галерею в виде изображения.</p>
<p><strong>Решение</strong>
В общем-то задача действительно не сложная, но сходу не понятно, как её решить. Нужно как-то склеить все текстуры в одну. И тут нам на помощь приходит класс из XNA под названием <a href="http://msdn.microsoft.com/en-us/library/bb198676.aspx">RenderTarget2D</a>.</p>
<!--more-->
<p></p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="n">RenderTarget2D</span> <span class="n">imageResult</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>
<p>Как можно понять из названия, с помощью этого класса, наследующегося от Texture2D, мы создаем двумерную текстуру, которую потом можно использовать в выборе цели для рендеринга.</p>
<p>По-умолчанию целью для рендеринга является дисплей:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="c1">// Set the sharing mode of the graphics device to turn on XNA rendering</span>
</span><span class='line'><span class="n">SharedGraphicsDeviceManager</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">GraphicsDevice</span><span class="p">.</span><span class="n">SetSharingMode</span><span class="p">(</span><span class="k">true</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Create a new SpriteBatch, which can be used to draw textures.</span>
</span><span class='line'><span class="n">spriteBatch</span> <span class="p">=</span> <span class="k">new</span> <span class="n">SpriteBatch</span><span class="p">(</span><span class="n">SharedGraphicsDeviceManager</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">GraphicsDevice</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>При разработки игры с использованием XNA+Silverlight установка цели для рендера происходит в методе OnNavigatedTo(), и вся дальнейшая отрисовка будет производиться, соответственно, на дисплей. Так что для того, чтобы отрендерить все на другую текстуру достаточно просто указать её в SpriteBatch:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="n">imageResult</span> <span class="p">=</span> <span class="k">new</span> <span class="n">RenderTarget2D</span><span class="p">(</span><span class="n">SharedGraphicsDeviceManager</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">GraphicsDevice</span><span class="p">,</span> <span class="n">photoW</span><span class="p">,</span> <span class="n">photoH</span><span class="p">);</span>
</span><span class='line'><span class="n">SharedGraphicsDeviceManager</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">GraphicsDevice</span><span class="p">.</span><span class="n">SetRenderTarget</span><span class="p">(</span><span class="n">imageResult</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>Если мы вставим этот код так же в метод OnNavigatedTo(), то весь вывод информации будет производиться не на дисплей, а в нашу текстуру. Нам этого не нужно, так что необходимо менять цель для рендеринга по какому-то определенному событию, например, по нажатию на кнопку. Далее мы отрисовываем все наши текстуры, как мы бы это делали обычно в методе OnDraw():</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="n">spriteBatch</span><span class="p">.</span><span class="n">Begin</span><span class="p">();</span>
</span><span class='line'><span class="n">bg</span><span class="p">.</span><span class="n">Draw</span><span class="p">(</span><span class="n">spriteBatch</span><span class="p">,</span> <span class="k">new</span> <span class="n">Vector2</span><span class="p">((</span><span class="kt">int</span><span class="p">)(</span><span class="n">photoW</span> <span class="p">/</span> <span class="m">2</span><span class="p">),</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">photoH</span> <span class="p">/</span> <span class="m">2</span><span class="p">)));</span>
</span><span class='line'><span class="k">foreach</span> <span class="p">(</span><span class="n">Sprite</span> <span class="n">sprite</span> <span class="k">in</span> <span class="n">sprites</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="n">sprite</span><span class="p">.</span><span class="n">Draw</span><span class="p">(</span><span class="n">spriteBatch</span><span class="p">,</span> <span class="k">new</span> <span class="n">Vector2</span><span class="p">((</span><span class="kt">int</span><span class="p">)(</span><span class="n">photoW</span> <span class="p">/</span> <span class="m">2</span><span class="p">),</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">photoH</span> <span class="p">/</span> <span class="m">2</span><span class="p">)),</span> <span class="n">bg</span><span class="p">.</span><span class="n">Scale</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">spriteBatch</span><span class="p">.</span><span class="n">End</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>
<p>После того, как мы закончили отрисовывать наши текстуры необходимо освободить наше устройство для рендеринга, чтобы оно вернулось к отрисовке на экране. Для этого достаточно передать в null в метод SetRenderTarget:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="n">SharedGraphicsDeviceManager</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">GraphicsDevice</span><span class="p">.</span><span class="n">SetRenderTarget</span><span class="p">(</span><span class="k">null</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>Всё! Теперь мы можем сохранить наше изображение в изолированном хранилище, галерее или использовать его где-нибудь ещё.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="n">IsolatedStorageFileStream</span> <span class="n">stream</span> <span class="p">=</span> <span class="k">new</span> <span class="n">IsolatedStorageFileStream</span><span class="p">(</span><span class="s">"/image.jpg"</span><span class="p">,</span> <span class="n">System</span><span class="p">.</span><span class="n">IO</span><span class="p">.</span><span class="n">FileMode</span><span class="p">.</span><span class="n">OpenOrCreate</span><span class="p">,</span> <span class="n">iso</span><span class="p">);</span>
</span><span class='line'><span class="n">imageResult</span><span class="p">.</span><span class="n">SaveAsJpeg</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="n">imageResult</span><span class="p">.</span><span class="n">Width</span><span class="p">,</span> <span class="n">imageResult</span><span class="p">.</span><span class="n">Height</span><span class="p">);</span>
</span><span class='line'><span class="n">stream</span><span class="p">.</span><span class="n">Close</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>
<p>О том, как сохранить наше изображение в галерее вы можете прочитать в моей предыдущей статье “<a href="http://mne.p0x.ru/2011/12/blog-post.html">Интеграция приложения с хабом Фото</a>”.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Интеграция приложения с хабом "Фото"]]></title>
<link href="http://Ponf.github.io/blog/2011/12/Integratciia-prilozheniia-s-khabom-Foto/"/>
<updated>2011-12-14T10:08:00+00:00</updated>
<id>http://Ponf.github.io/blog/2011/12/Integratciia-prilozheniia-s-khabom-Foto</id>
<content type="html"><![CDATA[<p>Однажды мне понадобилось интегрировать приложение в хаб “Фото” в Windows Phone 7. Что я понимаю под интеграцией:</p>
<ul>
<li>Добавление приложения на главную страницу хаба;</li>
<li>Добавление приложения в меню “Программы” (программы, которыми можно отредактировать изображение);</li>
<li>Выбор в программе изображения из галереи и с камеры;</li>
<li>Сохранение отредактированного изображения в галерее.</li>
</ul>
<p>Вроде бы все понятно, в интернете много информации и никаких проблем возникнуть не должно, но на практике, к сожалению, не всё так просто.</p>
<!--more-->
<p></p>
<h2>1. Добавление приложения на главную страницу хаба Фото</h2>
<p>Беглый поиск <a href="http://programming4.us/mobile/3758.aspx">показал</a>, что для интеграции приложения в хаб Pictures нам необходимо создать файл Extra.xml со следующим содержимым:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt"><Extras></span>
</span><span class='line'> <span class="nt"><PhotosExtrasApplication></span>
</span><span class='line'> <span class="nt"><Enabled></span>true<span class="nt"></Enabled></span>
</span><span class='line'> <span class="nt"></PhotosExtrasApplication></span>
</span><span class='line'><span class="nt"></Extras></span>
</span></code></pre></td></tr></table></div></figure>
<p>И создать некоторый обработчик в методе OnNavigatedTo().</p>
<p>Сделал я по этой инструкции и ничего у меня не заработало. Оказалось, что с приходом WP7 Mango все немного изменилось. Таким образом, метод, приведенный выше, не работает!</p>
<p>С приходом WP7 Mango нам теперь не нужно создавать отдельный файл Extra.xml, информация о всех расширениях должна находиться в WMAppManifest.xml.</p>
<p>Для отображения нашего приложения в хабе Фото необходимо в файл WMAppManifest.xml добавить следующие строчки:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt"><Extensions></span>
</span><span class='line'> <span class="nt"><Extension</span> <span class="na">ExtensionName=</span><span class="s">"Photos_Extra_Hub"</span> <span class="na">ConsumerID=</span><span class="s">"{5B04B775-356B-4AA0-AAF8-6491FFEA5632}"</span> <span class="na">TaskID=</span><span class="s">"_default"</span> <span class="nt">/></span>
</span><span class='line'><span class="nt"></Extensions></span>
</span></code></pre></td></tr></table></div></figure>
<h2>2. Добавление приложения в контекстное меню хаба Фото</h2>
<p>Здесь механизм добавления приложения не отличается от добавления приложения на главную страницу хаба, только ExtensionName будет “Photos_Extra_Viewer”, а ConsumerID станет “{5B04B775-356B-4AA0-AAF8-6491FFEA5632}”.</p>
<p>В итоге WMAppManifest.xml примет следующий вид:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='xml'><span class='line'> <span class="nt"></Tokens></span>
</span><span class='line'> <span class="nt"><Extensions></span>
</span><span class='line'> <span class="nt"><Extension</span> <span class="na">ExtensionName=</span><span class="s">"Photos_Extra_Hub"</span> <span class="na">ConsumerID=</span><span class="s">"{5B04B775-356B-4AA0-AAF8-6491FFEA5632}"</span> <span class="na">TaskID=</span><span class="s">"_default"</span> <span class="nt">/></span>
</span><span class='line'> <span class="nt"><Extension</span> <span class="na">ExtensionName=</span><span class="s">"Photos_Extra_Viewer"</span> <span class="na">ConsumerID=</span><span class="s">"{5B04B775-356B-4AA0-AAF8-6491FFEA5632}"</span> <span class="na">TaskID=</span><span class="s">"_default"</span> <span class="nt">/></span>
</span><span class='line'> <span class="nt"></Extensions></span>
</span><span class='line'> <span class="nt"></App></span>
</span><span class='line'><span class="nt"></Deployment></span>
</span></code></pre></td></tr></table></div></figure>
<p></p>
<h2>3. Создание обработчика</h2>
<p>Итак, теперь мы умеем не только вызывать нашу программу из хаба, а ещё и передавать ей любое изображение. Теперь надо его обрабатывать. Для этого необходимо перегрузить метод OnNavigatedTo:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="n">BitmapImage</span> <span class="n">bitmap</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnNavigatedTo</span><span class="p">(</span><span class="n">NavigationEventArgs</span> <span class="n">e</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">base</span><span class="p">.</span><span class="n">OnNavigatedTo</span><span class="p">(</span><span class="n">e</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">//Get a dictionary of query string keys and values</span>
</span><span class='line'> <span class="n">IDictionary</span><span class="p"><</span><span class="kt">string</span><span class="p">,</span> <span class="kt">string</span><span class="p">></span> <span class="n">queryStrings</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">NavigationContext</span><span class="p">.</span><span class="n">QueryString</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">//WaitingPic.Visibility = Visibility.Collapsed;</span>
</span><span class='line'> <span class="c1">//Ensure at least one querysting</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">queryStrings</span><span class="p">.</span><span class="n">ContainsKey</span><span class="p">(</span><span class="s">"token"</span><span class="p">))</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="n">MediaLibrary</span> <span class="n">library</span> <span class="p">=</span> <span class="k">new</span> <span class="n">MediaLibrary</span><span class="p">();</span>
</span><span class='line'> <span class="n">Picture</span> <span class="n">picture</span> <span class="p">=</span> <span class="n">library</span><span class="p">.</span><span class="n">GetPictureFromToken</span><span class="p">(</span><span class="n">queryStrings</span><span class="p">[</span><span class="s">"token"</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">//Create bitmap</span>
</span><span class='line'> <span class="n">bitmap</span> <span class="p">=</span> <span class="k">new</span> <span class="n">BitmapImage</span><span class="p">();</span>
</span><span class='line'> <span class="n">bitmap</span><span class="p">.</span><span class="n">SetSource</span><span class="p">(</span><span class="n">picture</span><span class="p">.</span><span class="n">GetImage</span><span class="p">());</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="n">NavigationContext</span><span class="p">.</span><span class="n">QueryString</span><span class="p">.</span><span class="n">Clear</span><span class="p">();</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Теперь мы можем делать с нашим изображением всё, что захотим :).</p>
<h2>4. Получение изображений из камеры и галереи</h2>
<p>Также мы хотим осуществить в нашем приложении доступ к изображениям в галерее и, если нужное изображение отсутствует, предоставить возможность сделать фото.</p>
<p>Для этого нам необходимо использовать PhotoChooserTaskиCameraCaptureTask, которые находятся в пространстве имён Microsoft.Phone.Tasks.</p>
<p>В общем случае код выглядит примерно так:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="k">private</span> <span class="k">void</span> <span class="nf">ChoosePhoto_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">RoutedEventArgs</span> <span class="n">e</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">try</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="n">selectphoto</span> <span class="p">=</span> <span class="k">new</span> <span class="n">PhotoChooserTask</span><span class="p">();</span>
</span><span class='line'> <span class="n">selectphoto</span><span class="p">.</span><span class="n">Completed</span> <span class="p">+=</span> <span class="k">new</span> <span class="n">EventHandler</span><span class="p"><</span><span class="n">PhotoResult</span><span class="p">>(</span><span class="n">photo_Completed</span><span class="p">);</span>
</span><span class='line'> <span class="n">selectphoto</span><span class="p">.</span><span class="n">Show</span><span class="p">();</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">catch</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="n">MessageBox</span><span class="p">.</span><span class="n">Show</span><span class="p">(</span><span class="s">"Some problem with loading your page"</span><span class="p">);</span>
</span><span class='line'> <span class="k">return</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">private</span> <span class="k">void</span> <span class="nf">LaunchCamera_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">RoutedEventArgs</span> <span class="n">e</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="n">CameraCaptureTask</span> <span class="n">cameraCapture</span> <span class="p">=</span> <span class="k">new</span> <span class="n">CameraCaptureTask</span><span class="p">();</span>
</span><span class='line'> <span class="n">cameraCapture</span><span class="p">.</span><span class="n">Completed</span> <span class="p">+=</span> <span class="k">new</span> <span class="n">EventHandler</span><span class="p"><</span><span class="n">PhotoResult</span><span class="p">>(</span><span class="n">photo_Completed</span><span class="p">);</span>
</span><span class='line'> <span class="n">cameraCapture</span><span class="p">.</span><span class="n">Show</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">void</span> <span class="nf">photo_Completed</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">PhotoResult</span> <span class="n">e</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">TaskResult</span> <span class="p">==</span> <span class="n">TaskResult</span><span class="p">.</span><span class="n">OK</span><span class="p">)</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="k">try</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="n">bitmap</span> <span class="p">=</span> <span class="k">new</span> <span class="n">BitmapImage</span><span class="p">();</span>
</span><span class='line'> <span class="n">bitmap</span><span class="p">.</span><span class="n">UriSource</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Uri</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">OriginalFileName</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">catch</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="n">MessageBox</span><span class="p">.</span><span class="n">Show</span><span class="p">(</span><span class="s">"Some problem with loading your page"</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Как вы можете видеть, ничего сложно в этом нет, данный код вернет нам изображение в приложение. Но мне такая реализация не очень нравится. Я предпочитаю делать следующее:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
</pre></td><td class='code'><pre><code class='csharp'><span class='line'><span class="k">void</span> <span class="nf">photo_Completed</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">PhotoResult</span> <span class="n">e</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">TaskResult</span> <span class="p">==</span> <span class="n">TaskResult</span><span class="p">.</span><span class="n">OK</span><span class="p">)</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="k">try</span>
</span><span class='line'> <span class="p">{</span>
</span><span class='line'> <span class="n">bitmap</span> <span class="p">=</span> <span class="k">new</span> <span class="n">BitmapImage</span><span class="p">();</span>
</span><span class='line'> <span class="n">bitmap</span><span class="p">.</span><span class="n">CreateOptions</span> <span class="p">=</span> <span class="n">BitmapCreateOptions</span><span class="p">.</span><span class="n">None</span><span class="p">;</span>
</span><span class='line'> <span class="n">bitmap</span><span class="p">.</span><span class="n">ImageOpened</span> <span class="p">+=</span> <span class="k">new</span> <span class="n">EventHandler</span><span class="p"><</span><span class="n">RoutedEventArgs</span><span class="p">>(</span><span class="n">bitmap_ImageOpened</span><span class="p">);</span>
</span><span class='line'> <span class="n">bitmap</span><span class="p">.</span><span class="n">ImageFailed</span> <span class="p">+=</span> <span class="k">new</span> <span class="n">EventHandler</span><span class="p"><</span><span class="n">ExceptionRoutedEventArgs</span><span class="p">>(</span><span class="n">bitmap_ImageFailed</span><span class="p">);</span>
</span><span class='line'> <span class="n">bitmap</span><span class="p">.</span><span class="n">UriSource</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Uri</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">OriginalFileName</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">catch</span>
</span><span class='line'> <span class="p">{</span>