Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> C# и WinAPI, Преобразование string в wparam 
V
    Опции темы
erm0l0v
Дата 12.1.2011, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



Мне нужно отправить сообщение.

Загружаю SendMessage
Код

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, string wParam, string lParam);


Отправляю сообщение
Код

str = "Hello World!\0";
SendMessage(hWnd, MsgId.PrintReport, str, null);


Сообщение приходит, но вот значение параметра wParam Совершенно не предсказуемо.

В чем может быть ошибка?

PM MAIL   Вверх
erm0l0v
Дата 12.1.2011, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



Кстати, забыл добавить сообщение ловит программа написанная на Delphi

Только что попробовал отправить сообщение WM_SETTEXT все сработало нормально.

Есть предположение что косяк в преобразовании из string C# в String Delphi.

Пробовал слать это же сообщение из C++ все работает нормально.

(Доступа к исходным кодам на Delphi нет) единственно что нашел в документации есть пример как отправлять это сообщение из Delphi там у них строка преобразуется так:

Код

WParam:=Integer(PChar(RepList.Text)); 

PM MAIL   Вверх
Любитель
Дата 12.1.2011, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 11
Всего: 92



Цитата(erm0l0v @  12.1.2011,  17:32 Найти цитируемый пост)
Пробовал слать это же сообщение из C++ все работает нормально.

Покажите код на C++. Скорей всего там у вас анси строк, а здесь юникод (по дефолту). В дельфийской проге кастится к анси строке (указателю, но не суть).


--------------------
PM MAIL ICQ Skype   Вверх
erm0l0v
Дата 12.1.2011, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



На C++ отправляю так:
Код

SendMessage(hWinPost, RegMessage::wm_winpost_printreport, (WPARAM)"\nHello world!!!", 0);


Я не думаю что проблема с кодировкой, он каждый раз выдает разные символы. Если бы проблема была с кодировкой то думаю что символы были бы одни и теже
PM MAIL   Вверх
Любитель
Дата 12.1.2011, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 11
Всего: 92



Попробуй маршалинг как анси строки для начала.


--------------------
PM MAIL ICQ Skype   Вверх
jonie
Дата 12.1.2011, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 22
Всего: 118



Правильная сигнатура должна быть такой: (http://www.pinvoke.net/default.aspx/user32.sendmessage)
Код

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

там же примеры как маршалить автоматически


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Любитель
Дата 12.1.2011, 20:54 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 11
Всего: 92



Что значит "правильная"? wParam/lParam на практике интерпретируются по разному. В принципе - делать вызовы Marshal.XxxToXxx в коде или прописать нужные типы и пр. сразу - не суть важно.

Вопрос собственно в том, как интерпретируются параметры в приложении, принимающем сообщения.


--------------------
PM MAIL ICQ Skype   Вверх
erm0l0v
Дата 13.1.2011, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



wparam по сути это ни что иное как ссылка на тип PCHAR. Именно к этому C# должен преобразовать string в конечном итоге, что он успешно делает при отправке сообщения WM_SETTEXT

Код

const int WM_SETTEXT = 0xC;

str = "New title\0";
IntPtr result = SendMessage(hWnd, WM_SETTEXT, null, str);


А при отправке сообщения WM_WINPOST_PRINTREPORT в WinPost (и есть та самая программа на Delphi) все вместо того текста который нужен отображается что то непонятное. Чаще всего пустое поле, или 2 - 3 символа. Причем отображает каждый раз разные символы при одинаковых начальных условиях. Такое впечатление что ссылка которая дошла в WinPost указывает куда угодно, но только не на мою строку.
PM MAIL   Вверх
Любитель
Дата 13.1.2011, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 11
Всего: 92



Цитата(erm0l0v @  13.1.2011,  09:44 Найти цитируемый пост)
wparam по сути это ни что иное как ссылка на тип PCHAR

Не. Вообще говоря это просто 32-битный параметр. Как он интерпретируется - другой вопрос smile

Попробуй всё-таки явно прописать маршаллинг как LPStr.


--------------------
PM MAIL ICQ Skype   Вверх
erm0l0v
Дата 13.1.2011, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



Я сделал так:

Код

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, [MarshalAs(UnmanagedType.LPStr)] string wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);


лучше не стало, пробовал преобразовать так Marshal.StringToXxx тоже не получилось.

Может я просто не правильно использую Marshal?
PM MAIL   Вверх
Любитель
Дата 13.1.2011, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 11
Всего: 92



Хм. Тогда не знаю точно :(
А есть возможность выложить/прислать клинетское приложение?


--------------------
PM MAIL ICQ Skype   Вверх
erm0l0v
Дата 14.1.2011, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



Вот мой код.

Код

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;

namespace WinTest
{

    public partial class MainForm : Form
    {
        [MarshalAs(UnmanagedType.LPStr)] string str;

        static IntPtr hWnd; 

        const int WM_CLOSE = 0x0010;

        const int WM_SETTEXT = 0xC;

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindow(string className, string windowTitle);
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern int RegisterWindowMessage(string lpString);

        [DllImport("User32.DLL", EntryPoint = "SendMessageA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        static extern IntPtr SendMessage(IntPtr hWnd, int Msg, [MarshalAs(UnmanagedType.LPStr)] string wParam, IntPtr lParam);
        [DllImport("User32.DLL", EntryPoint = "SendMessageA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);
        [DllImport("User32.DLL", EntryPoint = "SendMessageA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SendMessage(IntPtr hWnd, int Msg, [MarshalAs(UnmanagedType.LPStr)] string wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);

        public static class MsgId
        {
            public static int ModHandle =    RegisterWindowMessage("WM_WINPOST_MODWNDHANDLE");
            public static int SQLFree =        RegisterWindowMessage("WM_WINPOST_SQLEXEC");
            public static int SetProp =        RegisterWindowMessage("WM_WINPOST_SETPROP");
            public static int GetProp =        RegisterWindowMessage("WM_WINPOST_GETPROP");
            public static int Detach =        RegisterWindowMessage("WM_WINPOST_DETACH");
            public static int Post =        RegisterWindowMessage("WM_WINPOST_POST");
            public static int WinPostOk =    RegisterWindowMessage("WM_WINPOST_OK");
            public static int PrintReport = RegisterWindowMessage("WM_WINPOST_PRINTREPORT");
        }

        

        public MainForm()
        {
            InitializeComponent();
            hWnd = FindWindow("TfmSession", null);
            textBoxHWND.Text = hWnd.ToString("x");
            while (textBoxHWND.Text.Length < 8)
            {
                textBoxHWND.Text = "0" + textBoxHWND.Text;
            }
            textBoxHWND.Text = "0x" + textBoxHWND.Text;

            IntPtr hMyWnd = this.Handle;

            textBoxMyHWND.Text = hMyWnd.ToString("x");

            while (textBoxMyHWND.Text.Length < 8)
            {
                textBoxMyHWND.Text = "0" + textBoxMyHWND.Text;
            }
            textBoxMyHWND.Text = "0x" + textBoxMyHWND.Text;

            IntPtr result = SendMessage(hWnd, MsgId.ModHandle, hMyWnd, IntPtr.Zero);

            if (result.ToInt64() == 1)
            {
                textBoxType.Text = "Услуги";
            }
            if (result.ToInt64() == 2)
            {
                textBoxType.Text = "Просмотр";
            }
        }

        

        private void button1_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void buttonPrintreport_Click(object sender, EventArgs e)
        {
            str = textBoxPrintreport.Text + '\0';

            IntPtr result = SendMessage(hWnd, MsgId.PrintReport, str, IntPtr.Zero);
            MessageBox.Show(result.ToString());
        }

        private void buttonCloseWinPost_Click(object sender, EventArgs e)
        {
            if (SendMessage(hWnd, WM_CLOSE, (string)null, null) == IntPtr.Zero)
            {
                textBoxHWND.Text = "0x00000000";
            }
        }

        private void buttonTitle_Click(object sender, EventArgs e)
        {
            str = textBoxTitle.Text + '\0';

            IntPtr result = SendMessage(hWnd, WM_SETTEXT, null, str);
            MessageBox.Show(result.ToString());
        }
    }
}



Он запускается из dll для WinPosta как процесс.

Сам WinPost 107 MB можно взять здесь

Программу можно протестировать так:

В WinPost: Новый Клиент -> Услуги -> Внешний Модуль -> Пример подключаемого модуля

После этого можно запустить программу, по идеи будет работать так же как если бы она была запущена из dll.

Во вложении я скинул свою программку, исходный код которой приведен выше.

Присоединённый файл ( Кол-во скачиваний: 11 )
Присоединённый файл  WinTest.rar 43,85 Kb
PM MAIL   Вверх
erm0l0v
Дата 14.1.2011, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



Все проблему решил.

Я переделал C# код в dll (правда очень корява, путём пере компилирования dll в il и обратно)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1115 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.