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

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

MFC

CSimpleLock::IsLockedの罠

CriticalSectionの取り扱いを楽にするため、MFCのCCriticalSectionとCSimpleLockを使おうとして罠にハマったという話。 CCriticalSectionはCSemaphore等と異なりLock待ちのタイムアウトができない。そのため、ロックできなかったら諦める!という実装が不可…

C++REST (cpprest)をスタティック構成のMFCと一緒に使う

RedmineのデータをREST API経由でダウンロードするプログラムを作るためにcpprestを導入しようとした際に苦労した点のメモ。 前記ソフトをMFCランタイムをダウンロードできない/しづらい環境でも使えるようにするため、MFCをスタティックライブラリとして組…

Factorioでアイテム生産に必要な工場の数を試算するツール(FactorioFactoryCalculator)

Factorioでアイテム生産に必要な工場の数を試算するためのツール, FactorioFactoryCalculatorを公開しました。これを使えば、例えば製造サイエンスパックを毎秒3個作るために必要な、生産力モジュール1の工場の数やそのための発展基板工場の数などが試算でき…

重い処理中にステータス(状態)を表示するダイアログの実装(ユーザーインターフェーススレッド)

解決したい課題 MFCを使ったソフトにおいて重い処理をしている最中に、進捗等を表示するダイアログを表示したくなることは多々ある。しかし、単純にダイアログを作って表示しようとしても、以下のようにうまく行かないことが多い。 重い処理が終わるまでダイ…

重いイベントハンドラの処理状況をダイアログで表示する

背景 重い処理の進捗状況をダイアログで表示する場合、自分がよくやるのは 進捗状況を示すモードレスダイアログを作成 重い処理をAfxBeginThread()により別のワーカースレッドとして起動 モードレスダイアログは適宜タイマによって状況を更新 モードレスダイ…

CListViewにポップアップメニューを追加したけどON_UPDATE_COMMAND_UIが送られてこない件について

事象 CListViewにポップアップメニューを追加し、条件に応じてメニューのEnable/Disableを切り替えようとMFCの流儀に則りON_UPDATE_COMMAND_UIのハンドラを追加した。しかし、ポップアップメニュー表示時になぜかON_UPDATE_COMMAND_UIが来ない。 原因 CListV…

ダイアログバー上のエディットボックスから文字列を取得する方法

ダイアログバー上のエディットボックスから文字列を取得するのにちょっと苦労したのでメモ。 問題の背景 ダイアログを作る場合、通常はCDialog等を継承した、そのダイアログ固有のクラスを作成する。しかしMicrosoft曰く、CDialogBarは通常固有のクラスを作…

CDocumentからCViewを取得する一例

今時ドキュメントビューアーキテクチャなんて人は居ないだろうけど、メモ。 CDocumentからCViewにメッセージを投げたいときや関数を直接呼び出したいときに困るのが、CViewのアドレス取得方法。特に、自分はCSplitterWndを多用したためCViewが複数あり決め打…

CArchive::ReadString, CArchive::WriteStringの罠

