リンクフリーを近日中にとりやめる予定です

すでにリンクを貼っていただいている方、ご一報頂きたくお願い申し上げます。


ごく少数ですが、リンクをお断りする場合があります



ブログ内 風景光景カテゴリー

続編記事などをご希望の方は こちらへどうぞ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[未掲載分] 車輪の再発明 (5)

元来、好ましい意味で用いられない「車輪の再発明」。



筆者は、そのような行為を肯定的に捉えている。
なぜならば、新しい技術や文化が芽生えるきっかけは、一見無駄と思われることへの挑戦である・・・


お知らせ
活動休止にともない、この記事を事前に予約投稿してあります。
トップ記事の固定を目的としています


この題目は2012年暮れ頃に掲載しようと下書きし、諸事情により掲載却下とした分です。
前話、車輪の再発明 (4)にひきつづき、利用環境を OS はWindows , CPU は Intel 製、いわゆるウィンテル機を前提に綴ります。

前話までで、アプリの骨格を作る話題に触れた。今回は肉付け、アプリを作る過程では初歩的なことを綴ってゆこう。
Intel 製 CPUを搭載したPC、OS は Windows 7 、Visual Studio を用いる 、C/C++ 言語、など諸条件は以前と同じ。

この題目のきっかけとなったブロガーさんは、学業の合間をみてプログラミングを身につけたい様子。
全てのコードをここに載せれば解決しそうな話だが・・・理解いただけるとも思えない。

きっかけとなったブロガーさんより
「○○の書いたコードを見てみたい」との連絡がありました。
筆者は、
「他人様にコードを書いてもらうと高くつきますよ~」とお茶を濁しておいた。
その返答では、「○○はアプリが組めない」等の疑惑をもたれるてもいたしかたない。

コードを書いてほしいとリクエストされた内容、筆者にとっては数時間で書けそう。アプリをひとつ作るのに比べればごく一部。家を一軒建てることに例えれば、玄関だけ、キッチンだけ作るようなもの。って、実際何かを作るとなると、それで終わりではない。全体が仕上がってこそ意味がある。

返答の真意としては、「自分で課題をこなさないと力が付かない」の旨であったが、想いが通じたが不明。
たしかに、時代を問わず代行作業を引き受ける者が介在する。実生活の場では代行依頼もアリだ。しかし、学び・向上を目的とするならば如何なものか・・・

実生活の場で「○○はアプリが組めない」などと疑われようが、挑発的な言動には無視・放置。
このブログにおいて、2013年2月21日分の記事をはじめ、2012年8月24日2012年8月22日2012年6月19日2012年6月29日などの記事中、筆者が作ったアプリの画像が載っているハズ。
鋭いヒトが見れば、「筆者は入門書の練習課題などに四苦八苦しているレベルでない」ことはお察しいただけるだろう・・・

前話、車輪の再発明 (4)まででウィンドウを作成、表示、実行することを触れた。若干手を加えて、速度の違いを目で見て確認できるように変えてゆこう。

このお題の根底にあるのは
「~~することにより速度が向上する???」

速い遅いを把握するため、「何かの合図をしたら速度の測定を開始する」ように加工する。
ウィンドウ、フォーム上にボタンを配置、そのボタンをクリックすることで開始の合図とする仕組みが手っ取り早い。

既に前回までの流れでウィンドウ、メインフォームが表示されるようになっている。
今後、おおまかな流れとしては
(1) ボタンを作成
(2) 下記(3) を呼び出す準備
(3) 速度を測る部分を作成

の3点。

(0) その前に、SSE2 命令を使えるように修正する
SSE2 を使った場合とそうでない場合を比較する流れで話を進めてきた。

Visual Studio を使っている場合はソリューションエクスプローラ



ツリービューの中、ヘッダーファイル「stdafx.h」を開く。


※ stdafx.cpp と間違わないように注意

ヘッダーファイル「stdafx.h」の終盤、
// TODO: プログラムに必要な追加ヘッダーを ~~
の後に
#include <mmsystem.h>

#pragma comment(lib, "winmm.lib")
#include <emmintrin.h>

を追加して保存。

修正したファイルを保存するには、キーボードの[Ctrl]を押しながら[S]を押す。
複数のファイルを修正した場合はキーボードの[Ctrl]と[Shift]を押しながら[S]を押せば一括保存となる。
不慣れな段階のヒトは最終行が改行で終わっていることを確認してから保存する習慣を・・・


キーボードを使わなくとも、



開いているタブを右クリックし、表示されたメニューより「~~ の保存(S)」をクリックして保存することも可能。

追加した部分を簡単に説明すると、
mmsystem.h と winmm.lib は時間を取得するのに必要。本来は音声や動画データを扱うためのヘッダーとライブラリファイル。今回は時刻・時間を取得する目的でインクルードする。

emmintrin.h は SSE2 命令を使うのに必要なヘッダーファイル。SSE3 , SSE4 などを使いたいならば tmmintrin.h 、pmmintrin.h 、smmintrin.h などをインクルードすることになる。
Visual Studio ならば あれこれインクルードするのではなく、intrin.h ひとつをインクルードすれば済む。
ただし、Visual Studio 2005 に関しては intrin.h に重大な問題 (error C2733)が2行含まれているので注意が必要。
emmintrin.h が使えるのは Visual Studio .NET 2003 くらいから。
ちなみに、Visual Studio 6.0 でも Processor Pack を導入することでSSE2 命令の利用が可能になる。VC6 なら、Visual C++ ToolKit 2003 も使える。

(1-1) 開始の合図を決める

作業としては「Resource.h」という名前のヘッダーファイルに2つ修正を加える。
ひとつめの修正、実行開始のメッセージ、数値を決めます。



修正箇所が少ない段階ならば、メモ帳を使って「Resource.h」に修正を加えるのも良いだろう・・・

Visual Studio を使っている場合は左ペイン、ソリューションエクスプローラのツリービューの中、
ヘッダーファイル「Resource.h」を開く。

Resource.h ファイルを開くと #define ID~~ が並んでいる。



これらは「#define ディレクティブ」や「プリプロセッサディレクティブ」と呼ばれる。
マクロを定義したり、特定の文字列の置き換えとして用いたり、コンパイル条件を指定する。
このファイルにある #define ID~~は、アプリの中でやりとりされるメッセージの数値が定義されている。

