FC2ブログ


タブレットの手書文字入力問題

   プログラミング [2019/10/10]


プログラミングとはちょっと違うけど、まあパソコン絡みということで。

タブレット用のアプリを作って、キーボードなし状態で、そのアプリ上に文字(文章)を入力するときの話。

音声認識を使って文字入力するような仕掛けも作ってはみたものの、
MSがタダで使わせてくれる音声認識の精度は決して高くありません。
訓練してあげれば、少しは良くなってるかもしれないけど、実感できるほどにはなかなかならない。

もう一つ、キーボードが苦手な方用に、手書き文字入力という方法がある。
ソフトキーボードの内のキーレイアウトというか、入力タイプの1つとして手書き文字入力パッドがある。
タスクバーの右側にキーボードのアイコンがあって、
20191010_2.jpg


それをタップすると画面上に出てくる。
通常は、キーボードなしの状態だと、文字入力フィールドにフォーカスを移動しただけで、画面上に表示される。

最初に表示されるのは、一般的なキーボードのレイアウトになっているかもしれないが、左上のキーボードマークをタップすると色んなキーボードから好みのものを選択できるようになっている。

その一つが、手書き文字入力パッド。
20191010_1.jpg


タブレットを購入してすぐのころは、サクサク動いて、結構汚い字で書いても認識してくれて、
ひらがなを入力したら、漢字候補も出してくれるし、どうも前の単語も認識して続く表現の候補も出してくれる。
なかなかよい。

ところが、しばらくぶりで、使ってみようと思って動かすと・・・
20191010_4.jpg

なんだか、線の書き出しの反応が遅れる・・・文字の入力が不完全になる。
なので、まともな文字として認識しない。ゆっくり書けばいいのだけど、折角メモ代わりに使おうと思っても、これじゃぜんぜんダメというレベル。

なぜ、遅くなったのだ?
色々調べて試したことをダラダラ書きます。
「結果を言えよ」と思われる方は、最後の方をご参照ください。



続きを読む

スポンサーサイト





Eclipse-Perl環境でハマった件

   プログラミング [2019/10/07]
「VS2017-はじめの・・・」で説明してきた、Winタブレット向けのアプリの相方(サーバ側)の試作をしていたときの話です。
なにはともあれ、perlが大嫌いになりました。

事の起こりは、DBサーバからデータを抜き出して、加工して戻すという単純なプログラムを作ることだった。
サーバーにはApacheが組み込まれているという話だったので、少し慣れてるPHPでサーバスクリプトを書いた。

ところが、そもそも本番サーバにPHPは組み込まれていないらしい。
そこでPHPの追加を依頼したが、PHPと古いApacheのバージョンで不整合があって動かなかったそうだ。
(事前に有効バージョンを確認しなかったんですね・・・・ ^^;)
暗号化系の処理を行うためには、PHPの新めのバージョン(5.5以降)が必要なのだが、
「もう勘弁してくだせぇ。Perlでお願いします。」とのこと。
「コードをPerlで書き直す作業と、Apache環境にPHPを追加するのとどっちが効率いいですか?」
後者ですよねー。
かなり納得いかないが、まあしゃあない。やってあげようじゃありませんか。

手元のパソコンにはEclipseをインストールしてあり(その環境でデモ用PHPスクリプトを作った。)、
確かPerlも使えたはずと思って、コーディングを始めた。

ほぼ、はじめてのPerlです。
かなり、なじめねー。

・どこぞのサイトの説明も分かる人にはわかりやすいのかもしれないが、虫食い状態でしか説明を読まないど素人には殆ど歯が立たない。
・公式リファレンスのperldoc.jpの日本語訳が参照できるが、まったく十分な印象は受けない。何をどう指定したらいいのか、何を指定したらだめなのか・・・結局、要領を掴めなかった。

まあ、勉強する気も無いのが良くないんだけど。

Perlのわけわかんない文法もイライラしたが、そこはそれでも大したことはなかった。(ここまで3日くらい。)
※詳細は省略します。

なんとかかんとか、大雑把な動きの部分を一通りのコーディングを完了して、
じゃあちょっくら動かしてみましょう・・・

※以降、絵が小さいときは、クリックすると読める程度の絵が出ると思います。

続きを読む



Eclipse-PHP環境でちょっとハマった

   プログラミング [2019/09/30]
「VS2017-はじめの・・・」で説明してきた、Winタブレット向けのアプリの相方(サーバ側)の試作をしていたときの話です。
もう、半年以上前の話なので、ほとんど細かいことは覚えてないのですが、当時のメモがあったので、それを元にハマったことを書きます。

Eclipse上でPHPのサーバスクリプトを作ってデバッグするときの注意点になるかと思います。

Eclipseのバージョンは、Oxygen.2 Release (4.7.2)

◆初めて使うときに躓かないために
とは言っても結局は、あまり考えないで進めて、ハマってからしか詳細を調べないのが普通ですよね。

さるの場合、最初のワークスペース指定から、何も考えずに適当にやったら、Eclipse起動時、あるいはPHP実行時に「Post startup...中に内部エラーが発生しました。」、「ローカルホストのPHPビルトイン・サーバーに公開中・・・」などのエラーが出るようになった。テストできない状態になった。

原因は、適当にやりすぎたから。
でも、それを解消してやり直しを掛けるのに結構手間取った。

まずは、やらかしたときの手順を追って行きます。
長いです。
※以降、絵が小さいときは、クリックすると読める程度の絵が出ると思います。

続きを読む



VS2017-はじめの1/10歩(18):暗号化処理を取り込む

   プログラミング [2019/09/16]
「くりぷと」って聞いて・・・「元素にそんな名前のがあったよーな」と思ってしまうさるです。

Windows10タブレット向けのアプリを作ろうとしています。
VS2017を使うんだけど慣れてないからVS6でまずは作ってました。言わばWin32アプリです。
両方の環境(クロス環境)でコンパイルできるソースとして書いてます。
これまでの書き込みも含めると、

→ナレーション再生と音声認識を使う
  →そのため音声データの作り方(多言語対応)
  →ナレーション(.WAV)再生のサンプルコード
  →音声認識のサンプルコード
→VS6で作ったC/C++コードをVS2017に持って行って.cppレベルで共通にする方法
→ダイアログベースのプログラム
  →背景に画像(.BMP)を使う
  →ラベルを透かす
  →ボタンの色を変える
  →Windowsタブレット上でピンチイン/アウト:拡大縮小
  →タブレット画面の回転への対応
  →カスタムなチェックボックス作成
  →ボタンに画像を貼付ける
  →スクロールとスワイプ
→HTTPでファイルを送受信する
  →手法1:ブラウザ使って
  →手法2:Wininetを使う
暗号化処理を取り込む←今回

となってます。

世の中、データの暗号化は当たり前に使われる時代なんですよね。
ほぼ、そんなこと気にせず通信環境で動くアプリやサービスを使ってるけど。

例えば、LAN環境で使用するローカルなDBサーバシステムがあったとします。
そのサーバシステムに対して、LAN環境外でデータの更新がしたくなったとします。

つまり、持ち歩きのPCで加工したい部分を予め取り出して、どっか別の場所で加工して、戻す仕掛け。
そうすれば、DBとのデータの出し入れだけLAN環境のエリアで行えば、そのデータの加工はどこでへ行ってもできる。

「そんなの公衆回線を使ってDBアクセス環境を作っちゃえばいいじゃん。」と思われるでしょう。
今はほとんど通信料は定額だし、WiFi環境もそこいらに・・・・
ないんです。
さるの棲む田舎では、WiFiスポットを探すどころか、電波が届かないところも未だにざらにあるのですよ。

ちなみに、さるの実家でのポケットWiFiの可否としては
・Do*omo △ :スンゲー遅い。3G<->4G行ったり来たり。
・A*     × :通じません
・Softb* 不明:カバー域マップで見るとつながることになってる。

そんなところで外回りされる方のためには、データの部分的持ち歩きはあってもいい機能ではないかと。
定額と謂えども、その分の通信コストも削減できるはず。

ただし、ローカルなデータを持ち出すのだから、端末を落としたら大変です。
しかも今のところ持ち歩きデバイスはWindowsタブレットだし。
なのでファイル自体は「暗号化しておこう」と思ったのが、事の始まりです。

いつもながら、前置き長くてすいません。

そんなこんなで、「暗号化」についてちょっとだけ勉強することになった。

暗号化方式も色々あるらしが、「AES」というのがよさげらしい。

調べているうちに、「ローカル環境内の通信で、タブレットからDBアクセス時にハッキングされたら?」と思ってしまった。
(ローカルな環境でしかやれないことだし、そんなに心配するほどでもないのだけど。)

-ユーザ認証は必要でしょう。
-ってことは、ID/パスワードをサーバ側スクリプトに送り込むよな。
-裸で?
-せめてパスワードは分からないようにしようよ。
-どんなのがある?
-「PBKDF2」※という単語が出てきた。
-じゃそれ使って見よう。
-当然、データもダウンロード段階で暗号化。
-保存もそのままで、参照・編集時に復号ね。

と思ったのがウンのツキ。
この時点で「暗号化」についての知識はゼロです。
使われている言葉すら分かりません。

調べ始めたんだけど、色んな説明してくれてるサイトはあるんだけど、
Windows、VCで絞ると、割と無かった印象。
なので、結構時間が掛かりました。

それで・・・・

続きを読む



VS2017-はじめの1/10歩(17):HTTPでファイルを送受信する(2)

   プログラミング [2019/09/14]
VS2017を使うんだけど慣れてないからVS6でまずは作ってました。
さらに、言わばWin32アプリです。
両方の環境(クロス環境)でコンパイルできるソースとして書いてます。
これまでの書き込みも含めると、

→ナレーション再生と音声認識を使う
  →そのため音声データの作り方(多言語対応)
  →ナレーション(.WAV)再生のサンプルコード
  →音声認識のサンプルコード
→VS6で作ったC/C++コードをVS2017に持って行って.cppレベルで共通にする方法
→ダイアログベースのプログラム
  →背景に画像(.BMP)を使う
  →ラベルを透かす
  →ボタンの色を変える
  →Windowsタブレット上でピンチイン/アウト:拡大縮小
  →タブレット画面の回転への対応
  →カスタムなチェックボックス作成
  →ボタンに画像を貼付ける
  →スクロールとスワイプ
→HTTPでファイルを送受信する
  →手法1:ブラウザ使って
  →手法2:Wininetを使う←今回

前回、1週間くらい掛けて調べた挙句に、当初の前提をチャラにして、
ブラウザコントロールは使わずに必要な機能を再度作ることにしました。

つまり、サーバスクリプト側には、
 ・ダウンロード:欲しいデータをリクエストして、
          お返しにそのデータファイルをレスポンスしてもらう。
 ・アップロード:アップしたいデータを伝えて、一緒にファイルも送り込み、
          結果のステータスのみレスポンスしてもらう。

◆ファイルを単純にダウンロードするだけ
URLDownloadToFile()を使ったら、あっさりできた。
しかも、呼び出したプログラムのカレントフォルダに書き込んでくれる。
(前回の「IEイベント操作方法」捜索は、もっと早くにあきらめればよかった。)

ヘッダとかに以下が必要。
//----------------------------------------------
#include <urlmon.h> //URLDownload()
#pragma comment(lib, "urlmon.lib")
//----------------------------------------------


ダイアログとかにダウンロード用のボタンがあるものとして。
ウィンドウプロシジャ内で
//----------------------------------------------
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BTDL1) {
//パターン1:URLDownloadToFile
HRESULT rs;
rs = URLDownloadToFile(g_pWB2, g_FileDLUrl, "tameshite.zip", 0, NULL);
if (rs == S_OK) {
OutputDebugString(_T("Download success!\n"));
}
else if (rs == E_ABORT) { //0x80004004
//URLDownloadToFile()の第3パラメタでパス指定するとアボートされる。
//→IEテンプレートフォルダ?(このプログラムのカレント)に書き込まれる。
OutputDebugString(_T("Download error!! E_ABORT\n"));
}
else {
OutputDebugString(_T("Download error!! unknown\n"));
int rt = GetLastError();
}
}

//----------------------------------------------


URLDownloadToFile()関数の先頭パラメタg_pWB2は、AtlAxGetControl()が使えましたが、NULLでも大丈夫そうです。
g_FileDLUrlは、ダウンロードするファイルのURL、あるいはスクリプトのURLを指定します。


◆ファイルを問答無用でサーバ側に送りつける
ダウンロードで、ブラウザが必要なHTMLのフォームを介してのダウンロードは断念したので、アップロードも問答無用としたい。
調べました。

https://www.experts-exchange.com/questions/21043473/Automating-Internet-Explorer-to-upload-files-with-VC.html ★
HTMLとしてブラウザ上に表示されているformを操作するような感じなのかな?
まずは、キープ。

http://frog.raindrop.jp/knowledge/archives/000287.html
MFCを使う方法の説明。MFCかー。

http://programing-memo.blogspot.com/2011/05/ccgi.html
サーバ側の処理をC++で・・・みたいなので違います。

http://sdlabo.org/index.php?C%E8%A8%80%E8%AA%9E%E3%81%A7POST%E3%81%97%E3%81%A6%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89 ★
WinSockを使う方法かと思います。シンプルで分かりやすい。
これもキープ。

https://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=34969&forum=7 ▼
VBのWebClient.UploadFileをVCでやりたいけど、上手くいかないとのQ。
Aがない。
でも、WebClientってこれまでも出てきた気がする。
これしか、ないのか?

と、ここで「cURL」というワードが登場。
https://teratail.com/questions/100418
https://curl.haxx.se/libcurl/c/example.html
https://curl.haxx.se/download.html

wikiで説明を読むと、なんか自由に使ってよさげなフリーのライブラリらしく、Windows版もある。
使用方法を説明するサンプルコードもあって、見ると至ってシンプルだ。
ダウンロードもアップロードもある。
ぐっと来てますが、
あれもこれもを追加すると、今はいいけど先々の継続性に不安を抱えることになるわけで。
MS社提供環境に絞って仕方なく使っているのも、いくらかでもOS/VSのバージョンアップ時の「互換」を期待してのこと。
・・・もうちょっと調べよう。

これまで使ってきたヘッダやライブラリをベースにファイルのアップロードについて語っているところを探すために「COM」「IWebBrowser2」とかのキーワードをプラスして探しましたがなかなか、さるが理解できそうなところに当たらない。

飽きちゃって、ぼやっと検索されたサイトを見てたら、
あれ?「Wininet」ってあるのね。
要はブラウザじゃない、URLアクセスですよね。
なんだよ、ちゃんとあるんだね。

ダウンロードのサンプルはすぐ見つかりました。
https://blog.systemjp.net/entry/2016/08/10/110128
http://yamatyuu.net/computer/program/sdk/wininet/wgetbin/index.html

アップも?・・・ありました。
https://code.i-harness.com/ja-jp/q/7309e
https://stackoverflow.com/questions/10097216/c-wininet-file-upload-with-http-post
https://www.dinop.com/vc/wininet_post.html

またもや方針転換です。
URLDownLoad()を使うのは止めて、Wininet APIを使います。


まあともかく、動かせそうなレベルまでコードを書きました。(ほぼパクリですけどね。)

じゃあ、動かして見ましょー・・・

続きを読む



VS2017-はじめの1/10歩(16):HTTPでファイルを送受信する(1)

   プログラミング [2019/09/13]
VS2017を使うんだけど慣れてないからVS6でまずは作ってました。
さらに、言わばWin32アプリです。
両方の環境(クロス環境)でコンパイルできるソースとして書いてます。
これまでの書き込みも含めると、

→ナレーション再生と音声認識を使う
  →そのため音声データの作り方(多言語対応)
  →ナレーション(.WAV)再生のサンプルコード
  →音声認識のサンプルコード
→VS6で作ったC/C++コードをVS2017に持って行って.cppレベルで共通にする方法
→ダイアログベースのプログラム
  →背景に画像(.BMP)を使う
  →ラベルを透かす
  →ボタンの色を変える
  →Windowsタブレット上でピンチイン/アウト:拡大縮小
  →タブレット画面の回転への対応
  →カスタムなチェックボックス作成
  →ボタンに画像を貼付ける
  →スクロールとスワイプ
→HTTPでファイルを送受信する
  →手法1:ブラウザ使って←今回
  →手法2:Wininetを使う


以降、試行錯誤も含めて説明しているので、きっと「何言ってるかわかんない」ことが多いかと思います。
さる用の身勝手備忘録なのでご勘弁を。

やろうとしていることを簡単に説明すると
タブレット上のアプリでサーバ側のスクリプトをキックして、DB上のデータをtsvファイルの形で受け取ること。
当然tsvファイルは暗号化済みのもの。
当初は、サーバ側スクリプト(CGI)で取り出すデータを指定してやる手順を想定した。
以前だれかが作ったHTMLを吐き出す前提スクリプトが存在していて、それを「使えるなら使おう」と考えたから。
なので、タブレット側のアプリ内でブラウザを動かす方法から調べ始めた。


