Как MFC интерпретирует SetWindowTextW (LPCTSTR)? - PullRequest
0 голосов
/ 05 декабря 2018

В MFC нет методов, определенных как CWnd::SetWindowTextA / CWnd::SetWindowTextW, однако следующий код будет компилироваться и работать правильно в зависимости от настроек Unicode:

//UNICODE is defined
BOOL CMyDialog::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    //this line won't compile as expected
    //SetWindowTextA(L"ANSI");

    //this line compiles, but CWnd::SetWindowTextW doesn't exits
    //SetWindowTextW ends up calling CWnd::SetWindowText
    SetWindowTextW(L"Unicode");
    return TRUE;
}

//UNICODE is not defined
BOOL CMyDialog::OnInitDialog()
{
    CDialogEx::OnInitDialog(); 

    //this line compiles, but CWnd::SetWindowTextA doesn't exits!
    //SetWindowTextA ends up calling CWnd::SetWindowText
    SetWindowTextA("ANSI");

    //this line won't compile as expected
    //SetWindowTextW(L"Unicode");
    return TRUE;
}

Имеет смысл, что SetWindowTextотображается в SetWindowTextA / SetWindowTextW в зависимости от макроса.Но я не понимаю, как wnd->SetWindowTextA / wnd->SetWindowTextW возвращается обратно в CWnd::SetWindowText.

1 Ответ

0 голосов
/ 05 декабря 2018

Это побочный эффект объявления макроса в WinUser.h.Он применяется не только к объявлению глобальной функции для API Windows, но также к любому другому идентификатору с именем SetWindowText, который появляется в коде: глобальный, локальный или область действия класса.

#ifdef UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif // !UNICODE

Так что любой класс C ++, которыйобъявляет, что метод с именем SetWindowText получает весь этот метод, неявно преобразованный препроцессором.

У меня не установлено MFC, но я знаю, что этот метод существует для класса CWindow в ATL и определяется следующим образом.

    class CWindow
    {
    public:
        ...

        BOOL SetWindowText(_In_z_ LPCTSTR lpszString) throw()
        {
            ATLASSERT(::IsWindow(m_hWnd));
            return ::SetWindowText(m_hWnd, lpszString);
        }

        ...
    };

Но во время компиляции приведенный выше код (для отладочной сборки) будет преобразован препроцессором во что-то вроде следующего:

BOOL SetWindowTextW(  LPCTSTR lpszString) throw()
{
    (void)( (!!((::IsWindow(m_hWnd)))) || (1 != _CrtDbgReportW(2, L"c:\\program files...
    return ::SetWindowTextW(m_hWnd, lpszString);
}

Как ни странно, LPCTSTRПараметр метода - typedef'd вместо замены макроса, но вы понимаете, что это так.

Если у вас достаточно большое приложение для Windows, очень высока вероятность того, что один из ваших существующих классов C ++, который вы определили самостоятельно, имеетметод или переменная-член, которая соответствует Windows API.И он получает такое же лечение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...