Category Archives: Win32

Visual Studio 2017 Community

新規一転、プロジェクトを立ち上げようと、VisualStudio 2017 Proを買って正規の個人ライセンスで行こうと張り切っていたけれど、購入ページをよくみるとVS2017 Communityは Pro版との機能の違いはほとんどないみたいなので検証しつつ試用しながらインストールすることにした。(なんだかまだ環境だけでも長くかかりそうなので現在進行形)

一応価格は、Pro版で、スタンドアローンが$499、1 か月ごとのサブスクリプションで月$45。サブスクリプション版はMacでもつかえて、TFSも使えるようだ。

あとはクラウドサブスクリプション版で、月$45、年$539がある。クラウドサブスクリプションは旧版ののVSのライセンスもついて来て、その他もろもろの特典があるようだ。でもライセンスを買うならスタンドアローン以外に買う理由がない。(マイクロソフトに洗脳されるのは危険だしね)

結果からするとPro版とほぼ同じというのは、本当なようだ。

前回ExpressではWin32 C++プロジェクトで、COMのインスタンス数に制限があったり、スタティックライブラリを使えなかったりで一番使いたいところに制限がかけられていて使い物にならなかった。さらに検証するのに無駄な時間をさいてしまう結果だった(その時はVS2013Proを結局買った)けれど、今のところ既存のプロジェクトを開いてコンパイルも通っている。

一つ、見つかった不具合は、今日(8月15日)15.3のアップデートがリリースされていて、アップデート後Win32 C++プロジェクトをテンプレートから作成すると、文字化けが発生する。原因はテンプレートが吐き出すリソースファイルのテキストフォーマットがUTF-8になっている。UNICODEじゃないといけないんだけど、手動でNOTEPADでSaveAsするしかない。

結果としては、こういう画面になる。

このサイトは自分用のメモ書きなので、一つ一つ手順を書くことはしないが同じ問題に当たった人が検索でここにたどり着ければ、すぐにわかることなので詳細はこれ以上書かないよ。

15.2のWin32のテンプレートの名前はWin32Project1なんだけど、15.3ではWindows デスクトップ アプリケーションとされていて、感が的中。VSのスプラッシュが変わったのも変だと思ったけど。

今日と昨日で、2台のマシンにインストールして、今日インストールしたマシンだけこれが発生してちょっと焦った。2台入れて違うテンプレート名がでるなんてね。今日リリースという偶然で半日無駄にしてしまった。ふう。(お盆明けVS2017を使っている方々、アップデート結構時間かかるので要注意ですよ~。ってアップデート前にこの記事を見る人もいないと思うけど)

あと、SubVersionのプラグイン(ASVN)を入れたのだけれど、ローカルリポジトリを作ろうとするとVSごと固まってしてしまう。(VSが固まった後、OSがアプリケーションクラッシュのダイアログを出す)

原因はASVNプラグインにありそうだけれど、HTTPSのリポジトリは試していないので何とも言えない。MSでAzureのフリーアカウントでTeamServiceでGitを提供してくれるみたいなので、今後はGitでやっていこうかな。今後はGitが主流みたいだしね。(やっとSVNで慣れてきたのに。個人的にはLinux寄りのGitよりも、ApacheよりなSVNの方がすきなんだけど。その辺はどっちも使えないとね)

 

Windows 10 に搭載されているSAPI(音声合成)とCortanaについて

今回はWindows 10の音声合成の環境のアップデート。

Win7, 8, 8.1にはSAPIが搭載されており、sapi.hにOS標準の音声合成APIが含まれていました。Windows10も同様、標準のボイスの情報はSPCAT_VOICESに定義されているレジストリキー(HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices)にあり、バージョンは11.0となっています。

SAPI_REG1

さらに、Speech Platform Language Packでインストールされるボイスは”Speech Server”下に定義されます。このレジストリキーはSpEnumTokens関数でTokenを取得するときに第一引数として使用できます。(ただしSpeech Serverは Speech Platfrom Runtimeをインストールしないと、登録されていないボイスというエラーが返ってきます)