◆ダイアログ上でブラウザを動かす
まずは、上記のタイトル+「VC」でググりまくって、以下の参考サイトを見つけた。
http://www.nitoyon.com/vc/tips/ie_component.htm ★1
http://www.ne.jp/asahi/hishidama/home/tech/vcpp/webbrowser.html ★2
http://www14.big.or.jp/~ken1/tech/tech17.html
https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/controls/webbrowser-control-overview

上記の★サイトを参考に
1)リソース
以下はVS6で実施。
ダイアログを作成し、作ったダイアログ上で右クリックして表示されるプルダウンメニューから「ActiveXコントロ-ルの挿入」を選択し、表示されるダイログ上のリストから「Microsoft Web Browser」を選択する。
→なんか黒く塗り潰された矩形が表示されたので、多分追加できたのだろう。
 サイズだけダイアログ フルフルになるように調整。

2)ソースコード
共通ヘッダファイル(.h)とかに以下を追加
//----------------------------------------------
//WebBrowser(ActiveX)表示用
#include <atlbase.h> //ATL基本機能用
extern CComModule _Module; //ATL利用時必須。変数名は限定らしい。
#include <atlcom.h> //ATL COM共通用(VC6.0時には明示が必要)
#include <atlhost.h> //ATLコンテナ機能サポート用
//----------------------------------------------



WinMain()ソース(.cpp)のWinMain()内で
//----------------------------------------------
//メッセージループ前に
_Module.Init(0, g_hInst); //ATLモジュールを初期化
AtlAxWinInit(); //コンテナ機能の初期化

//メッセージループ後で、プログラム終了前に
_Module.Term(); //ATLモジュールの終了処理


//IEダイアログを呼び出したいところで
AtlAxDialogBox(g_hInst, MAKEINTRESOURCE(IDD_IE), hDlg, (DLGPROC) DlgBrowseProc, (LPARAM) szUrl);

//----------------------------------------------


IEダイアログ処理ソース(.cpp)内に以下追加
//----------------------------------------------
//グローバル変数
CComModule _Module; //CComModuleの実体定義
CComQIPtr<IWebBrowser2> g_pWB2; //IWebBrowser2へのスマートポインタ
//----------------------------------------------


IEダイアログのWM_INITDIALOGメッセージ処理で
//----------------------------------------------
CComPtr<IUnknown> punkIE;
g_pWB2 = (CComPtr<IUnknown>) NULL;
//ActiveXへのI/Fを要求する
if (AtlAxGetControl(GetDlgItem(hDlg, IDC_EXPLORER1), &punkIE) == S_OK) {
g_pWB2 = punkIE;
}
if (!g_pWB2) {
//エラー処理
EndDialog(hDlg, 0);
return TRUE;
}
CComVariant vEmpty, vUrl((PTCHAR) lParam);
g_pWB2->Navigate2( &vUrl,
&vEmpty, //Flags:BrowserNavConstants列挙体で定義されている値の組合せ?
&vEmpty, //TargetFrameName:フレーム名 <a ... target="xxxx" ...>で指定するような名前
&vEmpty, //PostData:POSTで送るデータ。指定しないとGET。
&vEmpty); //Headers:追加のHTMLヘッダ
//----------------------------------------------


あっさり表示されました。

「ラッキー!」とか思って、VS2017にそのコードを持っていって、実行させると、AtlAxDialogBox()でエラーで終わる。
ステップ実行で追っかけたりして、どうもコントロールのCreateWindowに問題がありそうなところまでは分かった。
VS2017のリソースエディタで、ActiveX(Microsoft Web Browser)を貼り付け直してみたが、ダメ。
OSを変えると、GUID/クラス名らしき部分の表現を変更するような例もあったので、まねっこしたが、ダメ。

一度VS6に戻って、

3)ソースコード再修正
AtlAxDialogBox()をDialogBox()に替えて
//----------------------------------------------
//AtlAxDialogBox(g_hInst, MAKEINTRESOURCE(IDD_IE), hDlg, (DLGPROC)DlgBrowseProc, (LPARAM)szUrl);
DialogBox(g_hInst, (LPCTSTR)IDD_IE, NULL, (DLGPROC)DlgBrowseProc);
//----------------------------------------------


AtlAxGetControl()前で、以下を追加
//----------------------------------------------
RECT rect;
HWND hwndie;
GetWindowRect(hDlg, &rect);
hwndie = CreateWindow("AtlAxWin",
"Shell.Explorer.2",
WS_CHILD | WS_VISIBLE,
0, 0, rect.right-rect.left, rect.bottom-rect.top,
hDlg, (HMENU)0, g_hInst, NULL);
//----------------------------------------------


AtlAxGetControl()自体は、以下に変更
//----------------------------------------------
//if (AtlAxGetControl(GetDlgItem(hDlg, IDC_EXPLORER1), &punkIE) == S_OK) {
if (AtlAxGetControl(hwndie, &punkIE) == S_OK) {
g_pWB2 = punkIE;
}
if (!g_pWB2) {
//エラー処理
EndDialog(hDlg, 0);
return TRUE;
}
//----------------------------------------------


VS6では、アッサリ動きました。
再度、VS2017に持って行ったら、やっぱりダメ。CreateWindow()でエラーになる。
リターンコードが、ERROR_CANNOT_FIND_WND_CLASS(1407)。

★1参考サイトに"AtlAxWin80"に変えみるとか、OSのバージョンに依存するらしいことが書かれてあったので、
"AtlAxWinXX"で、XX=70,71,80,81,100,120,170を全て試してみたけど・・全部ハズレでした。

「AtlAxWin」で検索しまくってたら
https://social.msdn.microsoft.com/Forums/en-US/88a981ea-8125-4917-a45e-87cfbc7fd1dd/createwindowatlaxwin-does-not-work-using-vs2003?forum=windowssdk★3
がひっかかった。

4)ソースコード再々修正
「ATLAXWIN_CLASS」というのがどっかに定義されてるっぽい記述。
「hwndie = CreateWindow(ATLAXWIN_CLASS,・・・」と指定したら、動いた。
なので、以下をヘッダとかに追加。
//----------------------------------------------
#ifndef ATLAXWIN_CLASS
#define ATLAXWIN_CLASS "AtlAxWin"
#endif
//----------------------------------------------


これで、VS2017でビルドしても動きます。

注意)AtlAxDialogBox()をDialogBox()に変えた影響で、最初に表示するURLをlParamで伝えられなくなったので、そこも別の方法にする必要あります。

さて、そこからが長かった。


続きを読む



VS2017-はじめの1/10歩(15):スクロールとスワイプ

   プログラミング [2019/09/08]
VS2017を使うんだけど慣れてないからVS6でまずは作ってました。
さらに、言わばWin32アプリです。
両方の環境(クロス環境)でコンパイルできるソースとして書いてます。
これまでの書き込みも含めると、

→ナレーション再生と音声認識を使う
  →そのため音声データの作り方(多言語対応)
  →ナレーション(.WAV)再生のサンプルコード
  →音声認識のサンプルコード
→VS6で作ったC/C++コードをVS2017に持って行って.cppレベルで共通にする方法
→ダイアログベースのプログラム
  →背景に画像(.BMP)を使う
  →ラベルを透かす
  →ボタンの色を変える
  →Windowsタブレット上でピンチイン/アウト:拡大縮小
  →タブレット画面の回転への対応
  →カスタムなチェックボックス作成
  →ボタンに画像を貼付ける
  →スクロールとスワイプ←今回

となってます。

今回は、さる的に毎回引っかかるスクロールの話です。

今回作ってたタブレット向けのアプリには、スクロール動作に影響のある以下の機能課題/仕様がありました。
・ダイアログの背景を単純な塗りつぶしではなく、画像を貼り付けるようにします。
・画面のサイズは、デスクトップの横方向サイズに合わせて可変です。
・ダイアログ内のレイアウト(表示項目)がデータに応じて縦方向に可変です。
・スクロールは、縦方向にのみサポートします。
・スワイプでのスクロールをサポートします。
多分、読んでもイメージしにくいかと思いますが、ともかく元のダイアログウィンドウの表示比率がコロコロ変わるので、
それに見合ったスクロール制御の処理ルーチンが必要だということです。


◆スクロール制御の基本
Windowsでは、スクロールを制御する際、まずはSCROLLINFO構造体を使ってSetScrollInfo()関数でスクロールに関連する情報をシステム側に通知します。
これをやれば、スクロールバーの操作には勝手に反応してスクロール制御をやってくれるのか?といえば、そうではない。
スクロール関連のイベント(WM_VSCROLL/WM_HSCROLL&SB_LINEDOWN/SB_LINEUP/SB_PAGEDOWN/SB_PAGEUP/SB_THUMBPOSITION/SB_THUMBTRACK)は、個別にプログラム内でScrollWindow()/SetScrollPos()/UpdateWindow()等で処理してあげないといけない。
・ScrollWindow()
  :スクロール対象のウインドウの中身の移動
   (無効領域(今まで見えてなかった部分)の再描画動作は含まない。)
