ドナドナされるプログラマのメモ

Windows用アプリのプログラミングメモ

GetLastError()の結果をCStringで出力するクラス

GetLastError()で得たエラーコードを毎回FormatMessageで変換するのが面倒だったので、両者をひとまとめにしてCStringまたはLPCTSTRで返すクラスを作った。

注意!

LPCTSTRは一時オブジェクトのアドレスを返すので、長時間使わないこと。すぐに無効なアドレスとなるので、LPCTSTRで返り値を受け取る場合は速やかに別バッファにコピーすること。コピーしなくていいのは、MessageBox(LPCTSTR message)等の引数に使うときなど、一時オブジェクトが生きている場合に限定される。

コード

上から順に、

・使用例

・本体のcpp

・本体の.h

です。

Get CString object from GetLastError information

2020/02/22追記:Gistのコードを変更しました。

■Example.cpp

  • Visual Studioの出力ウィンドウにメッセージを出すだけのサンプルを追加。

■GetLastErrorToString.cpp

  • Visual Studio2019以降はstdafx.hがpch.hに変更となったため、対応。なお#include "pch.h"以前に書かれた#ifdef等はプリヘッダのコンパイラからは無視されてしまうため、_MFC_VERを使った#includeの切り替えはできない。ひどい。
  • Visual Studioの出力ウィンドウにメッセージを出すコードがUnicodeのみの対応だったためマルチバイトコードにも対応するようUNICODE定義により切り替えるようにした。なぜ_RPTTNが定義されていないのかは謎。不便なので自作したものがあるが、今回のものには含めず。興味ある方は以下からコピペまたはGist内のDownloadより入手してください。

donadona.hatenablog.jp

参考

System Error Codes (0-499) (Windows) 

System Error Codes (500-999) (Windows)

System Error Codes (1000-1299) (Windows)

System Error Codes (1300-1699) (Windows)

System Error Codes (1700-3999) (Windows)

System Error Codes (4000-5999) (Windows)

System Error Codes (6000-8199) (Windows)

System Error Codes (8200-8999) (Windows)

System Error Codes (9000-11999) (Windows)

System Error Codes (12000-15999) (Windows)

CString等でUnicodeとマルチバイトを相互に変換する

CString等でUnicodeとマルチバイトを相互に変換する方法のメモ。こんな便利なマクロ(実態はクラス)があったとは。例えば、UnicodeからANSI(マルチバイト)に変換する場合はCW2A(string)でOK。逆に、ANSIからUnicodeならCA2W(string)。マクロの返り値が変換後の文字列となっているので、関数の引数を変換する場合に便利。

例:

Example of converting from Unicode to ANSI

このマクロの命名規則は以下の通り。

C SourceType 2[C]DestinationType[EX]

SourceType, DestinationTypeにはA, W, T, OLEのいずれかが入る。OLEはWと同等。DesitinationTypeの前にCを入れるとConst扱い。末尾にEXをつけると、変換バッファのサイズをテンプレートとして渡せる。

例えば、SourceTypeがANSI、DestinationTypeがUnicodeなら、CA2Wとなる。なお、CA2CW等の一部の組み合わせは実装されていない模様。公式な詳細はATL と MFC の文字列変換マクロにある。

#includeは<atlbase.h>と<atlconv.h>。MFCプロジェクトの場合はおそらくinclude不要。

 

GIGABYTE GA-Z87X-UD3H (rev. 1.x)のBIOS設定方法

GIGABYTEのGA-Z87X-UD3H (rev. 1.x) BIOS?にはちょっと酷いバグがあって、USBキーボードからはBIOS設定画面に入れないことがある。すでに5年も前のマザーボードなので需要は無さそうだけど、Windows10での解決方法を書いておく。

1. 「すべての設定」を開く。

f:id:donadonasan:20180611193218p:plain

2. 「更新とセキュリティ」をクリック。

f:id:donadonasan:20180611193324p:plain

3. 「回復」をクリック。

f:id:donadonasan:20180611193449p:plain