CArchive::ReadString()とCArchive::WriteString()を使って文字列を読み書きしようとしたら文字化けしてハマったのでメモ。 以下のようなコードを書いたら、読み込み時に文字化けした。 void Serialize(CArchive &ar){ TCHAR path[MAX_PATH+1]; if(ar.IsStor…

リソースエディタがWS_EX_COMPOSITEDを認識しない

とあるリソースをVisual Studio2019で開こうとしたら、error RC2104: undefined keyword or key name: WS_EX_COMPOSITED というエラーが出た。 error RC2104: undefined keyword or key name: WS_EX_COMPOSITED でも、おかしい。このキーワードはWindowsに存…

_RPTN, _RPTWN等をTCHARに対応させる

Visual Studioの出力ウィンドウに文字を出力する_RPT系関数は便利だが、なぜかTCHAR版が無い。 (_RPT系関数の参考) donadona.hatenablog.jp 仕方ないので、TCHAR版を作ってみた。なお、毎回_CRT_WARNを書くのが面倒だったので入力不要としている。別のもの…

CMultiLockの問題

Semaphoreの参照カウント数を知るために、カウント数を保持するクラスを作ってみたのだがうまくカウントしてくれない。原因を調べるために、CMultiLockのコードを読んでみたらびっくりした。Unlock()とかはCSyncObjectクラスのUnlock()を呼び出すようになっ…

CEventとCMultiLock::IsLocked

CEventとCMultiLock::IsLocked()の組み合わせでちょっと悩んだのでメモ。 CSemaphoreオブジェクトAのLock待ち中にAbortできるよう、以下のように組んだ。 悩んだのは、IsLocked()。Microsoftのドキュメントでは"Nonzero if the specified object is locked; …

mozjpegをつかった画像変換ソフトの開発 その6

マルチスレッド関連の実装方法に迷いが生じたので、ちょっと考えを整理する。 ■やりたいことは何か やりたいことはスレッドからスレッドへの通知?いや違う。それは手段であって、目的ではない。やりたいのは、 処理Aが終了したあと、その結果を使う処理Bを…

SendMessage / PostMessageにかかる時間

SendMessageやPostMessageにてメッセージを投げてから受け取るまでにかかる時間を調べてみた。Ryzen3700X @ Windows10 Prof. 1909では、SendMessage: 20us, PostMessage: 34usだった。SendMessageのほうが早いのは、WindowProcedureを速やかに呼ぶかららしい…

mozjpegをつかった画像変換ソフトの開発 その5

どういうふうにスレッドの制御をするか考え中。今回のソフトは、タスクごとにスレッドを作ってしまうという富豪方針である。ということは、リソースに見合った数のスレッドが常に走っているようにスレッドを生成し続ければよい。これを実現するには、ワーカ…

mozjpegをつかった画像変換ソフトの開発 その4

どのようにマルチスレッド化するかを考え中。 考えられる方針は大きく2つ。 ファイルを1個開くたびに1スレッド作り、1変換をするたびに1スレッドを作り、1個書き出すたびに1スレッド作る。ブルジョワ方針。 物理メディアごとに1スレッド作り、当該メディアで…

ツールチップに複数行の文字を表示させる

CToolTipCtrlのAddTool()を使ってツールチップを表示させようとしたときに、文字列が長い場合は指定した位置で改行したくなる・・よね?でも、テキストに\nを加えても改行してくれず、ちょっと苦労したのでメモ。 CToolTipCtrlを使って複数行にわたるテキス…

MFCを使う場合の多言語化

MFCを使う場合の多言語化メモ。以下の英語版より抜粋。 docs.microsoft.com マイクロソフトによると、言語ごとのリソースはリソース専用DLLに格納すればいいらしい。そうすると、以下の順番でリソースの読み込みにチャレンジしてくれる。 GetUserDefaultUILa…

Visual studioのC++で実行ファイルのプロパティにビルド番号を埋め込む

Visual studio, 便利なのに、なぜかビルドしたファイルのバージョンプロパティにビルド番号を埋め込めない。そこで、下記にあるIncrementBuildを導入した。 Build Incrementing for Visual Studio C++ Projects – Fooling Around 動作原理 ビルド後のイベン…

CInfoProgressCtrlの更新(プログレスバー伸長速度を切替可能に)

CInfoProgressCtrlはCProgressCtrlを継承することでプログレスバーの上に文字を表示できるようにしているのだが、このプログレスバーの欠点の一つに、バーを伸ばす速度が制限されている、というのがある。バーが縮む方向ならば瞬時に縮むので、これを利用し…

ProgressCtrlの上に文字を表示

プログレスバーの上に文字を表示する必要が生じたのだが、標準のCProgressCtrlは文字表示機能が無い。どうも、Windowsのデザインガイドではテキストを表示するな!となっているようだ(1次情報未確認)。そこで、他の方が作ったものがないかなーと調べてみる…

タブコントロール内のダイアログがESCキーで閉じてしまうのを防ぐ

タブコントロールを実装するには、各タブに相当する枠なしダイアログを用意するのだが、困ったことにESCキーを押すとこのタブ内のダイアログが閉じてしまい、真っ白になってしまう。これを回避するには、タブ内の各ダイアログのOnCancel()をオーバーライドし…

CProgressCtrlのSetStateが反映されない

CProgressCtrlの色を変えようとしたがハマったのでメモ。 CProgressCtrlは、WindowsThemeが有効だとプログレスバーの色を変えるSetBarColorが無視される。そこで、SetStateでPBST_NORMAL, PBST_PAUSED, PBST_ERRORのいずれかを指定することでテーマに沿った…

ダイアログのコントロール上でも右クリックでメニューを出したい

ダイアログ上で右クリックした際にメニューを表示するには、OnRButtonUpあたりをオーバーライドしてやればいい。しかし、OnRButtonUpはダイアログ上のプログレスバー等の上で右クリックした場合には呼び出されない。これは、ボタンの上で左クリックした場合…

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

GetLastError()で得たエラーコードを毎回FormatMessageで変換するのが面倒だったので、両者をひとまとめにしてCStringまたはLPCTSTRで返すクラスを作った。 注意! LPCTSTRは一時オブジェクトのアドレスを返すので、長時間使わないこと。すぐに無効なアドレ…

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

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

CImageからcv::Matへの画像コピー

MFCで画像をお手軽に使えるクラスCImageから、画像処理の定番OpenCV用のクラスcv::Matへ画像をコピーするのは、一見簡単だが罠がある。CImageが保持している画像データへのポインタはCImage::GetBits()で取得できるのだが、このポインタ、データの先頭を指す…

OpenCVのmatchTemplateがうまく動かない!

以下のコードが上手く動かず、しばし悩む。 まったく同じ画像のはずなのに、どうしてもminMaxLocの結果が0.85になる。なぜだ。そこで、各画像のメモリを覗いてみた。 まずはイメージの探索対象側。イメージサイズは2×4, 32bit。0xf0f0f000 というパターンが7…

CListBoxのスクロール制御

MFC

CListBoxに、垂直スクロールバーが表示される程度にアイテムが表示されている状態でAddStringやDeleteStringを実行すると、スクロールバーの位置がリセットされ最上位に戻ってしまうことがある。これは、リストボックスの操作をするときに困る挙動だ。 これ…