SendMessageA и SendMessageW в Win7 мигрировали из WinXP - PullRequest
1 голос
/ 15 сентября 2011

РЕДАКТИРОВАТЬ: рабочий код размещен ниже, нерабочий код закомментирован. Для извлечения данных из окон вы должны использовать тот же CHAR_T, который вы использовали для их создания в Win7.

У меня есть диалоговое окно, написанное на C, которое прекрасно работает в WinXP, но не может собрать пользовательский ввод из элемента управления редактирования в Unicode в Win7. Проблема возникает при первом вызове SendMessageW, как показано ниже:

/* handles to controls */
HWND hDomainEdit;
HWND hOtherEdit;
HWND hTextOut;
HWND hButton;
/* buffers to receive input */
WCHAR wszDomain[256];
CHAR szOtherInput[512];
CHAR szBuffer[512]; //added to hold temporary value of wszDomain
/* a test string */
const CHAR szTest[] = "This is a test of SendMessageA."

BOOL dialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {

    if (message == WM_INIT) {
        /* get all the handles shown above, then... */
        SendMessageA(hTextOut, WM_SETTEXT, 0, (LPARAM) szTest);
        /* worked fine */
        /* do a few other things */
    } else if (message == WM_COMMAND) {
        /* are some other conditions are true?  they sure are */
        /* time to collect a bunch of input from controls */
        int cchResultLen = (int) SendMessageA(hOtherEdit, WM_GETTEXT, 512, (LPARAM) szOtherInput);
        /* cchResultLen is correctly the length of the user input */
        /* cchResultLen = (int) SendMessageW(hDomainEdit, WM_GETTEXT, 256, (LPARAM) wszDomain); */
        /* begin new code */
        cchResultLen = (int) SendMessageA(hDomainEdit, WM_GETTEXT, 512, (LPARAM) szBuffer);
        cchResultLen = MultiByteToWideChar(CP_UTF8, 0, szBuffer, cchResultLen, wszDomain, 256);
        wszDomain[cchResultLen] = 0; /* above doesn't terminate string */
        /* after SendMessageW(), cchResultLen was 0, no string transferred, no error
           message.  using SendMessageA, all is well. */
    }
}

Похоже, что SendMessageA работает несколько раз с сообщением = WM_GETTEXT или WM_SETTEXT, и внезапно, когда требуется широкая строка, происходит сбой SendMessageW. Теперь я знаю, что все думают, что вы должны выбрать CHAR_T и придерживаться его, всегда используя SendMessage, но это не так; Win32.hlp явно отмечает, что можно использовать оба в одной и той же программе, вызывая отдельные функции вручную. Я уверен, что кто-то еще готов сказать, что сам элемент управления привязан или становится привязанным к одному конкретному CHAR_T, но это не относится к WinXP, где это работало идеально. Этот конкретный элемент управления для редактирования также никогда не устанавливается явно в строку ASCII.

Программа взаимодействует с WinHttp, для которого требуются все строки WCHAR, и именно здесь вступает SendMessageW. Остальные входные данные используются только для внутренних целей и представляют собой, в основном, анализируемые целые числа с метками модулей, которые более удобны и эффективны в ASCII, если только по той причине, что программа изначально была написана таким образом.

Так что же делать? Они действительно изменили что-то такое же неотъемлемое, как SendMessage, чтобы быть несовместимым? Если это так, то это известная ошибка с обходным решением или возможность переключать CHAR_T по желанию является устаревшей функцией? Есть ли какой-то другой более простой способ, чем расширение ввода вручную до WCHAR после получения его с помощью SendMessageA?

Ответы [ 2 ]

0 голосов
/ 01 октября 2011

Все ручки окон были в порядке. Люди из MSDN сообщили мне, что любое окно, созданное с помощью функции «A», в данном случае DialogBoxParamA (), должно быть доступно через функции «A». Что касается того, что это работает в XP, они сказали: «Только потому, что это работает, не значит, что это правильно». Я полагаю, что эта функциональность устарела - было бы приятно услышать об этом, прежде чем он перестал работать!

0 голосов
/ 30 сентября 2011

Насколько я понимаю, если вы пройдете свой код с помощью отладчика - вы увидите причину.

Прежде всего, два SendMessages у вас есть один за другим, они используют разные дескрипторы окна, поэтому они не из тех, которые дают вам одинаковый результат. Давайте поговорим о том, что дает вам проблему:

cchResultLen = (int) SendMessageW(hDomainEdit, WM_GETTEXT, 256, (LPARAM) wszDomain);
// cchResultLen is ZERO!  wszDomain[0] is null.  Edit control is not empty 

Стоя с отладчиком в этой строке, проверьте переменную hDomainEdit . Возможно, он недействителен, как NULL, или поврежден каким-либо другим кодом. Это объясняет неверный дескриптор и нулевой результат.

...