開発環境VC++6。

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

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2007/06/04 23:08:37
  • 終了:2007/06/07 18:56:48

ベストアンサー

id:jack_sonic No.2

じゃっくそにっく回答回数123ベストアンサー獲得回数252007/06/05 22:05:06

ポイント100pt

>質問者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回で、

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

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

id:harunoharuno

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

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

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

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

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

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

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

2007/06/07 18:56:20

その他の回答(1件)

id:jack_sonic No.1

じゃっくそにっく回答回数123ベストアンサー獲得回数252007/06/05 03:15:16

ポイント100pt

こんにちは。

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

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

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

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

■状況の説明

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

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

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

IDOK」や「IDCANCEL」といった、

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

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

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

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

■フックとは

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

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

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

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

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

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

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

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

フックのしくみ

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

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

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

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

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

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

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

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

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

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

  • サンプルの実行プログラム,
  • プロジェクトソース(VC++6.0)

を用意しましたので、

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

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)";	// キャンセルボタンの文字

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



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

■その他

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

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

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

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

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

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

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

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

id:harunoharuno

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

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

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

やってみます。

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

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

[追記]

>>>>>>>>>>>>>>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"

の所為でした。

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

後は動作確認だけです。

2007/06/05 20:55:38
id:jack_sonic No.2

じゃっくそにっく回答回数123ベストアンサー獲得回数252007/06/05 22:05:06ここでベストアンサー

ポイント100pt

>質問者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回で、

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

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

id:harunoharuno

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

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

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

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

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

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

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

