簡體   English   中英

C++:為什么這個窗口標題會被截斷?

[英]C++ : Why this window title gets truncated?

Visual C++ 2012 RC,Win7

簡體中文

項目屬性 > 使用多字節字符集

當我運行這個程序時,窗口的標題顯示一個字母“S”,而不是整個單詞“Sample”。

#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(項目屬性),保持源代碼不變,窗口標題顯示“示例”,看起來正確。

如果我使用多字節,在源代碼中我使用 WNDCLASS = { ..., "MyWindowClass" } 和 RegisterClassA,保持 CreateWindowExW 不變,窗口標題顯示單詞“Sample”,看起來正確。

如果我使用多字節,在源代碼中我使用 CreateWindowExA("MyWindowClass", "Sample"),保持 WNDCLASSW 和 RegisterClassW 不變,窗口標題顯示字母“S”。

是什么讓它顯示一個“S”,我做錯了什么嗎?

附加

如果我都保持不變,即使用多字節,使用如上所示的代碼,窗口標題顯示字母“S”。

(如果您運行此程序並在窗口標題上看到“示例”,而不是“S”,則更有可能是 vc++ 2012(或操作系統)的 chs 版本上的特定問題)。

您的代碼中的問題是您使用的是DefWindowProc而不是DefWindowProcW 更改這將修復代碼。

理想情況下,您應該更改項目設置以使用 Unicode,而不是多字節字符集。 這將簡化一切,您可以使用CreateWindowExRegisterClassEx等宏,而不是像您一樣顯式使用 Unicode / ANSI 版本。

正如其他人所說,這是字符集之間的不匹配。

理想情況下,您應該在所有相互交互的 API 調用之間匹配字符集。 所以如果你使用CreateWindowExW你也應該使用RegisterClassExW , DefWindowProcW , DispatchMessageW ...

這是一個非常好的,學到了一些新東西!

你需要改變

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

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

或者甚至更好:堅持一種字符編碼。 充其量只使用RegisterClassCreateWindowEx等,讓編譯器采用正確的 Unicode 或 ANSI 函數。

CreateWindowExA 將字符串解釋為 8 位字符。 L"Sample" 的后 8 位為零,因為它的第一個字符是 0x0053 - L 表示使用寬字符。 因此該函數將其解釋為 1 個字符的空終止字符串。

我認為RegisterClassmsdn 頁面提示了此處失敗的原因,在備注部分它提到如果您使用寬字符或 ansi 支持,它將以這種格式傳遞內部文本參數/消息(寬字符/安西)。 很可能這就是窗口標題發生的情況,即使我們說使用CreateWindowExA ,這也不起作用,因為 Windows SDK 在內部將該字符串編碼為寬字符串,並且CreateWinowExA嘗試輸出好像它是一個安絲弦。

簡而言之,不要混合 W 和 A 方法,除非您有充分的理由這樣做,並且如果您想要寬字符支持定義您的 UNICODE 宏,請讓 Windows 標題為您處理它。

在您的最后一種情況下,您的 L"Sample" 仍然是 Unicode,不是嗎? 您可以使用 _T() 宏,它會根據項目的 Unuicode 設置自動添加或刪除 L 前綴。

正如@Pete 已經說過的,Unicode L"Sample" 在 ascii 中是 "S\\0...",這就是為什么只打印一個符號的原因。

我很高興我找到了這個。 我一直在尋找答案,似乎很難通過 Google 等正確找到。我確實發現了針對特定程序報告的類似問題,總是歸咎於“某些插件”。

這令人抓狂,因為 WndProc 的問題遠不及調用 CreateWindowEx 或 RegisterClassEx!

順便說一句,我明確使用 -W 后綴,因為我想制作一個適用於以任何一種方式構建的程序的 DLL,或者克服我添加到的程序的非 Unicode 設置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM