Кое-какая информация о Windows Phone 7 OS утекла в сеть.
Что уже известно:

  • Разрабатывать можно будет на Silverlight
  • Для разработки можно будет пользоваться XNA
  • Векторный интерфейс будет на XAML
  • Для простых разработчиков будет возможность писать Managed код, для OEM-разработчиков планируется возможность написания нативных приложений
  • Будут Push-нотификации на всякго рода cсобытия

Сканы, вроде бы, официальных документов по этому поводу доступны здесь.

Previous ArticleNext Article
Технический директор IT-Dimension, компании-разработчика кросс-платформенного программного обеспечения

Leave a Reply

Your email address will not be published. Required fields are marked *

M.

Maemo 5 Beta SDK Released

И вот, вышла новая версия Maemo SDK. В этом релизе:

  • Поддержка OMAP3.
  • Поддержка HSPA.
  • Поддержка камер высокого разрешения.
  • Аппаратное ускорение вывода графики.

SDK включает упрощенную реализацию рабочего стола и меню приложений. Режим редактирования рабочего стола включен чтобы облегчить управление приложениями и тестирование виджетов.

В комплект включена предварительная версия документации для разработчиков.

maemo5-sdk-beta

У.

Учимся скачивать файлы программно в Windows Mobile

Разработка приложений, использующих в своей работе сетевое взаимодействие или доступ к ресурсам Internet – это довольно популярная штука в наши дни. И в этот раз мы рассмотрим такую часто используемую задачу как загрузка файлов из Internet.

Для того чтобы скачать файл в C++ приложении с wxWinCE надо совсем немного кода. В простейшем случае для реализации однопоточной загрузки файла мы можем использовать класс wxURL, скормив ему адрес загружаемого ресурса.

void MobileDownloaderMainFrame::OnDOWNLOADClick( wxCommandEvent& event )
{
	do
	{
		wxString address = wxGetTextFromUser(_("Input URL"), 
			wxGetTextFromUserPromptStr, 
			wxT("http://wxwidgets.info"));
		if(address.IsEmpty()) break;
		wxURL url(address);
		if(!url.IsOk()) break;
		wxInputStream * stream = url.GetInputStream();
		if(!stream) break;
		wxString result;
		wxStringOutputStream out(&result);
		out.Write(*stream);
		delete stream;
		m_SingleThreadedResultTextCtrl->SetValue(result);
	}
	while(false);
}

Приведенный пример хорош всем кроме того, что пока выполняется загрузка, приложение не отвечает на действия пользователя, т.к. загрузка происходит в основном потоке и пока выполнение функции не закончится, приложение не может продолжить работу.

Чтобы таких ситуаций не случалось можно использовать библиотеку wxDownloadFile, которая позволяет загружать каждый файл в отдельном потоке и получать уведомления о состоянии загрузки.

Наш следующий пример демонстрирует как можно реализовать многопоточную загрузку файлов с минимальными усилиями.

Для начала создадим класс, который будет содержать информацию о загрузке:

#ifndef _DOWNLOAD_INFO_H
#define _DOWNLOAD_INFO_H

#include <wx/wx.h>
#include <DownloadFile.h>
#include <DownloadEvent.h>

class DownloadInfo
{
private:
	wxInt64 m_DownloadedSize;
	wxString m_URL;
	wxDownloadEvent::DownloadSTATUS m_Status;
	wxDownloadFile * m_Downloader;
public:
	DownloadInfo(const wxString & url)
		: m_DownloadedSize(0), m_URL(url), 
		m_Status(wxDownloadEvent::DOWNLOAD_NONE), m_Downloader(NULL) {}

	const wxString & GetURL() {return m_URL;}

	wxInt64 GetDownloadedSize() {return m_DownloadedSize;}
	void SetDownloadedSize(wxInt64 value) {m_DownloadedSize = value;}

	wxDownloadEvent::DownloadSTATUS GetStatus() {return m_Status;}
	void SetStatus(wxDownloadEvent::DownloadSTATUS value) {m_Status = value;}

	wxDownloadFile * GetDownloader() {return m_Downloader;}
	void SetDownloader(wxDownloadFile * value) {m_Downloader = value;}
};

WX_DECLARE_STRING_HASH_MAP(DownloadInfo *, DownloadsHash);

#endif

Кроме самого класса с информацией о загрузке нам необходима еще хеш-таблица, которая будет содержать информацию об активных загрузках в приложении. Доступ к элементам хеш-таблицы будет производиться по строковому ключу, в качестве которого мы будем использовать URL.

Для отображения информации о загрузках мы будем использовать компонент wxSimpleHtmlListBox. Компонент будет содержать указатель на хеш-таблицу с загрузками.

Чтобы в списке загрузок отображалась актуальная информация, нам необходимо переопределить метод OnGetItem().

#include "DownloadInfo.h"
...
class wxDownloadListBox: public wxSimpleHtmlListBox
{
...
    DownloadsHash * GetDownloads() const { return m_Downloads ; }
    void SetDownloads(DownloadsHash * value) { m_Downloads = value ; }

    virtual wxString OnGetItem(size_t n) const;

    void AddNew() {SetItemCount(GetItemCount()+1);}

    DownloadsHash * m_Downloads;
};

wxString wxDownloadListBox::OnGetItem(size_t n) const
{
	wxString value;
	do 
	{
		DownloadsHash::iterator i = m_Downloads->begin();
		for(size_t j = 0; (j < n) && (i != m_Downloads->end()); j++)
		{
			i++;
		}
		if(i == m_Downloads->end()) break;
		value = wxString::Format(wxT("<b>%s</b>"), i->first.GetData());
		DownloadInfo * download = i->second;
		if(!download) break;
		switch(download->GetStatus())
		{
		case wxDownloadEvent::DOWNLOAD_INPROGRESS:
			value += wxString::Format(
				_(" - <i>downloaded %d bytes</i>"), 
				download->GetDownloadedSize());
			break;
		case wxDownloadEvent::DOWNLOAD_COMPLETE:
			value += _(" (finished)");
			break;
		case wxDownloadEvent::DOWNLOAD_FAIL:
			value += _(" (failed)");
			break;
		}
	}
	while (false);
	return value;
}

Метод AddNew() указывает компоненту, что у него добавился новый элемент.

Теперь рассмотрим код, создающий новую загрузку и добавляющий ее в список:

void MobileDownloaderMainFrame::OnADDClick( wxCommandEvent& event )
{
	do 
	{
		DownloadParametersDialog * dlg = new DownloadParametersDialog(this);
		int result = dlg->ShowModal();
		wxString url = dlg->m_URLTextCtrl->GetValue();
		wxString fileName = dlg->m_FileNamePicker->GetPath();
		dlg->Destroy();
		if(result != wxID_OK) break;
		DownloadInfo * info = m_Downloads[url];
		bool needAddNew(true);
		if(info != NULL)
		{
			info->GetDownloader()->CancelDownload();
			needAddNew = false;
		}
		else
		{
			info = new DownloadInfo(url);
		}
		wxDownloadFile * download = new wxDownloadFile(this, url, fileName, true);
		
		info->SetDownloader(download);
		m_Downloads[url] = info;

		download->Run();
		if(needAddNew)m_DownloadsListBox->AddNew();

		m_DownloadsListBox->RefreshLines(
			m_DownloadsListBox->GetFirstVisibleLine(),
			m_DownloadsListBox->GetLastVisibleLine());
	} 
	while (false);
}

Собственно, что у нас здесь происходит:

  • отображается диалог создания новой загрузки. В нем необходимо ввести URL и путь к результирующему файлу
  • В случае если диалог отработал успешно, мы проверяем наличие загрузки с указанным URL в хеш-таблице
  • Если загрузка присутствует, то она останавливается
  • Если загрузки с указанным URL в таблице нет, то создается новый объект DownloadInfo
  • Затем создается объект wxDownloadFile и запускается
  • После этого происходит обновление списка загрузок

Как уже было сказано ранее, класс wxDownloadFile позволяет получать уведомления о состоянии загрузки. Для этого используется обработчик события EVT_DOWNLOAD():

BEGIN_EVENT_TABLE( MobileDownloaderMainFrame, wxFrame )
...
EVT_DOWNLOAD(MobileDownloaderMainFrame::OnDownloadStatus)
END_EVENT_TABLE()

void MobileDownloaderMainFrame::OnDownloadStatus(wxDownloadEvent & event)
{
	do
	{
		wxString url = event.GetDownLoadURL();
		DownloadInfo * downloadInfo = m_Downloads[url];
		wxDownloadFile * download = downloadInfo->GetDownloader();
		if(!download) break;
		downloadInfo->SetStatus((wxDownloadEvent::DownloadSTATUS)event.GetDownLoadStatus());
		switch(event.GetDownLoadStatus())
		{
		case wxDownloadEvent::DOWNLOAD_FAIL:
			wxLogDebug(wxT("DOWNLOAD_FAIL"));
			downloadInfo->SetDownloader(NULL);
			break;
		case wxDownloadEvent::DOWNLOAD_COMPLETE:
			wxLogDebug(wxT("DOWNLOAD_COMPLETE"));
			downloadInfo->SetDownloader(NULL);
			break;
		case wxDownloadEvent::DOWNLOAD_INPROGRESS:
			wxLogDebug(wxT("DOWNLOAD_INPROGRESS"));
			downloadInfo->SetDownloadedSize(event.GetDownLoadedBytesCount());
			break;
		default:
			break;
		}
		m_DownloadsListBox->RefreshLines(
			m_DownloadsListBox->GetFirstVisibleLine(),
			m_DownloadsListBox->GetLastVisibleLine());
	}
	while(false);
}

В обработчике события мы получаем состояние загрузки из объекта wxDownloadEvent и, в зависимости от этого значения, выполняем обновление объекта DownloadInfo в хеш-таблице загрузок.

О чем еще важно помнить? Приложение остается висеть в памяти пока не будут завершены все его потоки. wxDownloadFile создает поток на каждую загрузку и если мы попытаемся закрыть приложение во время скачивания файлов, то приложение будет выгружено только по завершению всех потоков. Чтобы такой ситуации у нас не было, нам необходимо принудительно завершить все потоки при закрытии главной формы приложения. Для этого мы будем использовать обработчик EVT_CLOSE():

void MobileDownloaderMainFrame::OnCloseWindow( wxCloseEvent& event )
{
	for(DownloadsHash::iterator i = m_Downloads.begin(); i != m_Downloads.end(); i++)
	{
		DownloadInfo * download = i->second;
		if(!download) continue;
		if(download->GetDownloader()) download->GetDownloader()->CancelDownload();
		wxDELETE(download);
		i->second = NULL;
	}
    event.Skip();
}

Вот теперь все.
wxMobileDownloader - Пример использования wxDownloadFile
Скачать исходный код приложения и проекты для Win32 и Windows Mobile.