人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

開発環境VC++6。
AfxMessageBoxの
キャンセルボタンを英語表記にする方法がわかりません。
いい方法を教えてください。

●質問者: harunoharuno
●カテゴリ:コンピュータ インターネット
✍キーワード:VC キャンセル ボタン 環境 英語
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● じゃっくそにっく
●100ポイント

こんにちは。

ちょっと長いですが、「AfxMessageBoxなどのシステムメッセージボックスの

ボタンを書き換えられる唯一の方法」

をご説明いたしますので、ご精読下さい。

-----------------------------------------------------

■状況の説明

AfxMessageBox()MessageBox()などのシステムメッセージボックス関数は、

システムのAPIから呼び出すメッセージボックスなのですが、

これらの上のボタン表示は、

IDOK」や「IDCANCEL」といった、

システムで決まっている値に関連付けられており、

普通にやろうとしたのでは変更することができないものです。

しかし、「フック」(ローカルフック)というテクニックを使うこと

によって、変更することが可能です。

■フックとは

フックとは、ウィンドウズのシステムから、

アプリケーションウィンドウへと流れるメッセージの流れから、

釣り糸でひっかける(フックする)ように

特定のものを拾い上げて横取りし、

ウィンドウに渡る前にデータを書き換えるなどの何らかの

処理をほどこす手法です。

フックの詳細についてはこちらのリンクにありますが、

詳細な説明なので、まだわからないところは適当に読み飛ばしてください。あくまで今回の問題の具体的な実現方法が主体ですので。

フックのしくみ

フックは一般に高度な技法に分類されますが、今回は

「ローカルフック」といって、

自分自身のスレッドのみを対象とした

(自分のアプリケーションだけに影響がある)フックになります。

システム全体のフックよりも

ずっと簡単ですので、具体的なソースとファイルも用意してありますので大丈夫と思います。)

(システム全体のフックにはDLLが必要になりますが、今回は必要ありません)

----------------------------------------------------

■今回の説明及び、ダウンロード可能なファイル

今回、私が仕様にあわせて作った

を用意しましたので、

こちらのページからダウンロードし、保存・解凍してください。

