Why is SetWindowText not working any more?

Viewed 157

I have code that was 1st developed with Visual C++ Version 1.52 (working and self taught). A couple of years ago I adapted it with Visual Studio and got it working. I am now trying it again with Visual Studio 2022 but I can't get the SetWindowText function to work as it had. It does change the parent window title text but it is gobbledygook. I assume it's a UNICODE problem but so far haven't been able to negotiate the maze of explanation. It is set in a wizard generated MFC document. I'm including the function. Any suggestions?

void CTICTACView::Game()
{

    CWnd* p_Wnd = GetParent();
    const char* capt = "TIC TAC TOE";
    const char* gm = "GAME!";
    if (!game)
        p_Wnd->SetWindowText((LPCTSTR)capt);
    else
        p_Wnd->SetWindowText((LPCTSTR)gm);

}

After constructing Frankenstein from bits and pieces, this is what I finally got to work. Thank you everybody.

void CTICTACView::Game()
{
  CWnd* p_Wnd = GetParent();    
  const wchar_t* capt =_T("TIC TAC TOE");
  const wchar_t* gm = _T("GAME!");
  if (!game)
    p_Wnd->SetWindowText((LPCWSTR)capt);
  else
    p_Wnd->SetWindowText((LPCWSTR)gm);
}
1 Answers

Although the last revision will work in a Unicode project, it is still not very much OK. It's indeed kinda "Frankenstein", because it mixes types and definitions. wchar_t is a C++ type (albeit implementation-defined), while the whole T mechanism is Microsoft-specific and based on preprocessor defines. Depending on the compiler options T is defined as either W, for Unicode, or A (or nothing) for ANSI. This applies to types (eg LPCTSTR->LPCWSTR/LPCSTR) and functions (eg SetWindowText()->SetWindowTextW()/SetWindowTextA()). Also, why use a cast at all? Therefore, in order to be consistent I would suggest to modify your code as shown below:

A. Explicit Unicode Implementation

void CTICTACView::Game()
{
    CWnd* p_Wnd = GetParent();
    const wchar_t* capt = L"TIC TAC TOE"; // you could also use WCHAR
    const wchar_t* gm = L"GAME!";
    if (!game)
        p_Wnd->SetWindowTextW(capt);
    else
        p_Wnd->SetWindowTextW(gm);
}

The above code will also work even with the multibyte (ANSI) option, as all types and calls are explicitly Unicode. It will always call the wide version of SetWindowText() and pass a wide string. If the project is compiled with the multibyte character option, the function (not the compiler!) will convert the string to ANSI, based on the system's default codepage.

B. Using the "T" (conditional) definitions

void CTICTACView::Game()
{
    CWnd* p_Wnd = GetParent();
    const TCHAR* capt =_T("TIC TAC TOE"); // You could also use LPCTSTR instead of TCHAR*
    const TCHAR* gm = _T("GAME!");
    if (!game)
        p_Wnd->SetWindowText(capt);
    else
        p_Wnd->SetWindowText(gm);
}

The above code should work with both the Unicode and ANSI options. In the Unicode case the strings will be defined as wide-strings, and the wide version of SetWindowText() will be called, while in the ANSI case both the strings and the function call will be ANSI. No conversion will take place in either case.

Furthermore, the code could be consolidated quite a bit:

void CTICTACView::Game()
{
    GetParent()->SetWindowText(game ? _T("GAME!") : _T("TIC TAC TOE"));
}
Related