例えば、アプリが終了するときには「IDM_EXIT」と空白、それに対応する数値として「105」が割り当てられています。
「IDM_EXIT」の部分は「識別子」と呼ばれ、英数字やアンダースコア、空白を挟んで右の数値は、その識別子と対応する数値やマクロ。プログラムコード中に「IDM_EXIT」となっている箇所は、翻訳時に「105」に置き換えられる。

もちろん、識別子・定数に頼らず、プログラム中に直接数値を埋め込むことも可能です。が、後日修正の際などに手間が増えるだけです。何らか修正する際、直接埋め込んだ場合は全てを書き換えることになります。規模が大きくなるほど修正漏れも生じ易くなります。
それに比べ、定数を用いるならば「#define ~~ 」で定義した内容を1箇所変更すれば全体に反映されます。全ての箇所を修正するよりも楽なのは明白。

「#define」の後に続く識別子の文字長は32文字までが有効とされています。それより長い文字列はエラーになるか、コンパイラによっては無視されます。

「IDM_」「IDC_」や「IDR_」の意味や規則性に関しては MSDN ライブラリに詳細が載っているのでここでは割愛します。
知りたいヒトのために、以下に検索用リンクを貼っておきます。
テクニカルノート 20
テクニカルノート 20 (の原文)

今回は「IDM_」に実行の「RUN」を付け、実行開始の合図を「IDM_RUN」と決め、数値は直前までと衝突しない「106」とし、
「#define IDM_EXIT ~」の次の行に「#define IDM_RUN 106」を加えました。
この例では偶々「106」が空いていたのですが、新しく加えるID番号が既存と重複しないことが重要。

ふたつめの修正は「Resource.h」の終わりの数行に含まれている
「#define _APS_NEXT_~~_VALUE 数値」の部分をチェック。
この数値は、次回割り当てる番号。現状で割り当てられている数値の中で最も大きい数プラス1になっているのが望ましい。( すでに割り当ててある番号との重複を防ぐため )

「#define _APS_NEXT_COMMAND_VALUE ~」 や「#define _APS_NEXT_SYMED_VALUE ~」で割り当てられる数が適切か手動でチェックしたほうが良いでしょう。
今回は自ら追加したID「IDM_RUN」に「106」を割り当てた。よってプラス1の「107」より小さい数が割り当てられているならば要修正。

この辺もMSDN ライブラリに説明があるハズですので検索用リンクを貼っておきます。
テクニカル ノート 35

今回は簡単な例なので、リソーススクリプトやヘッダーファイルを直接書き換えました。ちなみに、筆者は普段ID などの定義は別の方法・・・

(1-2) アプリのフォームに開始ボタンを着ける

まず、ボタンを作成した際に返ってくるハンドル値を保存できるようにする。

ハンドルのことを大雑把に言ってしまえば、ウィンドウやボタン等のコントロールは異なる番号が割り当てられており、この番号のことを指す。言い換えれば、スポーツ選手の背番号みたいなもので、各々が独自の番号を持つことで識別が容易になります。
もし、この番号が無いとすれば
「複数のボタンのうち何番目がクリックされたかを知る」や
「複数のウィンドウが同時に開いていて、2番目のウィンドウを前に出す」などが難しくなります。

ハンドルを受け取る変数として
static HWND hBtn = NULL;

追加する。追加する場所は



LRESULT CALLBACK WndProc(HWND ~~
HDC hdc;
の後ろあたり。

HWND の前の「static」を付け忘れるとハンドルの値は正しく保持されない。
「= NULL」の意味としては初期化。頭に「static」を付けるのは、この変数が初めて使われる時だけ初期化される。
「static」を付けずに「= NULL」が付いている場合、関数が呼び出される毎に変数が初期化されてしまうのだ。つまり、作成したボタンのハンドルは保持されない。
今回ボタンはひとつで足りる。複数のボタンを配置したいときは配列変数を用いると良いだろう・・・

この段階で、アプリケーションウィザードによって作成されたコードは



となっているハズ。「case WM_COMMAND:」の前に
case WM_CREATE:
    hBtn = CreateWindow(_TEXT("BUTTON") , _TEXT("開始\0") ,
        WS_CHILD | WS_VISIBLE ,
         10 , 10 ,
        160 , 32 ,
        hWnd , (HMENU) IDM_RUN ,
        hInst , NULL);

        return 0;

を挿入する。
試しにビルド、実行。アプリを実行するには、キーボードの[F5]キーを押す。



アプリのフォーム上に開始ボタンが着いたハズ・・・

定数「WM_CREATE」はウィンドウが作成される際、つまり、アプリのフォームが表示される前に送信される。
「アプリが初めて表示される時に行いたい処理」を書いておく。
CreateWindow や CreateWindowEx 関数 が実行されるのと同時。

どこで実行されるのか知りたいヒトもいることだろう。今回の例では InitInstance 関数 の中で実行される。



アプリケーションウィザードで自動的に作成されるコード、InitInstance 関数の中に
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
という部分がある。この CreateWindow 関数を実行するとき、「WM_CREATE」以下が実行される。

ボタンの作成を失敗した時にエラーとみなしたいならば「return 0;」の前に
if (!hBtn) return -1;
を追加挿入すると良いだろう。
「return 0;」以外で終わる時は、CreateWindow 関数が正常に終了しなかったことを意味する。

ところで、「case WM_CREATE:」と対になるのは「case WM_DESTROY:」。
Create とDestroy 、つまり「作る」と「壊す」の関係。
ここでの Destroy は「壊す」というより、ウィンドウが閉じる際の「お片付け」「清掃」と考えると良い。

CreateWindow や CreateWindowEx といった関数はウィンドウ作成する。
ほかにも、ボタンやドロップダウンリストといったコントロールを作成する際にも用いられる。

_TEXT("BUTTON") などの _TEXT("") 、 _T("") といった部分は、文字列を Unicode で扱うか否かを楽にするオマジナイ。
初歩的な教本などでは Unicode を意識していないサンプルが載っている一方、現状は Unicode を意識したアプリ作成が主流。
例えば、文字列の型を宣言する際も char や wchar_t と直接書くのではなく、TCHAR 型で宣言する。
ビルドする時の状況に応じて Unicode 用のコードかそうでないコードを生成するか、コンパイラに任せてしまうのが楽。
なお、Windows での利用を想定したアプリでは、文字列の末端、ダブルクォーテーションの直前、半角英数で「¥0」を忘れないように。

(HMENU) IDM_RUN の部分で、「このボタンをクリックするとIDM_RUN というメッセージを送る」を意味する。
そのメッセージを受信するのは「case WM_COMMAND:」となる。後で述べる。

CreateWindow 関数と対になる DestroyWindow 関数もある。
一般的にウィンドウを破棄する際、( ユーザから見てウィンドウが閉じられる際 ) 子ウィンドウやコントロール類も自動的に破棄されることになっている。つまり、OS ( Windows ) が後片付けを行うことになっている。

律儀に「case WM_CLOSE:」「case WM_DESTROY:」あたりで DestroyWindow 関数 を付ける例も見かける。
DestroyWindow 関数を用いるならばウィンドウハンドルが無効でないことを確認するのが良い。
表面上、DestroyWindow 関数 や DestroyMenu 関数で無効なハンドルを解放してもエラーが出ない。のだが、深く追跡すると何らかの問題が生じているものだ。

ハンドル値を保持する変数を hw とするならば
if (::IsWindow( hw ) ) ::DestroyWindow( hw );
のように、IsWindow 関数を呼び出してから破棄するのが良策。
さらに安全を考えるならば
if ( hw ){if (::IsWindow( hw ) ) ::DestroyWindow( hw );}

くらい慎重な方が頼もしい。

プロシージャ内で「WM_ ~~」となっているのは、アプリに届くメッセージ。
例えば、アプリがサイズ変更された際には「WM_SIZE」、右クリックされた際には「WM_RBUTTONDOWN」などが通知される。
「WM_ ~~」として定義されているメッセージは多数あり、全てのメッセージに対応したコードを書く必要はない。
不慣れな段階であれば、対応するコードを省きOS に任せてしまおう。

※ 通常、「case ~:」と対になる「break;」を設置しますが、ここでは省いています。「return 0;」で脱出するため、「break;」を置いても到達できない・・・

※ 「WM_ ~~」 メッセージの定義は Winuser.h ファイルの中、もしくは 、MSDN ライブラリに詳しく載っています。

(1-3) 開始の合図 - ボタンを使わない場合
たしかに「いちいちボタンを作るのが面倒」との声も聞えてきそうだ。
ボタンを作成しなくとも、メニューバー、つまりアプリ上方に表示されるメニューに「開始」があればよい。
これは、リソース編集で簡単に修正できる。



しかし、Visual Studio の中でも Express エディションではリソースの編集が出来ないとされている。
その場合、リソーススクリプトをメモ帳で開き
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X)", IDM_EXIT
    END