さらに、Windows10で話題のCortana(コルタナ)ですが、同じフォーマットでSpeech_OneCoreに定義されています。このボイスはSpEnumTokens関数で指定可能です。

SpEnumTokensでCortanaのボイスを指定する例)

hr = SpEnumTokens(L”HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech_OneCore\\Voices”, strReqAttribute, NULL, &pEnum);

CortanaにはパラメータがSAPIよりも用意されていますが、公開されているかは不明です。今のところ、SAPIから使用可能ということだけでしょうか。あと、日本語Cortanaのボイス名は”Ichiro”と”Ayumi”となっています。

SAPI_REG2

誰を使って、AI作ろうか。

今回作った。SAPIの関数(COMのHRESULTのエラー処理は省略)

HRESULT speak(LPWSTR strSpeakString)
{
	HRESULT hr = S_OK;

	//ISpVoice * pVoice = NULL;
	ISpVoice *pVoice = 0; 
	ISpObjectToken *pToken = 0;
	IEnumSpObjectTokens *pEnum = 0;

	if (FAILED(CoInitialize(NULL)))
	{
		::MessageBoxW(NULL, L"Error to intiliaze COM", L"DBG", MB_OK);
		return S_OK;
	}	

	hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
	if (SUCCEEDED(hr))
	{

		hr = SpEnumTokens(SPCAT_VOICES, L"Language = 411", NULL, &pEnum); //SAPI default voice (OS language pack) 411:Japanese
		//hr = SpEnumTokens(L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech Server\\v11.0\\Voices", L"Language = 411", NULL, &pEnum); //Speech Platform v11.0 (Required runtime)
		//hr = SpEnumTokens(L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech_OneCore\\Voices", L"Language = 411", NULL, &pEnum); //Cortana voice

		ULONG ulCount = 0;
		USHORT usVolume = 0;
		
		long lRate = 0;


		hr = pEnum->GetCount(&ulCount);
		pEnum->Item(0, &pToken);
			
		hr = pVoice->SetVoice(pToken);
		hr = pVoice->GetVolume(&usVolume);
		hr = pVoice->SetVolume(100); //0 - 100

		hr = pVoice->GetRate(&lRate);
		hr = pVoice->SetRate(0); // -10 to 10


		hr = pVoice->Speak(NULL, SPF_PURGEBEFORESPEAK, 0);
		hr = pVoice->Speak(strSpeakString, SPF_IS_XML | SPF_DEFAULT, NULL);
		hr = pVoice->WaitUntilDone(INFINITE);

		if(pToken)
		{
			hr = pToken->Release();
			pToken = 0;
		}

		if (pVoice)
		{
			hr = pVoice->Release();
			pVoice = 0;
		}

		if (pEnum)
		{
			hr = pEnum->Release();
			pEnum = 0;
		}
	}

	if (pToken)
	{
		hr = pToken->Release();
		pToken = 0;
	}

	CoUninitialize();
	return S_OK;
}

 

 

 

TurtoiseSVNのコマンドでSubVersionのRevisionをexeファイルに埋め込む方法

TurtoiseSVNに標準で含まれているSubWCRev.exeを使ってレビジョン番号を表示、ファイル出力が可能です。

コマンドの例として以下のコマンドでテンプレートファイル(Version_Tempalte.h)内のキーワードを書き換えて、Version.hファイルに出力します。

"c:\Program Files\TortoiseSVN\bin\SubWCRev.exe" . Version_Template.h Version.h -nmdfe

すでにVersion.hファイルが存在すると、エラーになるのでVersion.batファイルを使ってファイルを削除するコマンドを追加します。Version.batファイルの内容は以下の通り。

cd %~dp0
IF EXIST Version.h del Version.h
"c:\Program Files\TortoiseSVN\bin\SubWCRev.exe" . Version_Template.h Version.h -nmdfe

