win32 - C++:なぜこのウィンドウタイトルが切り捨てられるのですか?




windows api main (4)

CreateWindowExAは文字列を8ビット文字として解釈します。 Lの「Sample」の2番目の8ビットはゼロです。その最初の文字は0x0053なので、Lはワイド文字を使用するという意味です。 そのため、関数はそれを1文字のNULLで終わる文字列として解釈します。

https://code.i-harness.com

ビジュアルC ++ 2012 RC、Win7

中国語(簡体字

プロジェクトのプロパティ>マルチバイト文字セットを使用

このプログラムを実行すると、ウィンドウのタイトルに "Sample"という単語が表示されるのではなく、 "S"が表示されます。

#pragma comment(linker, "/SubSystem:Windows")

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, int) {
    WNDCLASSW wc = { 0 };

    wc.style            = CS_VREDRAW | CS_HREDRAW;
    wc.hInstance        = hInstance;
    wc.hIcon            = LoadIcon(nullptr, IDI_APPLICATION);
    wc.hCursor          = LoadCursor(nullptr, IDC_ARROW);
    wc.hbrBackground    = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
    wc.lpszClassName    = L"MyWindowClass";

    wc.lpfnWndProc = [](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
        if (uMsg - WM_DESTROY)
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
        else {
            PostQuitMessage(0);
            return HRESULT();
        }
    };

    RegisterClassW(&wc);

    CreateWindowExW(0, L"MyWindowClass", L"Sample",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, SW_SHOW, CW_USEDEFAULT, 0,
        nullptr, nullptr, hInstance, nullptr);

    for (MSG msg; GetMessage(&msg, nullptr, 0, 0); DispatchMessage(&msg));
}

Unicode(Project Properties)を使用している場合は、ソースコードを変更しないでください。ウィンドウのタイトルに "Sample"と表示され、正しいように見えます。

マルチバイトを使用している場合、ソースコードでWNDCLASS = {...、 "MyWindowClass"}とRegisterClassAを使用し、CreateWindowExWを変更せずに、ウィンドウのタイトルに "Sample"と表示され、正しいように見えます。

マルチバイトを使用している場合、ソースコードでCreateWindowExA( "MyWindowClass"、 "Sample")を使用し、WNDCLASSWとRegisterClassWを変更せずにウィンドウタイトルに "S"を表示します。

それが単一の "S"を表示するのはなぜですか、私は何か悪いことをしていますか?

追加

すべてを変更しない、つまりマルチバイトを使用し、上記のコードを使用すると、ウィンドウのタイトルに文字 "S"が表示されます。

(このプログラムを実行し、ウィンドウタイトルに「S」ではなく「サンプル」が表示される場合は、vc ++ 2012(またはOS)のchsバージョンで発生する可能性が高いです。)


RegisterClassmsdnページはここで失敗の理由を示唆していると思います、備考のセクションであなたがワイド​​文字かansiサポートのどちらかを使うならそれがこのフォーマットで内部テキストパラメータ/メッセージを渡す方法を述べます(wide char / ANSI)。 たぶんそれはウィンドウタイトルで起こっていることです、私達がCreateWindowExA使うと言っても、これは内部的には動作しませんWindows SDKはワイド文字列としてその文字列をエンコードし、 CreateWinowExAはあたかもそれがそうであるかのように出力しようとしますAnsi文字列です。

あなたがそうするための正当な理由がない限り、手短に言えば、WとAのメソッドを混在させてはいけません、そして、ワイド文字サポートがあなたのUNICODEマクロを定義したいならば、あなたに代わってwindowsヘッダに任せます。


これはとても素敵なものです、何か新しいことを学びました!

変更する必要があります

return DefWindowProc(hWnd, uMsg, wParam, lParam);  

if(IsWindowUnicode(hWnd))  
  return DefWindowProcW(hWnd, uMsg, wParam, lParam);  
else  
  return DefWindowProcA(hWnd, uMsg, wParam, lParam);

もっと良いのは、1文字エンコーディングに固執することです。 せいぜいRegisterClassやCreateWindowExなどを使用して、コンパイラに正しいUnicode関数またはANSI関数を使用させるだけです。


コードの問題は、 DefWindowProc代わりにDefWindowProcWを使用していることです。 それを変更するとコードが修正されます。

理想的には、マルチバイト文字セットではなく、Unicodeを使用するようにプロジェクト設定を変更する必要があります。 これによりすべてが単純化され、Unicode / ANSIバージョンを明示的に使用する代わりに、 CreateWindowExRegisterClassExなどのマクロを使用できます。

他の人が言っているように、これは文字セット間の不一致です。

相互作用するすべてのAPI呼び出しの間で文字セットを一致させるのが理想的です。 したがって、 CreateWindowExWを使用する場合は、 RegisterClassExWDefWindowProcWDispatchMessageW ...も使用する必要があります。





winapi