を探そう。BEGIN と END の間に
MENUITEM "開始 (&G)", IDM_RUN
と加え、リソーススクリプトを上書き保存する。

ビルド、実行してみると、メニューバーに「開始 (G)」が加わったハズ。



筆者の私見を述べるが、今後のアプリ作成はメニューバーに依存しない流れになるだろう。旧来からのメニューバーはマウス操作には適しているのだが、今後は指先を使うタッチ操作が主流となる。

(2)開始の合図「IDM_RUN」が届いたら
速度を測るための関数を呼び出す。

(2-1) 新設する関数の名前を決めておく。
しばしば、パフォーマンスを比較・評価するのに「ベンチマーク」と言い、何かを開始するのは「Execute」。そこで、関数名は「execBench」とする。

(2-2) 関数を増設する
関数内、実行途中でエラーが生じた場合は、そのエラーを返すようにする。
その際、変数の型に注意。
一般的な、というか古典的な教本では値を返すような関数は 「int」 で扱われている。
Windows に限って言えば、「int」ではなく「LONG」や「HRESULT」。失敗か成功だけを問うならば「BOOL」でも良いだろう。

64ビットのプログラミング環境が意識された頃から「LONG_PTR」など「~~_PTR」といった変数の型が用いられるようになってきた。これはプラットフォームが32ビットなら32ビット幅の「LONG」つまり「LONG32」、64ビットなら「LONG64」。

とりあえず、戻り値の型を「LONG」として
LONG execBench(HWND hOwner)
{
    return NO_ERROR;
}