Prog/メッセージボックスのボタン表記などを書き換える - 情報処理研究所 ジャックズラボ(jack's Lab)

----------------------------------------------------

■処理の説明:使うもの、用意するもの

今回フックを使ってやることは、

メッセージボックスを呼び出す前に、

「フック関数」をシステムに登録(インストール)する

フック関数の中で、必要なデータの書き換えを行う

フック関数を解除(アンインストール)する

という処理です。

インストールといってもアプリケーションのインストールとは

性質が違うものです。ファイルに書き込んだりはしません。

具体的なソースで用意するもの

今回のフックに必要なものを、グローバルで記述したヘッダファイル

"HookMsgBox.h"の中身のソースは以下のようになります。

//////////////////////////////////////////////////////////////////
// フックハンドル用の変数をグローバルで宣言する。
HHOOK MyHookHandle;// フックハンドル変数
// OKの文字列と、キャンセルの文字列
// ボタンの文字を変更したい場合はここを変更してください
LPCSTR strOK = "OK(Hook)";// OKボタンの文字
LPCSTR strCancel = "Cancel(Hook)";// キャンセルボタンの文字
// プロトタイプ宣言
LRESULT CALLBACK MsgBoxHookProc (int nCode, WPARAM wParam ,LPARAM lParam );
int AfxMessageBoxHooked( LPCSTR message , UINT nType );

////////////////////////////////////////////////////////////////////
//
//メッセージボックス書き換えのための
//フック関数(ローカルフック用)
//※ グローバル関数である必要があります。
//この関数の中を変えるときは慎重に行って下さい。
//
LRESULT CALLBACK MsgBoxHookProc (int nCode, WPARAM wParam ,LPARAM lParam )
{
// コード判断
if (nCode >= 0)
{
if ( nCode == HCBT_ACTIVATE)
{
// OKボタン(IDOK)の内容を書き換える
SetDlgItemText( ( HWND )wParam, IDOK, strOK );
// キャンセルボタン(IDCANCEL)の内容を書き換える
SetDlgItemText( ( HWND )wParam, IDCANCEL, strCancel );
HRESULT ret;
// フック関数をアンインストール(フック解除!)
ret = UnhookWindowsHookEx ( MyHookHandle );

}
}
// 次のフックに渡す
return CallNextHookEx ( MyHookHandle, nCode, wParam, lParam);
}
/////////////////////////////////////////////////////////////////////
//
//AfxMessageBoxHooked(メッセージ, 
//
int AfxMessageBoxHooked( LPCSTR message , UINT nType )
{
// フック関数(MsgBoxHookProc)をインストールする SetWindowHookEx
MyHookHandle = SetWindowsHookEx ( WH_CBT, MsgBoxHookProc, NULL, GetCurrentThreadId( ) ); 
return ( AfxMessageBox(message, nType) ); 
//return MessageBox("フックメッセージボックス", "HookedMsgBox",MB_OKCANCEL);

}

■使い方

フック付きメッセージボックスの機能を使いたいファイルで、

ヘッダファイルHookMsgBox.hをインクルードします。

#include "HookMsgBox.h"

そして、使いたいときに、フック付きメッセージボックス関数

AfxMessageBoxHookedを呼び出します。

AfxMessageBoxHooked("フックメッセージボックステスト", MB_OKCANCEL);

■ソースの説明

フックに際し使うAPIは、

フック関数を登録(インストール)する

SetWindowsHookEx()関数、

及び、フックを解除する

UnhookWindowsHookEx()関数

です。

ソースの中での要素は、

・フック状態を維持するフックハンドル変数

今回 MyHookHandle

・フック処理の内容を記述するフック関数

今回 MsgBoxHookProc()

・フックされたメッセージボックスを呼び出す関数

今回 AfxMessageBoxHooked()

・OKボタンとキャンセルボタンの変更後の内容テキストを定義する定数

今回 strOK,strCancel

というものになります。

・フック付きメッセージボックス関数AfxMessageBoxHooked()では、

本来のAfxMessageBox()関数を内部で呼び出していますが、

その直前に、

SetWindowsHookEx関数で、ボタン表示を書き換えるための

フック関数MsgBoxHookProc()をインストールしています。

・フック関数MsgBoxHookProc()の中では、

メッセージボックスウィンドウが生成されたタイミングで、

「IDOK」,「IDCANCEL」の内容(ボタン表記)を書き換え、

書き換えた後で、

UnhookWindowsHookEx()で

フック関数をアンインストールする処理を行っています。

(これを行わないと、すべてのダイアログのOKボタンと

キャンセルボタンが書き換わったままになってしまいます。)

・このソースからOKボタン、キャンセルボタンの文字を自分で変えるには、

LPCSTR strOK = "OK(Hook)";// OKボタンの文字
LPCSTR strCancel = "Cancel(Hook)";// キャンセルボタンの文字

の、="文字"の部分を書き換えてください。



-----------------------------------------------------

■その他

今回のソースでは、フック関数をいじらなくても

ボタン表示を変更できるようにしています。

もしフック関数内部を独自に編集する場合は、

なるべく他の関数を編集する際よりも注意を払ってください。

(フック関数はクリティカルな部分にあり、

フック関数にバグがあると、メッセージが伝わらなくなり、

停止してしまいますため。)

何かわからない点、こうしたい点などあればご相談ください。

◎質問者からの返答

フックならやったことがあります。

参考書片手にやっとこさ実装したということも

ありやや苦手意識がありますが、じっくり

やってみます。

途中トラブルなどがあったら、この回答に

追記していきますので宜しくお願いします。

[追記]

>>>>>>>>>>>>>>HookMsgBox.h>>>>>>>>>>>>>>

//////////////////////////////////////////////////////////////////

// フックハンドル用の変数をグローバルで宣言する。

HHOOK MyHookHandle;// フックハンドル変数

// OKの文字列と、キャンセルの文字列

// ボタンの文字を変更したい場合はここを変更してください

LPCSTR strOK = "OK(Hook)";// OKボタンの文字

LPCSTR strCancel = "Cancel(Hook)";// キャンセルボタンの文字

// プロトタイプ宣言

LRESULT CALLBACK MsgBoxHookProc (int nCode, WPARAM wParam ,LPARAM lParam );

int AfxMessageBoxHooked( LPCSTR message , UINT nType );


>>>>>>>>>>>>>HookMsgBox.cpp>>>>>>>>>>>>>>

#inculude"HookMsgBox.h"

LRESULT CALLBACK MsgBoxHookProc (int nCode, WPARAM wParam ,LPARAM lParam )

{

(省略)

}

int AfxMessageBoxHooked( LPCSTR message , UINT nType )

{

(省略)

}

でもよいんじゃないかと思ってコーディングしたんですが、

ビルドでこけました。。。

何でだろう。

ちなみにサンプルに書かれていたとおりだと問題なく通りました。

実装には関係ないですが、理由を知りたいのでお手数をおかけしますが

再度教えていただきたく宜しくお願いします。

<ビルド時警告内容>

HookMsgBox.cpp(39) : fatal error C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。

警告位置

int AfxMessageBoxHooked( LPCSTR message , UINT nType )

{

// フック関数(MsgBoxHookProc)をインストールする SetWindowHookEx

MyHookHandle = SetWindowsHookEx ( WH_CBT, MsgBoxHookProc, NULL, GetCurrentThreadId( ) );

return ( AfxMessageBox(message, nType) );

}←ーーーーーーーーーーーーーーーーーーー----------------------ここです。

[追記2]

あっ・・・・警告は

#include "stdafx.h"

の所為でした。

前も同じ失敗やったことあるのに・・・

後は動作確認だけです。


2 ● じゃっくそにっく
●100ポイント ベストアンサー

>質問者harunoharuno様への返信

1で回答したjack_sonicです。

ヘッダファイルとソースファイルに分けて使う場合は、

分け方がありますので、このようにしてください。

・プリコンパイル?のエラーを出さないためには、

StdAfx.hをインクルードします。

・ヘッダには今回はプロトタイプだけおきます。

・ソースのほうでヘッダを読み込みます

具体的に、ヘッダファイル "HookMsgBox.h"を、

// HookMsgBox.h ヘッダファイル
// 1度しか読ませないため
#pragma once

// プロトタイプ宣言
LRESULT CALLBACK MsgBoxHookProc (int nCode, WPARAM wParam ,LPARAM lParam );
int AfxMessageBoxHooked( LPCSTR message , UINT nType );

にし、

--------------------------------------------------------

ソースファイル "HookMsgBox.cpp"を、

// HookMsgBox.cpp ソースファイル
// StfAfx.hインクルード プリコンパイル済み?のエラーを出さないために必要
#include "StdAfx.h"
// ヘッダインクルード
#include "HookMsgBox.h"

//////////////////////////////////////////////////////////////////
// フックハンドル用の変数をグローバルで宣言する。
HHOOK MyHookHandle;// フックハンドル変数
// OKの文字列と、キャンセルの文字列
// ボタンの文字を変更したい場合はここを変更してください
LPCSTR strOK = "OK(Hook)";// OKボタンの文字
LPCSTR strCancel = "Cancel(Hook)";// キャンセルボタンの文字

////////////////////////////////////////////////////////////////////
//
//メッセージボックス書き換えのための
//フック関数(ローカルフック用)
//※ グローバル関数である必要があります。
//この関数の中を変えるときは慎重に行って下さい。
//
LRESULT CALLBACK MsgBoxHookProc (int nCode, WPARAM wParam ,LPARAM lParam )
{
// コード判断
if (nCode >= 0)
{
if ( nCode == HCBT_ACTIVATE)
{
// OKボタン(IDOK)の内容を書き換える
SetDlgItemText( ( HWND )wParam, IDOK, strOK );
// キャンセルボタン(IDCANCEL)の内容を書き換える
SetDlgItemText( ( HWND )wParam, IDCANCEL, strCancel );
HRESULT ret;
// フック関数をアンインストール(フック解除!)
ret = UnhookWindowsHookEx ( MyHookHandle );

}
}
// 次のフックに渡す
return CallNextHookEx ( MyHookHandle, nCode, wParam, lParam);
}
/////////////////////////////////////////////////////////////////////
//
//AfxMessageBoxHooked(メッセージ, 
//
int AfxMessageBoxHooked( LPCSTR message , UINT nType )
{
// フック関数(MsgBoxHookProc)をインストールする SetWindowHookEx
MyHookHandle = SetWindowsHookEx ( WH_CBT, MsgBoxHookProc, NULL, GetCurrentThreadId( ) ); 
return ( AfxMessageBox(message, nType) ); 
//return MessageBox("フックメッセージボックス", "HookedMsgBox",MB_OKCANCEL);

}

のようににします。

こちらにまたそのように変更した

プロジェクトファイルを置いておきます。

Prog/メッセージボックスのボタン表記などを書き換える - 情報処理研究所 ジャックズラボ(jack's Lab)

LocalHookDialogSample2.zipです。

また、質問に設定されている回答上限回数が2回で、

この返信で使い切ってしまうため、

質問のコメント機能を開いておいていただきけると幸いです。

◎質問者からの返答

回答ありがとうございます。

おかげさまでメッセージボックスの

キャンセルを英語表記にすることができました。

#pragma onceの表記については意味をよく

理解せず使用していたんですが、

インクルードガードみたいなものだったのですね。

いろいろと教えていただき本当に助かります。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