2007/06/07 18:56:20
  • id:harunoharuno
    こんばんは、jack_sonicさん。
    以前教えていただいた方法を元に、
    CFileDialogクラスのダイアログに表示されているキャンセルも文字を置き換えCancelとして表示することができました。
    しかし、私の環境では
    ダイアログのタイトルバーにも
    『ファイルを開く』と表示されて
    おり、ここも値を設定しないと完璧に英語化できません。
    タイトルバーの値を設定する場合、

    MsgBoxHookProc のif ( nCode == HCBT_ACTIVATE)の中で何をすればよいのでしょうか?
    教えていただきたく宜しくお願いします。


  • id:harunoharuno
    jack_sonicさんへ
    新しく質問を立ち上げましたので、
    こちらも見ていただければ
    大変ありがたく宜しくお願いします。
    http://q.hatena.ne.jp/1181744434
  • id:jack_sonic
    >harunoharuno様へ
    システム系のダイアログの表記なども好きなように書き換える
    方法はあります。
    プログラムを書きますので少しお待ちください。

    いくつか同様の質問スレッドを立てられているようですが、
    どれに書き込めばよいでしょうか?
  • id:harunoharuno
    >>jack_sonic さん
    コメントいただきありがとうございます。
    質問が発展した内容なので回答はこの質問欄にコメントでいただけると嬉しいです。

    現状を報告いたしますのでご確認ください。

    CFileDialogの派生ダイアログを作成し、
    ・タイトルバーの『ファイルを開く』
    ・トップのディレクトリ選択用リストボックスの隣の文字『ファイルの場所(I)』
    ・ファイル名(N)
    ・ファイルの種類(T)
    ・キャンセルボタン
    を英語表記に変更することに成功しました。


    BOOL CFileDialogEx::OnInitDialog()
    {
    CFileDialog::OnInitDialog();

    CWnd *pWD = this->GetParent();
    pWD->SetWindowText("Select directory");

    pWD->SetDlgItemText(0x0441,"a");
    pWD->SetDlgItemText(0x0442,"b");
    pWD->SetDlgItemText(0x0443,"c");
    }
    みたいな感じで行っています。

    しかし、どうしても
    CFileDialogダイアログ右上に表示されるToolbarWindow32の英語化が出来ません。
    どうしたらいいんだ・・・
    英語化できない文字は以下のとおりです。

    『直前に表示したフォルダへ移動』
    『1つ上のフォルダへ』
    『新しいフォルダの作成』
    『表示メニュー』---『縮小版』
             |-『並べて表示』
             |-『アイコン』
             |-『一覧』
             |-『詳細』


    英語化できなければ消してしまえ、、、、と消す方法を調べてみました。

    HWND hTool;
    hTool = FindWindowEx(pWD->m_hWnd, NULL, "ToolbarWindow32", "");
    ::ShowWindow(hTool, SW_HIDE);

    上記方法からできることを確認!でもすっごい不便でした(T_T)。
    やはり、ツールバーは残したいです。

    CFileDialogの派生ダイアログを作成し、ダイアログをカスタマイズする
    以外の方法でも構いません。
    良い解決方法などありましたら教えていただけると助かります。
  • id:jack_sonic
    >>harunoharuno様
    URLリンクやはてな記法が使えないので
    コメント欄はちょっときついです。
  • id:harunoharuno
    >>jack_sonic さん

    コメントありがとうございます。

    >>URLリンクやはてな記法が使えないので
    >>コメント欄はちょっときついです。

    では、
    http://q.hatena.ne.jp/1181795123
    に回答してください。宜しくお願いしますm(_ _)m
  • id:jack_sonic
    >harunoharuno様
    >『直前に表示したフォルダへ移動』
    >『1つ上のフォルダへ』
    >『新しいフォルダの作成』
    >『表示メニュー』---『縮小版』
    >         |-『並べて表示』
    >         |-『アイコン』
    >         |-『一覧』
    >         |-『詳細』
    これらは、Staticでウィンドウの上に出ている文字ではなく、
    ツールヒント及び、ウィンドウの中のオブジェクトの中身で
    定義されているものですので、外に出ていない
    オブジェクトの中まで書き換えるは、
    通常そういうことはしないので難しいかもしれません。

    Staticで出ている文字はコントロールIDをSpy++で見なくても
    もっと簡単に書き換えられます。
    (色選択ダイアログなどのStatic文字も書き換えられます。)
    英語版のコモンダイアログDLLを持っていれば
    そちらを使うほうがよさそうですが・・
  • id:harunoharuno
    Jack_sonicさんへ
    コメントいただきありがとうございます。


    >ツールヒント及び、ウィンドウの中のオブジェクトの中身で
    >定義されているものですので、外に出ていない
    >オブジェクトの中まで書き換えるは、
    >通常そういうことはしないので難しいかもしれません。

    そうですか、、、
    ヒントなどの文字は変更が一筋縄ではいかないのですね。

    >英語版のコモンダイアログDLLを持っていれば
    >そちらを使うほうがよさそうですが・・

    よろしければ
    英語版のコモンダイアログDLLの
    ファイル名を教えていただけませんか?
    探してみて、使えるかどうか試してみたいです。
  • id:harunoharuno
    Jack_sonicさんへ
    ToolbarWindow32の英語表示は挫折しました。
    よろしければ、先ほどコメントいただいた
    >>Staticで出ている文字はコントロールIDをSpy++で見なくても
    >>もっと簡単に書き換えられます。
    の方法を教えていただけないでしょうか?
  • id:jack_sonic
    >harunoharuno様
    http://q.hatena.ne.jp/1181723549
    の質問のほうを開いてくださればそちらに書き込みます。

    英語版コモンダイアログは、英語版Windowsがインストールされていれば
    C:\WinUS\System32\comdlg32.dll
    などにあるかもしれません。
  • id:harunoharuno
    なんどもコメントいただきありがとうございます。

    http://q.hatena.ne.jp/1181723549
    の質問を再開しましたので、
    回答いただきたく宜しくお願いします。

    >>英語版コモンダイアログは、英語版Windows
    >>がインストールされていれば
    >>C:\WinUS\System32\comdlg32.dll
    >>などにあるかもしれません。

    http://www.dll-files.com/dllindex/dll-files.shtml?comdlg32
    検索すると見つかりますが、
    どこのOSのファイルか解らないので
    使えなさそうですね。
  • id:jack_sonic
    ツールチップを書き換える方法が見出せました。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません