diff --git a/OrderSupportTicket/ViewModels/PendingAttachmentViewModel.cs b/OrderSupportTicket/ViewModels/PendingAttachmentViewModel.cs index 110673f..e41b0f3 100644 --- a/OrderSupportTicket/ViewModels/PendingAttachmentViewModel.cs +++ b/OrderSupportTicket/ViewModels/PendingAttachmentViewModel.cs @@ -207,7 +207,7 @@ public sealed class PendingAttachmentViewModel : BindableBaseEx, IDisposable Path.GetTempPath(), "WxOrder-Clipboard-" + Guid.NewGuid().ToString("N") + ".png"); var encoder = new PngBitmapEncoder(); - encoder.Frames.Add(BitmapFrame.Create(bitmap)); + encoder.Frames.Add(BitmapFrame.Create(NormalizeClipboardBitmap(bitmap))); using (var stream = File.Create(filePath)) encoder.Save(stream); @@ -236,6 +236,29 @@ public sealed class PendingAttachmentViewModel : BindableBaseEx, IDisposable } } + private static BitmapSource NormalizeClipboardBitmap(BitmapSource bitmap) + { + if (bitmap.Format != PixelFormats.Bgra32 && bitmap.Format != PixelFormats.Pbgra32) + return bitmap; + + var stride = checked(bitmap.PixelWidth * 4); + var pixels = new byte[checked(stride * bitmap.PixelHeight)]; + bitmap.CopyPixels(pixels, stride, 0); + for (var i = 3; i < pixels.Length; i += 4) + { + if (pixels[i] != 0) + return bitmap; + } + + // 微信等截图工具可能将 DIB 的保留字节全部置零,WPF 将其解释为 Alpha。 + // 直接按 Bgr32 使用原始颜色,避免预乘 Alpha 转换时丢失 RGB;正常透明图保持原样。 + var normalized = BitmapSource.Create( + bitmap.PixelWidth, bitmap.PixelHeight, bitmap.DpiX, bitmap.DpiY, + PixelFormats.Bgr32, null, pixels, stride); + normalized.Freeze(); + return normalized; + } + public void Dispose() { if (_disposed) diff --git a/OrderSupportTicket/Views/TicketComposerView.xaml.cs b/OrderSupportTicket/Views/TicketComposerView.xaml.cs index 645a2e6..400d22f 100644 --- a/OrderSupportTicket/Views/TicketComposerView.xaml.cs +++ b/OrderSupportTicket/Views/TicketComposerView.xaml.cs @@ -14,16 +14,52 @@ public partial class TicketComposerView : UserControl private void ChatTextBox_PreviewKeyDown(object sender, KeyEventArgs e) { - var isPaste = (e.Key == Key.V && Keyboard.Modifiers == ModifierKeys.Control) || (e.Key == Key.Insert && Keyboard.Modifiers == ModifierKeys.Shift); - if (!isPaste || DataContext is not OrderSupportTicketViewModel viewModel) return; + var isPaste = (e.Key == Key.V && Keyboard.Modifiers == ModifierKeys.Control) + || (e.Key == Key.Insert && Keyboard.Modifiers == ModifierKeys.Shift); + if (!isPaste || DataContext is not OrderSupportTicketViewModel viewModel) + { + return; + } + IDataObject data; - try { data = Clipboard.GetDataObject(); } catch (ExternalException) { return; } - if (data == null) return; - if (data.GetDataPresent(DataFormats.Bitmap) && data.GetData(DataFormats.Bitmap) is BitmapSource bitmap) { viewModel.AddPendingImage(bitmap); e.Handled = true; return; } - if (!data.GetDataPresent(DataFormats.FileDrop) || data.GetData(DataFormats.FileDrop) is not string[] files) return; - var images = files.Where(path => PendingAttachmentViewModel.TryGetMimeType(System.IO.Path.GetExtension(path), out _)).ToArray(); - if (images.Length == 0) return; + try + { + data = Clipboard.GetDataObject(); + } + catch (ExternalException) + { + return; + } + + if (data == null) + { + return; + } + + if (data.GetDataPresent(DataFormats.Bitmap) + && data.GetData(DataFormats.Bitmap) is BitmapSource bitmap) + { + viewModel.AddPendingImage(bitmap); + e.Handled = true; + return; + } + + if (!data.GetDataPresent(DataFormats.FileDrop) + || data.GetData(DataFormats.FileDrop) is not string[] files) + { + return; + } + + var images = files + .Where(path => PendingAttachmentViewModel.TryGetMimeType(System.IO.Path.GetExtension(path), out _)) + .ToArray(); + + if (images.Length == 0) + { + return; + } + viewModel.AddPendingImages(images); e.Handled = true; } -} +} \ No newline at end of file