ab.com コミュニティ https://www.activebasic.com/forum/ |
|
タブページから開くモーダルウインドウ https://www.activebasic.com/forum/viewtopic.php?t=4612 |
ページ 1 / 1 |
作成者: | jacoby [ 2017年1月24日(火) 19:29 ] |
記事の件名: | タブページから開くモーダルウインドウ |
タブウインドウ(タブコントロール)のテストをしています。 「タブウインドウのページ上に配置したボタンを押すと、 モーダル・ダイアログを開く」、ということを実装したいのですが、 このモーダルダイアログを閉じた後、戻ったタブページ上のコントロールが 全く効かなくなってしまいます。 (つまりこの「モーダル・ダイアログを開くボタン」も再び押せなくなってしまいます。) テストしてみたところでは、ダイアログを閉じた後では、 戻っているはずのタブページのダイアログ・プロシージャに 以降メッセージが殆ど送られなくなるようです。 (例えばマウス・ポインタを上にかざして動かした時に送られるマウスムーブなども 飛んでこなくなります。) モーダルダイアログの代わりに、メッセージボックスやOpenFileDialogなどの コモンダイアログなどを開いた場合にはその後の動作に問題はありません。 ダイアログを閉じた後、再びページ上のコントロールが効くようにするには どうしたら良いのでしょうか? お知りの方がおられましたら教えて下さい。(AB4.24/Windows7) 長くなってしまいますが以下にコードを書いておきます。 (プロジェクト・ファイル"TabTest.pj") タブウインドウを乗せるベース・ウインドウ(MainWnd)、 そのクリエイト内でタブウインドウ(TabWnd)を作り(2ページ分)、 1ページ目(Tab_Page1)にボタンを配置。 ボタンを押すとモーダルダイアログ(ModalDlg)を開く という内容になっています。 新規プロジェクトで自動的に生成されるMainWndの他には タブページ1用のウインドウ(Tab_Page1)を「モードレス」、「チャイルド」、「枠無し」で追加。 モーダル用のダイアログ(ModalDlg)を「モーダル」で追加しています。 MainWnd.sbp コード: '----------------------------------------------------------------------------- ' イベント プロシージャ '----------------------------------------------------------------------------- ' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。 ' ウィンドウ ハンドル: hMainWnd ' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。 Const TCIF_TEXT = &H0001 Const TCM_FIRST = &H1300 Const TCM_INSERTITEM = (TCM_FIRST + 7) Const TCM_GETCURSEL = (TCM_FIRST + 11) Const TCM_SETCURSEL = (TCM_FIRST + &H0C) '=&H130C Const TCM_ADJUSTRECT = (TCM_FIRST + &H28) '=&H1328 Const TCN_FIRST = (0-550) As DWord Const TCN_SELCHANGE = (TCN_FIRST - 1) As DWord Const TCN_SELCHANGING = (TCN_FIRST - 2) As DWord Const TCS_FLATBUTTONS = &H0080 Const TCS_BUTTONS = &H0100 Type TCITEM mask As DWord dwState As DWord dwStateMask As DWord pszText As BytePtr cchTextMax As Long iImage As Long lParam As DWord End Type 'タブページ用文字列。 Const Tab_Page1_Str="Page1" Const Tab_Page2_Str="Page2" 'タブウインドウのハンドル、開いているページ番号、サイズ。 Dim hTabWnd As HWND Dim tabPageNum As Long Dim tabWndRc As RECT '----------------------------------------------------------------------------- ' ウィンドウメッセージを処理するためのコールバック関数 Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord ' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。 ' イベントプロシージャの呼び出しを行います。 MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam) End Function '----------------------------------------------------------------------------- ' ここから下は、イベントプロシージャを記述するための領域になります。 ' 'デストロイ・イベント。 ' Sub MainWnd_Destroy() TabTest_DestroyObjects() PostQuitMessage(0) End Sub ' 'クリエイト・イベント。 ' Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT) 'タブウインドウのサイズセット。 GetClientRect(hMainWnd, tabWndRc) Dim tabWndMaginV=12 As Long 'タブウインドウ周囲の(MainWnd上での)余白の大きさ。 tabWndRc.left=tabWndRc.left+tabWndMaginV tabWndRc.top=tabWndRc.top+tabWndMaginV tabWndRc.right=tabWndRc.right-tabWndMaginV-tabWndRc.left tabWndRc.bottom=tabWndRc.bottom-tabWndMaginV-tabWndRc.top-48 '「-48」の意味はOKボタンを表示するのウインドウ下部領域を空けるため。 'タブウインドウを作成する。 hTabWnd=CreateWindowEx(NULL,_ "SysTabControl32",_ "",_ 'タイトル(使用しない) WS_CHILD Or WS_VISIBLE,_'スタイル tabWndRc.left, tabWndRc.top, tabWndRc.right, tabWndRc.bottom,_ '位置とサイズ hMainWnd,_ '親ウィンドウのハンドル NULL,_ 'ID GetModuleHandle(0),_ 'インスタンスハンドル NULL) 'フォントを設定(タブの初期フォントはMainWndとは違うのでここでセットが必要) SendMessage(hTabWnd, WM_SETFONT, hFont_MainWnd, 0) 'タブ項目の追加。 Dim tci As TCITEM tci.mask=TCIF_TEXT tci.pszText=Tab_Page1_Str SendMessage(hTabWnd, TCM_INSERTITEM, 0, VarPtr(tci)) tci.pszText=Tab_Page2_Str SendMessage(hTabWnd, TCM_INSERTITEM, 1, VarPtr(tci)) 'タブ表示領域の取得。 tabWndRc.left=0 '上でセットしたウインドウ左上頂角座標が残っているので tabWndRc.top=0 'TCM_ADJUSTRECTを呼ぶ前にそれらをクリア SendMessage(hTabWnd,TCM_ADJUSTRECT,FALSE,VarPtr(tabWndRc)) tabWndRc.right=tabWndRc.right-tabWndRc.left tabWndRc.bottom=tabWndRc.bottom-tabWndRc.top '開くタブページ番号のセット。 tabPageNum=0 SendMessage(hTabWnd, TCM_SETCURSEL, tabPageNum, 0) Select Case tabPageNum Case 0 'ページ1のクリエイト。 hTab_Page1=CreateDialog(hTabWnd,"Tab_Page1") ShowWindow(hTab_Page1,SW_SHOW) Case 1 'ページ2のクリエイト。 End Select End Sub ' 'タブコントロール通知イベント ' Sub MainWnd_Notify(ByRef nmHdr As NMHDR) Select Case nmHdr.code Case TCN_SELCHANGING 'タブがこれから切り替わる時。 Select Case TabCtrl_GetCurSel(nmHdr.hwndFrom) Case 0 'ページ1を隠す。 ShowWindow(hTab_Page1,SW_HIDE) Case 1 'ページ2を隠す。 End Select Case TCN_SELCHANGE 'タブが切り替わった時。 Select Case TabCtrl_GetCurSel(nmHdr.hwndFrom) Case 0 'ページ1のタブに替わったときの処理。 if hTab_Page1=0 Then hTab_Page1=CreateDialog(hTabWnd,"Tab_Page1") ShowWindow(hTab_Page1,SW_SHOW) tabPageNum=0 Case 1 'ページ2のタブに替わったときの処理。 End Select End Select End Sub Function TabCtrl_GetCurSel(hWnd As HWND) As Long TabCtrl_GetCurSel=SendMessage(hWnd, TCM_GETCURSEL, 0, 0) End FunctionTab_Page1.sbp コード: '----------------------------------------------------------------------------- ' イベント プロシージャ '----------------------------------------------------------------------------- ' このファイルには、ウィンドウ [Tab_Page1] に関するイベントをコーディングします。 ' ウィンドウ ハンドル: hTab_Page1 ' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。 '----------------------------------------------------------------------------- ' ウィンドウメッセージを処理するためのコールバック関数 Function Tab_Page1Proc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord ' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。 ' イベントプロシージャの呼び出しを行います。 Tab_Page1Proc=EventCall_Tab_Page1(hWnd,dwMsg,wParam,lParam) End Function '----------------------------------------------------------------------------- ' ここから下は、イベントプロシージャを記述するための領域になります。 ' 'クリエイト・イベント ' Sub Tab_Page1_Create(ByRef CreateStruct As CREATESTRUCT) 'タブページのウインドウ位置セット。 MoveWindow(hTab_Page1, tabWndRc.left,tabWndRc.top,tabWndRc.right,tabWndRc.bottom,FALSE) End Sub ' 'ページ1上のボタンが押されたときの処理。 ' (モーダルダイアログを表示。) ' Sub Tab_Page1_CommandButton1_Click() DialogBox(hTab_Page1, "ModalDlg") 'ここでモーダルダイアログから戻ってきた後、 'その後ページ1上の全てのコントロールが効かなくなる。 '(例えばここのボタンも再び押せなくなる。) 'MessageBox(hTab_Page1, "test", "test",MB_OK) 'モーダルダイアログの代わりに、上記のようにメッセージボックスや 'OpenFileDialogなどのコモンダイアログなどを表示した場合には 'その後の動作に問題は無い。 End SubModalDlg.sbp (これについては実質、空です。) コード: '----------------------------------------------------------------------------- ' イベント プロシージャ '----------------------------------------------------------------------------- ' このファイルには、ウィンドウ [ModalDlg] に関するイベントをコーディングします。 ' ウィンドウ ハンドル: hModalDlg ' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。 '----------------------------------------------------------------------------- ' ウィンドウメッセージを処理するためのコールバック関数 Function ModalDlgProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord ' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。 ' イベントプロシージャの呼び出しを行います。 ModalDlgProc=EventCall_ModalDlg(hWnd,dwMsg,wParam,lParam) End Function '----------------------------------------------------------------------------- ' ここから下は、イベントプロシージャを記述するための領域になります。 |
作成者: | たかせ [ 2017年1月26日(木) 19:02 ] |
記事の件名: | Re: タブページから開くモーダルウインドウ |
お久しぶりです。 上記の現象を私のPC(Windows 7 SP1/X86)にて確認しました。 上記の現象についてなぜそうなるか私にはわかりません。 またネットで検索すると何らかの解決方法があるようですが私にとっては難しい内容でした。 そこでモーダル用のダイアログ(ModalDlg)を「モーダル」から「モードレス」に変更します。 特に理由がなければ「モードレス」のダイアログで良いと私は思いますがいかがでしょうか? よろしくお願いいたします。 |
作成者: | jacoby [ 2017年1月30日(月) 01:18 ] |
記事の件名: | Re: タブページから開くモーダルウインドウ |
たかせさん、返信ありがとうございます。 随分とここの板ともご無沙汰してしまっていたので まだ質問しても大丈夫なのかな?と思っていたのですが たかせさんやイグトランスさんの名前を見つけて、ホッとしつつ 質問を書かせてもらった次第です。こちらの返信が遅れてしまい 申し訳ありません。お久しぶりです。 そうですか、少し難しい問題のようですね。 あんまりタブページからモーダルって一般的には開かないものなのかな と思ってみたり、そんなこともないよな、とも思い直したり。 タブコントロール自体は自分でも今まで何度か作っていたのですが 実際にこのようなケースに出会うことは無かったのでどうにも まごついてしまいました。 おっしゃられる様にモードレスでの対処というのも 現実的な解決かもしれませんね。 久し振りにたかせさんのレクを嬉しく読ませてもらい ました。また何かお分かりのことがありましたら 教えて下さい。ありがとうございました。 |
作成者: | redfox [ 2017年4月09日(日) 22:55 ] |
記事の件名: | Re: タブページから開くモーダルウインドウ |
モーダルダイアログの生成時に与えるhOwnerWnd引数に hTabPage1を与えているのが原因のようです DailogBoxの実行コードの中で GetWindowでオーナを探すのですが これに失敗しているため ダイアログを閉じた段階でTabPage1がDisable状態になるためです 対処としては DialogBoxへは hMainWndを与えてやるか EnableWindow(hTabPage1,1)を実行してやるかになるでしょう |
作成者: | たかせ [ 2017年6月02日(金) 21:15 ] |
記事の件名: | Re: タブページから開くモーダルウインドウ |
redfox様 DialogBox(hTab_Page1, "ModalDlg")をDialogBox(hMainWnd, "ModalDlg")に変更することにより、 期待どおりに動作しました。 ありがとうございました。 |
作成者: | jacoby [ 2018年9月16日(日) 19:15 ] |
記事の件名: | Re: タブページから開くモーダルウインドウ |
redfoxさん、ご回答ありがとうございます。 返信が遅くなりすみません。 教えていただいた方法でこちらでもきちんと動作しました。 引用:
DailogBoxの実行コードの中で GetWindowでオーナを探すのですが これに失敗しているため
自分はTabPage1が直近のオーナーだろうと単純に考えていたんですがこれではダイアログを閉じた段階でTabPage1がDisable状態になるためです ダメなんですね。 これはモーダルダイアログとモードレスダイアログのメッセージループにおける 動作の違いということなんでしょうか。あわてて調べているのでちょっとまだ理解が怪しいのですが。 いずれにしてもこの方法で綺麗に動作してくれます。助かりました。 それからたかせさん、自分が立てたスレなのにご返信頂いて申し訳ありません。 お二方ともどうもありがとうございました。 |
ページ 1 / 1 | 全ての表示時間は UTC+09:00 です |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |