Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > передача текста другому приложению SendMessage()


Автор: wallstreet 31.5.2012, 12:59
Всем добрый день. 
Собственно суть моей задачи сводится к освоению коммуникации двух приложений разных процессов путем передачи сообщения SendMessage(). Таким образом я создал два приложения (Sender и Acceptor) в одном из которых (Sender) происходит ввод текста пользователем в едит бокс и передача его другому (Acceptor), которое его принимает и выводит в элемент управления статик текст.
Проблема заключается в том, что передаю я то что ввел, а принимаю иероглифы. Есть предположение что обработка сообщения WM_COPYDATA работает только с ASCII кодировкой.

ссылки для скачивания: =>http://zalil.ru/33352189  http://zalil.ru/33352200

вобщем буду рад любой подсказке   smile 

Автор: DarkProg 31.5.2012, 13:44
В Delphi есть специальная функция, SendTextMessage, реализация её вот такая 
Код

SendMessage(Handle, Msg, WParam, Windows.LPARAM(PWideChar(LParam)))


На стороне принимающего приложения нужно определить структуру(код делфи, но перевести на структуру не так сложно)

Код

  TTextMessage = packed record
      Msg: Cardinal;
      WParam: Integer;
      LParam: String;
      Result: LRESULT;
    end;


И принимать сообщение типа TTextMessage.

Извиняюсь, что не код на C, но думаю всё получится.

Автор: feodorv 31.5.2012, 14:08
Вытяну код из многомегабайтных архивов. 

Sender
Код

INT_PTR CALLBACK Dialog1(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HWND hText, hEdit;
    static TCHAR *p;
    TCHAR *q;
    COPYDATASTRUCT cds;
    TCHAR text[256];
    switch(message)
    {
    /*case WM_CREATE:
        p = new TCHAR[256];
        break;*/
    /*case WM_COPYDATA:
        p = new TCHAR[((COPYDATASTRUCT*)lParam)->cbData/sizeof(TCHAR)];
        q = (TCHAR*)(((COPYDATASTRUCT*)lParam)->lpData);
        for(int i=0; i<256; ++i)
            text[i] = *q++;
        SetDlgItemText(hDlg, IDC_STATIC, text);
        break;*/
    case WM_INITDIALOG:
        hText = GetDlgItem(hDlg, IDC_STATIC);
        hEdit = GetDlgItem(hDlg, IDC_EDIT1);
        SetDlgItemText(hDlg, IDC_EDIT1, _T(""));
        return TRUE;
    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case IDOK:
            GetDlgItemText(hDlg, IDC_EDIT1, text, 256);
            /*for(int y=0; y<256; ++y)
                *p[y] = text[y]; */
            p = &text[256];
            SetDlgItemText(hDlg, IDC_STATIC, text);
            cds.cbData = 256 * sizeof(wchar_t);
            cds.lpData = p;
            SendMessage(FindWindow(NULL, _T("Acceptor")), WM_COPYDATA, 0, (LPARAM)&cds);
            SetFocus(hEdit);
            return TRUE;
        case WM_DESTROY:
            EndDialog(hDlg, LOWORD(wParam));
            return TRUE;
        }
    default: return FALSE;
    }
    return FALSE;
}


Acceptor
Код

INT_PTR CALLBACK Dialog1(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HWND hText, hEdit;
    static TCHAR *p;
    TCHAR *q;
    int x;
    /*COPYDATASTRUCT cds;*/
    TCHAR text[256];
    switch(message)
    {
    /*case WM_CREATE:
        p = &text[256];
        break;*/
    case WM_COPYDATA:
        p = new TCHAR[((COPYDATASTRUCT*)lParam)->cbData/sizeof(TCHAR)];
        q = (TCHAR*)(((COPYDATASTRUCT*)lParam)->lpData);
        for(int i=0; i<256; i++)
            p[i] = *q++;
    
        SetDlgItemText(hDlg, IDC_STATIC, p);
        break;
    case WM_INITDIALOG:
        hText = GetDlgItem(hDlg, IDC_STATIC);
        hEdit = GetDlgItem(hDlg, IDC_EDIT1);
        SetDlgItemText(hDlg, IDC_EDIT1, _T(""));
        return TRUE;
    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case IDOK:
            GetDlgItemText(hDlg, IDC_EDIT1, text, 256);
            SetDlgItemText(hDlg, IDC_STATIC, text);
            /*cds.cbData = 256 * sizeof(TCHAR);
            cds.lpData = p;*/
            /*SendMessage(FindWindow(NULL, _T("Acceptor")), WM_COPYDATA, 0, (LPARAM)&cds);*/
            SetFocus(hEdit);
            return TRUE;
        case WM_DESTROY:
            EndDialog(hDlg, LOWORD(wParam));
            return TRUE;
        }
    default: return FALSE;
    }
    return FALSE;
}