・SetScrollPos()
  :スクロールバーの表示状態の変更
・UpdateWindow()
  :ウィンドウ内容の再描画を促す
   (無効領域(今まで見えてなかった部分)の描画)

なんで、こんなに面倒なの?と素朴な疑問を感じるのですが、そうなってるんです。

◆ローカルなスクロール情報
上記の制御をプログラム内で分かりやすく管理しようと思って以下のような、構造体(テーブル)を使ってます。
//----------------------------------------------
//スクロール関係
typedef struct _myscroll_inf {
INT fullh; //本来の表示の高さ
INT disph; //見えている部分の高さ
INT range; //表示されていない部分の高さ
INT pos; //現在の表示縦位置
INT dy; //移動量の単位
INT boxh; //スライダーのサイズ※実は・・・
} MYSCROLLINF, *PMYSCROLLINF;
//----------------------------------------------


MYSCROLLINF内にboxhという名前のメンバを用意してあります。
これは、システム側で準備しているSCROLLINFO内のnPageというメンバがあって、どこぞのサイトの説明を見ると「スライダーのサイズ」という説明があったので、それを単純に解釈して準備しました。
ただし、「サイズ」とは言うものの単位のある「サイズ」ではないということを理解できていませんでした。
実際のスライダーのサイズはコントロール側がSCROLLINFO内の他メンバとの計算で決めているようです。
なので、このboxhは(セットはしてるけど)使われてません。

もうちょっとさるの解釈を説明すると、
SCROLLINFOのnMin/nMaxは、nPosの取り得る範囲を示しています。
nPosはスライダーの位置を示します。
nPageは、nMin~nMaxの何個分を1ページと扱うかを示すもので、1ページとして見せるサイズです。
SCROLLINFOは、あくまでもスクロールバーの見せ方を指定するものであって、nMin、nMax、nPage、nPosの値に単位の概念はないと思ってください。

なので、実際のスクロールバーの稼動範囲の大きさがH(pixel)だとすれば、スライダーの実際の大きさHsはおそらく
 Hs=H/((nMax-nMin+1)/nPage) だと予想します。
なので、スクロールバーのサイズを変えれば、スライダーのサイズは変わる。
バー全体に対する大きさの比率は変わらないと思ってます。(試してないので、予想です。)

20190908_1.jpg

前にも説明しましたが、実際のウインドウの内容のスクロールは別のAPIでpixel単位で制御しなくちゃならないので、
単位なしのSCROLLINFOと、同時に実際のpixel単位の実際の表示域で2系統の数値が出てくることになります。
それはちょっと混乱の元だと思ったので、SCROLLINFOにはどうせ単位の概念がないのだから、pixel単位の数値で指定することにしました。

それでは、処理サンプルです。

◆ウィンドウプロシジャ内の処理
//----------------------------------------------
case WM_INITDIALOG:
{


//ResetScrollInfo(・・・); //※1

return TRUE;
}



//****** スクロール関連
case WM_SIZE:
//lParam:上位がウィンドウの高さ
SetMyScrollInfo(hDlg, (INT) HIWORD(lParam), &g_ScEdit);
return TRUE;
case WM_VSCROLL:
//wParam:下位がスクロールタイプ、上位がスクロール位置
MoveMyVScroll(hDlg, LOWORD(wParam), HIWORD(wParam), &g_ScEdit);
return TRUE;
case WM_MOUSEWHEEL:
if ((SHORT) LOWORD(wParam) == MK_CONTROL) {
//**** ズーム処理
}
else {
//**** スクロール処理
if ((SHORT) HIWORD(wParam) > 0)
PostMessage(hDlg, WM_VSCROLL, SB_PAGEUP, 0);
else
PostMessage(hDlg, WM_VSCROLL, SB_PAGEDOWN, 0);
}
break;



//----------------------------------------------


※1:このブログの「VS2017-はじめの1/10歩(12):タブレット画面の回転への対応」で、RelocationControlles()という関数経由でコールする例を載せてあります。
それをご参照ください。

・ウィンドウのサイズが変更された場合(WM_SIZE発生)のSCROLLINFOの設定しなおしは、SetMyScrollInfo()関数
・スクロールバー操作等で発生するイベント(WM_VSCROLL)は、MoveMyVScroll()関数
・マウスホイール操作(WM_MOUSEWHEEL)イベントでは、WM_VSCROLLイベントを自分自身に発行するようにしています。

・g_ScEditというMYSCROLLINF型のテーブルを外部変数として確保しています。
 複数のダイアログを同時制御するような場合は、ダイアログ毎にMYSCROLLINF型のテーブルを準備する必要があります。
 (これも、本当はクラス化すれば、もっとスッキリするんですけど・・・。先送りです。)

WM_MOUSEWHEELイベントは、VS6の普通の状態ではサポートされていなかったようで、
以下の定義を共通ヘッダ等に入れる必要がありました。(昔から使ってたので、たぶん。)

//----------------------------------------------
//******************************************************************************
// マウスホイールサポート用(V6.0)
#ifndef _INC_WHEELMOUSE_H_
#define _INC_WHEELMOUSE_H_
#ifndef WM_MOUSEWHEEL
#include "zmouse.h"
#endif
#endif
//----------------------------------------------


実際の処理関数の中身は・・・

続きを読む



VS2017-はじめの1/10歩(14):ボタンに画像を貼付ける

   プログラミング [2019/09/07]
VS2017を使うんだけど慣れてないからVS6でまずは作ってました。
Win32アプリとして実装した内容の備忘録です。

これまでも含めた内容は、

→ナレーション再生と音声認識を使う
  →そのため音声データの作り方(多言語対応)
  →ナレーション(.WAV)再生のサンプルコード
  →音声認識のサンプルコード
→VS6で作ったC/C++コードをVS2017に持って行って.cppレベルで共通にする方法
→ダイアログベースのプログラム
  →背景に画像(.BMP)を使う
  →ラベルを透かす
  →ボタンの色を変える
  →Windowsタブレット上でピンチイン/アウト:拡大縮小
  →タブレット画面の回転への対応
  →カスタムなチェックボックス作成
  →ボタンに画像を貼付ける←今回

となってます。

今回、要はアイコンをボタンにする話です。
至ってありふれた内容で、申し訳ないです。
さるの個人的備忘録が主目的なので、勘弁してやってください。m(__)m


ベースは、ボタンコントロールを使います。
まずは、ボタンを作成する際のスタイルに「オーナー描画」=BS_OWNERDRAW を指定します。
リソースエディタ上では、見た目フツーのキャプション入りのボタンコントロールです。

◆リソースの準備
まずは、アイコンを用意します。
VS2017のリソースエディタは、使えるんだか使えないだか・・・。
できなくて、追加で何かをインストールしたような気がします。(曖昧ですいません。)
現状のさるの環境では、リソースビューから追加/編集できるようになってました。
外部エディタ(ペイント)を呼び出すこともできました。

一方、VS6だとビットマップの編集が16色までしかできなくて、綺麗なアイコンを作るのは至難の業。
なので、外部のエディタ(GIMP)を使って256色のビットマップを作りました。

見た目四角じゃないボタンを作ろうとすると、最低2つ。
何かの機能のON/OFF状態を示すには、さらに1つのビットマップが必要です。

例えば、或る機能が有効(ON)なときと無効(OFF)のときの2種類の表示(ビットマップ)があって、
さらにそのときのアイコン(画像)を四角以外に見せるための・・・なんていうのかなー
謂わば「型」のビットマップを準備します。下右側のような感じ。
20190907_2.jpg  20190907_3.jpg  20190907_1.jpg

まずは、「型」(上の右側)で透ける(真白)の部分を決めて、ON/OFF用(左と真ん中)で「描く」部分(真黒以外)を指定してます。(たぶん)
それを、重ねて描くんです。

ビットマップを準備したら、リソースエディタ上でビットマップを定義します。
(詳細な操作方法は省略しちゃいます。すいません。)
.rc上だと以下のような行が追加されている状態になります。
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//

IDB_BMPSNDOFF BITMAP MOVEABLE PURE "mic256off.bmp"
IDB_BMPSNDON BITMAP MOVEABLE PURE "mic256on.bmp"
IDB_BMPCIRCALPH BITMAP MOVEABLE PURE "circ_alph256.bmp"


※綺麗に見せるためには元のビットマップが結構重要なんだけど、
 初めての方は試行錯誤してみてください。

◆ウィンドウプロシジャ内の処理
//----------------------------------------------
case WM_INITDIALOG:
{


//アイコンボタンのプロシジャの変更
SwapBitmapButtonProc(hDlg, IDC_BTSOUND);

return TRUE;
}



//******* オーナードローボタン描画
case WM_DRAWITEM:
{
INT cid = LOWORD(wParam);
LPDRAWITEMSTRUCT podraw = (LPDRAWITEMSTRUCT) lParam;
switch (cid) {


//アイコンボタン
case IDC_BTSOUND: //g_fHearing
DrawBmpToButton(GetDlgItem(hDlg, IDC_BTSOUND), podraw->hDC, IDB_BMPSNDON, g_fHearing);
break;


}
return TRUE;
} //end WM_DRAWITEM



//****** ボタンクリック等
case WM_COMMAND:
switch (LOWORD(wParam)) {



//**** 音声入力ON/OFF
case IDC_BTSOUND:
if (!g_fHearing) {
g_fHearing = TRUE;


}
else {
g_fHearing = FALSE;


}
InvalidateRect(GetDlgItem(hDlg, LOWORD(wParam)), NULL, FALSE);
return TRUE;



} //end switch WM_COMMAND-lParam
break;
//----------------------------------------------



ざっくり説明すると、
ダイアログの初期化の時点で、アイコンボタンのウィンドウプロシジャを別のプロシジャに置き換えます。
置き換えられたプロシジャでは、WM_ERASEBKGND(背景描画)のときだけ「何もしない」処理に置き換えて、
その他のメッセージは、元の置換え前のプロシジャに処理させます。
コントロールの再描画が必要なときは、WM_DRAWITEMメッセージが来るので、そこで実際にビットマップを描画します。
「型」とON/OFF用のどっちか。
g_fHearingは、機能のON/OFFを示すグローバル変数です。(本来、クラス化するべきだとは思います。はい。)

描画等処理の中身は・・・

続きを読む



VS2017-はじめの1/10歩(13):カスタムなチェックボックス作成

   プログラミング [2019/09/06]

VS2017を使うんだけど慣れてないからVS6でまずは作ってました。
タブレットで使うので、それっぽいGUIをちょっとだけ目指してます。

これまでの、この備忘録の内容は、
→ナレーション再生と音声認識を使う
  →そのため音声データの作り方(多言語対応)
  →ナレーション(.WAV)再生のサンプルコード
  →音声認識のサンプルコード
→VS6で作ったC/C++コードをVS2017に持って行って.cppレベルで共通にする方法
→ダイアログベースのプログラム
  →背景に画像(.BMP)を使う
  →ラベルを透かす
  →ボタンの色を変える
  →Windowsタブレット上でピンチイン/アウト:拡大縮小
  →タブレット画面の回転への対応
  →カスタムなチェックボックス作成←今回


前回、タブレット画面の回転動作に対応するためのコントロール類の拡縮の処理例を書きましたが、それでは、うまくいかないコントロールがありました。
ラジオボタンとチェックボックスです。(他にもあると思いますが、代表的なものという意味です。)

上記の2つは、ボタンコントロールの一種で、OwnerDrawができないものなんだそうです。
つまり、フォントやコントロールのサイズ、あるいはそれなりのサイズ指定の属性を持っていれば、前回の説明の類似で済むのですが、そうはいきませんでした。
※Win32 SDKの範囲内だけの話なのかもしれません。その辺をカスタマイズできるクラスとかがどっかにあるのかも。

ともかく、そうなると自分で描画するコントロールを作らないといけません。
そもそもがBUTTONコントロールの発展形みたいなものなので、ベースの動きはBUTTONクラスを利用して、足りない動き/描画の部分を個別に実装します。

幸い、ラジオボタンは利用してなかったので、サンプルはチェックボックスだけになります。

まずは、ボタンを作成する際のスタイルに「オーナー描画」=BS_OWNERDRAW を指定します。
リソースエディタ上では、見た目フツーのキャプション入りのボタンコントロールです。


◆ウィンドウプロシジャ内の処理
//----------------------------------------------
case WM_INITDIALOG:
{


//オーナードロー・ボタンのステート初期化
//切り替えは、WM_COMMANDで実施
g_fChkOpen = FALSE;
g_fChkPrint = FALSE;

return TRUE;
}



//******* オーナードローボタン描画
case WM_DRAWITEM:
{
INT cid = LOWORD(wParam);
LPDRAWITEMSTRUCT podraw = (LPDRAWITEMSTRUCT) lParam;
switch (cid) {


//チェックボックス風ボタン
//※※checkboxは文字サイズを大きくしても、ボックスの大きさが変わらない。
//かつ、BS_OWNERDRAWスタイルは、他のcheckbox、radiobuttonスタイルとは排他。
//よって、checkboxスタイルのままでオーナードローは不可。
//通常のbutton+オーナードローとし、ステートはフラグで保持する。
case IDC_CHOPEN: //g_fChkOpen
DrawCheckBoxCtrl(hDlg, podraw, g_fChkOpen);
break;
case IDC_CHPRINT: //g_fChkPrint
DrawCheckBoxCtrl(hDlg, podraw, g_fChkPrint);
break;


}
return TRUE;
} //end WM_DRAWITEM



//****** ボタンクリック等
case WM_COMMAND:
switch (LOWORD(wParam)) {



//**** チェック・ボックス風ボタン
case IDC_CHOPEN:
if (!g_fChkOpen) g_fChkOpen = TRUE;
else g_fChkOpen = FALSE;
InvalidateRect(GetDlgItem(hDlg, LOWORD(wParam)), NULL, FALSE);
return TRUE;
case IDC_CHPRINT:
if (!g_fChkPrint) g_fChkPrint = TRUE;
else g_fChkPrint = FALSE;
InvalidateRect(GetDlgItem(hDlg, LOWORD(wParam)), NULL, FALSE);
return TRUE;



} //end switch WM_COMMAND-lParam
break;
//----------------------------------------------


コアな描画処理は・・・

続きを読む



VS2017-はじめの1/10歩(12):タブレット画面の回転への対応

   プログラミング [2019/09/05]
だいぶ間が空いてしまいましたが、ポツポツながら再開します。

VS2017を使うんだけど慣れてないからVS6でまずは作ってました。
→ナレーション再生と音声認識を使う
  →そのため音声データの作り方(多言語対応)
  →ナレーション(.WAV)再生のサンプルコード
  →音声認識のサンプルコード
→VS6で作ったC/C++コードをVS2017に持って行って.cppレベルで共通にする方法
→ダイアログベースのプログラム
  →背景に画像(.BMP)を使う
  →ラベルを透かす
  →ボタンの色を変える
  →Windowsタブレット上でピンチイン/アウト:拡大縮小
  →タブレット画面の回転への対応←今回


前回、ピンチイン/アウトによるウィンドウ内容の拡大/縮小は、プログラム内に処理を入れるまでもなく、フリーのユティリティを追加インストールして間に合わすことにしました。

もう一つタブレットらしい機能として、タブレットの向きを重力方向に対して、縦横回転させると画面の内容もそれに合わせて回転する機能があります。

作成するアプリが、「縦横回転してもウィンドウを移動すりゃいい」くらいのサイズなら何も気にする必要はないい話。
でも、PCとは言ってもタブレットの画面サイズは小さい。老眼の出始めたさるくらいになると、タブレットの小さい文字は辛い。
なので、大きい文字にしたい。

そこで、考えたデザインの方針は、
・ダイアログは、普通のシステムデフォルトの文字サイズで作って、ダイアログ内のコントロール/文字の配置をデザインする。
 内容に可変部分がなければ、リソースエディタで作って済ますということ。
・表示内容の多い少ないはどうしても出てくるので、基本的にウィンドウ内の配置は内容に応じて縦に伸ばす。
・画面の方向が縦長/横長関わらず、横方向に合わせたフルサイズに拡大して、文字も拡大比率に合わせて大きくする。
・横フルサイズ表示、縦スクロール可能、ウィンドウの移動は不要とする。

結局、ピンチイン/アウト操作での拡縮は止めましたが、画面のサイズに応じての拡大縮小を実装することにしました。


まずは、基本的に画面配置の回転は誰がやってるのか?
→当然ですが、Windowsでした。
回転したときに、ウィンドウ(アプリ)側に何かイベントが来る?
→WM_DISPLAYCHANGEメッセージが来るらしい。

ということなので、ディスクトップサイズに合わせたアプリのウィンドウサイズ変更は、WM_INITDIALOGとWM_DISPLAYCHANGEのときにやればよい
ということになります。

※このあと、スクロール/スワイプで結構手間が掛かってますが、その詳細はまた別途説明するとして。

以下のようなコードでやりました。

