Windows C/C++ 検証報告プロジェクト AssistKeep 03/03 2026/04/01
※ 当ブログの解釈・意図の構築の仕方は、それは当ブログ筆者がたまたま統合前 32 Bit 時代から見渡してきた Microsoft の Windows 標準 API 史的、CRT 史的、UNICODE 対応史的な、ここ30年のOS内部仕様をざっと見渡しての、統合期 Windows XP 以後の 64 Bit 化以降も進められてきた Microsoft のC原点回帰的な概念整理を、ISO9000系善用重視で見渡した上であることを、前章までにその経緯をこれまでひと通り説明してきている。
※ ここでは、外・下・新参側( よそのこと道義領域外のこと )に厳しさを向ける以上は( 合格・高次元・格上/失格・低次元・格下 を等族指導する側を気取る以上は )、内・上・古参側( まずは自分たちの次の段階の上同士視点の手本の作り合い )にはそうなる前の5年前10年前にその100倍1000倍の厳しさが既に問い合われ済み( ISO9000系善用の年期計画的な選任評議序列敷居改めのためのまずは上同士の上方修正といえる式目整備の原本作りの論述整理・議事録処理体制 = 荀子・韓非子・孫子の兵法の組織論の基本中の基本として、異環境間情報処理力・領域敷居管理力による構想競争の段階で既に勝負するまでもない優劣差が開いていく一方になる、だからまずは何にしても自分たちの上同士視点の敷居の見直し最優先で危機感・自己等族統制観を常にもてと指摘 )で間違いないから低次元ないがみ合い( 低次元化させ合う下の作り合いしかしていないただの性善説放任主義・偽善憎悪・老害浪費の乱立拡散 = 法賊行為・老害愚行 )を2度と繰り返させない側( 近代選任評議会観といえる敷居交流規律の手本を示す側 )で間違いない前提が言うまでもない最低限としている。そもそもその前提になっていない時点で、まずは自分たちにとっての人間性( 自力信仰性・当事者軸性・痛感性・自己責任性 )と社会性( 他力信仰性・主体軸性・教訓性・社会的責任性 )の領域敷居管理による、自分たちの年期計画的な社訓改め・式目序列規律改め( まずは上同士の上方修正の原本からのきざみ下方修正的な再細分化と再集約化による旧互換・非互換の統廃合管理。プログラム設計の上達でも基本中の基本 )の手本の作り合いなど自分たちで全くしてこれなかったのと同じ、よそのこと道義領域外のことをどうのの前の自分たちのその最低限も自分たちで認識できるだけの知能もない教育機関絶対およびオブジェクト指向の規律絶対のただのいいなりの知能障害の集まりの偽善法賊どものような、何もかもをケンカ腰に徹底的に面倒がり合いうやむやに低次元化させ合う下の作り合いを繰り返しているだけの上同士失格の怠慢の顔色のたらい回し合い( 特に道義領域外に対する反等族指導的・反選任評議序列式目規律的・ISO9000系悪用的な無関心・無神経・無計画な厳しさの向け合い )は、ここでは次世代敷居交流荒らしの旧廃策の対象と見なし合うことが当然の上から順番の厳しさ上乗せ倍増論で踏みにじり合う前提になっている。
本題に入り、前章 Windows C/C++05章 AssistKeep で Project_AssistKeep.zip をダウンロードしている前提、Windows 10 / 11 でそのプログラムソースファイルを Visual Studio 2026 で確認できる前提、4章 WindowBuild までの経緯( 非MFC事情 )をざっと把握している前提で、AssistKeep プログラムについての前回の続きを進める。
こと細かに全て説明していくこと自体、当ブログ筆者としては面倒がる気は一切無い姿勢だが、伝えたい部分の進行具合とブログ機能の字数制限の都合とで、やむなく要点的な説明をしていくことにする。
※ 当ブログでアップロード紹介しているプログラムコード( 05章 AssistKeep 01/03ページからダウンロードできる )は、if や while の条件部カッコ内、手続き引き数カッコ内への条件・値指定への手続き呼び出しの詰め込み等の、概念整理と無関係の詰め込み記述( 戻り値用変数の設置をただ面倒がっているだけ/記述をただ短くしたがっているだけの詰め込み記述 = 再細分化と再集約化のための関連概念の見直しをしにくくする原因、改善余地を見つけにくくする原因 )は避ける前提、つまり意義・象形の重視による概念間の混乱・誤認・不一致の元を見つけやすし、その再細分化・再集約化を常に怠らない前提が上達の鍵であることを繰り返し記述している。そうした普段からの式目規律的な見渡し方は他の分野でも同じことがいえ、そこがうやむやな目先の利害次第の詰め込み止まり( よその正しさのただのたらい回し合い止まり = 上同士失格の怠慢の顔色の偽善曲解止まり )の改善余地がいつまでも直されなければ、次の段階( 前回分・今回分・次回分以降 )に結びつく概念整理( ひいてはその手本の作り合い )に向かう訳もないというだけの話になる。
ブログ側の方で触れていない箇所については AssistKeep プログラムコードを見てもらえば、全体像をざっと理解する分には少し時間はかかる所もあるかも知れなくても、箇所ごとの見渡しは、その意味を重視しようとしている前提であればだがそんなに難しくないはずと当ブログ筆者は見ている。
その前提から今回のブログ側の説明では、全体像視点( 前回分・今回分・次回以降分の概念整理視点等も含める )の要点の説明をしていきたい。
AssistKeep ではまず、ダイアログ画面( 名前を付けて保存 画面など )に所属する部品を捜索する CheckWndStr 手続き( 関数。プロシージャ )を追加することになった。
どんな仕組みなのかをざっと説明していくが
< CheckWndStr 赤1 >
ウインドウハンドルを捜索する際の、判定用の ① クラス名( ClassName 名。 CreateWindow 時の Windows 標準 API 側の機能名 )または ② キャプション名( WindowText 名。GetWindowText と SetWindowText の文字列 )の対象文字列。捜索用の文字列については手続き内で完結させることにした。なお ① クラス名 ② キャプション名 について 赤2 赤3 の方で順述。
定数群 WNDSEARCH_ 系の方で処理別を管理、CheckWndStr の引き数 iID で対応する仕組みにしている。4 の WNDSEARCH_DIALOGFOLDER については Windows 11 では失効仕様のため廃止予定。
この CheckWndStr 手続きを使って Windows 全ウインドウハンドル捜索をするのが DialogNameWndSearch 手続きで、このWNDSEARCH_ 系定数もそちらと共用になっている。
< CheckWndStr 赤2 赤3 >
WNDSEARCH_ 系定数によって、クラス名で判定かキャプション名で判定かの作りになっているが Microsoft Spy ++ でいう
1がキャプション名、2がクラス名( 機能名 )になる。
AssistKeep 画面に所属例の R全 ボタン のプロパティ画面で
詳細側からも確認できる。
ここで少しややこしい話として、クラス名については Windows 標準 API の GetClassNameW でよいが、キャプション名については Windows 標準 API の GetWindowTextW および SetWindowTextW で読み書きする方法と、Windows 標準 API の SendMessageW の WM_GETTEXT および WM_SETTEXT メッセージで読み書きする方法と、ふたつの方法がある。
前者は基本的には同プロジェクト内( 同インスタンス内 )のみ有効、後者は他プロジェクト( 他インスタンス間。他 exe 間 )にも対応という意味になる。
後者は両方に対応しているため、後者で統一する作りにしてしまっても問題はないものの、Mircosoft としてはその都合( 同インスタンス内か他インスタンス間か )によって使い分けることを推奨している。
GetWindowTextW / SetWindowTextW の方がパラメータ( 引き数 )指定がスッキリしていることもあるが、その使い分けの前提の方が概念整理に結びつくため当ブログ筆者としてもそれを推奨する。
当 CheckWndStr では、他インスタンス間のウインドウハンドルにも対応の意図があったため、ここ( 赤3 )では後者( SendMessageW 系 )によるキャプション名の取得をしている。
GetWindowTextW / SetWindowTextW は要するに、SendMessageW 系で WM_ 系を介しての機能のやりとりの原始観が強すぎる記述を簡略化かつ概念名化するためのラップ化( 具体名代替化 )手続きといえ、WM_ 系メッセージに対するこのようなラッパー手続きはそれほど多くないが、例えば SendMessageW の WM_ENABLE のラッパー化が Windows 標準 API の EnableWindow といった具合になる。
WM_ 系メッセージならどのウインドウハンドルも共用の素の原始共用的な機能部( ENABLE による動作可/動作不可の管理、表記文字列の変更、画面の表示状態、キーボード受付/マウス操作受付 等 )を意味、LB_ 系メッセージならリストボックス機能系も備えたウインドウハンドルのその機能に向けて、BM_ / BCM_ 系等メッセージならボタン機能系も備えたウインドウハンドルのその機能に向けて、EM_ / ES_ 系等メッセージならエディット機能( 文字列入力 )も備えたウインドウハンドルのその機能に向けて、と、例えばボタン機能を備えている訳ではないウインドウハンドルに対してボタン系のメッセージを投げかけても無効扱い、といった具合になる。
ボタン (Windows コントロール) - Win32 apps | Microsoft Learn
リスト ボックスについて - Win32 apps | Microsoft Learn
編集コントロールについて - Win32 apps | Microsoft Learn
上述の Microsoft Spy ++ のプロパティ画面の ウインドウキャプション の項目の文字列が、GetWindowText / SetWindowText ( WM_GETTEXT / WM_SETTEXT )の対象で、Windows API 側としての概念名は Caption ではなく Text という表記にしているため少しややこしい。
この ウインドウキャプション の概念は、そのウインドウハンドルがメインウインドウの場合ならタイトルバー文字列に、STATIC なら表記用文字列に、BUTTON ならボタンの表面に書かれる文字列に、EDIT なら現在の入力文字列のことになり、LISTBOX なら特に使われない(?)といった具合に、そのウインドウハンドルが CreateWindowW 系でどのような機能目的( クラス名 )で生成されたかに応じて ウインドウキャプション の文字列の使われ方が少し違ってくるのもややこしい。
Microsoft Spy ++ は、そのウインドウハンドルが例えば LISTBOX の部品機能も備えていても、どのウインドウハンドルも共通してもち合わせている WM_ 系までの素の情報群の表示までしかしない、そのウインドウハンドルが備えている部品機能( 拡張 )側の情報群まで表示する機能は備わっていないことがむしろ特徴といえる。
各ウインドウハンドルに対して Microsoft Spy ++ で確認できる情報群については、それを変更/取得するためのラッパー的手続き( SendMessageW 系でのメッセージ、WPARAM、LPARAM による原始やりとりの代替概念名化手続き )は Windows 標準 API 側である程度用意されているが、部品機能側( ドットNET部品等の拡張側 )に対する取得/変更の方は、オブジェクト指向側の方ではその( SendMessageW 系と部品系メッセージによる原始的なやりとりへの )ラッパー的手続き( クラスメソッド的情報・関数プロシージャ )が世の倣( なら )いであるかのようにその規律絶対( 低次元序列規律 )で積極的に用意されていったが( それでできあがっていった大半が非概念整理的・非汎用的な、Windows の仕様への非理解・非敷居交流・偽善曲解的な低次元な制限性を強めるのみの、まさに教育機関絶対の知能障害どもの姿そのもののろくでもない集大成でしかないが )、Windows 標準 API 側は限定的にしか用意されてこなかった。
そのため、当ブログの AssistKeep / WindowBuild プロジェクトのように、オブジェクト指向の規律絶対( ただの性善説放任主義・偽善憎悪・老害浪費の顔色のたらい回し合い )を極力排除する前提、すなわちC原点回帰の Windows 標準 API 中心で Windows プログラムを進めていく場合は、部品機能側に対する取得/変更の多くは SendMessageW 系での部品用メッセージを介した原始的なやりとりで自前で作っていかなければならない前提となる。
今回議題 AssistKeep のように実際に自身で作ってみることで、上同士視点( まずは上同士からの年期計画的な概念整理面の上方修正 )の手本の作り合いを目先の利害次第にケンカ腰に荒らし合うことしか能がない教育機関絶対やオブジェクト指向の規律( 次の段階に向けた改善余地に一切向き合われて来なかった低次元規律 )が、Windows というややこしい難題に挑まれ概念面からの改善がC原点回帰的に Windows 標準 API 仕様側の 64 Bit 化以降も加えられ続けてきた Microsoft のOS史的仕様をそもそも網羅できるだけの知能などある訳がない、すなわち Windows プログラムにおける次の段階の概念整理の手助けなど一切していない、それをできなくさせ合っているだけの低次元規律丸出しのだらしない実態も改めてよく把握できる。
< CheckWndStr 赤4以下 >
赤3 までがクラス名またはキャプション名の取得に関する準備で、赤4 からが、引き数指定のウインドウハンドルが探しているウインドウハンドルかどうかを CRT の _wcsnicomp を用いて文字列比較することで、ピッタリ一致していれば true で、違っていれば false で終了する、という作りになっている。
< CheckWndStr の追加による次回分改善点 >
この CheckWndStr 手続きが追加されたことで、WindowBuild 時点での WndProc の Tab キー処理等での
部品名の頭文字による判定方法を、CheckWndStr 内の項目とこの関連の定数の項目の概念が新たにできたことで、そちらを増やして項目的に統一する改善余地の形ができた。
今回は、いきなり直すことによる混乱を避けるために、この説明をするためにあえて直さなかったが、次回以降のプロジェクトで WindowBuild 系譜の仕様を用いる際は、この旧態部分を CheckWndStr の概念で統一する予定にしている。
このように、必要になった追加分の概念が加わっていくことによって再集約できそうな箇所が次々に見つかるのも常、そこをいつまでも概念分散させ続けるのではなく計画的に統廃合をしていく前提で進めていく姿勢が、各概念機能の実現快適性を向上させられるきっかけ、こういう所を面倒がらずにひとつひとつを地道に改良していくことが、結局は上達の近道になる。
次は、ソースの行数順は前後するが、 WndProc ( 主にキー入力/マウス入力の契機動作 )の概要を説明する。
< WndProc( GetMessage ) WM_COMMAND >
WM_COMMAND の説明をしていく。
前回議題に続いて今回議題でも WindowBuild 手続きによる画面構成をする際に、外部テキストファイル( AssisKeep01 ~ 03.txt ファイル )の情報を元に、Windows 標準 API の CreateWindowExW を使って画面部品が構成されていく際に、HMENU パラメータ( 引き数 )に
役割番号を設定しているため、その画面部品がマウス左クリックによる具体動作がある部品だった場合( 主に BUTTON の場合 )は WndProc の WM_COMMAND メッセージと HMENU の設定値( Tab 機能の都合も含めて設置順の数値を設置 )が通知される仕組み( Windows としての画面部品の仕様 )になっている。
WindowBuild で画面を生成する際のテキスト情報からの読み込みの際に、役割番号は共用変数の g_iWndCate に保管していく仕組みにしてあるため、
WndProc 画像の方の ↑1 で、主に WndCategory の方で部品番目から役割番号 WCOM_ 系を取得、↓2 以降がその定数群 WCOM_ 系を目印に
どの役割番号が意味付けられた部品ウインドウ W_COMMAND メッセージ通知なのか、その各処理が if の定数で手続き単位的に記述されているだけで、構造自体は単純になる。
↑1 では、基本は WndCategory で役割番号を取得、つまり GetMessage からの WM_COMMAND 通知による ↓2 以下が大半になるが、GetMessage からでない WndProc の WM_COMMAND の呼び出しをすることもあり、その場合での一定条件の処理用定数が WCOM_LIST_LMODECANCEL 190 で、↑1 でその場合( GetMessage からでない場合 )の役割番号の割り振りをする作りになっている。
GetMessage からでない WndProc の呼び出し自体がひとつの概念事項だからこそ、今回はここについては大した概念整理していないが「いったん作ってみて形になったから改めて見えてきたが、ここは( 後で )別の概念名にしてこの概念用の手続きも作った方が良いかも知れない」という見渡し方は常に怠らないようにし、規模に応じてその概念部分が顕著に目立つようになり次第に、その割り振りの仕方や概念名自体を見直し、前回分・今回分・次回分以降という段階管理的な再細分化・再集約化を予定していく前提を常にもっておくことが上達のコツに結びつく。
以下、WM_COMMAND の ↓2 以降の今回分の WCOM_ 系定数管理ごとの処理をざっと触れていく。
< WndProc WM_COMMAND WCOM_BUTTON_SETH / WCOM_BUTTON_SETR : H確/R全 ボタン >
Windows 標準 API 手続き = 赤1:UnhookWindowsHookEx 赤3:GetWindowTextW 赤6:IsWindow 赤7:GetAncestor と GetDesktopWindow 赤10:GetWindowLongPtrW と SetWindowsHookExW 赤12:SetWindowTextW
CRT 手続き = 赤5:wcstoll 赤9:_i64tow_s 赤11:wcscpy_s
AssistKeep プロジェクト共用手続き = 赤2:WndCategorySearchHandle 赤4:CheckNum 赤8:CheckWndStr
※ H確/R全 ボタン が押される際に、Windows の特殊機能 HOOK ( どのウインドウがアクティブ状態になっていてもキーやマウス等の入力操作を拾う仕様 )をいったん停止し、有効なウインドウハンドルの確定処理だった場合に HOOK 機能を開始しているのが、UnhookWindowsHookEx と SetWindowsHookExW の部分になる。HOOK 側の手続き hookProc については下述。
< WndProc WM_COMMAND WCOM_BUTTON_SETXY / WCOM_BUTTON_SETR : 座確/R全 ボタン >
Windows 標準 API 手続き = 赤2:GetWindowTextW 赤4:SetWindowTextW
CRT 手続き = 赤3:wcstoll
AssistKeep プロジェクト共用手続き = 赤1:WndCategorySearchHandle
< WndProc WM_COMMAND WCOM_BUTTON_LMODE / WCOM_BUTTON_LMODECANCEL : ■フォルダ式/●登録式 ボタン >
Windows 標準 API 手続き = 赤2・5・7:SetWindowText( W の付け忘れ。SetWindowTextW と同じ ) 赤3・6:EnableWindow
AssistKeep プロジェクト共用手続き = 赤1:WndCategorySearchHandle 赤4:UnionEventPathList
< WndProc WM_COMMAND WCOM_BUTTON_ENTRYA : 登録フォルダ追加 ボタン >
AssistKeep プロジェクト共用手続き = 赤1:AllocListStrAdd
< WndProc WM_COMMAND WCOM_BUTTON_ENTRYD : 登録フォルダ削除 ボタン >
Windows 標準 API 手続き = 赤2・7:SendMessageW 赤4:SetWindowTextW
AssistKeep プロジェクト共用手続き = 赤1・4:WndCategorySearch 赤3:AllocListStrDel 赤5:WndProc( GetMessage 仕様 ) 赤6:ListFolderBuildEntry 赤8:ListFolderMoveEntry
< WndProc WM_COMMAND WCOM_BUTTON_HISTORY : 履歴のファイル移動 ボタン >
Windows 標準 API 手続き = 赤2:SendMessageW 赤10:MoveFileW
CRT 手続き = 赤5:wmemset 赤7:wcscpy_s 赤9:wcscpy_s と wcscat_s
AssistKeep プロジェクト共用手続き = 赤1:WndCategorySearchHandle 赤3:CheckFolder 赤4:CheckFullPath 赤6:FolderSearchNumber 赤8:StrFileExtension 赤11:AllocListStrDel 赤12:AllocListStrAdd 赤13:WndCategorySearch 赤14:ListFolderBuildHistory
< WndProc WM_COMMAND WCOM_BUTTON_INITFS : 初期フォルダ位置変更 ボタン >
Windows 標準 API 手続き = 赤4:MessageBoxW
CRT 手続き = 赤3:wcscpy_s
AssistKeep プロジェクト共用手続き = 赤1:CheckFolder 赤2:CheckStr
< WndProc WM_COMMAND WCOM_BUTTON_INITFM : 初期フォルダ位置移動 ボタン >
Windows 標準 API 手続き = 赤2:SetWindowText( W の付け忘れ。SetWindowTextW と同じ )
AssistKeep プロジェクト共用手続き = 赤1:WndCategorySearchHandle 3:WndCategorySearch 赤4:WndProc( GetMessage 仕様 )
< WndProc WM_COMMAND 共用最終部 >
Windows 標準 API 手続き = 赤2:SetFocus
AssistKeep プロジェクト共用手続き = 赤1:WndCategorySearchHandle 3:WndProc( GetMessage 仕様 )
------------------------------------
------------------------------------
以上が、各ボタンが押された際を契機の WM_COMMAND メッセージ通知による、それぞれの手続き単位的( WCOM_BUTTON_ 系 )な各処理の配置部分で、それぞれは大して難しい記述などないこともあり、詳細説明はブログ機能の字数制限の都合で省略する。
WM_COMMAND 通知の仕組みを見渡してみると、定数名と定数値による想定計画を優先重視の、定数を手続き代わりに見立てる手法の方が良い場合もあることが窺える。
とりあえず手続きや変数を増やしていったことで概念間の詳細の形ができ始めた、だから概念関連の傾向を整理できるようになり、例えば定数計画で処理分けしていく作りに5、6個あった手続きを2、3種別に集約し直せそうなことに気づくといったことも常、そういう所を計画的に直していく積極的な繰り返しが上達の問われ所になる。
再細分化 = 別概念が混同されたまま詰め込まれ続けている部分を計画的に再編し直していく取り組み
再集約化 = まとめられる同概念がいつまでも分散され続けている部分を計画的に再編し直していく取り組み
今回例では WndProc に詰め込んでしまっているように見えるかも知れないが、逆に、各所のその if 内や while 内が大きめになったからという感覚だけで大した考えも無しに手続き化してしまっていないかが注意点になる。
それが ① 概念整理的な共用概念の強い手続き化 なのか、それとも ② その概念は今回分においてはそこで固定単体的・完結的なまとまりがある箇所内のただの小分けの手続き化 でしかないか、自身で箇所ごとに ① 前者 か ② 後者 かの傾向を見渡していくことも怠ってはならない。
今回の AssistKeep プロジェクトの例では、① 前者 の傾向が弱いものは積極的な手続き化はしない方針にしているが、ソースプログラム公開の観点からのそもそもとして、こと細かに手続き化され過ぎていると、関与している訳でもない第三者から見ればただでさえ誰かが分散した( 特に概念間統制・領域敷居管理が甘いばかりの )作りなど見やすい訳がないという配慮も含めている。
以下、WndProc( GetMessage )の、他の今回分の要点だけざっと触れていく。
< WndProc WM_KEYDOWN : エンターキー >
AssistKeep プロジェクトでは、上述した CheckWndStr 手続きの概念が作られたが、しかし今回は WndProc 側ではあえて前回 WindowBuild プロジェクトの部品判定( BUTTON か EDIT か LISTBOX かの判定 )の方式のまま( GetClassName で部品名を取得して頭文字で部品を判別する方法のまま )にしている。
次回以降で AssistKeep プロジェクトを元とする場合の次プロジェクトの場合、ここは CheckWndStr による判定で統一、CheckWndStr 用の WNDSEARCH_ 系定数の追加に改める、というその順序的な説明をしたかった、いきなり直すことの混乱を避けるために、こうした積極的な統廃合( 概念の分散や詰め込みを減らしていく互換/非互換領域管理 )が重要だという、よくあることだという例としての説明をしたかったため今回はあえて直さなかった。
※ WM_KEYDOWN 内での部品判定を CheckWndStr で統一することで、Enert キーと Tab キーのために設置していた WCHAR pClassName[ 8 ] が不要になり、さらに判定も true / false にできることで少しごちゃごちゃしていた部分を自然にすっきりさせられるようになる。気づき次第のこうした概念間の関連直しを面倒がらずに積極的に向き合うことが結局は上達の近道。
AssistKeep プロジェクトからは、例えば EDIT と LISTBOX とでの連動的な処理をしたい場合のために UnionEventPathList 手続きを用意することにし、UNION_ 系定数 で処理分けする方式にしている。
ここでは、EDIT なり LISTBOX なりにフォーカスがある時に Enter キーが押されたら UnionEventPathList 手続きを呼ぶ仕組みにしてあるが、Enter が押された際のその EDIT なり LISTBOX なりが連動を想定している役割番号かどうかの判定を UnionEventPathList 手続きの方で請け負い、そうなら連動処理( EDIT 側のフォルダ入力がされたら LISTBOX 側のフォルダ覧を更新/ LISTBOX 側でフォルダ選択やフォルダ移動をしたら EDIT 側のフォルダ文字列をそれに変更 )を実行する仕組みにしてある。
ここはやりようは様々で、CheckWndStr の概念を元に例えば UNION_ 系の想定値を返す CheckWndStrEvent という手続きを新たに作って、その取得値を UnionEventPathList に渡す作りにするのも手、また UnionEventPathList に UNION_系 による想定値を渡すのではなく HWND を渡す形にして UnionEventPathList 内でそれらを全て請け負う形にするのも手、といった改善余地の見渡し方などいくらでもできる。
いったん形ができるからこそ改善余地が次々に見つかる「さてどうするか」の繰り返しの世界だからこそ、教育機関絶対およびオブジェクトの規律絶対のただのいいなりどもように過程的な形に頭が良いだの悪いだのの低次元な正しさとやら( 目先の利害次第に何もかもをうやむやに徹底的に面倒がり合っているだけのただの性善説放任主義・偽善憎悪・老害浪費 )に全意識を全力で向けたがることしか能がない自分たちのその末期症状の愚かさだらしなさも自分たちで直せたことがない時点で、常に息切れとつまづきの急所を抱え続ける自分たちの低次元旧態体質をいつまでも改められる訳もない、だからこそ詳細の形ができ次第にいくらでも改善余地が出てくることに対する、その計画的な前回分・今回分・次回以降分という段階管理( ISO9000系善用の選任評議序列敷居観・概念間領域管理観 )の見渡し方が重要になる。
※ どの分野の商戦( 目的構築体制 )に対する向き合い方や人事敷居( 組織構想体制 )に対する向き合い方にも原理的に共通。荀子・韓非子・孫子の兵法の組織論で特に指摘している大事な教訓部分。
< WndProc WM_LBUTTONDOWN および WM_LBUTTONUP : マウス左ボタン押下( おうか )状態 および マウス左ボタン押下から離された状態 >
Windows 標準 API 手続き = 赤2:GetWindowLongPtrW と LoadCursorW 赤3:SetCursor
AssistKeep プロジェクト共用手続き = 赤1:WndCategoryCmp 赤4:UnionEventListPath
ここでは、HWND 取得 ボタン での、例の、ここでの押しっぱなしから始まるウインドウハンドルと座標の取得動作の開始契機と、また 赤4 の所では LISTBOX をマウス操作することでセル選択が移動した際の連動処理も行っている。
HWND 取得 ボタン から押し続けている最中はマウスカーソルが + のマークに変更、離すと元のマウスカーソルに戻るようにしているのが、LoadCursorW と SetCursor の部分になる。
LoadCursorW 関数 (winuser.h) - Win32 apps | Microsoft Learn
SetCursor 関数 (winuser.h) - Win32 apps | Microsoft Learn
カーソルについて - Win32 apps | Microsoft Learn
ID?_ 系定数は Microsoft 側が用意している定数で、Microsoft Learn の「カーソルについて」の所に定数群がひと通り記述されている。
赤2 の GetWindowLongPtrW の所の GWLP_ 系定数も Microsoft 側が用意している定数だが、この説明記述をしていて気づいたが 赤2 の GetWindowLongPtrW は結局不要だったことが解った後に、消すのを忘れてしまった。
< WndProc WM_MOUSEMOVE : マウスカーソル座標が動いた時 >
Windows 標準 API 手続き = 赤1:GetCursorPos と WindowFromPoint 赤4:SetWindowTextW
CRT 手続き = 赤2:_i64tow_s と _itow_s
AssistKeep プロジェクト共用手続き = 赤3:WndCategorySearchHandle
HWND 取得 ボタンからの押しっぱなしが続いている状態かどうかを保持する g_bMouseTagetDown によって、現在のマウス位置のウインドウハンドルの取得と座標の取得をして、AssistKeep 画面部品にそれぞれ反映させる処理。
当ブログ筆者は共用変数( どのプロジェクト内手続きからも参照できるグローバル変数 )は g_ を付けているが、g_bMouseTagetDown の変数名に r を入れ忘れてしまった。
ここでは HWND 3個( 8 x 3 = 24 BYTE )と WCHAR [ 20 ] 3セット( 40 x 3 = 120 BYTE )の変数、合わせて計 144 バイト分の設置しているが、統合前 32 Bit 時代でもこのような箇所ごとの変数 144 バイトごときで負荷になどならないため、概念整理優先の変数の設置の仕方をしてしまって問題ない。
< WndProc WM_SETFOCUS : 自ウインドウ( AssistKeep )が非アクティブからアクティブに戻った時 >
Windows 標準 API 手続き = 赤2:SetFocus
AssistKeep プロジェクト共用手続き = 赤1:WndCategorySearchHandle
AssistKeep では、ウインドウハンドルを取得/確定した後は、AssistKeep 画面が非アクティブ状態や最小化( タスクバー隠し )状態でも 無変換キー + Shift キー で 名前を付けて画像を保存 画面を呼び出して自動保存する作りにしてあるが、ウインドウの都合としては、現在のアクティブウインドウ( 最前面ウインドウ )のハンドルを一時的に保持し、Microsoft Edge をいったん最前面にして自動保存し、終わったらそのウインドウハンドを最前面に遷移し直す、という仕組みにしてある。
ここでは、AssistKeep が最前面( アクティブ )状態から 無変換キー + Shift キー で自動保存が行われて最前面が再び AssistKeep に戻った場合、もしくはマウス操作等で AssistKeep から他の画面が最前面になった後に、マウス操作等で再び AssistKeep に戻った際に、AssistKeep 内の部品フォーカスをフォルダリストに当て直している。
AssistKeep が再最前面した際に、フォルダリストに常にフォーカスを当てておくことによって、すぐにキーボードの上下キーとエンターでリスト側を操作できるようにしておいた方が便利かも知れないと思っての処理になる。
ここでは、画面が再アクティブ化した際に通知される WM_SETFOCUS の意味と、画面部品のフォーカスを制御するための Windows 標準 API の SetFocus / GetFocus の、アクティブ/フォーカスを巡る厳密な意味が少し違っていて( WM_SETFOCUS は、画面の再アクティブで画面部品フォーカスの復帰が起きた契機という意味と見られる )少々ややこしい。
< hookProc >
赤A は最前面ウインドウハンドルの取得で、この GetForegroundWindow が Windows 標準 API、B1~6 はいずれも AssistKeep プロジェクト共用手続きになる。
赤A の意味としては、まず AssistKeep 側の都合として H確/R全 ボタンによるウインドウハンドル( つまり Microsoft Edge )に対する操作を投げかける際に、AssistKeep をいったん最前面化しなければならない必要があり、用途終了後に開始前の最前面ウインドウに戻す一時保持のためで、B以降は省略するが、HOOK による用途処理の終了時に SetForegroundWindow で戻す作りにしてある。
B側は
B1 CallDialogNameSearch 名前を付けて保存 画面が既に表示されているかどうかを確認する( されてたら無効終了 )
B2 IMEOff 対象ウインドウハンドル( Microsoft Edge )のIMEをオフにする
B3 CallPopup 対象ウインドウハンドル( Microsoft Edge )のポップアップメニュー画面を呼び出す
B4 CallDialogName ( ポップアップメニュー 画面表示中の想定で )名前を付けて画像を保存 画面を呼び出す
B5 CallDialogNameFolderToFile ( 名前を付けて保存 画面表示中の想定で )AssistKeep 側で指定しているフォルダ位置に移動し、ファイル名を自動番号ファイル名に変更する
B6 CallDialogNameEnter ( 名前を付けて保存 画面が表示されている想定で )保存 ボタンを押したことにして保存する
という手順的な並びになっている。
以下、各手続きの要点に触れる。
< AssistKeep 共用手続き B1 CallDialogNameSearch >
Windows 標準 API 手続き = 赤1:GetDesktopWindow 赤2・4:GetWindow
AssistKeep プロジェクト共用手続き = 赤3・5:CheckWndStr
< AssistKeep 共用手続き B2 IMEOff >
Windows 標準 API 手続き = 赤1:ImmGetFefaultIMEWnd 赤2:SendMessageTimeoutW
AssistKeep の HWND 取得 ボタンと H確/R全 ボタン によって対象にしたウインドウのIMEをオフにする。
※ IMEのオンオフの投げかけは、他インスタンス間ウインドウの場合は SendMessage 系だが、自インスタンス内ウインドウの場合はコンテキストを使った全く違う手法になることに注意。
< AssistKeep 共用手続き B3 CallPopup >
Windows 標準 API 手続き = 赤1:IsWindow 赤3:SetForegroundWindow 赤4:SendMessageW 赤6・9:GetWindow 赤8:MessageBox
AssistKeep プロジェクト共用手続き = 赤2:AccumScreenToWindow 赤5:TimeLimitStart 赤7:TimeLimitCounter
Microsoft Edge のポップアップメニューを表示させるための手続き。
< AssistKeep 共用手続き B4 CallDialogName >
Windows 標準 API 手続き = 赤1:SetForegroundWindow 赤2:keybd_event 赤3:Sleep 赤7:MessageBox 赤9:IsWindowVisible
AssistKeep プロジェクト共用手続き = 赤4:TimeLimitStart 赤5・8:CallDialogNameSearch 赤6:TimeLimitCounter
Microsoft Edge のポップアップメニュー画面が表示されている前提で、ポップアップメニュー画面の 名前を付けて画像を保存 画面を押したことにして 名前を付けて保存 画面を表示させる。
keybd_event はいわば最終手段のキー操作 API で、現在の最前面ウインドウがどこかなど関係無しに Windows 側にキーボードのそのキーを押したことに する API で、そのマウス版が mouse_event になる。
例えば、Microsoft Visual Studio のデバッグモード( F5 キー実行 )でこの keybd_event の直前でブレークポイント中断し、ソース画面が表示されている状態から再開するとソース画面に keybd_event の実行をしてしまう特性のため、例えば GetFocus / SetFocus なり GetForegroundWindow / SetForegroundWindow なりによる想定の用法が重要なことに少し注意になる。
keybd_event関数 (winuser.h) - Win32 apps | Microsoft Learn
mouse_event関数 (winuser.h) - Win32 apps | Microsoft Learn
赤5 赤8 の CallDialogNameSearch の所のコメントを消し忘れていた。
当初、CallDialogNameSearch はこの CallDialogName 内の手続き内手続きとして設置していたが、プロジェクト共用手続きに改めることにし、その際にコメントを消し忘れてしまった。
< AssistKeep 共用手続き CallDialogNameFolderToFile >
手続き内手続き = TextSetCheck 呼び出し:赤10・14・21
Windows 標準 API 手続き = 赤3・8:SendMessageW 赤7:SetForegroundWindow 赤9・13・20:Sleep 赤11・15・19・22:MessageBoxW 赤12・23:keybd_event
CRT 手続き = 赤2:wmemset 赤5:wcslen 赤6:_wcsnicmp 赤18:wcscat_s
AssistKeep プロジェクト共用手続き = 赤1:DialogNameWndSearch 赤4:CheckFolder 赤16:StrFileExtention 赤17:FolderSearchFileNumber
名前を付けて保存 画面が表示されている前提から、ファイル名の入力項目を使って AssistKeep 指定のフォルダに保存場所を移動させ、その指定フォルダの番号ファイル名を生成して入力項目に貼り付る、所までの動作を請け負っている手続き。
この処理は Window 7 / 10 までならもう少し簡単かつ処理速度的にもだいぶ快適にできたが、Windows 11 にも対応する場合、細かい所の挙動の違いが多かったことでここの同期が急激に難しくなったため驚いた。
処理速度的にあまりモタつかせないよう、各 Sleep の待ち時間を 100 ( 0.1秒 )にしている箇所が多いが、全て 200 にした方が良かったかも知れない。
< AssistKeep 共用手続き CallDialogNameEnter >
Windows 標準 API 手続き = 赤2・3・7:SendMessageW と SendMessageTimeoutW 赤5:IsWindow
CRT 手続き = 赤8:wcscpy_s と wcscat_s
AssistKeep プロジェクト共用手続き = 赤1:DialogNameWndSearch 赤4:TimeLimitStart 赤6:TimeLimitCounter 赤9:AllocListStrAdd 赤10:AllocListStrDel 赤11:WndCategorySearch 赤12:ListFolderBuildHistory
< AssistKeep 共用手続き DialogNameWndSearch >
Windows 仕様のための典型的な手続きであるため、ついでに紹介。
Windows 標準 API 手続き = 赤1:GetWindow 赤3:GetNextWindow
AssistKeep プロジェクト共用手続き = 赤2:CheckWndStr
DialogNameWndSearch 手続きは、指定するウインドウハンドルに所属する部品ウインドウハンドルに目的の 部品名/キャプション名 があるかどうかの捜索だが、今回の AssistKeep での使い方としては、Microsoft Edge の 名前を付けて保存 画面の
ファイル名の入力項目の部品を探し、そのウインドウハンドルを取得することを目的としている。
その場所というのが
名前を付けて保存 画面の所属階層の、5層目の Edit がその入力項目になる。
所属する部品ウインドウハンドルに所属している子ウインドウハンドル( 子階層 )も順々に捜索の、所属階層全体を1周捜索する作りになっている。
今回の AssistKeep での使い方では 名前を付けて保存 画面に対する想定の定数( ここでは WNDSEARCH_ 系 )しか用意していないが、ダイアログ式の画面に対してなら( 入力項目やボタンやリストといった Windows のおなじみの部品概念で構成されている画面なら )定数の追加次第でどのウインドウにも対応している。
------------------------------------
------------------------------------
今回、timeGetTime( TimeLimitStart )と IME 関連の API の使用で、インクルード( framework.h )に
これらを追加しなければならない所に注意になる。
1P内でこの倍の分量の説明をしたい所だったが、ブログ機能の字数制限の都合で今回はここまでにする。
今後もこのように何かを作りながらのオープンソースの姿勢で、あるあるな他の分野の取り組みにおいても共通する説明を続けていく予定。

