4. 「PCの起動をカスタマイズする」の下の「今すぐ再起動」をクリック。

f:id:donadonasan:20180611193605p:plain

5. オプションの選択 にて、「トラブルシューティング」をクリック。

f:id:donadonasan:20180611194432p:plain

6. 「詳細オプション」をクリック。

f:id:donadonasan:20180611194512p:plain

7. 「UEFIファームウェアの設定」をクリック。

f:id:donadonasan:20180611194609p:plain

8. 「再起動」をクリック。

f:id:donadonasan:20180611194651p:plain

9. BIOS画面が出たら、パソコン前面のUSBポートにキーボードやマウスを差し替える。これで(今だけは)BIOSいじれるはずです。

f:id:donadonasan:20180611194759p:plain

 

 

日立製作所 水戸事業所 さつきまつり

日立製作所水戸工場の2018さつきまつりに行ってきた。一般人も参加OKだが、基本的に社員向けのイベントらしく情報が殆ど無い。そこで、来年へのメモも兼ねて行き方等を。

開催日は、6月第1土曜日。時間は09:00~13:00, 開場は08:45から。

入場は、水戸工場の国道門か日立側門から。車で行く場合は日立側門限定。鉄道で行く場合はJR常磐線勝田駅より徒歩24分。勝田駅西口 - 日立側門間に往復バスあり。

f:id:donadonasan:20180602202311p:plain

勝田駅西口 - 日立側門のバスダイヤは、2018年は以下の通り。

勝田駅西口発 08:40 09:00 09:30 10:30
日立側門発 11:45 12:15 12:45 13:15

バスの行き先表示は「HITACHI」。

f:id:donadonasan:20180602203550p:plain

写真撮影する場合は、日立側門にある申請所(名前忘れた)に住所氏名、連絡先を書いて許可証を貰う必要があるので、忘れずに。

自分が行ったときには許可証切れになっていたのでどんなものか不明だけど、2017年の許可証には以下が書かれていた模様。

  • 建屋内への立入禁止
  • まつりの催し物以外は撮影禁止
  • 係員の指示に従うこと

見どころは

です。

f:id:donadonasan:20180602205507p:plain

  • ED78-1

昨年のヘッドマークは「快速かもしか」だったが、今年は津軽だった)

f:id:donadonasan:20180602205759p:plain

  • ED15-1(左、本線用電気機関車の国産第1号機)とL4型貨車加減速装置(L4カー)

f:id:donadonasan:20180602211045p:plain

f:id:donadonasan:20180602211707p:plain

f:id:donadonasan:20180602211739p:plain

  • G1タワー(高さ213.5mの世界一高いエレベータ研究塔)の見学

常磐線からもよく見える、あの塔に登れます。ただし、先着450名程度まで。整理券は日立側門付近で入手できます。内部は撮影禁止。

f:id:donadonasan:20180602212233p:plain

ちなみに、ここへ行く途中には古いエレベータ研究塔もあります。見学できないけど。

f:id:donadonasan:20180602212351p:plain

  • 化学消防車試乗

f:id:donadonasan:20180602212736p:plain

スピーカー使用可です。皆さん楽しそうに「消防車がとおりま~す!どいてくださーい!」などとやってました。広大な工場の敷地内だからこそできる技。3台体制で走っているので、回転率は良い模様。ちなみに、日立グループが届け出ている消防車の台数は、ひたちなか市勝田市合わせて22台。公営?の消防車と同等とは・・・(公営:23台(うち指揮車4台))

A4ドキュメントスキャナのランニングコスト

A4ドキュメントスキャナが欲しくなってきたので、どれがいいかを決めることにした。

必要な機能は、

・オートフィーダ

・両面スキャン

・多重搬送の検知 (紙の長さ以外で)

また、ランニングコストに優れることも必要。生涯スキャン枚数を30万枚として、消耗品込みのスキャンコストを比較する。消耗品の寿命はスキャン枚数依存とし、公称値の半分とする。

