Vb.net 将bmp文件放入RichTextBox:在不丢失质量的情况下调整大小+;处理窗口缩放

Vb.net 将bmp文件放入RichTextBox:在不丢失质量的情况下调整大小+;处理窗口缩放,vb.net,graphics,richtextbox,image-resizing,metafile,Vb.net,Graphics,Richtextbox,Image Resizing,Metafile,目标: 我的目标是将一张图片(一个bmp文件)放入RichTextBox,大小由我选择,比如说400像素高,宽度按比例缩放以匹配,而不会被Windows缩放(125%、150%、200%等)破坏,也不会丢失质量 这是我的密码: <DllImport("user32.dll", EntryPoint:="OpenClipboard")> Private Shared Function OpenClipboard(ByVal hWnd As IntPtr) As Boolean End

目标:

我的目标是将一张图片(一个bmp文件)放入RichTextBox,大小由我选择,比如说400像素高,宽度按比例缩放以匹配,而不会被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
私有共享函数OpenClipboard(ByVal hWnd作为IntPtr)作为布尔值
端函数
私有共享函数EmptyClipboard()为布尔值
端函数
私有共享函数将ClipboardData(ByVal uFormat作为整数,ByVal hWnd作为IntPtr)设置为IntPtr
端函数
私有共享函数CloseClipboard()为布尔值
端函数
私有共享函数copyenhetafile(ByVal hemfSrc作为IntPtr,ByVal hNULL作为IntPtr)作为IntPtr
端函数
作为布尔值的私有共享函数deleteenhetafile(ByVal hemfSrc作为IntPtr)
端函数
私有子PasteMeta(imgPathName作为字符串)
'创建要绘制到图元文件的图像的位图
将bm变暗为新位图(imgPathName)
'创建窗体的图形对象并获取其hdc句柄
Dim me_grx As Graphics=me.CreateGraphics()
将me_hdc调暗为IntPtr=me_grx.GetHdc()
尺寸刻度=400/bm.高度
'创建与图像大小相同的新图元文件,并为其创建图形对象
将emf设置为新的Imaging.Metafile(“Tmp.emf”、me_hdc、新矩形(0,0,bm.Width*scale,400)、Imaging.MetafileFrameUnit.Point)
Dim emf\u gr As Graphics=Graphics.FromImage(emf)
emf\u gr.DrawImage(bm,0,0,CInt(bm.Width*比例)*\u窗口缩放,CInt(bm.Height*比例)*\u窗口缩放)
'处理位图和图元文件图形对象
emf_gr.Dispose()
bm.Dispose()
PutEnhMetafileOnClipboard(Me.Handle,emf)
'将新图元文件粘贴到RichTextBox中
JournalRichTextBox.Paste()
'处理我们创建的其余对象
me\u grx.ReleaseHdc(me\u hdc)
me_grx.Dispose()
emf.Dispose()
端接头
私有共享函数PutEnhMetafileOnClipboard(ByVal hWnd作为IntPtr,ByVal mf作为Imaging.Metafile)作为布尔值
Dim bResult作为新布尔值()
bResult=False
Dim hEMF,hEMF2作为IntPtr
hEMF=mf.GetHenhmetafile()'使mf无效
如果hEMF.不等于(新的IntPtr(0)),则
hEMF2=复制图元文件(hEMF,新IntPtr(0))
如果不是hEMF2.Equals(新的IntPtr(0)),那么
如果打开剪贴板(hWnd),则
如果EmptyClipboard()则
作为IntPtr的Dim hRes
hRes=SetClipboardData(14,hEMF2)'14==CF_ENHMETAFILE
bResult=hRes.Equals(hEMF2)
CloseClipboard()
如果结束
如果结束
如果结束
删除图元文件(hEMF)
如果结束
返回结果
端函数
以下是我运行sub时RTB发生的情况:

背景和我尝试过的内容

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

然后我发现了一种神奇的方法,可以对质量进行分类。简而言之,这是最重要的答案:

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

我的工作做得很好。然而,我的4K屏幕缩放为200%,这意味着图片的大小是正确的,但放入的图元文件的大小是原来的两倍

我花了大约4个小时在谷歌上搜索,并尝试了我能找到的一切来解决这个问题。无论我做什么,表单或表单中的控件的DPI总是96,所以我不能使用DpiX解决方案

如果我加上:

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

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

私有共享子集ProcessdPiaware()
端接头
公共分新()
SetProcessDPIAware()
初始化组件()
端接头
它只是使表单没有缩放(一些按钮和标签仍然被缩放-奇怪!)

尝试重写scalecontrol事件总是返回一个factor.X,factor.Y=1,而不是其他任何值

如果可能,我想要什么:

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

我想我的主要问题是我使用了太多我不理解的代码。我真的很感激你在回答的时候能把这一点牢记在心,如果你的回答给了我太多的怀疑,我可能无法理解。我认为解决办法可能是:

但这是我在密苏里州的想法。因此,任何帮助或建议都将不胜感激


仅供参考,我的目标是3.5,如果可能的话,我希望坚持这一目标。

如果您想获得有关Dpi意识的显示比例,以及。你真的需要电动势吗?如果没有,我前几天就发布了。Jimi-如果我尝试设置ProcessDPiawarenessContext(-4)(例如),事情开始起作用了,但是有没有办法让它继续扩大?它使表单变小。您是否按照这些说明中的说明设置了
应用程序清单
?表单的缩放模式是什么?它是否可以扩展到Dpi?您正在使用一些锚定模型来调整控件的大小。作为锚定的明智组合和两者的混合,对接可能会起作用
TableLayoutPanels
/
FlowLayoutPanels
这样的功能可以帮助更多。扩展到Dpi、锚定和停靠都很好,只是很小。for本身没有被放大以匹配屏幕缩放,任何按钮等也没有。我没有做清单,因为它是clickOnce部署