◆ウィンドウプロシジャ内の処理
//----------------------------------------------
case WM_INITDIALOG:
{

//可変のコントロール作成、リスト/コンボの内容設定など

//スクリーンサイズに合わせて、各コントロールの位置/サイズ/フォントの変更
//※可変項目が全部整ってからやる。
RelocationControlles(hDlg, RELO_INIT,
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
&g_hFntEmpEdit, &g_ScEdit);

//その他、ウィンドウレイアウトに関係ない初期化

return TRUE;
}
case WM_DESTROY:

//拡大時フォントオブジェクトの廃棄
if (g_hFntEmpEdit != NULL) {
DeleteObject(g_hFntEmpEdit);
g_hFntEmpEdit = NULL;
}

break;



//******* 解像度変更(回転)時処理
case WM_DISPLAYCHANGE:
{
INT scrn_w = LOWORD(lParam);
INT scrn_h = HIWORD(lParam);
RelocationControlles(hDlg, RELO_REIN, scrn_w, scrn_h, &g_hFntEmpEdit, &g_ScEdit);
InvalidateRect(hDlg, NULL, FALSE);
break;
}
//----------------------------------------------


実効の処理は・・・

続きを読む



VS2017-はじめの1/10歩(11):Windowsタブレット上でピンチイン/アウト:拡大縮小

   プログラミング [2019/05/15]
なんか忙しいなー・・・・

実はタブレット向けのプログラムを作るにあたって、
出来て当たり前だと思っていたピンチイン/アウトで画面の内容が大きく表示されたり小さくなったりするアレ・・・
(ピンチイン/アウト:二本指で画面をタッチして指の間隔を広げたり/狭めたり画面上で指を滑らす動作。)

Windows10とかでも、普通にはアプリが対応してないとそんな動きはしないらしい。
え、OS側で勝手に制御してくれるんじゃねーの?

「ストアアプリ」対応?・・・ダウンロードして使えるようになるアプリ専用の開発環境(?)だとその機能を持たせることが容易?


実際、Windows10のタブレットを1年前の初売りで安く手に入れてたのでやってみた。

ホンマや。ほとんどのPC用アプリではそんなタッチへのアクセスには反応してくれない。
チャント拡大縮小するのは、ブラウザやフォトビューアくらいのもの?
テキストエディタとかで、字を大きくするくらいの対応をしている場合もあった。

「なーんだ、Windows10大したことねーな」 と一瞬思った。

でも、手持ちのスマフォを、改めて触ってみたら、
こっちも、全部のアプリが対応して拡大縮小するわけでもないのね。
勘違いしてた。どんな、スマフォアプリも、ピンチイン/アウトできるもんだと。

まあ、タブレットは画面が小さいけど、割と画質は高い(画角は広い)。
だから、普通のPC向けに作ったアプリをタブレットで見ると、かなり小さい字で表示される。

老眼間近の方々には、結構辛い。

というわけで、Windows10のピンチイン/アウトの機能はどうやって使えるのか調べてみた。



続きを読む



VS2017-はじめの1/10歩(10):ボタンの色を変える

   プログラミング [2019/03/11]

VS2017を使うんだけど慣れてないからVS6でまずは作ってます。
→ナレーション再生と音声認識を使う
  →そのため音声データの作り方(多言語対応)
  →ナレーション(.WAV)再生のサンプルコード
  →音声認識のサンプルコード
→VS6で作ったC/C++コードをVS2017に持って行って.cppレベルで共通にする方法
→ダイアログベースのプログラム
  →背景に画像(.BMP)を使う
  →ラベルを透かす
  →ボタンの色を変える←今回

と来てます。
これまでと違って、さらに必要性は低いかな。

個別に色んなボタンを配置するというよりは、
「このプログラムではこの色が【ボタン】です。」的なデザインを前提にしてます。

始めます。
ラベルのときのWM_CTLCOLORSTATICと同じようなWM_CTLCOLORBTNというWMメッセージが存在します。
でも、このときに色チェンジをできるのか?と思いきや・・できないみいです。
なぜだ?

ともかく、ボタンコントロールの場合は、オーナードローって属性にして、
「自分で描きます」って宣言しないといけない。

まずは、リソースエディタを使って、ダアイアログに乗っけたボタンのスタイルに「オーナー描画」とあるのでそれを設定してください。
指定すると、そのボタンを「描画する必要があるとき」に、ダイアログのウィンドウプロジジャにWM_DRAWITEMメッセージがデバイスコンテキストハンドルとともにやって来ます。

以下のような処理をウィンドウプロシジャ中に加えます。
//---------------------------------------------
//****** ボタンコントロールの背景色設定
//※以下ではできない。
//case WM_CTLCOLORBTN:
// return ChangeColor((HDC)wParam, RGB(255,255,255), RGB(255,64,64), &g_hBrsBtn);

//******* オーナードローボタン描画
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT podraw = (LPDRAWITEMSTRUCT) lParam;
DrawButtonCtrl(hDlg, podraw);
return TRUE;
} //end WM_DRAWITEM
//---------------------------------------------


で実際の描画の中身は、・・・






続きを読む



VS2017-はじめの1/10歩(9):ラベルを透かす

   プログラミング [2019/03/10]
ダイアログベースのプログラムを作る場合に「背景に画像を貼る」の続きの話になります。

画像を描いたその上に各種コントロールが表示されます。
画像を貼ってみて分かるのですが、
エディットやボタン等の入力とか機能を持ったコントロールはいいのですが、
「見出し」として付けてるラベル(スタティックコントロール)も矩形で背景が塗りつぶされていると、なんか格好悪い。

ドーンと目立たせたい場合とは別に、隣のコントロールの説明的にラベルを貼ってるだけなので、文字さえ見えれば、後ろは透けていいことがある。

で、透けさせる方法です。
他でもいくらでも解説してくれてるから、さるがいい加減な説明をする必要はないのですが、
前から言ってるように、さる自身のための備忘録ですから。

始めます。

まずは、
1)VSのリソースエディタで、ラベルを貼る際に透けさせたいラベルのプロパティ(拡張スタイル)に「透明」を選択します。
これだけでもスケスケになるんだったかな?・・・ならなかった気がします。
2)特に固定文字列を表示するだけで、他の機能を持たせるつもりがない場合、透けさせるラベルのIDはデフォルトのIDC_STATICのまま共通としておきます。

3)透けさせるのには処理コードが必要です。
ダイアログのウィンドウプロシジャ内に以下のようなWM_CTLCOLORSTATICメッセージを処理するコードを追加します。
//---------------------------------------------
//****** スタティックコントロールの背景色設定
case WM_CTLCOLORSTATIC:
if (GetDlgCtrlID((HWND) lParam) == IDC_STATIC) {
return BeTransparent((HDC)wParam);
}
else if (GetDlgCtrlID((HWND) lParam) == IDC_STTITLE) {
return ChangeColor((HDC)wParam, RGB(0,0,0), RGB(128,255,255), &g_hBrsTitle);
}
break;
//---------------------------------------------

勢いが余って透けさせないラベルの処理もはいっちゃったので、後でそっちの説明もします。
ともかくスケスケにしたいラベルのIDはIDC_STATICなのでそのIDでWM_CTLCOLORSTATICが来たら、
BeTransparentという関数を呼びます。
こんな処理です。
//---------------------------------------------
//name :BeTransparent
//function :スタテックコントロールを透過にする。
// リソースエディタでIDC_STATICのコントロールの「透過」設定が必要。
//parameter :hDc -対象コントロールのデバイスコンテキストハンドル
//global :なし
//return :ブラシハンドル(NULL_BRUSH)

LRESULT BeTransparent(
HDC hDc)
{
HBRUSH hbr;

SetBkMode(hDc, TRANSPARENT);
hbr = (HBRUSH) GetStockObject(NULL_BRUSH);
return (LRESULT) hbr;
}
//---------------------------------------------

文字背景色を透明にして、背景塗りつぶし用のブラシ(透明)をリターンします。
ブラシのハンドルは、WM_CTLCOLORSTATICの処理結果のリターン値になります。

これだけです。

では、背景色/文字色を変更する方も・・・

続きを読む



VS2017-はじめの1/10歩(8):ダイアログの背景に画像を使う

   プログラミング [2019/03/09]
タイトルには含まれませんが、目指しているのは
「タブレット的な、向きな、らしいアプリを作ってみる」です。
では、らしいアプリ」ってなんだよ・・・んー・・・分かんないね。

今回は、比較的にありがちな、「ダイアログの背景に画像を貼る」です。
お前に言われなくてもな話。

早速ですが、
外部変数を3つほど。
//---------------------------------------------
HBITMAP g_hBgBmp = NULL; //背景画像のBitmapハンドル
HBITMAP g_hPrvBmp = NULL; //元の背景画像のBitmapハンドル
HDC g_hDcBase = NULL; //画像描画用コピー元hDC
//---------------------------------------------


