質問編集履歴

3

表示されない状態についての詳細を「発生している問題」と「確認したこと」に追記しました。

2020/05/29 07:37

投稿

heero
heero

スコア8

test CHANGED
File without changes
test CHANGED
@@ -90,6 +90,10 @@
90
90
 
91
91
  成功しているのですが、受信間隔が短い(3秒未満)場合に2枚目以降のビットマップイメージが表示されません。
92
92
 
93
+ 表示されない状態というのは、1枚目のビットマップイメージが消え、ビットマップイメージ表示領域が
94
+
95
+ 白背景の状態です。
96
+
93
97
 
94
98
 
95
99
  エラーメッセージの表示やアプリケーションが落ちることはなく、2枚目以降が表示さず動き続けています。
@@ -570,6 +574,12 @@
570
574
 
571
575
  いくつか見つかりました。
572
576
 
577
+ ビットマップイメージを表示するための"Imageタグ"のプロパティにデータがセット
578
+
579
+ されていることはデバッグで確認しているのですが、先に表示されていたイメージが
580
+
581
+ 消え白背景に更新されてしまいます。
582
+
573
583
  そのため、現状何が原因か分からず、手詰まりの状態です。
574
584
 
575
585
 

2

Viewへのデータ変更を通知するためのViewModelの基底クラス、"ViewModelBase"のソースコードを追加しました。

2020/05/29 07:37

投稿

heero
heero

スコア8

test CHANGED
File without changes
test CHANGED
@@ -148,6 +148,120 @@
148
148
 
149
149
  ```
150
150
 
151
+ ViewModelBase(ViewModelの基底クラス)
152
+
153
+ ```C#
154
+
155
+ // ViewModelのプロパティにセットされたデータをViewへ反映する
156
+
157
+ public abstract class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
158
+
159
+ {
160
+
161
+ ~ViewModelBase()
162
+
163
+ {
164
+
165
+ ClearResource();
166
+
167
+ }
168
+
169
+
170
+
171
+ private bool _isCrlResource = false;
172
+
173
+
174
+
175
+ protected virtual void ClearResource()
176
+
177
+ {
178
+
179
+ if (_isCrlResource) return;
180
+
181
+
182
+
183
+ if (PropertyChanged != null)
184
+
185
+ {
186
+
187
+ foreach (var handler in PropertyChanged.GetInvocationList())
188
+
189
+ {
190
+
191
+ PropertyChanged -= (PropertyChangedEventHandler)handler;
192
+
193
+ }
194
+
195
+ }
196
+
197
+
198
+
199
+ PropertyChanged = null;
200
+
201
+ _isCrlResource = true;
202
+
203
+ }
204
+
205
+
206
+
207
+ /// <summary>
208
+
209
+ /// INotifyPropertyChanged.PropertyChanged の実装。
210
+
211
+ /// INotifyPropertyChanged.PropertyChanged implement.
212
+
213
+ /// </summary>
214
+
215
+ public event PropertyChangedEventHandler PropertyChanged;
216
+
217
+
218
+
219
+ /// <summary>
220
+
221
+ /// INotifyPropertyChanged.PropertyChangedイベントを発生させる。
222
+
223
+ /// INotifyPropertyChanged.PropertyChanged event is generated.
224
+
225
+ /// </summary>
226
+
227
+ protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
228
+
229
+ {
230
+
231
+ if (object.Equals(storage, value)) return false;
232
+
233
+
234
+
235
+ storage = value;
236
+
237
+
238
+
239
+ if (PropertyChanged != null)
240
+
241
+ {
242
+
243
+ PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
244
+
245
+ }
246
+
247
+ else
248
+
249
+ {
250
+
251
+ PropertyChanged = null;
252
+
253
+ }
254
+
255
+
256
+
257
+ return true;
258
+
259
+ }
260
+
261
+ }
262
+
263
+ ```
264
+
151
265
  WindowViewModel.cs(ViewModel)
152
266
 
153
267
  ```C#

1

USB通信処理を行うC++ DLLの呼び出し部分を追加しました。"USBCommクラス"をModel内でメンバとして使用していましたが間違いでした。

2020/05/28 07:32

投稿

heero
heero

スコア8

test CHANGED
File without changes
test CHANGED
@@ -148,8 +148,6 @@
148
148
 
149
149
  ```
150
150
 
151
-
152
-
153
151
  WindowViewModel.cs(ViewModel)
154
152
 
155
153
  ```C#
@@ -256,9 +254,7 @@
256
254
 
257
255
 
258
256
 
259
- // ビットマップコントロールにデータをセット
257
+ BitmapImageData = bitmapImg; // ビットマップコントロールにデータをセット
260
-
261
- BitmapImageData = bitmapImg;
262
258
 
263
259
  }
264
260
 
@@ -266,8 +262,6 @@
266
262
 
267
263
  ```
268
264
 
269
-
270
-
271
265
  WindowModel.cs(Model)
272
266
 
273
267
  ```C#
@@ -276,8 +270,6 @@
276
270
 
