Проблема с SendMessage

Я разрабатываю приложение с использованием С#, имеющее аналогичную функциональность копирования и вставки, как в Windows. Я добавил пункты меню и связал их с соответствующими приложениями.

Пожалуйста, посмотрите на следующее изображение, чтобы получить больше информации.

http://softwaregenius.net/myimages/menu.jpg

Подобно тому, как мы выбираем несколько элементов в проводнике Windows, вам нужно выбрать несколько файлов и/или папок, а затем выбрать OS Util->FastCopy. Форма открывается, как показано ниже

http://softwaregenius.net/myimages/fastcopy1.jpg

Приложение работает отлично. Основная проблема здесь заключается в том, что после выбора файлов все эти файлы открываются в соответствующем программном обеспечении. То есть, если я выбрал текстовый документ, то имя файла добавляется в форму FastCopy, но также открывается в Word.

Когда я исследую, я обнаружил, что эта проблема связана с SendMessage. Я должен использовать PostMessage вместо SendMessage. Но когда я это делаю, приложение не работает.

Ниже приведен код моей основной функции в C # 2005.

static class Program
{
    static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE92}");
    [STAThread]
    static void Main(string[] args)
    {
        string fileName = "";
        if (args.Length > 0)
        {
            fileName = args[0];
        }
        if (mutex.WaitOne(TimeSpan.Zero, true))
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            frmFastCopy frm = new frmFastCopy();
            frm.AddItemToList(fileName);
            Application.Run(frm);

        }
        else
        {
            //The following message is sent just to show up the form
            NativeMethods.PostMessage(
                    (IntPtr)NativeMethods.HWND_BROADCAST,
                    NativeMethods.WM_SHOWME,
                    IntPtr.Zero,
                    IntPtr.Zero);

            //Send the filename
            SendFileName(fileName);
        }
    }

    static void SendFileName(string s)
    {
        Win32.CopyDataStruct cds = new Win32.CopyDataStruct();

        cds.cbData = (s.Length + 1) * 2;
        cds.lpData = Win32.LocalAlloc(0x40, cds.cbData);
        Marshal.Copy(s.ToCharArray(), 0, cds.lpData, s.Length);
        cds.dwData = (IntPtr)1;
        Win32.SendMessage((IntPtr)NativeMethods.HWND_BROADCAST, Win32.WM_COPYDATA, IntPtr.Zero, ref cds);
        //NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, Win32.WM_COPYDATA, cds.lpData, IntPtr.Zero);
    }
}

}


Ниже приведена копия WndProc и другого кода из формы.

общедоступный частичный класс frmFastCopy: Form {делегат недействителен AddItemToListDelegate (string itm);

    public frmFastCopy()
    {
        InitializeComponent();
    }

    public void AddItemToList(string itm)
    {
        if (lvFilesAndFolders.InvokeRequired)
        {
            AddItemToListDelegate m = new AddItemToListDelegate(AddItemToList);
            this.Invoke(m, new object[] { itm });
        }
        else
        {
            lvFilesAndFolders.Items.Add(itm);
        }
    }
    protected override void WndProc(ref Message m)
    {
        if (m.Msg==NativeMethods.WM_SHOWME)
        {
                ShowMe();
        }
        if (m.Msg==Win32.WM_COPYDATA)
        {
                //string s = Marshal.PtrToStringUni(m.LParam);
                MessageBox.Show("Got message");

                Win32.CopyDataStruct st = (Win32.CopyDataStruct)Marshal.PtrToStructure(m.LParam, typeof(Win32.CopyDataStruct));
                string strData = Marshal.PtrToStringUni(st.lpData);
                AddItemToList(strData);
        }
        base.WndProc(ref m);
    }
    private void ShowMe()
    {
        this.Show();
        if (WindowState == FormWindowState.Minimized)
        {
            WindowState = FormWindowState.Normal;
        }
        // get our current "TopMost" value (ours will always be false though)
        bool top = TopMost;
        // make our form jump to the top of everything
        TopMost = true;
        // set it back to whatever it was
        TopMost = top;
    }

Вот класс NativeCode

internal class NativeMethods
{
    public const int HWND_BROADCAST = 0xffff;
    public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32")]
    public static extern int RegisterWindowMessage(string message);

}

Я знаю, что вы, ребята, гении. Может ли кто-нибудь сказать мне, где я должен внести изменения в то, что выбранные файлы должны быть открыты, или, скорее, как я должен использовать postmessage.

Спасибо, что поделились своим драгоценным временем.

С Уважением

Ирфан


person IrfanRaza    schedule 07.01.2010    source источник
comment
Не пишите расширения оболочки в управляемом коде, это приглашение потенциально привести к сбою любой программы, которая использует стандартный диалог открытия или сохранения. См. также blogs.msdn.com/oldnewthing/archive/2006/ 18.12.1317290.aspx   -  person nielsm    schedule 07.01.2010
comment
Можете ли вы уточнить использование, чтобы удовлетворить мое любопытство? Почему вы не используете класс Clipboard?   -  person Benjamin Podszun    schedule 07.01.2010
comment
Каково значение WM_SHOWME?   -  person Lasse V. Karlsen    schedule 07.01.2010
comment
Есть ли класс буфера обмена? На самом деле у меня нет идеи. Если да, то я постараюсь это реализовать. Во-вторых, программирования оболочки не так много, потому что каждая форма представляет собой отдельное приложение C# и привязана к меню оболочки. Поле «Открыть» или «Сохранить» вообще отсутствует. Спасибо   -  person IrfanRaza    schedule 07.01.2010
comment
@Irfan: все, что добавлено в меню оболочки, является расширением оболочки и, следовательно, программированием оболочки. См. комментарий @nielsm и перейдите по предоставленной ссылке.   -  person Ken White    schedule 11.01.2010


Ответы (1)


Пожалуйста, посмотрите на мой комментарий (интересно, почему вы не используете здесь класс Clipboard). Но игнорируя это: почему вы транслируете сообщение?

Можете ли вы найти свое приложение (по имени, классу окна и т. д.) и отправить сообщение только своему приложению?


Чтобы уточнить обработку сообщений: вы говорите о HWND_BROADCAST в комментариях ниже:

Это не что иное, как глобальный дескриптор моего приложения.

Нет, это не так. Это специальное значение, которое сообщает Windows, что «это сообщение для всех приложений». Вы отправляете WM_SHOWME всем приложениям. Вот почему я спросил, почему вы хотите это сделать?

См. этот пост в старом новом блоге. относительно рассылки сообщений.

person Benjamin Podszun    schedule 07.01.2010
comment
Да, я использовал мьютекс для создания только одного экземпляра. Я думаю, вы не заметили мой код. Приложение работает нормально, так как мне нужно было только проблема в том, что выбранные файлы также открываются в соответствующем программном обеспечении. - person IrfanRaza; 07.01.2010
comment
Хороших новинок друзья!!!! Класс Clipboard решил мою проблему. Большое спасибо Бенджамин. Но все же я хотел бы спросить вас, ребята, как здесь использовать postmessage? - person IrfanRaza; 07.01.2010
comment
Рад, что вы узнали о (готовом, пригодном для использования) классе Clipboard. Что касается кода: я просто хотел понять, почему вы будете использовать HWND_BROADCAST вместо того, чтобы искать свое собственное приложение и публиковать или отправлять свое сообщение напрямую, без трансляции. - person Benjamin Podszun; 07.01.2010
comment
Это не что иное, как глобальный дескриптор моего приложения. - person IrfanRaza; 11.01.2010
comment
Использование буфера обмена на 100 % неправильно. Буфер обмена принадлежит пользователю приложения, а не вашей программе. IOW, единственный раз, когда что-то должно быть помещено в буфер обмена или извлечено из него, это когда пользователь приложения решает это сделать. В противном случае ваше приложение может уничтожить контент, который пользователь фактически +делал+, а также может получить контент, которого он не ожидал. - person Ken White; 11.01.2010
comment
@Ken: Вы действительно читали его требование? У него есть пункт контекстного меню, который что-то копирует и называется FastCopy. Вы можете спорить, полезно ли это, и я согласен с тем, что вам не следует использовать расширения оболочки в C#. Но если моя программа предлагает копирование и вставку и помечает это как это, есть один класс для использования: буфер обмена. Дело не в том, что он случайно выбирает что-то туда положить... - person Benjamin Podszun; 12.01.2010
comment
Спасибо, Бенджамин, что поправил меня. Честно говоря, часть кода здесь копируется/вставляется с помощью Google. Я думал, что HWND_BROADCAST является глобальным дескриптором моего приложения. Привет, Кен, ты прав, но я создал свой собственный формат данных для буфера обмена. Разве это неправильно? - person IrfanRaza; 13.01.2010