0

目标:

我的目标是将图片(bmp 文件)以我选择的大小(例如 400 像素高和宽度缩放以匹配)放入 RichTextBox 中,而不会被 Windows 缩放(125%、150%、200% 等)破坏.),或失去质量。

这是我的代码:

<DllImport("user32.dll", EntryPoint:="OpenClipboard")> Private Shared Function OpenClipboard(ByVal hWnd As IntPtr) As Boolean
End Function
<DllImport("user32.dll", EntryPoint:="EmptyClipboard")> Private Shared Function EmptyClipboard() As Boolean
End Function
<DllImport("user32.dll", EntryPoint:="SetClipboardData")> Private Shared Function SetClipboardData(ByVal uFormat As Integer, ByVal hWnd As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="CloseClipboard")> Private Shared Function CloseClipboard() As Boolean
End Function
<DllImport("gdi32.dll", EntryPoint:="CopyEnhMetaFileA")> Private Shared Function CopyEnhMetaFile(ByVal hemfSrc As IntPtr, ByVal hNULL As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll", EntryPoint:="DeleteEnhMetaFile")> Private Shared Function DeleteEnhMetaFile(ByVal hemfSrc As IntPtr) As Boolean
End Function

Private Sub PasteMeta(imgPathName As String)
    'Create a bitmap of the image you want to draw to the metafile
    Dim bm As New Bitmap(imgPathName)

    'Create a graphics object of the Form and get its hdc handle
    Dim me_grx As Graphics = Me.CreateGraphics()
    Dim me_hdc As IntPtr = me_grx.GetHdc()
    Dim scale = 400 / bm.Height
    'Create a new metafile the same size as the image and create a graphics object for it
    Dim emf As New Imaging.Metafile("Tmp.emf", me_hdc, New Rectangle(0, 0, bm.Width * scale, 400), Imaging.MetafileFrameUnit.Point)
    Dim emf_gr As Graphics = Graphics.FromImage(emf)


    emf_gr.DrawImage(bm, 0, 0, CInt(bm.Width * scale) * _windowsScaling, CInt(bm.Height * scale) * _windowsScaling)

    'Dispose the bitmap and the metafile graphics object
    emf_gr.Dispose()
    bm.Dispose()

    PutEnhMetafileOnClipboard(Me.Handle, emf)
    'Paste the new metafile in the RichTextBox
    JournalRichTextBox.Paste()
    'Dispose the rest of the objects we created
    me_grx.ReleaseHdc(me_hdc)
    me_grx.Dispose()
    emf.Dispose()
End Sub

Private Shared Function PutEnhMetafileOnClipboard(ByVal hWnd As IntPtr, ByVal mf As Imaging.Metafile) As Boolean
    Dim bResult As New Boolean()
    bResult = False
    Dim hEMF, hEMF2 As IntPtr
    hEMF = mf.GetHenhmetafile() ' invalidates mf
    If Not hEMF.Equals(New IntPtr(0)) Then
        hEMF2 = CopyEnhMetaFile(hEMF, New IntPtr(0))
        If Not hEMF2.Equals(New IntPtr(0)) Then
            If OpenClipboard(hWnd) Then
                If EmptyClipboard() Then
                    Dim hRes As IntPtr
                    hRes = SetClipboardData(14, hEMF2)    ' 14 == CF_ENHMETAFILE
                    bResult = hRes.Equals(hEMF2)
                    CloseClipboard()
                End If
            End If
        End If
        DeleteEnhMetaFile(hEMF)
    End If
    Return bResult
End Function

这是我运行子程序时 RTB 发生的情况: https ://i.imgur.com/rqChD4Q.png

背景和我尝试过的

我的第一个尝试是只使用位图大小属性,但这真的会破坏质量 - 它完全没用。

然后我发现了这种对质量进行分类的神奇方式。简而言之,这是这里的最佳答案:https ://social.msdn.microsoft.com/Forums/vstudio/en-US/355bfc59-cd0a-4e81-984e-9f066fd3a897/richtextbox-images-quality-loss?forum= VB通用

总之,它制作了一个元文件和图形,使用它调整大小并将其放入剪贴板,然后将其粘贴到 Richtextbox 中。

我得到了很好的工作。但是,我将 4K 屏幕缩放为 200%,这意味着图片大小合适,但放入的图元文件大小是原来的两倍。

我花了大约 4 个小时在谷歌上搜索并尝试了我能找到的一切来解决这个问题。无论我做什么,我为表单或其中的控件获得的 DPI 始终为 96,因此我无法使用其中一种 DpiX 解决方案。

如果我添加:

<DllImport("User32.dll")>
Private Shared Sub SetProcessDPIAware()
End Sub

Public Sub New()
    SetProcessDPIAware()
    InitializeComponent()
End Sub

它只是使表单未缩放(尽管某些按钮和标签仍然被缩放 - 很奇怪!)

试图覆盖 scalecontrol 事件总是返回一个 factor.X,factor.Y = 1,从来没有其他任何东西。

如果可能的话,我想要什么:

请注意,最好的解决方案是只获取比例因子的数字。125% = 1.25, 150% = 1.5 等等。如果我有这个数字,我可以将图形的尺寸乘以它,它非常适合(例如)

我认为我的主要问题是我使用太多我不理解的代码来完成这项工作。我真的很感激你在回答时能记住这一点,如果它给了我太多怀疑的好处,我可能无法理解你的回答。我认为解决方案可能在这里:https ://msdn.microsoft.com/en-us/library/cc250585.aspx

但这在我看来是遥不可及的。因此,任何帮助或建议将不胜感激。

仅供参考,我的目标是 3.5,如果可能的话,我想坚持下去。

4

0 回答 0