No.4ベストアンサー
- 回答日時:
ダイアログが表示される前に次の処理が実行されているとのことですが、
SendKeys "^h",True
にするとどうでしょうか?
それでもダメなら
hwnd=FindWindow(...)
の戻り値が≠0になるまでループで
hwnd=FindWindow(...)
を繰り返し実行するという手もありますが、なんらかの理由でダイアログが表示されなかった場合、無限ループとなり応答なしになってしまうと思います。
ちなみに、私の環境(WindowsXP+Excel2003)では、
SendKeys "^h",True
SendKeys "^h"
いずれにせよダイアログは表示されませんでした。
仕方がないので、手で「検索と置換」のダイアログを表示させてから実行しましたら、DWL_DLGPROC だとうまくいきませんでしたが、GWL_WNDPROC (-4) に変更するとうまくいきました。ただし、Visual Basic Editor を表示させている状態で実行すると応答がなくなってしまいました。( Control+Break で停止しましたが )
ANo.3で教えて頂いたコードから下記3箇所を変えたら動きました。
Public Const GWL_WNDPROC As Long = -4 '追加行
OrgDlgProc = GetWindowLong(hWnd, GWL_WNDPROC) 'DWL_DLGPROCをGWL_WNDPROCに変更
Call SetWindowLong(hWnd, GWL_WNDPROC, AddressOf NewDlgProc) 'DWL_DLGPROCをGWL_WNDPROCに変更
また、SendKeysは関係なくDWL_DLGPROCを引数にしたせいでした
ただ、ダイアログから実際の置換作業を使うことは出来ません。
しかし今回の事でサブクラス化を触りだけでも解かり,APIの難しさも分りました。
本当に、本当に、本当に、有難う御座いました。
No.3
- 回答日時:
今、確認できる環境がありませんので、動作未確認です。
(お正月休みが明けるまで確認できません。)
応答なしや異常終了になる可能性がありますので十分ご注意の上、自己責任において実行してください。
'標準モジュールで記述
Public Const DWL_DLGPROC As Long = 4
Public OrgDlgProc As Long
Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Const WM_DESTROY As Long = 2
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Function NewDlgProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = WM_DESTORY Then
'ダイアログが閉じられる時
End If
NewDlgProc = CallWindowProc(OrgDlgProc, hWnd, uMsg, wParam, lParam)
End Function
'実行ボタンのモジュール
Private Sub CommandButton1_Click()
Dim hWnd As Long
SendKeys "^h"
hWnd = FindWindow("bosa_sdm_XL9", "検索と置換")
If hWnd Then
OrgDlgProc = GetWindowLong(hWnd, DWL_DLGPROC)
If OrgDlgProc Then
Call SetWindowLong(hWnd, DWL_DLGPROC, AddressOf NewDlgProc)
End If
End If
End Sub
見やすくするために、全角スペースでインデントしています。
前回の内容と異なっているところがあります。
FindWindowEx でなくても FindWindow で十分なので、FindWindow にしました。
WM_CLOSE は×ボタンやシステムメニューの「閉じる」の時のメッセージなので、WM_DESTROY にしました。
この回答への補足
やはり動きませんでした。
SendKeys "^h" でダイアログが立ち上がる前に、後のコードが流れてる可能性が有ります。
マクロ実行する前に「検索と置換」ダイアログを立ち上げても
OrgDlgProcにゼロしか入らないので、SetWindowLongに行かない。
色々と有難う御座います。答えを知りたいですが、諦めるしかないかなと感じています。
No.2
- 回答日時:
モーダルの置換ダイアログではダメなんでしょうか?
モードレスだと、保護の解除がされている間に好き勝手なことをされる可能性があるので、モーダルの方が良いのではないかと思いますけど。
モーダルのダイアログは
Application.Dialogs(xlDialogFormulaReplace).Show
で表示できると思います。
ちなみに、APIでモードレスダイアログの終了を検出するには、
1.hwnd=FindWindowEx(0,0,"bosa_sdm_XL9","検索と置換")
でダイアログのウインドウハンドルを取得
2.OrgDlgProc=GetWindowLong(hwnd,DWL_DLGPROC)
でダイアログプロシージャを取得
3.SetWindowLong(hwnd,DWL_DLGPROC,AddressOf NewDlgProc)
で独自のダイアログプロシージャをセット
独自のダイアログプロシージャでは
メッセージ=WM_CLOSE
で判定し、プロシージャの最後で、CallWindowProcを使用して2.で取得したプロシージャを呼び出す。
という流れになると思います。(あまりおすすめできませんが)
このAPIを使用した方法については、「サブクラス化」で検索すると参考になるサイトが見つかるんじゃないかと思います。
ユーザーフォームで置換ダイアログを作成できるなら、APIを使用するよりユーザーフォームでの作成をおすすめします。
この回答への補足
回答有難う御座います。
出来れば、実際に動くコードまで教えてください。
宜しくお願いします。
また、ユーザーフォームで作る方が良いと気づいたのですが
API分らないので、これを機会にAPIを理解したいと思った次第です。
ヒントを頂いたのですが進みません。自分で考えれたのは下記迄です。
---標準モジュール---------------------
Option Explicit
Public Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" ( _
ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" ( _
ByVal hWnd As Long, _
ByVal nIndex As Long) As Long
Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" ( _
ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Const DWL_DLGPROC As Long = 4
-----以下実行ボタンのモジュール-------------------
Private Sub CommandButton1_Click()
Dim hWnd As Long
Dim OrgDlgProc As Long
ActiveSheet.Unprotect 'シート保護解除
SendKeys ("^h") '「検索と置換」ダイアログ表示
hWnd = FindWindowEx(0, 0, "bosa_sdm_XL9", "検索と置換")
OrgDlgProc = GetWindowLong(hWnd, DWL_DLGPROC)
'
'ここからが分りません
'
'ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True 'シート保護
End Sub
No.1
- 回答日時:
APIを使ってWindowの有無を確認しようということだと
思いますが、面倒なことをしなくても
下のどちらかのuserformのイベントプロシージャに
フラグをたてておけばいいと思います。
Option Explicit
Dim Closed_flg As Boolean
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'Closed_flg = True '閉じようとした
End Sub
Private Sub UserForm_Terminate()
Closed_flg = True '閉じられた
End Sub
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) マクロVBA 1シートをまとめる 閉じ方 初心者 SOS! 1 2022/06/17 14:54
- Visual Basic(VBA) シートをコピーする下記記述でダイアログを用いた記述がわかりません?( A = Dir(ThisWor 4 2022/08/22 12:26
- Visual Basic(VBA) VBA 検索と入力 Excel ブック ぶぶぶ シート ししし 列V 検索対象の列です 最終行は、お 6 2023/05/17 01:40
- Excel(エクセル) Excel-VBAの「しばらくお待ちください」のダイアログが自動的に閉じない 2 2023/05/24 15:31
- Excel(エクセル) フォルダ内のワードファイルをPDFに一括変換するVBA 3 2023/06/09 16:51
- Visual Basic(VBA) Excel VBA 教えてください。 VBA初心者です。 詳しい方がいましたら教えてください。 下記 3 2023/04/25 11:22
- Visual Basic(VBA) EXCEL VBA 単語置き換え について質問です ブック名 ぶぶぶ シート名 ししし セル V3〜 3 2023/03/08 01:41
- Excel(エクセル) マクロでボタンにつける名前がどこに設定されているかわからないケースがありました。 1 2023/06/19 19:37
- Visual Basic(VBA) Excel vba で1と10を正確に判断させる方法を教えてください。 TからU列に1と入力があれば 3 2022/12/26 16:54
- Visual Basic(VBA) 動かなくなってしまった古いVBAを動くようにしたい 8 2022/09/20 13:57
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBA 置換文字がみつからない時
-
【Excel VBA】文字列の置換作業...
-
EXCEL VBA でCTRL+Fのダイア...
-
PowerShellでテキストの空白行...
-
ハングルを日本語に置換
-
python 大文字小文字を区別しな...
-
csvデータ ダブルクォーテ...
-
○文字目に文字挿入
-
Excel VBA 教えてください。 VB...
-
C言語の質問です、プログラミン...
-
モードレスダイアログを閉じた...
-
テキストファイル中の文字列の置換
-
住所編集のマクロを組んでいて...
-
pythonで特殊文字を含むファイ...
-
ExcelVBA バッチファイル編集
-
バッチファイルの処理が実際の...
-
スペースで区切られた氏名から...
-
テキストボックスの文字列を置...
-
サクラエディタ 数字だけを置...
-
文字列置換C言語 置換前<置換後...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
各項目がダブルクォーテーショ...
-
VBA 置換文字がみつからない時
-
正規表現で、特定の文字列を含...
-
スペースで区切られた氏名から...
-
csvデータのダブルクォーテーシ...
-
csvデータ ダブルクォーテ...
-
GoogleAppsScript文字列置換の...
-
C言語でテキストファイルの内容...
-
正規表現 特定の文字列を含む行...
-
テキストボックスの文字列を置...
-
EXCEL警告「置換対象のデータが...
-
TeraPadエディターの操作方法に...
-
python 大文字小文字を区別しな...
-
xmlファイル内の文字列置換
-
C#で空白行を削除する方法
-
Excel VBA 教えてください。 VB...
-
テキストファイル中の文字列の置換
-
ハングルを日本語に置換
-
EXCEL VBA でCTRL+Fのダイア...
-
PowerShellでテキストの空白行...
おすすめ情報