发送消息的问题
我正在使用 C# 开发一个应用程序,具有与 Windows 中类似的复制、粘贴功能。 我添加了菜单项并与相应的应用程序链接。
请查看下图以获得更多想法。
添加到 shell 菜单的项目 http://softwaregenius.net/myimages/menu.jpg
像我们一样在 Windows 资源管理器中选择多个项目,您需要选择多个文件和/或文件夹,然后选择 OS Util->FastCopy。打开一个表单,如下所示
FastCopy 上显示的表单 http://softwaregenius.net/myimages/fastcopy1.jpg
该应用程序运行良好。这里的主要问题是,选择文件后,所有这些文件都会在相应的软件中打开。也就是说,如果我选择了 Word 文档,则文件名将添加到 FastCopy 表单中,但也会在 Word 中打开。
当我调查时,我发现这个问题是由于SendMessage造成的。我必须使用 PostMessage 而不是 SendMessage。但是当我这样做时,应用程序无法运行。
下面是我在 C# 2005 中的 Main 函数编码
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 的副本以及 Form
公共分部类 frmFastCopy 中的其他代码: { 委托无效 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。
感谢您分享您的宝贵时间。
问候
伊尔凡
I am developing an application using C# having similar functionality of copy,paste as in Windows.
I have added menu items and linked with respective applications.
Please look at the following image for getting more idea.
Items added to shell menu http://softwaregenius.net/myimages/menu.jpg
Like we select multiple items in windows explorer, you need to select multiple files and/or folders and then select OS Util->FastCopy. A form is opened as shown below
Form shown on FastCopy http://softwaregenius.net/myimages/fastcopy1.jpg
The application is working perfectly. The major problem here is that after selecting the files all these files are opening up within there respective softwares. That is if i selected word document then the filename is added to FastCopy form but the is also opening up within Word also.
When i investigate i found that this problem is due to SendMessage. I have to use PostMessage instead of SendMessage. But when i do so the application is not working.
Below is my Main function coding in 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);
}
}
}
Below is the copy for WndProc and other code from within the Form
public partial class frmFastCopy : Form
{
delegate void 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;
}
Here is the NativeCode class
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);
}
I know you guys are genius. Could someone tell me where should i make changes to that the selected files should be opened or rather how i should use postmessage.
Thanks for sharing your valuable time.
Regards
Irfan
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请看我的评论(我想知道为什么你不在这里使用 Clipboard 类)。但忽略这一点:你为什么要广播这条消息?
您能否找到您的应用程序(通过名称、窗口类等)并仅将消息发送到您自己的应用程序?
详细说明消息处理:
您在下面的评论中提到了关于 HWND_BROADCAST 的内容:
不,不是。它是一个特殊值,告诉 Windows“此消息适用于所有应用程序”。您正在向所有应用程序发送
WM_SHOWME
。这就是为什么我问你为什么要这样做?请参阅旧新事物博客上的这篇文章关于消息广播。
Please look at my comment (I wonder why you don't use the Clipboard class here). But ignoring that: Why do you broadcast the message?
Can you locate your application (by name, window class, whatever) and only send the message to your own application?
To elaborate on the message handling:
You say regarding HWND_BROADCAST in the comments below:
No, it's not. It is a special value that tells Windows "this message is for all applications". You are sending a
WM_SHOWME
to all applications. Which is why I asked why you would want to do that?Please see this post on the old new things blog regarding message broadcasts.