当前位置:   article > 正文

通过进程协作显示图像-C#

通过进程协作显示图像-C#

前言

如果一个软件比较复杂或者某些情况下需要拆解,可以考试将软件分解成两个或多个进程,但常规的消息传递又不能完全够用,使用消息+共享内存,实现图像传递,当然性能这个方面我并没有测试,仅是一种解决思路吧。

一、效果展示

1、调用方

2、被调用方

二、实现代码

1、主调打开调用进程

主要是为了拿到Handle,为发送消息函数提供操作句柄。

2、创建共享内存

  1. /// <summary>
  2. /// 创建共享内存
  3. /// </summary>
  4. /// <returns>0=创建成功;1=创建共享体失败;2=打开失败;3=印射失败; 4=共享内存命名错误</returns>
  5. public int CreateMemory()
  6. {
  7. if (MemSize <= 0) MemSize = 0x00800000;
  8. if (ShareName.Length > 0)
  9. {
  10. //创建内存共享体(INVALID_HANDLE_VALUE)
  11. m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)MemSize, ShareName);
  12. if (m_hSharedMemoryFile == IntPtr.Zero)
  13. {
  14. m_bAlreadyExist = false;
  15. m_bInit = false;
  16. MemPtr = IntPtr.Zero;
  17. return 1; //创建共享体失败
  18. }
  19. else
  20. {
  21. if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建
  22. {
  23. m_bAlreadyExist = true;
  24. CloseHandle(m_hSharedMemoryFile);
  25. m_hSharedMemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, ShareName);
  26. if (m_hSharedMemoryFile == null)
  27. {
  28. MemPtr = IntPtr.Zero;
  29. return 2;//打开共享内存失败
  30. }
  31. }
  32. else //新创建
  33. {
  34. m_bAlreadyExist = false;
  35. }
  36. }
  37. //创建内存映射
  38. m_rwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, (uint)MemSize);
  39. if (m_rwData == IntPtr.Zero)
  40. {
  41. m_bInit = false;
  42. CloseHandle(m_hSharedMemoryFile);
  43. MemPtr = IntPtr.Zero;
  44. return 3; //创建内存映射失败
  45. }
  46. else
  47. {
  48. m_bInit = true;
  49. MemPtr = m_rwData;
  50. }
  51. }
  52. else
  53. {
  54. return 4; //参数错误
  55. }
  56. return 0; //创建成功
  57. }

3、读取本地图像并写图像数据到共享内存中

  1. MyAlgoProcessNet.HImage hImage = new MyAlgoProcessNet.HImage(fileName);
  2. IntPtr prt = hImage.GetImagePointer1(out string type, out imageData.Widht, out imageData.Height);
  3. imageData.dataLength = imageData.Widht * imageData.Height;
  4. byte[] datas = new byte[imageData.dataLength];
  5. Marshal.Copy(prt, datas, 0, imageData.dataLength);
  6. int pos = Marshal.SizeOf(imageData);
  7. share1.WriteToMemory(imageData);
  8. //写共享内存
  9. if (share1.WriteBytes(datas, pos + 1) == 0)
  10. {
  11. WriteMsg("share1写入共享内存成功");
  12. }
  13. else
  14. {
  15. WriteMsg("share1写入共享内存失败!!");
  16. }
  17. public int WriteBytes(byte[] datas, int pos = -1)
  18. {
  19. if (IntPtr.Zero == MemPtr)
  20. {
  21. return -1;
  22. }
  23. if (pos == -1)
  24. {
  25. Marshal.Copy(datas, 0, MemPtr, datas.Length);
  26. }
  27. else
  28. {
  29. IntPtr offPtr = IntPtr.Add(MemPtr, pos);
  30. Marshal.Copy(datas, 0, offPtr, datas.Length);
  31. }
  32. return 0;
  33. }

4、通知读取数据

  1. private void SendMsg2(string msg)
  2. {
  3. // 获取目标进程句柄
  4. IntPtr hWnd = process.MainWindowHandle;
  5. // 封装消息
  6. byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);
  7. int len = sarr.Length;
  8. COPYDATASTRUCT cds2;
  9. cds2.dwData = (IntPtr)0;
  10. cds2.cbData = len + 1;
  11. cds2.lpData = msg;
  12. // 发送消息
  13. WriteMsg(msg + " Start");
  14. SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds2);
  15. WriteMsg(msg + " End");
  16. }

5、被调用方关联消息处理函数

  1. protected override void OnSourceInitialized(EventArgs e)
  2. {
  3. base.OnSourceInitialized(e);
  4. HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
  5. if (hwndSource != null)
  6. {
  7. IntPtr handle = hwndSource.Handle;
  8. hwndSource.AddHook(new HwndSourceHook(WndProc));
  9. }
  10. }

6、被调用方处理图像数据

  1. private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  2. {
  3. if (msg == WM_COPYDATA)
  4. {
  5. WriteInfo(1, "WndProc Start");
  6. COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam,
  7. typeof(COPYDATASTRUCT)); // 接收封装的消息
  8. string rece = cds.lpData; // 获取消息内容
  9. // 自定义行为
  10. // Console.WriteLine(rece);
  11. if (rece == "Read")
  12. {
  13. Task.Run(() =>
  14. {
  15. //读共享内存
  16. // datastruct = (MemoryClass)shareMemory.ReadFromMemory(typeof(MemoryClass));
  17. // WriteInfo(1, $"读取数据:{datastruct.bianliang1},{datastruct.bianliang2},{datastruct.bianliang3}");
  18. imageData = (ImageData)shareMemory.ReadFromMemory(typeof(ImageData));
  19. int ShareSize = Marshal.SizeOf(imageData);
  20. byte[] datas = shareMemory.ReadByteFromMemory(imageData.dataLength, ShareSize + 1);
  21. HImage hImage = new HImage();
  22. using (PinnedObject pinnedObject = new PinnedObject(datas))
  23. {
  24. hImage.GenImage1("byte", imageData.Widht, imageData.Height, pinnedObject.Pointer);
  25. }
  26. // hImage.GenImage1(imageData.DataType, imageData.Widht, imageData.Height, imageData.dataPrt);
  27. ImgControl.HalconWindow.AttachBackgroundToWindow(hImage);
  28. WriteInfo(1, "图像处理完成");
  29. });
  30. }
  31. // Thread.Sleep(2000);
  32. WriteInfo(2, rece);
  33. if (rece.Equals("Close"))
  34. {
  35. this.Close();
  36. }
  37. }
  38. return hwnd;
  39. }