277
271
  {
278
272
 
279
- private USBComm m_usbComm; // USB通信処理クラス
280
-
281
273
  private Action<byte[]> m_displayBitmap; // ViewModelのビットマップイメージ表示メソッド
282
274
 
283
275
  private byte[] m_bitmapData; // ビットマップイメージデータ
@@ -288,8 +280,6 @@
288
280
 
289
281
  {
290
282
 
291
- m_usbComm = new USBComm();
292
-
293
283
  m_displayBitmap = null;
294
284
 
295
285
  m_bitmapData = null;
@@ -302,7 +292,9 @@
302
292
 
303
293
  {
304
294
 
305
- m_usbComm.SetDelegateFunc(DisplayBitmapImage);
295
+ USBComm.SetDelegateFunc(DisplayBitmapImage); // イメージデータを取得するためのデリゲート設定
296
+
297
+ USBComm.ReadImageData(); // イメージデータ取得
306
298
 
307
299
  }
308
300
 
@@ -310,19 +302,33 @@
310
302
 
311
303
  // USB通信処理クラスからビットマップイメージを受け取るデリゲート
312
304
 
313
- private void DisplayBitmapImage(byte[] bitmapData)
305
+ private void DisplayBitmapImage(uint dataSize, bool dataErrFlag)
314
-
306
+
315
- {
307
+ {
308
+
316
-
309
+ // 受信したデータに異常がない場合のみDLLから取得する
310
+
311
+ if (dataErrFlag == false)
312
+
313
+ {
314
+
315
+ byte[] buff = new byte[dataSize];
316
+
317
+ USBComm.GetReceiveData(ref buff);
318
+
319
+
320
+
317
- m_bitmapData = bitmapData; // 意味ないと思うが念のためメンバにセット
321
+ m_bitmapData = bitmapData; // 意味ないと思うが念のためメンバにセット
318
-
319
-
320
-
322
+
321
- m_displayBitmap(m_bitmapData); // Viewのビットマップイメージ表示メソッド呼び出し
323
+ m_displayBitmap(m_bitmapData); // Viewのビットマップイメージ表示メソッド呼び出し
322
-
323
-
324
-
324
+
325
- m_bitmapData = null;
325
+ m_bitmapData = null;
326
+
327
+ }
328
+
329
+
330
+
331
+ USBComm.ClearReceiveData(); // DLL内のデータをクリア
326
332
 
327
333
  }
328
334
 
@@ -330,6 +336,114 @@
330
336
 
331
337
  ```
332
338
 
339
+ USBComm.cs(USB通信処理DLLインターフェイス)
340
+
341
+ ```C#
342
+
343
+ public static class USBComm
344
+
345
+ {
346
+
347
+ /// <summary>
348
+
349
+ /// DLL内で取得したイメージデータのサイズとエラー情報を取得するデリゲート
350
+
351
+ /// </summary>
352
+
353
+ /// <param name="dataSize">イメージデータサイズ</param>
354
+
355
+ /// <param name="errFlag">データエラーフラグ : 0 = Not error / !0 = Error</param>
356
+
357
+ public delegate void DelegateDisplayBitmapImage(uint dataSize, byte errFlag);
358
+
359
+
360
+
361
+ static DelegateDisplayBitmapImage m_delegateFunc;
362
+
363
+
364
+
365
+ // イメージデータ取得用デリゲートメソッドのセット
366
+
367
+ [DllImport("USBComm.dll", EntryPoint = "SetDelegateFunc", CallingConvention = CallingConvention.StdCall)]
368
+
369
+ private static extern void DllSetDelegateFunc(DelegateDisplayBitmapImage func);
370
+
371
+ // イメージデータ受信
372
+
373
+ [DllImport("USBComm.dll", EntryPoint = "ReadImageData", CallingConvention = CallingConvention.StdCall)]
374
+
375
+ private static extern void DllReadImageData();
376
+
377
+ // 受信データ取得
378
+
379
+ [DllImport("USBComm.dll", EntryPoint = "GetReceiveData", CallingConvention = CallingConvention.StdCall)]
380
+
381
+ private static extern void DllGetReceiveData(IntPtr iPtr);
382
+
383
+ // 受信データクリア
384
+
385
+ [DllImport("USBComm.dll", EntryPoint = "ClearReceiveData", CallingConvention = CallingConvention.StdCall)]
386
+
387
+ private static extern void DllClearReceiveData();
388
+
389
+
390
+
391
+ public static void SetDelegateFunc(DelegateDisplayBitmapImage func)
392
+
393
+ {
394
+
395
+ m_delegateFunc = func;
396
+
397
+ DllSetDelegateFunc(m_delegateFunc );
398
+
399
+ }
400
+
401
+
402
+
403
+ public static void ReadImageData() => DllReadImageData();
404
+
405
+
406
+
407
+ public static void GetReceiveData(ref byte[] buff)
408
+
409
+ {
410
+
411
+ // 取得するデータサイズ分IntPtrのメモリ領域を確保
412
+
413
+ IntPtr ptr = Marshal.AllocHGlobal(buff.Length);
414
+
415
+ // DLLからデータを取得
416
+
417
+ DllGetReceiveData(ptr);
418
+
419
+ // DLLから取得したデータをコピー
420
+
421
+ Marshal.Copy(iPtr, buff, 0, buff.Length);
422
+
423
+ // IntPtrのメモリ解放
424
+
425
+ Marshal.FreeHGlobal(ptr);
426
+
427
+ }
428
+
429
+
430
+
431
+ public static void ClearReceiveData() => DllClearReceiveData;
432
+
433
+ }
434
+
435
+ ```
436
+
437
+ USBCommクラスで参照しているDLL(USBComm.dll)はC++で実装しています。
438
+
439
+ DLLのソースコードは、セキュリティの問題で掲載できません。
440
+
441
+ 同じDLLを使用したC++ MFCのツールが存在し、そちらで同じように複数枚のイメージデータを
442
+
443
+ 非同期処理で受信→表示することができています。
444
+
445
+
446
+
333
447
 
334
448
 
335
449
  ### 確認したこと