MSOS/ 2PM のプログラ ミングについて
‑ マル チ ス レ ッ下及 びヘ ル プ ‑
行 方 常 幸
目 次 1.は じめに
2.マルチスレッド 3.ヘルプ
4.おわ りに 参考文献
1.はじめに
ここでは具体的なプログラムを通 して OS/2のマルチス レッ ド及 びPM (プ レゼ ンテー シ ョンマネー ジャ) におけるヘルプに関 して述べ る.
シングルユーザマルチタスクの OSであるOS/2は複数の プ ログラム (プロ セス)を同時 に実行で きる。 さ らに1個のプログラム (プ ロセス)をい くっか のス レッ ドに分割 してそれ らを同時に実行で きる。 す なわ ちOS/2において実 行単位 はス レッ ドであ り, 1個 のプログラム (プロセス)が 1個のス レッ ドか ら成 り立 ってい る場合 や,複数のス レッ ドか ら成 り立 っている場合があるわ け であ る。例え ば,C言語で プ ログラムを書 くときはmain関数 はメイ ンス レッ ドを構成 し, プログラム中で新 しくス レッ ドを生成 しない限 り 1個のス レッ ド か らな るプ ログラム とな る。 OS/2のGUI環境 であ るPMの プログラムにお いて は長 い処理時間を要す る仕事 を別 ス レッ ドとして生成 し,ユーザーか らの (キーボー ドやマ ウスによ る)入力 を処理す る部分 と別 け る ことによ りユ ー
〔463〕
464 商 学 討 究 第 42巻 第2・3号
ザ‑か らの入力に対する反応を早 くすることが出来 る。新 しいスレッ ドを生成 するのはシステム関数を呼び出すだけでよいのだが,マルチス レッ ド化により 新たに対処 しなければな らない問題 (資源の共有) も生 じる。
PM のプログラムではユーザーの便宜のために各 メニ ュー項 目等にヘルプ をっけることが勧め られている。ユーザーがどうした ら良いか分か らない時に
< f・1>キーを押せば適当な指示を記載 したヘルプ画面を表示するようにす るのである。
以上のマルチス レッ ド及びヘルプを実現する方法を以下に説明する。利用 し たプ ログラム例 は以前発表 した 「フル ス ク リー ン用 プ ログラムの始動」
(STARTFUL.EXE)である。図にソースプログラムの一部を入れてある が, これ らは元の完全なものか ら大部分を削除 してあり,プログラムの流れの 大体の感 じを表す ことだけを意図 している。また,関数のうちWinとDosで 始まるものはシステム関数であり,それ以外は作成 したものである。
2.マルチス レッ ド
OS/2の実行単位 はス レッ ドと呼ばれ るものである。 このス レッ ドをある 時間実行 して次にまた別のスレッ ドを実行する。 これを続けることにより複数 のス レッドを同時に実行 している。 ここであるス レッドの処理を中断 したとき にどのスレッ ドの処理を始めるかであるが,各ス レッドは3つの優先順位のク ラス (タイムクリティカル, レギュラー,アイ ドルタイム),さらに各 クラス が32の レベルに分かれている,のどれかに属 しており, この うち優先順位の高 いものか ら順にCPU時間が割 り当て られる。長い処理時間がかかる仕事を別 ス レッ ドとして生成 し,ユーザーか らの入力を処理す るスレッ ドの優先権を上 げてお くと長い仕事の処理中で も優先権の高いユーザーか らの入力を先に処理 す ることになる. 「フルスク リー ン用 プログラムの始動」 (STARTFUL EXE)において以下のようにマルチスレッ ド化を行 った。
「フルスクリーン用プログラムの始動」ではリス トボックスか らプログラム を選択することによって始動 させる。 このプログラムを実際に始動 させる部分
MSOS/ 2PMのプログラ ミングについて 465
を別 ス レッ ドとして生成 した。 まず,main関数 内でユーザーの入力処理 を含 む クライア ン トウィ ン ドウプ ロシー ジャClientWndProcの属 す るメイ ンス
レッ ドの優先権 を1レベル上 げ る。 (図.1参照)
DosSetPrty(PRTY S̲ TH REA D,PR TY C̲ N OCH A N GE,1,0);
削nclude''myhelp.h'' /‡ヘルプのためのヘッダファイル*/
USHORTmainくSHORTargc) i
hab=Uinlnitialize(0);
hmq≡UinCreateMsIQueue(hah,0);
UinRegisterClass(hah,szClientClass,
ClientUndProc,CS̲SIZEREt)RAW,0);
hndFranle=UinCreateStdUindow(HUND̲DESKTOP,OL,
&f]FrameFIags,sZCHentC)ass,
NULL,OL,(HMODULE)NULL,.D̲RESOURCE,
&hndClient);
if(日nitHe]p(hah,hvndFrame)) /*ヘルプインスタンスの作成 ‡/
t
UinMessageBox(HWND̲DESKTOP,HUND̲DESKTOP,
"ヘルプがインストール出来ません!",
szClientCtass,0,
MB̲OK IMELICONEXCLAMAT10N);
uinDestroyUindoLJ(hwndFrame);
UinDestroyMsgQueue(hmq);
UinTerminate(hah);
returnl;
〉
DosSetPrty(PRTYS̲THREAD,PRTYC̲NOCH'ANGE,1,0),・
/*メインスレッドの優先権を1レベル上げる 事/
while(TRUE) t
while(UinGetMsS(hah,&叩Sg,NULL,0,0)) UinDispatchMsg(hah,&qmsg);
if(UinDIgBox(HUND̲DESKTOP,hwndCl看ent,
EndDlgProc,(HMODULE)NULL,lDD̲END,NULL)) break;
UinCanceIShutdown(hmq,FALSE);
〉
TerminateHelp(hndFrame); /事ヘルプインスタンスの破壊‡/
UinDestroyUindow(hundFrame);
UinDestroyMsgQueue(hmq);
WinTermimate(nab);
「eturn0;
)
図.1 m ain関数
466 商 学 討 究 第42巻 第2・3号
後 は リス トボ ックスか らのプログラムが選択 された とい うメ ッセージを受 け 取 った時点でそのプログラムを始動す るス レッ ドを生成す るだけである。新 し
いス レッ ドを生成す るにはシステム関数 DosCreateThreadを呼び出すか, C言語のライブラ リ関数̲beginthreadを呼び出す ことによって可能である。
後者を使 う場合 はメモ リモデル としてラージモデルを利用す る必要があ り,私 としてはなるべ くスモールモデルでプログラ ミングを行いたいので,前者を利 用 す る ことに した。 リス トボ ックスか らの メ ッセ ー ジによ り関数 Start‑ Sessionが呼び出されス レッ ド用スタ ックなどの領域を確保 し必要なデータを 初期化 し,その後,システム関数 DosCreateThreadを呼び出す (図.2参照)。
システム関数 DosCreateThreadの引数 は生成す るス レッ ド (ス レッ ドと 言 って も見かけは普通の関数 と同 じ)のア ドレス,ス レッ ドIDを受け取 る変 数のア ドレス,スタック領域のア ドレスである。 ここで少 しだけ注意す るとこ
ろがある。 システム関数DosCreateThreadの第 1引数でア ドレスを指定す る関数 は引数を持っ ことが出来ない, とマニュアルではなっている。 しか しな が ら文献 [1]に習 って,強引にスタ ックに引数を入れ,それを使 う関数 も引 数を取 るように定義 してお くと実際はうま く行 くようである (コンパイラをだ ますために少 し細工 は要 るようだが !)。別 ス レッ ドStartThreadで は引数 か ら始動すべ きプログラム情報を獲得 しシステム関数 DosStartSessionでプ ログラムを始動 させ,その後 このス レッ ドが利用 したスタック領域を解放す る よ うにメ ッセー ジをメイ ンス レッ ドにポス ト(WinPostMsg)し, 自分 自身 だけを終了 させ る。このよ うにプログラム してお くと,ス レッ ドStartThread はメインス レッ ドより優先権が 1レベル低いためメイ ンス レッ ドに処理 しなけ ればな らない仕事が残 っている間はメイ ンス レッ ドを先に実行す る。すなわち ユーザーの入力処理が待たされることはない。
さて,別ス レッ ドStartThreadを生成す る毎にそれ用のスタ ック等の領域 を確保 しな くてはな らない。別ス レッ ドをい くつ生成す るかはあ らか じめ分か らないことと,共通の資源であるメモ リを有効 に利用す るめに,別ス レッ ドを 生成す る毎 に領域を確保 し,ス レッ ドが終了すれば解放す ることが望ま しい。
MSOS/ 2PMの プ ログラ ミングにつ いて
USHORTStartSession(HUNDhwnd) t
VOIDFAR 紬ummy;
/‡スレッド用スタックなどの領域確保 ‡/ /事構造体DOSSTARTDATAの初期化 事/ dummy=(VO柑 FAR辛)StartThread;
DosCreateThread((PFNTHREAD)dummy,&(PDosStData‑>tid),stack);
returnVALID;
)
VOIDFARStartThread(PDOSSTARTDATA pDosStData)
〈
DosStartSession(a(PDosStData‑>stdata),a(PDosStData‑>idSession),
&(PDosStData‑>pid)),'
UinPostMsg(PDosStData‑>hwnd, WM‑MYMESSAGEIFREE,
MPFROMSHORT(pidinfo.tid),MPFROMSHORT(PDosStData‑>pData));
DosExit(EXIT̲THREAD,0);
)
VOLDSuspendAllThread(VOID) t
MEME事LOCK*pMemBlock;
DOSSTARTDATA *PDosStartE)ata;
DosEnterCritSec();
for(pMemBlock=PStartData;PMemBIock;
PMemBlock=(MEMBLOCK*)(PMemBIock‑>ppChar)) i
pDosStartData=(DOSSTARTDATA*)pMemBlock‑>Char;
DosSuspendThread(pOosStartData‑>tid);
)
DosExitCritSec();
〉
図.2 ス レッ ドの生成、実行 中断
467,
そのために別 ス レッ ドStartThread終了間際に作成者のメイ ンス レッ ドに確 保 して くれたメモ リが もう不要 になる由を伝えれば良い。細かい話になるが, メ ッセー ジを送 るには2個の システム関数 W inSendM sg とW inPostM sg
があり,関数 StartThreadではW inPostM sgを利用 している。それはス レッ ドStartThreadはメイ ンス レッ ドm ainのよ うにシステム関数 W inCreate M sgQueを呼び出 して メ ッセー ジキ ューを作成 して いないので W inSend‑
M sgを利用で きないためである。W inSendM sgは送付 したメ ッセージの処
468 商 学 討 究 第 42巻 第 2・3号
理が終 わ るまで呼び出 し元へ戻 って こないが,W inPostM sgはメ ッセージを 送付先 のメ ッセー ジキ ュ‑に入れた らす ぐに戻 って くる。 さて,最後 にメイ ン
ス レッ ドが別 ス レッ ド用 に確保 したメモ リを解放す るときに若干 の問題点が残 る。別 ス レッ ドが終了す る前 に このス レッ ド用 に確保 したメモ リを解放 して し ま うと最悪の場合暴走 して しま う。 また,確保 したメモ リを解放す る必要があ るの は別 ス レッ ドが もう自分 は終了す るか ら解放せ よ, とい う場合 の はか に ユーザーが プログラム 自体 を終了す る時の後処理の場合 もある。前者 の処理 は 図.3の C1ientW ndProcの メ ッセ ー ジ W M ̲ M Y M ESSA GE̲ PR EE の 所,後者 の処理 はメ ッセ ‑ ジW M ̲ D ESTR OY の所 で行 ってい る。 どち ら
MRESULTCALLBACKClientUndProc(HUNDhnd,USHORTmsg,MPARAMmpl,MPARAMmp2)
〈
sIJitch(msg)(
caseUM̲COMMAND:
svitch(COMMANDMSG(&msg)‑>cmd) (
case IDMIABOUT:/‡必ず処理す るようにする ‡/
UinDlgBox(HUND‑DESKTOP,hwnd,
AboutDlgProc,(HMODULE)NULL,
FDD̲ABOUT,NULL);' return0;
CASE̲REPLY̲HELP̲AAB̲MSG
/*UM̲COMMANDメッセージ処理文中に入れる 事/ I
break;
CASEIREPLY̲HM̲MSS
/*メッセージ処理文中(一番外のswitch)に入れ る ‡′
caseUMIMYMESSAGE̲FREE:
DosSuspendThread(SHORTIFROMMP(mpl));
PStartData=(MEMBLOCK辛)MemFree(PStartData,
(CHAR辛)SHORTIFROMMP(mp2));
「eturn0;
caseUM̲DESTROY:
SuspendAlIThread();
i千(PStartData)
MemFree(PStartData,NULL);
return0;
)
return uinDefUindowProc(h nd,m
s g
, mpl,mp2);)
図.3 ウ ィ ン ドウプ 田 シー ジ ャClientW ndProc
MSOS/2PMのプログラ ミングにつ いて 469
もメモ リを解放す る前に利用者であるス レッ ドをシステム関数 DosSuspend Threadで中断 し, この後メモ リを解放 している。 これでプログラムが暴走 し て しまう心配 はないOメッセ‑ジWM̲DESTROY処理中に呼び出 してい る関数 SuspendAllThreadで はス レッ ドを中断す る前後で システム関数 DosEnterCritSecとDosExitCritSecを呼び出 している。 この2個の関数 呼び出しの間に書かれている処理 は他のス レッドによって中断されない。
以上のようにマルチス レッ ド化 した ことによる実際の効果 は次のよ うであ る。バ ックグラウン ドで実行,実行時最小化 しない, と設定 しておいてか ら, 例えば,マウスを システムメニ ューボックスの所 に移動 させておき,CMD EXEにカーソルを移動 し素早 くリター ンキーを10回押す。その後 また素早 く マウスをダブルクリックし終了 して もよいかの質問に対 して リターンキーを押
しはいと答える。画面には2,3個の今始動 させたCMD.EXEのアイコン が残 り,STARTFUL.EXEはすでに終 了 している。 これ によ りCMD.
EXEを始動 させるス レッ ドStartThreadを10回作成 したが,優先権が 1レ ベル高いメインス レッドがユーザーか らの終了要求を処理するまでに 2, 3個 のStartThreadが CMD.EXEを始動す ることがで き,その他 は途中で中 断させ られたことが分かる。マルチス レッ ド化 していない場合はCMD.E支E
が10個始動 され るまでSTRTFUL.EXEが終了す ることはないo この例は 多分に窓意的なものであるが,時間のかか る処理を間違 って実行 させて しまっ てか らそれを取 り消 した くて もその手段がな く長い時間待つ羽 目に陥 ったユー ザーな らこのマルチス レッド化の有用性 は納得 して頂けると思 う。
3.ヘ ル プ
ソフ トウェアを利用 している時,途中で操作法が分か らな くなって困 った, 等 ということは誰で も経験す ることと思われる。その時まさに困 っている場面 のヘルプがあった らどんなにソフ トウェアが使いやす くなるであろうか ?ここ では, このヘルプ機能を如何にすれば実現できるかを説明す る。現在, 日本語
MSOS/2はVer.1.21になっているが,私がヘルプ機能を最初 に実現 しよ
470 商 ・学 討 究 第 42巻 第 2・3号
うとした5カ月 ぐらい前 はVer.1.1であった。Ver.1.1の時には無か ったヘ ルプマネージャと呼ばれ るものがVer.1.21には組み込まれてお り,ヘルプを 実現する労力が大分軽減 されている。 ここではヘルプマネージャを使わない方 法 と使 う方法の両方を説明す る。Ver.1.21のヘルプマネージャを使 う方が 目 次や‑イパ ーテキス トを利用で きる等 の利点が あるが,ヘルプを関連付 けた ウィン ドウをヘルプウィン ドウの前面に持 ってきたりヘルプウィン ドウをアイ コンにで きない欠点がある。
ユーザーはヘルプを必要 とす る時に< f・1>キーを押 した り,ヘルプボタ ンがあればマウスでそれをク リックする。 この動作を感知 してその時にキー入 力を待 っていたウィン ドウに関す るヘルプを表示すればよいわけである。通常 で は<f・1>キーを押 した りMIS̲HELPスタイルを持っ メニ ュー項 目
(メニューバ ーの右端 にある 「F 1‑ヘルプ」)をマウスでク リックすると, その時にキー入力を待 っていたウィン ドウにWM̲HELPメ ッセージが送付 され る。また,ヘルプボタ ンをクリックす るとボタンのオーナーウィン ドウへ WM̲HELPメ ッセージが送付 され るoそ こで,ヘルプを処理 したいウィン ドウプロシージャにWM̲HELPメ ッセージの処理 として適当なヘルプを表 示す るよ うにプログラムすればよい。 しか しなが ら各 ウィン ドウプロシージャ でWM̲HELPを処理す る方法ではメニュー項 目に対す るヘルプを処理す る ことがで きない。メニ ュー項 目に対す るヘルプを処理す るためにはヘルプフッ クと呼ばれ るものを利用 しな くてはな らない。ヘルプマネージャを利用 しない
「方法 1」もヘルプマネージャを利用す る 「方法 2」も共 にヘルプフックを利 用 している。「方法 1」ではヘルプフックを直接利用 し,ヘルプを表示す るウィ
ン ドウを自分で作 る必要があるためプログラムの中心 はこのウィン ドウの管理 であ り,全ての場合に対す るヘルプを準備す ることとヘルプを利用 し易 くする
こと等に関 しては対処 していない。それに対 して 「方法2」ではヘルプフック を利用 している部分 は我々ユーザーには隠されてお り,全ての場合 に対す るヘ ルプを準備で き,さらに細かい点にも配慮がなされている。ただ,最初 にも述 べた通 り,ヘルプウィン ドウが背面 に移動 しないこと,アイコン化出来ないこ
MS OS/ 2PMのプログラ ミングについて 471
とが私には欠点 と思われる。以下, 「方法 1」に関 してはヘルプウィン ドウの 管理を中心に, 「方法2」ではヘルプマネ‑ジャの利用法を中心に述べる。
「方法 1」
方法 1ではメニューとメ ッセージボ ックスのヘルプにヘルプフ ックを利用 し,それ以外 は各 ウィン ドウプロシージャでWM̲HELPを処理することで 対応 している。また,ダイアログボ ックスでは 1つのヘルプ しか表示できずそ の子 ウィン ドウのヘルプには対応 していない。先ずmain関数でメ ッセージ ループへはいる前にヘルプフックを設定 してお く。 (図.4参照)
WinSetHook(hah, hmq, HK̲HELP,(PFN)HelpHook, NULL);
こうしてお くと,例えば,メニュー項 目を矢印キーで選択 して< f・1>キー を押す とその情報が 4番 目の引数 に指定 してある関数 HelpHookへ送 られ
るOメ ッセージループが終了 した ら
WinReleaseHook(hah,hmq,HK̲HELP,(PFN)HelpHook, NULL);
と設定を無効に してお く。関数 HelpHook(図.4参照)ではヘルプ要求がメ ニューか らか処理すべ きメッセージボックスか らかを判断 しその場合には
WinSendMsg (hwndHelp, WM MYMESSAGE HELP OPEN,MPFROMSHORT(idHelp),NULL);
と表示すべ きヘルプ内容を区別するidHelp(この場合はメニュー項 目の識別子 またはメッセージボックスの識別子)を含むメッセージWM̲MYMESSAGE
HELP̲OPEN (表示要求を意味するユーザー定義のメッセ‑ジ)をヘルプ を表示するウィンドウに送付する。その他ヘルプを付けるウィン ドウ (クライア ン トウィンドウ,ダイアログボックス等)で も,図.4のC1ientWndProcのよ うにWM̲HELPメッセージの処理として適当なidHelpを指定 して
WinSendMsg(hwndHelp,WM̲MYMESSAGE̲HELP̲OPEN, MPFROMSHORT(idHelp),NULL);
472 商 学 討 究 第42巻 第2・3号
#includenHELPUND.H"
MRESULTCALLBACKClientUndProc(HtJNDhwnd,USHORTmss,MPARAMmpl,MPARAMmp2);
BOOLCALLBACKHelpHook(HADhah,USHORTusMode,USHORT idTopic, USHORT idSubTopic,PRECTLpreposition);
USHORTmain(VOID);
USHORTmain(VOID)I
hab=Uinlnitialize(0);
hmq=UinCreateMsgQueue(hah,0);
UinRegisterClass(hah,szClientClass,ClientUndProc,CS‑SIZEREDRAU,0);
hwndFrame=UinCreateStdUindotJ(HUND̲DESKTOP,OL,
&flFrameFlags,szClientClass,
NULL,OL,NULL,lD̲RESOURCE,
&hndCIient);
if(hl州dFrame==NULL) t
UinDestroyMsgQueue(hmq);
UinTerminate(hab);
returnl;
〉
if(!(hwndHelp=CreateHelpUindow(hah,hwndFrame)))′‡ヘルプ画面の生成 ‡′ t
UinMessageBox(HUND̲DESKTOP,HUND̲DESKTOP,
''ヘルプが インス トール出来 ません !'', szClientClass,0,
Ⅷ̲OK IMB̲ICONEXCLAMAT10N);
UinDestroyUindow(hndFrame);
UinDestroyMsgQueue(hmq);
tJinTermimate(hah);
returnl;
)
tJinSetHook(hah,hmq,HK̲HELP,(PドN)HelpHook,NULL);/事ヘルプフック設定 ‡/ uhile (UinGetMsg(hah,&qmsg,NULL,0,0))
UinDispatchMsg(hah,&qmsg);
uinReleaseHook(hah,hmq,HK̲HELP,(PFN)HelpHook,NULL);/‡ヘルプフック破棄 */
DestroyHelpUindow(hwndHelp);/‡ヘルプ画面の破棄 ‡/
UinDestroyUindotJ(hwndFrame);
UinDestroyMsgQueue(hmq);
UinTermimate(hah);
return0;
〉
MRESULTCALLBACKClientUndProc(HUNDhwnd,USHORTmsg,MPARAMmpl,MF)ARA‖mp2)(
sIJitch(msg)〈
caseUM̲HELP):
WinSendMsg(hwndHelp,UM̲MYMESSAGE̲HELP̲OPEN, MPFROMSHORT(lD̲HELP̲川TRO),NULL);
return0;
‡
図.4 (つづ く)
MSOS/ 2PMの プ ログラ ミングにつ いて returnUinDefUindoIJProc(hwnd,ms名,mPl,mp2);
〉
473
BOOLCALLBACKHelpHook(HADhah,USHORTusMode,USHORT idTopjc,
USHORT idSubTopic,PRECTLpreposition) (
suitch(usMode) t
caseHLPM̲MENU:
stJitch(idTopic) i
case 川M̲SET/‡ トップレベルメニューのid辛/:
shlitch(idSubTopic)
〈
CaseOxFFFF:
/寺caseサブメニューのid*/
case IDM̲ADD̲FROG:
case トDM̲REV̲FROG:
case lDM̲DEL̲FROG:
caseJDM̲BACK:
Case JDM̲MIN.I Case JDM̲ABOUT:
caseSC̲CLOSE:
uinSendMsg(hwndHeIp,
UM̲MYMESSAGE̲HELf)̲OPEN,MPFROMSHORT(idSubTopic),NULL);
「eturnTRUE;
)
〉 break;
caseHLPM̲MNDOV:
switch(idTopic)
〈
caseMB̲lDlt)ELETEPROGRAM/‡ メッセージボックスのid*/:
UinSendMs苫(hlJndHelp,W̲MYMESSAGE̲HELP̲OPEN,
MF'FROMSHORT(idTopic),NULL);
returnTRUE;
〉 )
returnFALSE;
〉
図.4 方法 1のTEMPLATE.C とする。
残 っているのはヘルプを表示す るウィン ドウ (hwndH elpが意味す るもの) を作成す ることである。 このウィン ドウの作成 と破壊 は図.4の
hwndH elp‑ CreateHelpW indow (hah,hwndFram e);
DestroyHelpW indow (hwndH elp);
であると これ らの実際の内容 とこのウィン ドウの動作を次に述べ る0
474 商 学 討 究 第42巻 第2・3号
♯include''MYHELP.H''
MRESULTCALLBACKHelpUndProc(HUNDhwnd,USHORTmss,MPARAMmpl,MPARAMmp2);
MRESULTCALLBACKHelpTextUndProc(HUNDhwnd,USHORTms苦,MPARAMmpl,MPARAMrnp2);
HUNDCreateHelpUindow(‖ADhah,HUNDhwnd);
BOOLDestroyHelpUindow(HIJNDhwnd);
typedefstruct
〈
USHORT id;
PCHAR Title;
)HELPITEM;
HUNDCreateHelpUindow(HADhah,HUNDhwnd)t habSaved=hah;
uinRegisterClass(hah,szHelpClass,HelpUndProc,CS̲SIZEREDRAtJ,siZeOf(HWND));
UinCreateStdUindow(HUND̲DESKTOP,OL,
&flHelpFrameFlags,sZHelpClass,
NULL,US̲CLIPCHJLDREN,(HMODULE)NULL, lD̲HELP̲RESOURCE,&hwndHelp);
UinSetUindowPtr(hwndHelp,0,hwnd);
returnhundHelp;
i
BOOLDestroyHelpUindow(HUNDhtJnd)(
returnUinDestroyUindow(UinQueryUindotJ(h州d,QU̲PARENT,FALSE));
〉
MRESULTCALLBACKHelpTextWndProc(仙NDhwnd,USHORTmss,MPARAMnpl,MPARAMmp2)(
switch(msg)t
caseVM̲CREATE:
/*水平及び垂直スクロールバーの作成 ‡/
「eturn0;
caseUMISIZE:
/事スクロールバーの位置 と大きさの変更 寺/
/iスライダーの位置決め ‡/
/‡スクロールバー表示非表示の変更 ‡′
「eturn0;
caseUM̲HSCROLL:
/*水平スクロールバ‑からのメッセージの処理 ‡/ /‡表示画面のスクロール等 手/
return0;
caseWM̲VSCROLL:
/*垂直スクロールバーからのメッセージの処理 ‡/ /*表示画面のスクロール等 */
「eturn0;
caseUM̲MYMESSAGEHELPOPEN:
idHelp=(SHORTIFROMMP(mpl)); /‡ヘルプのIDa/ if(DosGetResource((HMODULE)NULL,
JDT̲TEXT,idHelp,&selResource)) 図.5 (つづ く)
MSOS/ 2PMの プ ロ グ ラ ミ ン グ に つ い て 475
〈
idHelp=lD̲HELP̲lNTRO;
DosGetResource((HMODULE)NULL,IDT̲TEXT,
ZD̲HELPJNTRO,&se7Resource);
)
/事読み込んだヘルプテキス トの行数と最大桁数 を計算 ‡′ /事必要な画面の大 きさを求めスクロールバーの表示非表示 ‡/
/*スライダーの位置の決定 ‡/
/*クライアン トウイン ドウの描画要求 事/
return0;
caseUM̲CHAR:
/*矢印キー人力の処理 車/
b「eak;
caseUM̲PA川T:
/事クライアン トウイン ドウへヘルプテキス トを表示す る */
return0;
i
caseUM̲DESTROY:
/‡後処理 */
return0;
)
ret urnlJinE)eflJindoIJProc(hwnd,msg,mpl,mp2);
〉
MRESULTCALLBACKHelpUndProc(HUNDhwnd,USHORTmss,MF'ARAMmpl,MPARAMmp2)t switch(mss)(
caseUM̲CREATE:
/*ヘルプテキス トを表示す るウイン ドウを作成 */ /‡ヘルプ索引を表示するリス トボ ックスを作成 ‡/
/* この2つは重なってお りどち らか一方のみを表示する 事/ /* リス トボ ックスに索引を記入する ‡/
return0;
)
caseuM̲MYMESSAGE̲HELP̲OPEN:/‡ヘルプの要求 事/
/*ヘルプを終了するときにアクテ ィブにするウイン ドウを調査 ‡/
/事ヘルプ画面を可視状態にする 事/
jf(SHORTIFROMMP(mpl)==LD̲‖EL㌣̲LNDEX)/‡ヘルプの索引 ‡/
〈
/‡ヘルプ索引を表示す るリス トボックスを ‡/
/*ヘルプテキス トを表示するウィン ドウの前面に移動 */
/* リス トボ ックスにキーボー ドフォーカスを設定す る 事/ return0;
)
etse/辛SHORTIFROMMF)(mpl)はヘルプID辛/
〈
/*ヘルプテキス トを表示するウ ィン ドウを ‡/
/*ヘルプ索弓トを表示するリス トボ ックスの前面に移動 ‡/
/*テキス ト表示画面にキーボー ドフォーカスを設定 し ‡/
/*同 じメッセージを送付 */ return0;
)
図.5 (つづ く)