2012-02-23 54 views
3

私はANSIプロジェクトを持っています。 CDialogの派生クラスのタイトルバーをUnicodeテキストに設定する必要があります。ANSIプロジェクトのSetWindowTextW

BOOL CMyDialog::OnInitDialog() 
{ 
    CDialog::OnInitDialog(); 

    ::SetWindowTextW(GetSafeHwnd(), PathFindFileNameW(filename)); 

    return TRUE; // return TRUE unless you set the focus to a control 
    // EXCEPTION: OCX Property Pages should return FALSE 
} 

ただし、UnicodeテキストにANSI以外の文字が含まれている場合は、疑問符で表示されます。私は "?????。doc"のようなものを手に入れます。静的コントロールにも同様の問題がありますが、不思議なことに、エディットボックスSetWindowTextWが機能します。

ああ、このプロジェクトは、ユニコードに変換できない大きなレガシープロジェクトです。

+0

これらの関連する質問もご覧ください:http://stackoverflow.com/questions/4989820/win32-problem-with-unicode-in-an-edit-box and http://stackoverflow.com/questions/1322801/piecewise -conversion-of-an-mfc-app-to-unicode-mbcs –

答えて

6

SetWindowText()とSetWindowTextA()とSetWindowTextW()はすべて、実際にWM_SETTEXTであり、マルチバイト/ Ansiウィンドウを作成するときにコードページ変換の対象となる少数のメッセージの1つです。これは、メッセージのWバージョンとAバージョンがないことを意味します。

でも、Ansi/Multibyteアプリケーションとして構築されたVista/Win7タイトルバーには、Unicodeを表示するのは簡単です。あなたのウィンドウ内のWM_SETTEXTメッセージを傍受し、通常のDefWindowProcA/DefWindowProc()の代わりにDefWindowProcW()に引数を渡すだけです。これは内部的にすべてのウィンドウが実際にユニコードであるために機能します。

引数をDefWindowProcW()に渡すだけであれば、引数が本当にwchar_t文字列を指していることを絶対に確かめる必要があることに注意してください。

私の場合、すべての文字列はUTF-8文字とみなされます。つまり、通常のANSI文字列は以前と同じように動作します。ウィンドウでWM_SETTEXTメッセージを傍受すると、UTF-8 charをMultiByteToWideChar()を使用してwchar_tに変換し、その結果をDefWindowProcW()に明示的に渡します。

良い副作用は、ユニコード文字もタスクバーに表示することです。

XPには、タスクバーが正しく表示されていないのにタイトルバーが正しく表示されないという問題があります。

1

マイクロソフトでは、API関数の多くをいくつかの趣旨で定義しています。 PathFindFileName()の3つのバージョンがあります(指定されていない、コンパイラによってANSIが設定されています)。PathFindFileNameW()(Unicode)とPathFindFileNameA()(ANSI)です。 HereはMSDNの説明です。

は、私はあなたがこれまであなたの行を変更する必要があると思う(最終的にはあなたもfilenameの世話をする必要があります):

::SetWindowTextW(GetSafeHwnd(), PathFindFileNameW(filename)); 

あなたはそのため、あなたが以下のように使用することはできません、あなたはUnicodeのクラスから派生言います。

::SetWindowTextA(GetSafeHwnd(), PathFindFileNameA(filename)); 

またはすべてが未指定のままになっている場合:

::SetWindowText(GetSafeHwnd(), PathFindFileName(filename)); 
+0

実際にPathFindFileNameWを使用しましたが、手作業でサンプルコードを入力しました。私は今それを修正しました。 – sashoalm

2

あなたがUnicodeにプロジェクトを変換することができないならば、あなただけの限界を受け入れる必要がありますこれは、純粋なANSIプロジェクトのためになります。ダイアログはANSIダイアログです。必要ならばSetWindowTextWを使うことができますが、システムがダイアログをペイントしたいときは、ANSI APIを使ってウィンドウテキストを取得します。 ANSIテキスト描画GDI関数を使用してペイントを実行します。 Unicodeダイアログが必要な場合は、Unicode用にコンパイルする必要があります。

0

SetWindowTextAに関する上記の正しい答えに加えて、同様の問題の一般的な解決策として、変換を実行するCStringにユニコード文字列を割り当ててから、CStringを使用することができます。これは、編集ボックスでボンネットの下で起こっている可能性が最も高いです。一般に、MFCの下で関数のUnicodeまたはANSI固有のバリアントを指定しないと、どちらかで動作するより移植性の高いコードが得られます。

2

トム・ネルソンの答えは、おそらく最高のですが、私はちょうど別の迅速な解決策を見つけたと私は共有したいと思った:その最後の行がなければ

LONG_PTR originalWndProc = GetWindowLongPtrW(hwnd, GWLP_WNDPROC); 
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) DefWindowProcW); 
SetWindowTextW(hwnd, L"✈✌❦♫"); 
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, originalWndProc); 

デバッグするときにクリックがのdidnを無視しても、我々は、アサーションエラーを取得しました。問題が発生していると思われ、リリースモードが正常に動作しません。 MFCはまだ私たちの多くにとって謎なので、うまくいけば、このコードは健全です。

+0

この方法を試しましたが、ワイドテキストはMBCSモードでは表示されません。しかし、ありがとう... –