7、共享内存操作

  1. internal class ShareMemory
  2. {
  3. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  4. public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
  5. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
  6. public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);
  7. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
  8. public static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);
  9. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
  10. public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
  11. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
  12. public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);
  13. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
  14. public static extern bool CloseHandle(IntPtr handle);
  15. [DllImport("kernel32", EntryPoint = "GetLastError")]
  16. public static extern int GetLastError();
  17. private const int INVALID_HANDLE_VALUE = -1;
  18. private const int ERROR_ALREADY_EXISTS = 0xB7;//183
  19. private const int PAGE_READWRITE = 0x04;
  20. private const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;
  21. private const int FILE_MAP_READ = 0x0004;
  22. private const int FILE_MAP_WRITE = 0x0002;
  23. private IntPtr m_hSharedMemoryFile = IntPtr.Zero;
  24. private IntPtr m_rwData = IntPtr.Zero;
  25. private bool m_bAlreadyExist = false;
  26. private bool m_bInit = false;
  27. private string ShareName { get; set; } //共享内存的名字
  28. private long MemSize { get; set; }//共享内存大小
  29. private IntPtr MemPtr { get; set; }//共享内存印射地址
  30. /// <summary>
  31. /// 共享内存初始化
  32. /// </summary>
  33. /// <param name="MemName">共享内存名字</param>
  34. /// <param name="MemSize">共享内存大小</param>
  35. public ShareMemory(string MemName, long Size)
  36. {
  37. ShareName = MemName;
  38. MemSize = Size;
  39. MemPtr = IntPtr.Zero;
  40. m_bInit = false;
  41. m_bAlreadyExist = false;
  42. m_rwData = IntPtr.Zero;
  43. m_hSharedMemoryFile = IntPtr.Zero;
  44. }
  45. ~ShareMemory()
  46. {
  47. ShareMemoryClose();
  48. }
  49. /// <summary>
  50. /// 创建共享内存
  51. /// </summary>
  52. /// <returns>0=创建成功;1=创建共享体失败;2=打开失败;3=印射失败; 4=共享内存命名错误</returns>
  53. public int CreateMemory()
  54. {
  55. if (MemSize <= 0) MemSize = 0x00800000;
  56. if (ShareName.Length > 0)
  57. {
  58. //创建内存共享体(INVALID_HANDLE_VALUE)
  59. m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)MemSize, ShareName);
  60. if (m_hSharedMemoryFile == IntPtr.Zero)
  61. {
  62. m_bAlreadyExist = false;
  63. m_bInit = false;
  64. MemPtr = IntPtr.Zero;
  65. return 1; //创建共享体失败
  66. }
  67. else
  68. {
  69. if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建
  70. {
  71. m_bAlreadyExist = true;
  72. CloseHandle(m_hSharedMemoryFile);
  73. m_hSharedMemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, ShareName);
  74. if (m_hSharedMemoryFile == null)
  75. {
  76. MemPtr = IntPtr.Zero;
  77. return 2;//打开共享内存失败
  78. }
  79. }
  80. else //新创建
  81. {
  82. m_bAlreadyExist = false;
  83. }
  84. }
  85. //创建内存映射
  86. m_rwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, (uint)MemSize);
  87. if (m_rwData == IntPtr.Zero)
  88. {
  89. m_bInit = false;
  90. CloseHandle(m_hSharedMemoryFile);
  91. MemPtr = IntPtr.Zero;
  92. return 3; //创建内存映射失败
  93. }
  94. else
  95. {
  96. m_bInit = true;
  97. MemPtr = m_rwData;
  98. }
  99. }
  100. else
  101. {
  102. return 4; //参数错误
  103. }
  104. return 0; //创建成功
  105. }
  106. public byte[] ReadByteFromMemory(int dataLength, int pos = -1)
  107. {
  108. if (IntPtr.Zero == MemPtr)
  109. {
  110. return new byte[0];
  111. }
  112. byte[] datas = new byte[dataLength];
  113. if (pos == -1)
  114. {
  115. Marshal.Copy(MemPtr, datas, 0, dataLength);
  116. }
  117. else
  118. {
  119. IntPtr offPtr = IntPtr.Add(MemPtr, pos);
  120. Marshal.Copy(offPtr, datas, 0, dataLength);
  121. }
  122. return datas;
  123. }
  124. /// <summary>
  125. /// 读取共享内存并返回到类
  126. /// </summary>
  127. /// <param name="type">读取的类型</param>
  128. /// <returns>读取的数据</returns>
  129. public Object ReadFromMemory(Type type)
  130. {
  131. if (IntPtr.Zero == MemPtr)
  132. {
  133. return null;
  134. }
  135. Object obj = Marshal.PtrToStructure(MemPtr, type);
  136. return obj;
  137. }
  138. /// <summary>
  139. /// 读取类并写入共享内存
  140. /// </summary>
  141. /// <param name="obj">需要读取的类(结构体)</param>
  142. /// <returns>返回0表示写入成功,返回-1表示写入失败</returns>
  143. public int WriteToMemory(Object obj)
  144. {
  145. if (IntPtr.Zero == MemPtr)
  146. {
  147. return -1;
  148. }
  149. Marshal.StructureToPtr(obj, MemPtr, false);
  150. return 0;
  151. }
  152. /// <summary>
  153. /// 关闭共享内存(解除印射,关闭句柄)
  154. /// </summary>
  155. public void ShareMemoryClose()
  156. {
  157. if (m_bInit)
  158. {
  159. UnmapViewOfFile(m_rwData);
  160. CloseHandle(m_hSharedMemoryFile);
  161. m_bInit = false;
  162. }
  163. }
  164. /// <summary>
  165. /// 获取共享内存印射地址
  166. /// </summary>
  167. /// <returns></returns>
  168. public IntPtr GetPtr()
  169. {
  170. return MemPtr;
  171. }
  172. /// <summary>
  173. /// 获取文件句柄
  174. /// </summary>
  175. /// <returns></returns>
  176. public IntPtr GetFileMapPtr()
  177. {
  178. return m_hSharedMemoryFile;
  179. }
  180. /// <summary>
  181. /// 获取共享内存大小
  182. /// </summary>
  183. /// <returns></returns>
  184. public long GetSize()
  185. {
  186. return MemSize;
  187. }
  188. /// <summary>
  189. /// 获取共享内存名字
  190. /// </summary>
  191. /// <returns></returns>
  192. public string GetName()
  193. {
  194. return ShareName;
  195. }
  196. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号