ダイアログのウィンドウプロジシャのWM_INITDIALOGとかで
//---------------------------------------------
//背景ビットマップ描画準備(全ダイアログ共通)
g_hBgBmp = (HBITMAP) LoadImage(g_hInst, "背景.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (g_hBgBmp) {
g_hDcBase = CreateCompatibleDC(hdc);
g_hPrvBmp = (HBITMAP) SelectObject(g_hDcBase, g_hBgBmp);
}
//---------------------------------------------

カレントディレクトリ上に「背景.bmp」という名前のWindowsビットマップ形式のファイルがあるものとしてます。

先に後始末のためにWM_DESTROYとかで
//---------------------------------------------
if (g_hPrvBmp != NULL) SelectObject(g_hDcBase, g_hPrvBmp);
if (g_hBgBmp != NULL) DeleteObject(g_hBgBmp);
//---------------------------------------------

まあ、プログラムを終わらせるだけならいらないかもしれないけど、「躾」として入れます。

で、ダイアログではあまりしないWM_PAINTの処理を入れます。
//---------------------------------------------
//******* 描画処理
case WM_PAINT:
DrawBackGround(hDlg, NULL);
break;
//---------------------------------------------

関数化してあるのは、ダイアログを複数使うようなプログラムで、共通の背景画像を使うことを想定してます。

関数の中身は、・・・


続きを読む



VS2017-はじめの1/10歩(7):そろそろVS6→VS2017

   プログラミング [2019/03/03]
使い慣れてないVS2017は何かとストレスになるので、
VS6である程度つくってVS2017に持ってく話なのですが、「持ってく」ところに話が辿りついてませんね。


例えば、VS6で”Hello World!”ってメインウィンドウに出すウィンドウプログラムを作ったとします。
(・・・手順は説明しませんよ。余りにも基本的なんで。)

VS6作成のプロジェクトをフォルダ毎コピーして、「元の名前vs2017」と名前を付けたとします。
フォルダ内の.dswファイルをVS2017で「開き」ます。
 →何か変換するから「元には戻せないよ」的なメッセージが表示されます。OKを応答します。
VS2017だと(さる的には違和感のある)右側にクラス/リソース/ソースファイルリスト的なものが表示されます。
 いきなりビルドします。メニューの[ビルド]-[(Xxxxプロジェクト)のビルド]ですね。注)
HelloWorldならたぶん何事もなくビルドが通るハズ。
→動かせます。

これだけです。ここしばらく書いていたメインテーマ「VS2017-はじめの1/10歩」は終了ー
ってなっちゃいますね。

注)VS2017のビルド対象・・・は、x86です。
(64bit環境しかインストールしてないとできないと思う。
 ・・・とはいうものの32/64bit環境のインストールで選べるんだっけ?)


でもね、それでもVS2017で、あれこれ付けたしでプログラムに機能追加して行こうと思うと、
使い方わかんないから大変なのよ。
アイコン1個追加しようと思うだけで、調べまくらないとできない!
(一回、調べて納得したけど忘れた。何か追加インストールしないといけなかったような・・・
先にpython環境として使い始めて、必要コンポーネント?(numpy、cmake、openCV、dlib、・・・・)のインストールとかで触りまくったのであまりよく覚えてない。

ならば、ということで

①VS6で編集/デバッグして、②VS2017でリビルドして、
③うまくいかない部分を直す

をやってます。
VS2017使い方の解説を期待して読み始めた方には申し訳ないですが、そっちは他のサイトをご覧ください。

さあ、またまた前置きが長いですが、
今回は、標準関数とかの話にします。


続きを読む



VS2017-はじめの1/10歩(6):音声辞書の調整

   プログラミング [2019/02/27]
前回のコードでは、認識(聞き取り)した後の処理について説明してませんでした。
少し補足します。

WM_RECOEVENTメッセージは、「話した内容をテキストに落としましたよ」というときに発信されて、
その内容はSPEI_RECOGNITIONというイベントIDになります。
その受け取りの処理を行っているのが、RecogEvent()という関数内になります。
関数内では、グローバル変数にマルチバイトストリングとして取り出してます。
さらにその後、ウィンドウプロシジャ内からChecKeyWord()で、期待しているキーワードが含まれているかをチェックすることを想定しています。
まあ、そこら辺りは「ご自由に」ってことで、省略してます。

例えば、
//----------------------------------------------------------

pos = (PTCHAR) _mbsstr((const unsigned char *) g_szRecogText, (const unsigned char *) pKeyWord);
if (pos != NULL) {
//###debug->
//wsprintf(g_MsgBuf, "キーワード発見!!=%s", pTxt);
//MessageBox(NULL, g_MsgBuf, "音声認識", MB_ICONERROR|MB_OK);
//###debug<-
return TRUE;
}

//----------------------------------------------------------

とかでいいかなと思います。


では、Windowsに含まれる音声認識機能で、少しでもうまい具合に言ったことを文字にしてくれるようにする設定です。

●聞き取りたいキーワードを音声辞書に登録
 例えば、こんにちは/ハロー/ニイハオ/ナニョハセヨを日本語音声認識で認識させたい
 場合、以下の手順で音声辞書に登録する。
 
◆Windows7の場合
[コントロールパネル]を開いて、右上検索欄に「音声辞書」と入力して検索し、さらに表示される「Windowsヘルプサポートで"音声辞書"を検索します」をクリック

「Windowsヘルプとサポート」ダイアログで「1.音声辞書で単語を追加または編集する」をクリック

説明文が表示されるので「音声辞書に単語を追加するには」をクリックし、「1.クリックして[Windows音声認識]を開きます。」をさらにクリック

「音声認識」のウィンドウが画面上部中央辺りに出るので、「オフ」と表示されている場合は、マイクのアイコンボタンをクリック

“音声辞書を開く”とマイクに向かって発話する。

「音声辞書」ダイアログが開くので、「新しい単語を追加する」をクリック。「音声認識」のマイクアイコンをクリックし、一旦認識をオフする。

「単語または表現」に登録したいキーワード(例えば“ハロー”)を入力し、[次へ]をクリック

「完了時に発音を録音する」をチェックして、[完了]ボタンをクリック

「音声認識」のマイクアイコンをクリックし、[音声辞書]ダイアログ上の[録音]ボタンをクリックした後、キーワードを発話する。しばらくすると録音が完了するので、[再生]ボタンで再生してみて、大丈夫なら[完了]ボタンをクリックする。

上記⑥から⑨を繰り返すことで、複数のキーワードを登録できる。

◆Windows10の場合
[コントロールパネル]を開いて、右上検索欄に「音声認識」と入力して検索。検索の結果、「音声認識」(複数あるので、縞の入ったマイクアイコン側をクリックし、「音声認識」ダイアログ内の「音声認識の開始」をクリック、あるいは、検索の結果に「音声認識の開始」がある場合は、それをクリック。

「音声認識」のウィンドウが画面上部中央辺りに出るので、「オフ」と表示されている場合は、マイクのアイコンボタンをクリック

“音声辞書を開く”とマイクに向かって発話する。

「音声辞書」ダイアログが開くので、「新しい単語を追加する」をクリック。「音声認識」のマイクアイコンをクリックし、一旦認識をオフする。

Windows7の⑦~⑧に同じ。

実際、動かしてみれば分かることですが、

続きを読む



VS2017-はじめの1/10歩(5):音声認識をプログラム制御に使う

   プログラミング [2019/02/25]
しゃべった内容が即文章データになる?

Windows10とかだと、何かの拍子に「何かご質問は?」的な催促をしてくることありますよね。
調子にのって、「Xxxxってどうやるの?」とか聞いてやると、
「何ですか?」とか二三度聞き返した挙句に頓珍漢なことを答えてくれちゃったりする。

#スマフォのサービスだとそんなことないけど。

オンラインのサービスの方が、そりゃ上等な認識をしてくれるのは当然かとは思うけど、
こんなに酷いんじゃねー。
初回の「御使用感」がさんざんなので、その後は間違って押しちゃって出てきても、
「頼んでねーよ」で直ぐに消えてもらいます。

そんな、ネットアクセスが不要な音声認識を何かに使えないか
なーと考えて、短いワードを数種類くらいで、それを検知したら、プログラムの動作制御に使う。
キーボード/マウス・タッチの代わりくらいに使えないかってことです。

やってみることにしました。
ついでに、外人がしゃべったらそれなりに。

●音声認識のセットアップ
 通常、Windowsに標準で組み込まれている。
 デフォルトのロケールに合わせた言語(認識)が入っている。

◆確認の仕方
 [コントロールパネル]-[音声認識]-左側メニュー「高度な音声オプション」をクリック
 「音声認識のプロパティ」ダイアログの「言語」欄に現在の認識エンジンが表示される。
 プルダウンを開くと選択できる認識エンジンが表示される。

◆追加する場合
 Windowsのエディションにより、簡単に追加できる場合と、結構な手順があるエディションがある。
 後者の場合は、問題があっても非標準扱いなので、ケアされない。
 ちなみに、HomeやProfessionalは後者。インストール方法などは、以下を参照願う。
 https://denspe.blog.fc2.com/blog-entry-168.html

※他言語の音声認識を同時に使用することは、ちょっと難しそう。
 [認識言語の切り替え→認識→コマンド解釈→プログラム制御]となる。
 最初の「どの言語に切替えるのか」を、結局何か発話/操作させて行うことにならざるをえない。
 よって、ここは現状の言語(認識)設定で、キーワードを認識させるのが安易な方法だろう。
 [カレントの認識→キーワード解釈→プログラム制御]

続きを読む



VS2017-はじめの1/10歩(4):音声データを再生する

   プログラミング [2019/02/24]
やっとこさ「プログラミング」らしい内容になるのかな。

まずは、機械に喋らせた発話で.WAVファイルを作ります。
前回(3)で説明した「◆PowerPoint読み上げ&録音」⑦の手順(audacity)で、
「Export」形式を「WAV(Microsoft) 16bit PCM 符号あり」を指定してファイルに書き込みます。
audacityはでの、音自体の編集は、説明してくれてるところが沢山あるので、必要ならそちらを参考にされてください。


.WAVを再生するなんて、しかもVS6とか使うんじゃもはや古典ですな。
でも、構わず書きます。
さる的にも随分昔にコーディングしたので、
どこのサイトを参考(半分コピペ?)して作ったものなのかは、既に記憶にありません。
ちょっと、参考させていただいたところには申し訳ないです。

使用するのは、WaveOutXxxx APIです。
使うためには以下のヘッダが必要だそうです。

//----------------------------------------------------------
//****<<音声(.wav)再生API(waveOutXxxx)に必要
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
//----------------------------------------------------------


で、参考にしたサンプルが、イッキに.WAVデータをメモリにロードして使っていたので、そこはそのままにしています。
1)ロードの処理と、2)解放、3)ロードされたデータを再生させて、4)再生が終了したら終了処理をする
をそれぞれ関数化。 サンプルもそうなってたかなー。