あとは、参考値として読み取り幅、スキャン速度、最大dpi、フィーダにセット可能な枚数、PCとのインターフェースを比較する。

型式 FI-IX500A FI-7160B DR-M260 DR-C240 DR-C225W DS-530C9 DS-780N
メーカー 富士通(PFU) 富士通(PFU) キヤノン キヤノン キヤノン EPSON EPSON
本体価格 (¥) 38500 86000 87000 47000 37000 38000 77000
消耗品価格 (¥/枚) 7800 13000 4800 10000 4800 6400 6400
消耗品寿命 (枚) 200000 200000 200000 200000 100000 200000 200000
生涯コスト@30万枚 (¥) 54100 112000 96600 67000 51400 50800 89800
読み取り幅 (mm) 216 210 216 216 216 216 216
スキャン速度@A4 白黒300dpi (枚/分) 25 80 60 45 25 35 45
最大dpi (dpi) 600 600 600 600 600 600 600
フィーダにセット可能な枚数 (枚) 50 80 80 60 30 50 100
PCとのインターフェース USB 3.0, Wi-Fi USB 3.0 USB 3.1 USB 2.0 USB 2.0 USB 3.0 USB 3.0, LAN
備考   液晶パネル 液晶パネル
多重搬送時リトライ
      液晶パネル

コストあたりのスキャン速度ならEPSON DS-530、7万円以上のクラスで高コストパフォーマンスならキヤノン DR-M260、両者の中間ならキヤノンのDC-C240か。

・・・DR-M260、魅力的だなあ・・・

式の中で複数のインクリメントは危険

会社で他の人が作ったコードをデバッグしているときに見つけた、ひどい罠。

例えば、下記コードにおいてsum, pはどう表示されるだろうか?

An example of code including 2 increments in a lin ...

 

これ、sum=1, p=2となりそうだが、少なくともVisual C++ 2017 00369-60000-00001-AA379ではsum=0, p=2となる。どうやら、何らかの最適化により最初にsumを計算し、その後インクリメントをしているようだ。この最適化は無効にできないようで、色々試したが結果は変わらなかった。

では、次のコードではsum, pはどう表示されるだろうか?

Example of code including 2 increments in a line

これの実行結果はinput=0 input=1 sum=1 p=2となりそうである。しかしVisual C++ 2017 00369-60000-00001-AA379では異なる結果となる。しかも、debugモードとreleaseモードでは実行結果が変わる。

まずはreleaseモードでの結果から。

f:id:donadonasan:20180512164507p:plain

inputはともに0, sum=0, p=2となる。どうやら前の例と同様の挙動をしているようだ。

次に、debugモードでの実行結果を示す。

f:id:donadonasan:20180512164942p:plain

先ほどとは結果が変わり、まずinput=1が現れ、その後input=0が現れ、sumとpは予想通りsum=1, p=2となる。

どうやら、debugモードでは関数の引数ならば個別に評価されるようだ。しかし、input=1が最初に現れるのが気になる。呼び出し順はどうなっているのだろうか?これを調べるために、下記コードを作成してみた。

An example of code including 2 increments in a lin ...

debugモードでの結果は以下のようになった。

f:id:donadonasan:20180512170314p:plain

どうやら、まずは関数呼び出し無しで演算可能な部分を左から順に実行し、ついで関数呼び出し必要な演算を右から順にしている模様?

releaseモードでは以下のようになった。

f:id:donadonasan:20180512170616p:plain

演算順はdebugモードと同じで、値の更新が必要な部分は後からまとめて更新する挙動のようだ。

この挙動に気づくまで、1時間ぐらいかかった・・・。

教訓:一つの式に、インクリメント演算子を複数入れてはならない。または、もっと広く「一つの式に、同一の変数を操作する関数・演算子を複数入れてはならない。」

教訓:MSDN「演算の順序は、言語によって定義されていません。 コンパイラは、一貫性のある結果を保証できる場合には、このような式を任意の順序で自由に評価します。」などと書いてあっても信用しない。

誰だよこんなコード書いたの・・・ほんとにもう・・・。