Цитата(wallstreet @  31.5.2012,  13:59 Найти цитируемый пост)
передаю я то что ввел, а принимаю иероглифы

Цитата

    p = &text[256];

Что это такое???  smile 
И это Вы посылаете? Это не то, что Вы ввели. То, что Вы ввели, находится здесь: &text[0].

Автор: wallstreet 31.5.2012, 14:48
Цитата(feodorv @  31.5.2012,  14:08 Найти цитируемый пост)
Что это такое???   И это Вы посылаете? Это не то, что Вы ввели. То, что Вы ввели, находится здесь: &text[0]. 

Я в шоке просто. Неделю разбирался и писал все остальное и на такой мелочи попался.

Всех благодарю за помощь. smile  smile  smile 

Автор: feodorv 31.5.2012, 18:58
Цитата(wallstreet @  31.5.2012,  15:48 Найти цитируемый пост)
и на такой мелочи попался.

Там есть ещё немного мелочёвки))))


Цитата(feodorv @  31.5.2012,  15:08 Найти цитируемый пост)
    case WM_COPYDATA:
        p = new TCHAR[((COPYDATASTRUCT*)lParam)->cbData/sizeof(TCHAR)];
        q = (TCHAR*)(((COPYDATASTRUCT*)lParam)->lpData);
        for(int i=0; i<256; i++)
            p[i] = *q++;
    
        SetDlgItemText(hDlg, IDC_STATIC, p);
        break;

При каждом WM_COPYDATA для p будет выделяться память (а прошлая выделенная - теряться). Зачем её вообще выделять, если выше есть объявление
Цитата(feodorv @  31.5.2012,  15:08 Найти цитируемый пост)
    TCHAR text[256];

Достаточно просто проверить, что данных пришло не слишком много, и они все умещаются в text.
p, кстати, так нигде и не высвобождается...


Далее. Здесь размер присланного ещё как-то учитывается:
Цитата(feodorv @  31.5.2012,  15:08 Найти цитируемый пост)
new TCHAR[((COPYDATASTRUCT*)lParam)->cbData/sizeof(TCHAR)];

Вот тут - 256 символов, и точка:
Цитата(feodorv @  31.5.2012,  15:08 Найти цитируемый пост)
        for(int i=0; i<256; i++)


Автор: wallstreet 5.6.2012, 16:16
Благодарю за подсказку. 
Незнаю правильно или нет, но переделал проблемный кусок и пока все работает как надо.
Код

case WM_COPYDATA:
        if(((COPYDATASTRUCT*)lParam)->cbData/sizeof(TCHAR)<=256)
        {
            q = (TCHAR*)(((COPYDATASTRUCT*)lParam)->lpData);
            for(int i=0; i<((COPYDATASTRUCT*)lParam)->cbData/sizeof(TCHAR); i++)
            {
                text[i] = *q++;
            }
        }
        SetDlgItemText(hDlg, IDC_STATIC, text);
        break;


Теперь необходимость в выделении памяти отпала, как и в ее удалении. smile 

Автор: volatile 5.6.2012, 23:34
Цитата(wallstreet @  5.6.2012,  16:16 Найти цитируемый пост)
        if(((COPYDATASTRUCT*)lParam)->cbData/sizeof(TCHAR)<=256)
        {
            q = (TCHAR*)(((COPYDATASTRUCT*)lParam)->lpData);
            for(int i=0; i<((COPYDATASTRUCT*)lParam)->cbData/sizeof(TCHAR); i++)
            {
                text[i] = *q++;
            }
        }
        SetDlgItemText(hDlg, IDC_STATIC, text);
        break;

Если данных пришло больше 256, зачем посылать мусор из text[] в IDC_STATIC ?

Зачем вообще столько лишних движений ?
Код

case WM_COPYDATA:
        SetDlgItemText(hDlg, IDC_STATIC, (TCHAR*)(((COPYDATASTRUCT*)lParam)->lpData));
        break;

Автор: wallstreet 6.6.2012, 09:57
О да, супер!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)