各関数のパラメタの数を減らすためにテーブルを定義しました。
//----------------------------------------------------------
//****<<Waveファイル再生制御用のテーブル定義
typedef struct _waveinfo {
PBYTE WaveBuff; //WAVEファイルデータバッファ
HWAVEOUT hWaveOut; //WAVEハンドル
WAVEFORMATEX Wfe; //WAVEフォーマットデータ
WAVEHDR Whdr; //WAVEヘッダ
} WAVEINFO, *PWAVEINFO;
//----------------------------------------------------------


では、実際の処理を載せます。








続きを読む



VS2017-はじめの1/10歩(3):続・多言語音声データを作る

   プログラミング [2019/02/21]
前のPCへのインストールと設定で、パワポが複数言語を読みげできるようになってるはず。
前回の続きです。

●多言語文章を作ってパワポに読み上げさせる
パワポのデータを作成する。説明は特定の言語(自国語)で。
作成した文章をinfoseek翻訳で他言語に翻訳する。
別名でセーブしたパワポを開き、自言語の文章を翻訳結果で置き換える。
※日本語→中国語(簡体字)、韓国語(ハングル)に置き換えた場合、数字/句読点やローマ字表記が残ってたりする。それをそのままコピペすると読み上げできない。
 <中国語(簡体字)>:
 日付などにローマ数字が入るとNG。句読点は、大丈夫。
 簡体字の数字コードを無理やり作る方法としては。
 例えば、「8」がほしい場合、infoseek翻訳で、「八代亜紀」を翻訳すると
 「八」(簡体字)が作れる。

 <韓国語(ハングル)>:
 本来、「、」→「,」、「。」→「.」らしいが、読み上げではNG。
 仮対処として、
 「,」→半角スペース(元々入っていた、「,」の後にスペースが入っているが取る)
 「.」→半角スペース(複数)

読み上げさせたい文章を選択(クリック&[Shift]+カーソル移動)する。
読み上げ可能かどうかは、範囲選択していけば「読み上げ」アイコンボタンの活性/非活性が変化するので分かる。

範囲選択して読み上げさせる。


●読み上げをパワポのナレーションにする
お分かりいただけたかと思うが、スライドショー時に自動で読み上げを行う仕掛けは、パワポにはないっぽい。
「なんだよ~」
ちょっと、世の中にないかググってみた。
※PPT2Voice Neo:パワポのノートを読み上げるアドイン(個人で使うにはお値段のハードルが。)
※「PowerTalk - automatic speech for PowerPoint presentations」:パワーポイント上のテキストを読み上げるフリーソフト。
 同時多言語読み上げが可能かは不明。(Windowsの音声合成設定を利用するらしいので、たぶんできない。)
※スクリーンリーダー:未調査。これが、よさそう。

上記のように新たなソフトを導入しないとスライドショーに同期してのナレーション再生はできなさそうなので、音声データを作成してページに貼り付ける方法を使う。

では、PCで再生中の音をサウンドレコーダーで録音・・・・
できねー。
前は、たしかできてたような・・・




続きを読む



VS2017-はじめの1/10歩(2):多言語音声データを作る

   プログラミング [2019/02/20]
音声とは言うものの、「声」の方です。
主題のVS2017からいきなり離れます。

最近は音声合成/音声認識とかやたら聞く。
お金を払って使えるものもあるらしいけど、GoogleとかSiriとか普通にしゃべるし、
こっちが話した文言なんかかなりの正確さで文字にしてくれる。
Windows10にしたら、音声の案内も機能としてある。(ほぼ使ったことないけどね。)

以前、ナレーションをプロに頼んで録音/データ化してもらったことがあったが、
さもない内容なのに費用は結構掛かった。
で結局、「気に入らない声」だというお客の意見でその「声」はボツになった。

今は、さらに外人向けに数ヶ国語の「声」が必要な時代。
日本語→翻訳→ナレーターに読み上げさせて録音→組込み となるわけだが、
却下されるかもしれない「声」にお金を掛けてらんない。
かといって、訛りまくりの自分の声の録音では、さすがにデモにもならない。
英語他も絶対だめだしね。

簡単に多言語のナレーションを作る術(スベ)はないか調べてみた。

パソコンに喋らせて、それを録音することを考えた。
他国の言語は、カタコト、もしくはちょとくらい変でも、ネイティブでもなければ気付くまい。
それに、「機械がしゃべるんだからこんなもんですよ。あくまでもデモですから。」という言い訳が利きそうだ。

つまり、なんちゃって多言語音声合成
これだけでも、数回になりそうです。

MS社PowerPointの機能に、書いた内容(文章)を「読み上げ」る機能があるらしい。
それを使っちゃえば、ナレーター雇って、録音スタジオ借りて・・・なんてやらなくていい。
PCの音声ならきっと元はプロの方のお声/発音がベースだろうし、PC上で再生することに何の縛りもないはず。
(「声」って、その声の主のなんか権利的なものがあって、
当初目的以外の用途で使っちゃならん!とかいうのがあると聞いたことがある。
なので面倒に巻き込まれないことが保障されるPCの音声合成は、お手軽です。)

さあ、やっと本題です。
おおまかな手順としては以下になります。

1)PowerPointにナレーションの元の文章を日本語で書き込みます。
2)その文章をコピペして、Web上の翻訳サービス(例えば、Infoseekマルチ翻訳)で
  よくある 英/中/韓に翻訳します。
3)その内容をコピペして、別のPowerPointファイルか、別ページにコピペします。
4)PowerPointに読み上げさせて、それを録音し.WAVデータを作成します。

そうすれば、日本語も合わせて、4ヶ国語の同じようなことを説明しているナレーションデータが出来上がる・・・はず。

1)と4)についての詳細を以降(続きを読む)で説明します。

続きを読む



カレンダー
10 | 2019/11 | 12
- - - - - 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
プロフィール

さるもすなる

Author:さるもすなる
さるです。別HPサイト「さるもすなる」から侵食してきました。 山菜/きのこ、それとタイトルにしたPPバンド籠のことをメインに徒然に・・・・暇を持て余したさるの手仕事:男手芸のブログってことで。

最新記事
最新コメント
月別アーカイブ
カテゴリ
天気予報

-天気予報コム- -FC2-








本家のHPのトップ
山菜や茸の話です
PPバンドの籠作品と作り方です
投稿をお待ちしております



ブログランキング・にほんブログ村へ にほんブログ村 ハンドメイドブログへ



マニュアルのお申し込み



検索フォーム
リンク
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QR