を追加。場所は LRESULT CALLBACK WndProc( ~~ より前が良い。もちろん、それより後方に設置することも可能だが関数プロトタイプを置き、事前に宣言せねばならない。
今回に限っては、int APIENTRY _tWinMain(HINSTANCE ~~ の直前に追加するのが判り易いかも。

この段階でexecBench の中身は空。呼び出すことはできるが、何も作業せず、NO_ERROR つまり OK と返事をするだけ。

(2-3) 増設した関数を呼ぶ準備
execBench 関数 からの返却された値を受け取るための変数を準備する。
LONG l;
追加する。場所としては先ほど
static HWND hBtn = NULL;
を追加した直後あたり。
execBench を実行した結果 (成功もしくは失敗のお知らせ)が 整数型の変数 l に入る。

そして、「IDM_RUN」が通知されたとき、execBench 関数を呼ぶためのコード
case IDM_RUN:
    ::EnableWindow(hWnd , FALSE);
    l = execBench(hWnd);
    ::EnableWindow(hWnd , TRUE );
    break;
を追加する。場所は「case WM_COMMAND:」の下



「case IDM_EXIT:」より後ろ「break;」と「default:」の間。

EnableWindow 関数でウィンドウの有効 / 無効 を切り替える。execBench を呼び出す前に アプリ本体を無効にすることでキーボードやマウスの処理を受け付けなくなる。より作業に集中させるためのオマジナイ的なモノ。
execBench から戻った後、再びEnableWindow 関数でアプリのフォームを有効に戻す。有効に戻さないと、マウスやキー操作を受け付けず、アプリの終了が不能になる。通常終了できないので、タスクマネージャ等で終了させることになる。

本来、execBench から戻ってきた値に応じてエラーのメッセージを画面に出すのだが・・・ここでは省いてあります。後で追加します・・・

初歩の段階、不慣れなうちは、戻り値・返却された値の確認を疎かにしがちである。入門書などでも省かれている例が多いので、確認の重要性が実感できないことだろう。しかし、それが習慣となると、本格的にアプリを組む段階において苦労する。
筆者としては、初歩の段階のヒトほど戻り値をチェックしてほしいと願うばかり・・・

※ 段階(3) 速度を測る部分を作成する は次回以降。

長くなりましたので続きはまた後日・・・
スポンサーサイト

本日も最後までご覧いただきありがとうございます。

「つまらなかった」「判り辛った」という方もご遠慮なくコメント欄へどうぞ

テーマ : プログラミング
ジャンル : コンピュータ

[未掲載分] 車輪の再発明 (4)

元来、好ましい意味で用いられない「車輪の再発明」。



筆者は、そのような行為を肯定的に捉えている。
なぜならば、新しい技術や文化が芽生えるきっかけは、一見無駄と思われることへの挑戦である・・・


お知らせ
活動休止にともない、この記事を事前に予約投稿してあります。
トップ記事の固定を目的としています


この題目は2012年暮れ頃に掲載しようと下書きし、諸事情により掲載却下とした分です。
前話、車輪の再発明 (3)にひきつづき、利用環境を OS はWindows , CPU は Intel 製、いわゆるウィンテル機を前提に綴ります。

前回、「アプリを開発するアプリ」として Visual Studio を取り上げた。
たしかに、統合開発環境に依存せずとも、OS (Windows) に付属している「メモ帳」などでソースコードを書いてアプリを作成することもできる。それは、「建設現場で近代的な手法を一切用いずに建てる」ようなもので、莫大な時間を要する。

ほか、Visual Studio などの統合開発環境を利用するメリットはデバッグ作業が効率的になることだ。
ここで言うデバッグ作業とは、簡単に言えば、動作チェック。アプリが想定した動きをしない場合や頻繁にエラーで停止する場合にソースコード内の不適切な箇所を潰してゆく作業。
「デバッグ作業が楽」というのは、ある程度の段階に進むまでは実感できない。プログラミングを学習、とくに入門書を読みながらあれこれ試している段階のヒトにとってピンと来ないのは当然である・・・

まずは前回の補足。

ここから前回の補足 ---
(1) もっと簡単な方法もある。
いわゆる Hello World! 、つまり「文字を表示するだけの単純なアプリ」を組むだけならば、他の手段もある。
なるべく、導入コストをかけたくないというのであれば、「WTL」というライブラリを導入するのも良い。

(2) 日本語版の MSDN ライブラリではいくらかの情報が省かれている、抜け落ちている。
「// メイン メッセージ ループ:」とコメントがある下に
GetMessage 関数が使われている。
while 構文 で囲われた部分、アプリが終了するまで GetMessage(&msg が繰り返される。
慣れないうちはこのままでも、良いだろう。
現に、入門用の書籍やその類のWebサイトでも「while(GetMessage(」のまま紹介されている。
実戦段階ではGetMessage の戻り値・返却値を確認するように修正するのが賢明である。

なぜならば、少し古めのMSDN ライブラリを漁ってみると以下の注意書きがあった。
最近の日本語版 MSDN ライブラリではこの記述が見当たらない

If the function retrieves a message other than WM_QUIT, the return value is nonzero.
If the function retrieves the WM_QUIT message, the return value is zero.
Warning Because the return value can be nonzero, zero, or -1, avoid code like this:

while (GetMessage( lpMsg, hWnd, 0, 0)) ...
The possibility of a -1 return value means that such code can lead to fatal application errors. Instead, use code like this:

少し古めの日本語版では以下の通り
戻り値
WM_QUIT 以外のメッセージを取得した場合、0 以外の値が返ります。
WM_QUIT メッセージを取得した場合、0 が返ります。
エラーが発生した場合、-1 が返ります。たとえば、hWnd パラメータで無効なウィンドウハンドルを指定した場合や、lpMsg で無効なポインタを指定した場合は、エラーが発生します。拡張エラー情報を取得するには、GetLastError 関数を使います。

警告 GetMessage 関数は、0 以外の値、0、-1 のいずれかを返します。したがって、次のようなコードは避けてください。

while (GetMessage(lpMsg, hWnd, 0, 0)) ...

このようなコードを作成すると、GetMessage 関数が失敗して -1(0xFFFFFFFF、つまり TRUE)が返った場合、ループが持続し、致命的なアプリケーションエラーを発生させる可能性があります。

MSDN ライブラリでは、その問題に対処したメッセージループも紹介されている。

おおざっぱに言えば、GetMessage 関数の戻り値の型に注意を払う必要がある。
通常、BOOL 型 なので戻りは TRUE か FALSE。
BOOL 型 は ブーリアン型 で、人間でいうところの「はい」「いいえ」の返事を確認するのに使われる。
※ 詳しく知りたいヒトは 「windef.h」というファイルを開いて typedef を見ると良いでしょう。

「いいえ」の返事に相当するのは「FALSE」と考えると良い。
「false」の意味を調べると「間違った」「誤った」などなど。
例えば、「うまく出来た?」の問われた時、「間違った」「失敗した」は「いいえ」の旨となる。
FALSE は ゼロなのだが、TRUE は ゼロ以外とされていて、多くの場合「1」 と定義されている。

アプリが終了する時、WM_QUIT というメッセージを送る。この時に「ゼロ」か「ゼロ以外」の返事を期待しているとする。
BOOL 型 に従えば、FALSE を意味する「0」かTRUE を意味する「1」が戻ってくると勘違いするヒトがいてもおかしくはない。
しかし、
「~~ 0 以外の値、0、-1 ~~」の部分に記されているように実際には「-1」が戻ってくることもある。
「-1」が戻ってきた際の対応も、GetMessage の後に追加しておくのが良策。

たいてい、「-1」が戻ってくる場合はアプリが異常終了する例が多く、致命的なバグ ( 欠陥 )がどこかに潜んでいるものだ・・・

このように、日本語版 MSDN ライブラリでは、GetMessage 関数の戻り値に関する記述が省かれている。
英語で記されたサイト等を閲覧するが苦手なヒトもいるだろう。
しかし、このような、原文(英語版)に載っていても日本語版で省かれている情報は見落としがち。これらを見落として「うまく進まない」と悩むのはモッタイナイ。
力をつけたいヒトは原文を漁ることも近道である・・・
--- 前回の補足はここまで

ここから筆者の雑感 ---
手厳しいことを記す。
この題目のきっかけとなったブロガーさんから感じたことがある。
「C/C++ 言語を理解する」ことと「Windows 上で動くアプリを作る」ことはイコールではない。
それは「自動車の構造に詳しくなる」ことと「自動車をうまく運転する」ことくらい、根本的に異なる。
ここでは話の対象をウィンテル機に絞っているが、コンピュータのOSは数多あり、Windows はその中のひとつに過ぎない。
筆者の私見かもしれないが、手順としては「ウィンドウ(やダイアログボックス)を表示させる」ことが先、次に「何の言語で組むか」ではないだろうか。
「Windows 上で動くアプリを作る」という基礎的な段階で右往左往するようであれば、Visual Basic (もしくは VB.Net) や C# 、Java などの選択肢がある。

C/C++ 言語に興味を持つヒトの中には「アプリが高速に動くらしい」との話を鵜呑みにしているのではないかと感じることがある。もちろん、はじめてプログラミングを習うのにC/C++ 言語から入るヒトもいる。
筆者の想像であるが、ほかの言語でアプリ作成をある程度経験を積んだが、実行速度面で不満が生じる。やがて、「高速さ」に誘われて、C/C++ 言語に挑もうとするのであろう。

アプリを動かす機器の特性を十分に理解し、ほどよく最適化された実行ファイルを生成する等の条件が整えば、「C/C++ 言語で組んだアプリが高速に動く」は間違っていない。しかし、実際は、C/C++ 言語 で組んだアプリが Java で組んだモノより遅い事例もあり、ハードウェアの特性を理解するのも容易ではない。

ウィンドウを表示したり、マウスのクリックに応答する部分といった「ユーザとやりとりする部分」を考えた場合、C/C++ 言語 では、Visual Basic や C# に比べ手間がかかるのは否めない。
ズバり言ってしまえば、お手軽ではない。Visual Basic や C# であればウィンドウの処理やメッセージへの応答などを意識せずにアプリを作れる。

「高速さを求めるあまり作業に多くの時間を費す」こと、全てが無駄とは言わない。しかし、どこかで線引きが必要。
なかには、ウィンドウが表示される仕組み、クリックしたらメニューがポップアップされる仕組みを学びたいヒトもいるだろう。
その辺の情報は多くの先人が触れており、書籍を漁るなり、ネット検索で多くの情報がみつかる。これらの技を習得するのはある程度経験を積んでからでも遅くはない。

多くのヒトにとって重要なのは「自動車の構造を知る」ことよりも、「自動車を使って何をするか」である。まずは、完走できること、目的地にたどり着くことが優先課題・・・

不慣れな段階において完走を目指すなら、別のアプローチを模索するのも良いだろう。
古くから用いられている例だが、
ウィンドウを表示させる部分、ボタン等のユーザとやりとりする部分を Visual Basic や C# で組み、
速度が求められる部分を「DLL」( = 動的リンクライブラリ 、Dynamic Link Library の略 ) として作成し、実行時に呼び出すといった手法もある。
想像するのが難しいかもしれない。簡単な図で現すと、以下のような感じだろうか・・・



実生活の場で例えるならば、「専門的な作業が得意なスタッフを抱える」と「専門的な作業は外部委託する」といった違いのようなもの。
外部委託する利点としては、委託先の内部状況を気にする必要が無い。
仮に、自ら専門的な作業を行うとして、あまり得意でない作業ならば、常に間違いが起こらないように気を配ったり、出来上がりの精度も不満が残ることだろう。

※ 32ビット版、64ビット版のOSごとに別々の DLL を作成する必要がある。
※ 高速さを求めるならば DLL 部は C/C++ 言語 やアセンブリ言語で組むのが望ましい。

--- ここまで筆者の雑感

さてさて、Visual Studio の使い方に戻ろう。
リハーサル用と本番用

Visual Studio の操作画面をよく見ると、ドロップダウンリストで「Debug」となっている部分がある。



このドロップダウンリストで、「Debug」版と「Release」版といった、作成するアプリの構成を切り替えが可能。
Visual Studio に不慣れな段階でアリガチなのは、Debug と Release の切り替えずに進んでしまう!?!?



ところで「Debugって何??? 」「Debug と Releaseって何が違うの??? 」が
Debug と Release の違いをここで述べると長くなる。
簡単に言ってしまえば「リハーサル」用と「本番」用の違い。

「Debug 」や 「Release」という表記、名称は絶対的なモノではない、ユーザが自由に変更できる。
ここでは慣例に慣例に従い、そのまま用いる。
例えば本番用として、異なる設定の実行ファイルをビルドすることも可能。つまり、複数パターン作成するのもアリ。

もうひとつ、切り替えを忘れそうな箇所がある。
対象プラットフォームの切り替え
初期状態では「Win32」となっている。
実際のところ、32ビット版、64ビット版のOS が両方出回っている段階では「Win32」のままでも構い。
なぜならば、32ビット版のアプリでも64ビット版のOS上で動くから。ただし、64ビット版のOS上では64ビット版のアプリの方が性能を発揮する。
かつて、16ビット版のアプリから32ビット版のアプリへ切り替わってきたように、いずれ「Win32」という選択肢が消えるのかも・・・

64ビット版のOSに対応したアプリを作りたい場合、



「Win32」が表示されているドロップダウンリストをクリック。
「構成マネージャ」をクリック。



構成マネージャのダイアログボックス右側、
「アクティブ~~プラットフォーム」のドロップダウンリストから「<新規作成>」をクリック。



新しいプラットフォームを選択するダイアログボックスの中から「x64」を選択する。



※ 64ビット向けのアプリを作る時は、後で述べるプリプロセッサの定義に要注意。
2014年1月25日付けの記事でも触れたように、64ビット版を現す語句として、「EM64T」「amd64」や「IA64」などもあります。一般的な PC 、つまり、Intel 製 CPU や AMD 製 CPU を搭載したプラットフォームを対象とするならば「x64」でOK。

ところで、Visual Basic や C# ではプラットフォームが「Win32」ではなく、「Any CPU」等になっている。



「Any CPU」 とは「32ビット用、64ビット用に関係なく動くアプリ」を作成すること。
この辺も、動作させたいプラットフォームに合わせることで、より効率的に動くアプリが作成されることだろう・・・

プロジェクト毎の設定
Release 版 ( 本番用 ) のアプリは初期設定のままビルドしても、ある程度高速に動きます。
少し設定を変更することで、実行速度が上がるかもしれません。
基本的にはプロジェクトを作成するごとに設定する習慣をつけるのが良いでしょう。

個別設定を行うには、キーボード操作ならば、[Alt]ボタンを押しながら[F7]を押す。
マウスを用いるなら、操作画面メニューの「プロジェクト」 -> 「プロパティ」。でも良いのだが、昨今の風潮として操作画面メニューが省略されてゆくようだ・・・



Visual Studio の左側ペイン「ソリューションエクスプローラ」から、プロジェクトファイルのアイコンを右クリック。



コンテクストメニューの一番下、「プロパティ」をクリック。



ダイアログボックス左側ペインのツリービュー、「構成プロパティ」の「C/C++」を選択。
[全般]の中で、[警告レベル]が変更できます。

警告レベルを高く設定するのは C/C++ 言語に慣れてからで良いでしょう。警告レベルを高く設定することで、不具合のもととなる箇所を潰せる確率が高まります。
逆に、不慣れな段階では警告レベルを高くしないほうが無難です。プログラミングを学習中のヒトは教本に載っているコードなどを丸ごと打ち込んだり、何れかのWebサイトにあるサンプルコードを貼り付けることもあるでしょう。
出回っているサンプルコードの中には、古めルールに従ったコード、つまり、現在のルールと異なる部分が多く残っています。古いコードをそのままビルドすれば大量の警告が出ます。大量の警告と対峙しているうちに挫折してしまうヒトが出てくるのも当然。



Release 版のアプリならば、左側ペインのツリービュー、「C/C++」の[最適化]も変更。
最適化については「実行速度」を上げる、もしくは「ファイルサイズ」を小さくするの方針を設定できる。
※今回は省きますが、「実行速度」優先に設定しつつ、「ファイルサイズ」を小さくする方法が幾かあります。

「インライン関数の展開」を「拡張可能な~~」に切り替えることで実行速度の向上を期待できます。ただし、全般的にファイルサイズが大きくなります。



左側ペインのツリービュー、[プリプロセッサ]に関しては要注意。
これは Visual Studio 2008 での例です。
プラットフォームを「x64」に切り替えた直後、初期状態ではビルド・コンパイルに失敗するヒトが多いかも。

ちなみに、筆者は「x64」の設定として
WIN64;_WIN64;_X64_=1;DBG=0;_NDEBUG;_MT;_UNICODE;UNICODE
を加えています。置き換えではなく、「WIN32;NDEBUG;_WINDOWS」を残し、その後に「;WIN64;_WIN64; ~~ ;UNICODE」を付け加えます。
64ビット版のアプリを作る場合でも、Windows 95 や NT 以来 OS ( Windows ) に備わっている諸々の機能を使いたい場合は「WIN32」や「_WINDOWS」などのシンボルを定義する必要があります。

少し古めの教本やサンプルコードでは、文字列処理に絡む箇所でエラーが生じるかもしれません。
_UNICODE;UNICODE;
を外すとエラーが減るかもしれません。
それでも、文字列に絡むエラーが生じる場合もあります。サンプルコードで日本語の文字列が含まれていて、いわゆるユニコードではなくシフトジス、Shift_JISを想定したサンプルコードがビルドできない場合、プリプロセッサで定義しているシンボル
_UNICODE;UNICODE; を _MBCS; へ変更するとうまくゆくこともあります。
_MBCS; を定義することでマルチバイト文字セットを扱えるようになります。ただし、時代の流れから言えばマルチバイト文字セットは旧式。それよりもユニコード対応のコードを組めるのが望ましい・・・

ほかにも、左側ペインのツリー[コード生成]の[バッファ セキュリティ チェック]など速度向上を期待できそうな項目があります。・・・どの項目を変更すれば良いのか、筆者なりの見解もあるのだが・・・いろいろ試して最適な設定を探ることが上達への近道となるだろう・・・



もうひとつ・・・
左側ペインのツリー[リンカ]の[全般]にある[出力ファイル]という項目がある。
通常ここは、
~~$(ProjectName).exe
となっている。
筆者は Debug 版と Release 版を区別するため「.exe」の部分を「_d.exe」に変更する。

通常は、プロジェクトのフォルダー内に「Debug」と「Release」いったフォルダーが作成され、その中にアプリ本体、すなわち実行ファイルが作成される。
ときには、Debug 版のアプリと Release 版のアプリを同じフォルダーに作成したいこともある。
既に述べたように、Visual Studio 等の統合開発環境を使っているうちは、Debug 版と Release 版の切り替えには苦労しない。統合開発環境が使えないとなると、あちこちフォルダーを移動しながら切り替えることになる。手間が増える。

出力先の設定例としてRelease 版では
$(SolutionDir)$(ProjectName).exe
Debug 版 では
$(SolutionDir)$(ProjectName)_d.exe
と変更すれば、Debug 版のアプリと Release 版のアプリを同じフォルダーに作成できる。

長くなりましたので続きはまた後日・・・

本日も最後までご覧いただきありがとうございます。

「つまらなかった」「判り辛った」という方もご遠慮なくコメント欄へどうぞ

テーマ : プログラミング
ジャンル : コンピュータ

[未掲載分] 車輪の再発明 (3)

元来、好ましい意味で用いられない「車輪の再発明」。



筆者は、そのような行為を肯定的に捉えている。
なぜならば、新しい技術や文化が芽生えるきっかけは、一見無駄と思われることへの挑戦である・・・


お知らせ
活動休止にともない、この記事を事前に予約投稿してあります。
トップ記事の固定を目的としています


この題目は2012年暮れ頃に掲載しようと下書きし、諸事情により掲載却下とした分です。
前話、車輪の再発明 (2)にひきつづき、利用環境を OS はWindows , CPU は Intel 製、いわゆるウィンテル機を前提に綴ります。

何らかの改善を加えることにより、どの程度速くなるのかを確認したい。となると、
「Windows 上 で動くアプリ(ソフトウェア)を作成する」ことになる。
ダイアログ上に測定結果を表示することで、違いを把握し易くなる。



今回は「速い・遅い」の話から逸れます。
この題目のきっかけとなったブロガーさんを見るかぎり、「まだ実戦ではなく、C/C++ 言語の習得に奮闘している段階」とのことでした。その際、いわゆる Hello World! 、「文字を表示するだけの単純なアプリ」を組むのにも、時間を費やしていたように感じました。
それ故、開発環境について綴ります。

今までにひきつづき、話の前提としては
・OS ---> Windows 7
・PC ---> Intel 製 CPU を搭載、ただし Itanium を除く
・開発言語 ---> C/C++

アプリ(ソフトウェア)を作るアプリ
つまり統合開発環境の中で使い勝手の良いものを入手するのが先決。
開発環境は多々ある。その中でも使い勝手が良い、「アプリを作るためのアプリ」として挙げられるのは、「Visual Studio」だろう・・・


※ これは2012年6月15日に掲載した記事の画像です

2012年6月15日分の過去記事でも載せたとおり、筆者も永年愛用している。
該当記事に写っているのは Visual Studio 6.0。Windows 98 や Windows NT 4.0 が全盛の頃のモノ。

筆者は C/C++ 言語用には Visual C++ 4.0 あたりから利用している。(それまでは別のモノを利用していた。) 時期としてはWindows 95 が登場した頃であろうか。
その頃は、Visual Basic 4.0 などは別売りされていた。やがて、C/C++ , Basic , Java などの開発が全てがひとつのパッケージにまとまり、Visual Studio シリーズとしてリリースされるようになった。

「アプリを作るためのアプリ」として「Visual Studio」を推すにはそれなりの理由がある。
かつては、統合開発環境においても対抗製品が複数介在した。利用する側としては選択に迷う。
やがて、ワープロや表計算の分野でも同様であったように、時間を経て淘汰された結果、OS ( Windows ) を製造、販売している Microsoft の製品が生き残る結果となった。
敗者からは、「OSとアプリは接に関わっているので ~~」などの弁が聞こえてきそうだ。
しかし、筆者が想うに「利用者からみた使い勝手」が断然違った。
「乗り心地の悪い自動車を買ってしまった」と後悔すれば、次の買い替え時には別のメーカーの自動車を選択することだろう・・・

名称からも判るように、Visual Studio 2005 や 2008 のようにリリースされた年号が付いている。
大まかに言えば、新しいバージョンのOS ( Windows ) が登場とリンクするように Visual Studioも新版がリリースされてきた。

Windows に Home 版や Pro 版 といったエディションの違いがあるのと同様、Visual Studio にもいつくかのエディションが存在する。各エディションごとに、細かい違いはある。

Visual Studio の中でも 無償で提供されているエディションがある。Express Edition と呼ばれ、学生さんやプログラミングを学習している方々を対象としている。
Express Edition は無償で提供されるのとひきかえに、いくらかの機能が削減されている。
本格的にプログラミングしたいときに何かが足りない感じは否めない。
例を挙げれば、MFC ( Microsoft Foundation Class の略 ) と呼ばれるクラスライブラリ集が付属していない。「車輪の再発明」を避けるためには、既存のライブラリを使うのが望ましい・・・

※ 学生さんの中で本格的にプログラミングしたいヒトは何らかの優待制度があるので各自調べてみるとよいでしょう。

※ Express エディションがあるのは Visual Studio 2005 以降です。それより古いバージョンに無償のエディションはありません。

昨今、64ビット版の OS が搭載された PC が増えている。Express エディションで64ビット向けのアプリを作成するのも可能。その場合は Windows SDK のインストールが必要。32ビット/64ビットを問わず、Windows 上で動作するアプリを作成したいならばインストールすべきである。
Windows SDK は無償で配布されている。
Windows SDK とは、かつて Microsoft Platform SDK (PSDK) と呼ばれていたもので、ライブラリ、ヘッダファイル、やサンプルが含まれている。
その役割としては「アプリ作成の手間を減らす」、というよりも、これが無い状態で Windows 上で動くアプリを作成するのは ( 不可能ではないが ) 困難である。
簡単に記すと、Windows SDK の中に「画面に点を打つ」「画面に線を引く」や「ファイルを操作する」といった、頻繁に使われそうな機能からマイナーな機能まで集約されている。

Visual Studio の中にも ある程度のライブラリ、ヘッダファイルが含まれている。が、それらは Windows SDK の簡略版であり、いくらか削られている。

ほか、Visual Studio のバージョンとWindows SDK の組み合わせには相性問題が生じるので要注意。
Visual Studio 2005 ならば Windows SDK 6.0、
Visual Studio 2008 ならば Windows SDK 6.1 もしくは 7.0、Visual Studio 2010 ならば ・・・

ちなみに、Visual Studio Express 2012 以降は何も追加せずに 64ビット向けのアプリを作成することができる。
Visual Studio Express 2012 は Windows Vista 以前の OS をサポートしない。

さてさて、この題目のきっかけとなったブロガーさんは学生とのこと。さらに、当時 Windows XP を利用しているとのことでした。ということで、無償版の Visual Studio 2005 Express Edition もしくは 2008 Express Edition 、に加え WindowsSDK の導入が良い旨を返信しました。当時、2005 Express Edition の入手が難しくなりつつあったので、入手を急ぐように伝えました。

※ Visual Studio 2005 シリーズならば、Windows 2000 や Windows 98 といった古い OS 向けのアプリを組むことも可能。Visual Studio 2005 が登場した時期は、まだ Windows 2000 はサポート期間内でした。

※ Visual Studio 2005 Express に関して、「Visual Studio 2005 Express Edition の提供を 2009 年 3 月 31 日を・・・」とのアナウンスがありました。

アプリの骨格を作る

改良前と改良後の違いを確認できるように、ウィンドウ、もしくはダイアログを表示するのが手っ取り早い。

冒頭と重複するが、この題目のきっかけとなったブロガーさんは、C/C++ 言語の学習に取り組むにあたり、Visual Studio 以外の環境だったようで、
「単純に Window を表示するだけのアプリ」を組む段階で苦労していた感がありました。
C/C++ の学習過程においては、たくさんの教材が出回っていて、どれが近道なのか右往左往するのも当然である。

書籍を出版する側から考えてみれば、その「単純に Window を表示するだけのアプリ」のソースコードを掲載せることでページ数が稼げる。つまり、本の中身が厚くなる。本の厚さと内容の濃さとは別。
文献を読む側から考えれば、長文は気力が失せる・・・

それらのソースコードを丸暗記したいとの想いで、キーボードを叩き続けるのも無駄ではないだろう。
この題目のきっかけとなったブロガーさんは、ソースコードの長さに嫌気がさしていたように見えた・・・

筆者の個人的な意見を言えば、K&R 本 と 「MSDN ライブラリ」 が近道。
Visual Studio を使うのであれば、そのヘルプ機能も頼り甲斐がある。
「MSDN ライブラリ」の原文は英語。ゆえに、以前は誤訳や誤植も目立ったが、昨今でMSDN はネットを経由することもあり改善されてきた。

アプリを作る話に戻ります。
Visual Studio を使えば少ないステップで「単純に Window を表示するだけのアプリ」を構築できる。
--- 以下、Windows 7 , Visual Studio 2008 での例 ---

ツールバーのメニューから、



[ファイル (F) ] -> [新規作成 (N) ] -> [プロジェクト] と進む。
ひな型 (テンプレート) を選択するダイアログが表示されるので、



左側ペインより「Visual C++」を選択、ツリーの中から「Win32」。
右側ペインに「Win32 プロジェクト」が表示されるので選択。

プロジェクト名、ソリューション名の欄を入力して次に進む。
ここでは、参考例としてソリューション名に「new01」と入力しました・・・

Visual Studio 2005 や 2008 の Express エディションにおいて初期状態で「Win32 プロジェクト」が利用できないかもしれません。これに関しては、ネット上に諸々の情報があります。ここでは取り上げません・・・



ウィザード画面では「Windows アプリケーション」が選択されていることを確認。

この辺の画面も Express エディションと多少異なるかもしれません。重複しますが、Express エディション は無償配布されているのとひきかえに「MFC」「ATL」などのライブラリは付属していません。「MFC」の代替としては「WTL」というライブラリもあります・・・

ウィザード画面で設定して、[完了]ボタン等をクリック。



このような感じで、「単純に Window を表示するだけのアプリ」のソースコードやリソースファイルが自動的に作成されます。
キーボードの[F7]ボタンを押せばアプリが作成されます。アプリを実行するにはキーボードの[F5]ボタン。

いざアプリを実行してみると、冒頭の画像と異なり、「Hello World!」は表示されないハズ。
筆者の手元にあるVisual Studio で確認したところ、2002 以降は「Hello World!」を表示しないテンプレートに変更されています。

Visual Studio 6.0 までは、「Hello World!」が表示されるテンプレートでした。
そのコードと比べ、



WndProc プロシージャ内、「case WM_PAINT:」の辺り「// TODO:~~」と「EndPaint( ~~」の間、

RECT rt;
GetClientRect( hWnd, &rt );
DrawText( hdc, szHello, strlen(szHello), &rt, DT_CENTER );

の3行が削られています。
「Hello World!」と表示したい場合、この3行を追加しただけではエラーが発生します。
szHelloに関しては、WndProc プロシージャ内の冒頭、変数定義の辺り「HDC hdc;」と「switch (~~」の間に
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

の2行を挿入し、さらに、ストリングテーブルに「IDS_HELLO」を定義するなどの修正が必要・・・

ちょっと待った。
その前に、Visual Studio に不慣れな段階では
「WndProc って何処」という声があがるのも当然。
そのような時はいちいちスクロールして探す !?!?
それとも、文字列検索!?!?
これも時間を費しそう・・・



統合開発環境ならではの機能を使えば、少し楽になる。
Visual Studio であれば、ドロップダウンリスト ( 図の赤い枠あたり ) をクリックし、「WndProc(HWND ~~」を選択すれば編集したい関数へジャンプできるハズ。

よく見ると、DrawText(~~ の辺り、文字列の長さを求める部分が「strlen」となっています。
Windows 向けのアプリ作成に慣れているヒトならば「lstrlen」「_tcslen」などもご存知のことでしょう。
「strlen」や「strcpy」といった古くから C/C++ 言語の教本に載っている関数、これらを最近の環境で用いると警告が出ます。
この辺は「strlen_s」「strcpy_s」といった具合に末尾に「_s」が付いた関数に変更すると解消されます。
なお、「strcpy」と「strcpy_s」では呼び出しだけでなく、返却値が異なるので変更は慎重に。

「strcpy_s」などの拡張はバッファオーバーフローなどの致命的なエラーを減らす目的があると言われています。
・・・バッファオーバーフローやバッファオーバーランと呼ぶと難しいかもしれません。想定外のメモリアクセスと言い換えても、さらに判り難そうです。おおざっぱに言えば、立ち入り禁止とされている場所に無断で入るようなこと・・・
末尾に「_s」を付けた関数は Visual C++ 独自の拡張であり、標準的な C/C++ 言語の教本には載っていません。
逆に言えば、末尾に「_s」が付く文字列操作の関数は Windows 以外の OS や古いコンパイラで通用しません。

たしかに、旧来からの「strncpy」などの関数があります。これらがあれば「strcpy_s」などが拡張・追加されたことに疑問を抱くのも当然。「strncpy」に対し、「strncpy_s」も追加されたことから察すれば、疑問が解けることでしょう。

ほかにも、プリプロセッサ「#define」で特定の文字列を定義して警告を減らす手段もあります。しかし、単純に警告が通知されないだけであり、致命的なエラーの発生を防ぐことにはなりません。
警告の箇所が少ない段階ならば末尾に「_s」が付く関数に変更するが無難かも・・・

長くなりましたので続きはまた後日・・・

本日も最後までご覧いただきありがとうございます。

「つまらなかった」「判り辛った」という方もご遠慮なくコメント欄へどうぞ

テーマ : プログラミング
ジャンル : コンピュータ

検索サイトからお越しの方へ
検索サイトからお越しの方は、ブラウザのアドレス欄vitalaboloveおよび、fc2.comが含まれているかご確認ください。
含まれていない場合、偽サイトを閲覧なされている可能性があります。

偽サイトは、当ブログの文字部分や画像部分が有害サイトへのバナーと置き換わっているようです。
プロフィール

Author:Vitalabolove
ご訪問ありがとうございます。
店長を任されておりますVitalaboloveです。

コメントはお気軽に。
今のところリンクフリーですが、あと数日でとりやめます。

画像データ、文言の引用は事前連絡くださるようお願い申し上げます。事前連絡の際は、左下、メールフォームを経由をご利用ください。

最新記事
カレンダー
04 | 2014/05 | 06
- - - - 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
カテゴリ
ランキング
いつも応援いただきありがとうございました。ただいま休養中につきランキングへ参加していません・・・

フリーエリア
内緒話などはおきてがみをご利用ください。
月別アーカイブ
メールフォーム
掲載された記事について、ご不明な点はここからお問い合わせください

名前:
メール:
件名:
本文:

最新コメント
最新トラックバック
スパムと思われるトラックバックは削除しました
QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。