cd %~dp0 は、カレントディレクトリを現在のフォルダに移動するコマンドです。Version.hファイルをソリューションフォルダに置いた場合、プロジェクトのビルドはプロジェクトフォルダがカレントになるので、ソリューションフォルダに移動するようにします。

プロジェクト側の設定は、.rc ファイルにVersion.hをインクルードして、変数を下記のように書きます。

Version.batコマンドをプロジェクトのPREBUILDイベントコマンドに追加してプロジェクトをリビルドして.exeファイルのファイルの詳細を確認して完了です。

#include "..\Version.h"
.....
FILEVERSION FILE_VERSION
PRODUCTVERSION PRODUCT_VERSION
"c:\Program Files\TortoiseSVN\bin\SubWCRev.exe"
SubWCRev 1.8.11, Build 26392 - 64 Bit

Usage: SubWCRev WorkingCopyPath [SrcVersionFile DstVersionFile] [-nmdf]

Params:
WorkingCopyPath    :   path to a Subversion working copy.
SrcVersionFile     :   path to a template file containing keywords.
DstVersionFile     :   path to save the resulting parsed file.
-n                 :   if given, then SubWCRev will error if the working
                       copy contains local modifications.
-N                 :   if given, then SubWCRev will error if the working
                       copy contains unversioned items.
-m                 :   if given, then SubWCRev will error if the working
                       copy contains mixed revisions.
-d                 :   if given, then SubWCRev will only do its job if
                       DstVersionFile does not exist.
-q                 :   if given, then SubWCRev will perform keyword
                       substitution but will not show status on stdout.

-f                 :   if given, then SubWCRev will include the
                       last-committed revision of folders. Default is
                       to use only files to get the revision numbers.
                       this only affects $WCREV$ and $WCDATE$.
-e                 :   if given, also include dirs which are included
                       with svn:externals, but only if they're from the
                       same repository.
-E                 :   if given, same as -e, but it ignores the externals
                       with explicit revisions, when the revision range
                       inside of them is only the given explicit revision
                       in the properties. So it doesn't lead to mixed
                       revisions

-x                 :   if given, then SubWCRev will write the revisions
                       numbers in HEX instead of decimal
-X                 :   if given, then SubWCRev will write the revisions
                       numbers in HEX with '0x' before them

Switches must be given in a single argument, e.g. '-nm' not '-n -m'.

SubWCRev reads the Subversion status of all files in a working copy
excluding externals. If SrcVersionFile is specified, it is scanned
for special placeholders of the form "$WCxxx$".
SrcVersionFile is then copied to DstVersionFile but the placeholders
are replaced with information about the working copy as follows:

$WCREV$         Highest committed revision number
$WCREV&$        Highest committed revision number ANDed with the number
                after the &
$WCREV+$        Highest committed revision number added with the number
                after the &
$WCREV-$        Highest committed revision number subtracted with the
                number after the &
$WCDATE$        Date of highest committed revision
$WCDATE=$       Like $WCDATE$ with an added strftime format after the =
$WCRANGE$       Update revision range
$WCURL$         Repository URL of the working copy
$WCNOW$         Current system date & time
$WCNOW=$        Like $WCNOW$ with an added strftime format after the =
$WCLOCKDATE$    Lock date for this item
$WCLOCKDATE=$   Like $WCLOCKDATE$ with an added strftime format after the =
$WCLOCKOWNER$   Lock owner for this item
$WCLOCKCOMMENT$ Lock comment for this item


The strftime format strings for $WCxxx=$ must not be longer than 1024
characters, and must not produce output greater than 1024 characters.

Placeholders of the form "$WCxxx?TrueText:FalseText$" are replaced with
TrueText if the tested condition is true, and FalseText if false.

$WCMODS$        True if local modifications found
$WCMIXED$       True if mixed update revisions found
$WCEXTALLFIXED$ True if all externals are fixed to an explicit revision
$WCISTAGGED$    True if the repository URL contains the tags classification patt
ern
$WCINSVN$       True if the item is versioned
$WCNEEDSLOCK$   True if the svn:needs-lock property is set
$WCISLOCKED$    True if the item is locked