SnippingTool zoomt, wenn Windows Skalierung an ist

  • VB.NET
  • .NET (FX) 4.0

Es gibt 26 Antworten in diesem Thema. Der letzte Beitrag () ist von Blackn0va.

    SnippingTool zoomt, wenn Windows Skalierung an ist

    Hallo,

    meine kleine Anwendung das die erstellung eines Support Ticket erleichtern soll, hat ein kleines Problem. Wenn ein User die windows Skalierung auch nur auf 25% stehen hat, dann zoomt das snippingTool beim aufruf noch einmal weiter rein.

    Auf dem Bild nummer 2. Ist die Skalierung in windows ausgeschaltet, also zoomt snippingTool nicht, alles so wie es soll.
    Auf dem Bild nummer 3. ist die Skalierung angeschaltet auf 125%, wird nun SnippingTool gestartet, zoomt es noch weiter rein, nicht so wie ich es gerne hätte...

    Hier der Code von SnippingTool (x86)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class SnippingTool
    3. Shadows Text As String
    4. Private Shared _Screen As Screen
    5. Private Shared BitmapSize As Size
    6. Private Shared Graph As Graphics
    7. Private Structure MultiScreenSize
    8. Dim minX As Integer
    9. Dim minY As Integer
    10. Dim maxRight As Integer
    11. Dim maxBottom As Integer
    12. End Structure
    13. Private Shared Function FindMultiScreenSize() As MultiScreenSize
    14. Dim minX As Integer = Screen.AllScreens(0).Bounds.X
    15. Dim minY As Integer = Screen.AllScreens(0).Bounds.Y
    16. Dim maxRight As Integer = Screen.AllScreens(0).Bounds.Right
    17. Dim maxBottom As Integer = Screen.AllScreens(0).Bounds.Bottom
    18. For Each aScreen As Screen In Screen.AllScreens
    19. If aScreen.Bounds.X < minX Then
    20. minX = aScreen.Bounds.X
    21. End If
    22. If aScreen.Bounds.Y < minY Then
    23. minY = aScreen.Bounds.Y
    24. End If
    25. If aScreen.Bounds.Right > maxRight Then
    26. maxRight = aScreen.Bounds.Right
    27. End If
    28. If aScreen.Bounds.Bottom > maxBottom Then
    29. maxBottom = aScreen.Bounds.Bottom
    30. End If
    31. Next
    32. Dim m_MultiScreenSize As MultiScreenSize
    33. With m_MultiScreenSize
    34. .minX = minX
    35. .minY = minY
    36. .maxBottom = maxBottom
    37. .maxRight = maxRight
    38. End With
    39. Return m_MultiScreenSize
    40. End Function
    41. Public Shared Function Snip() As Image
    42. Dim m_MultiScreenSize As MultiScreenSize = FindMultiScreenSize()
    43. Dim bmp As New Bitmap(m_MultiScreenSize.maxRight - m_MultiScreenSize.minX,
    44. m_MultiScreenSize.maxBottom - m_MultiScreenSize.minY,
    45. System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
    46. Dim gr As Graphics = Graphics.FromImage(bmp)
    47. Graph = gr
    48. gr.SmoothingMode = Drawing2D.SmoothingMode.None
    49. BitmapSize = bmp.Size
    50. Using snipper = New SnippingTool(bmp)
    51. snipper.Location = New Point(m_MultiScreenSize.minX, m_MultiScreenSize.minY)
    52. If snipper.ShowDialog() = DialogResult.OK Then
    53. Return snipper.Image
    54. End If
    55. End Using
    56. Return Nothing
    57. End Function
    58. Public Sub New(ByVal screenShot As Image)
    59. InitializeComponent()
    60. Me.BackgroundImage = screenShot
    61. 'Me.BackgroundImageLayout = ImageLayout.None
    62. Me.ShowInTaskbar = False
    63. Me.StartPosition = FormStartPosition.Manual
    64. Me.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center
    65. Me.DoubleBuffered = True
    66. End Sub
    67. Public Property Image() As Image
    68. Get
    69. Return m_Image
    70. End Get
    71. Set(ByVal value As Image)
    72. m_Image = value
    73. End Set
    74. End Property
    75. Private m_Image As Image
    76. Private rcSelect As New Rectangle()
    77. Private pntStart As Point
    78. Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
    79. ''*** Start Snip bei MausDown
    80. If e.Button <> MouseButtons.Left Then
    81. Return
    82. End If
    83. pntStart = e.Location
    84. rcSelect = New Rectangle(e.Location, New Size(0, 0))
    85. Me.Invalidate()
    86. End Sub
    87. Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
    88. ''*** Modiviziere die Selection ***
    89. If e.Button <> MouseButtons.Left Then
    90. Return
    91. End If
    92. Dim x1 As Integer = Math.Min(e.X, pntStart.X)
    93. Dim y1 As Integer = Math.Min(e.Y, pntStart.Y)
    94. Dim x2 As Integer = Math.Max(e.X, pntStart.X)
    95. Dim y2 As Integer = Math.Max(e.Y, pntStart.Y)
    96. rcSelect = New Rectangle(x1, y1, x2 - x1, y2 - y1)
    97. Me.Invalidate()
    98. End Sub
    99. Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
    100. '*** Bild Vervollständigen mit MouseUp ***
    101. If rcSelect.Width <= 0 OrElse rcSelect.Height <= 0 Then
    102. Return
    103. End If
    104. Image = New Bitmap(rcSelect.Width, rcSelect.Height)
    105. Using gr As Graphics = Graphics.FromImage(Image)
    106. gr.DrawImage(Me.BackgroundImage, New Rectangle(0, 0, Image.Width, Image.Height),
    107. rcSelect, GraphicsUnit.Pixel)
    108. End Using
    109. DialogResult = DialogResult.OK
    110. End Sub
    111. Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    112. '*** Zeichnet die aktuelle auswahl ***'
    113. Using br As Brush = New SolidBrush(Color.FromArgb(120, Color.White))
    114. Dim x1 As Integer = rcSelect.X
    115. Dim x2 As Integer = rcSelect.X + rcSelect.Width
    116. Dim y1 As Integer = rcSelect.Y
    117. Dim y2 As Integer = rcSelect.Y + rcSelect.Height
    118. e.Graphics.FillRectangle(br, New Rectangle(0, 0, x1, Me.Height))
    119. e.Graphics.FillRectangle(br, New Rectangle(x2, 0, Me.Width - x2, Me.Height))
    120. e.Graphics.FillRectangle(br, New Rectangle(x1, 0, x2 - x1, y1))
    121. e.Graphics.FillRectangle(br, New Rectangle(x1, y2, x2 - x1, Me.Height - y2))
    122. End Using
    123. '*** Wír zeichnen mit der Maus mit einem 2px Breiten Stift das gwünschte Bild
    124. Using pen As New Pen(Color.Red, 2)
    125. e.Graphics.DrawRectangle(pen, rcSelect)
    126. End Using
    127. End Sub
    128. Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
    129. '*** Erlaubt das abbrechen miit der Escape Taste ***
    130. If keyData = Keys.Escape Then
    131. Me.DialogResult = DialogResult.Cancel
    132. End If
    133. Return MyBase.ProcessCmdKey(msg, keyData)
    134. End Function
    135. Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    136. MyBase.OnLoad(e)
    137. Dim m_MultiScreenSize As MultiScreenSize = FindMultiScreenSize()
    138. Me.Size = New Size(m_MultiScreenSize.maxRight - m_MultiScreenSize.minX,
    139. m_MultiScreenSize.maxBottom - m_MultiScreenSize.minY)
    140. Graph.CopyFromScreen(m_MultiScreenSize.minX, m_MultiScreenSize.minY, 0, 0, BitmapSize)
    141. End Sub
    142. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    143. '*** Label nach 5 Sekunden ausblenden ***
    144. Me.Label1.Text = ""
    145. Me.Label1.Enabled = False
    146. End Sub
    147. End Class



    der Aufruf erfolgt durch

    VB.NET-Quellcode

    1. '***Variablendeklaration ***
    2. Dim Bild As Image
    3. '*** Screenshot erzeugen ***
    4. Dim Bild As Image = SnippingTool.Snip()



    Hat jemand eine Idee das zu Handeln? Ohne Groß ins System des Users einzugreifen..

    EDIT: Hier mal ein kleines Sample Project das funktionniert, auch mit dem zoom^
    Bilder
    • 2.JPG

      79,89 kB, 833×737, 140 mal angesehen
    • 3.JPG

      52,66 kB, 1.033×591, 130 mal angesehen
    • 4.JPG

      17,26 kB, 651×131, 128 mal angesehen
    Dateien
    • SnippSupp.rar

      (65,07 kB, 118 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Blackn0va“ ()

    Blackn0va schrieb:

    dann zoomt das snippingTool beim aufruf noch einmal weiter rein.
    Wie berechnest Du den Zoom?
    Wieso ist der abhängig von der Windows-Skalierung?
    Wenn Du überall mit Pixeln arbeitest, sollte das nicht passieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Blackn0va Ich hab jetzt keine Lust, Dein Projekt durchzuflöhen.
    Mach mal eim kleines Testprojekt, wo nur der relevante Code drinne steht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ^Guten morgen,

    also mehr code kann ich nicht rausnehmen, ich nehme die Bounds und zähle die Monitore.

    Wie gesagt, ich kann es mir nicht erklären..
    Aber danke für die Hilfe !

    Die zeile mit:

    VB.NET-Quellcode

    1. Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)


    Edit:
    da wird die Form mit dem Desktophintergrund erzeugt und eine milchige Farbe drüber gelegt, also die FromArgb 120..

    Sowas habe ich auch schon versucht..

    VB.NET-Quellcode

    1. Me.Font = New Font(Me.Font.FontFamily, Me.Font.SizeInPoints * 125 / 96)
    2. MyBase.OnLoad(e)


    Dateien
    • SnippSupp.rar

      (105,91 kB, 145 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Blackn0va“ ()

    Hab den Code nun noch mehr gekürzt, der Fehler ist noch immer da:


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.ComponentModel
    3. Public Class SnippingTool
    4. Shadows Text As String
    5. Private Shared _Screen As Screen
    6. Private Shared BitmapSize As Size
    7. Private Shared Graph As Graphics
    8. Private Structure MultiScreenSize
    9. Dim minX As Integer
    10. Dim minY As Integer
    11. Dim maxRight As Integer
    12. Dim maxBottom As Integer
    13. End Structure
    14. Private Shared Function FindMultiScreenSize() As MultiScreenSize
    15. Dim minX As Integer = Screen.AllScreens(0).Bounds.X
    16. Dim minY As Integer = Screen.AllScreens(0).Bounds.Y
    17. Dim maxRight As Integer = Screen.AllScreens(0).Bounds.Right
    18. Dim maxBottom As Integer = Screen.AllScreens(0).Bounds.Bottom
    19. For Each aScreen As Screen In Screen.AllScreens
    20. If aScreen.Bounds.X < minX Then
    21. minX = aScreen.Bounds.X
    22. End If
    23. If aScreen.Bounds.Y < minY Then
    24. minY = aScreen.Bounds.Y
    25. End If
    26. If aScreen.Bounds.Right > maxRight Then
    27. maxRight = aScreen.Bounds.Right
    28. End If
    29. If aScreen.Bounds.Bottom > maxBottom Then
    30. maxBottom = aScreen.Bounds.Bottom
    31. End If
    32. Next
    33. Dim m_MultiScreenSize As MultiScreenSize
    34. With m_MultiScreenSize
    35. .minX = minX
    36. .minY = minY
    37. .maxBottom = maxBottom
    38. .maxRight = maxRight
    39. End With
    40. Return m_MultiScreenSize
    41. End Function
    42. Public Shared Function Snip() As Image
    43. Dim m_MultiScreenSize As MultiScreenSize = FindMultiScreenSize()
    44. Dim bmp As New Bitmap(m_MultiScreenSize.maxRight - m_MultiScreenSize.minX,
    45. m_MultiScreenSize.maxBottom - m_MultiScreenSize.minY,
    46. System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
    47. Dim gr As Graphics = Graphics.FromImage(bmp)
    48. Graph = gr
    49. gr.SmoothingMode = Drawing2D.SmoothingMode.None
    50. BitmapSize = bmp.Size
    51. Using snipper = New SnippingTool(bmp)
    52. snipper.Location = New Point(m_MultiScreenSize.minX, m_MultiScreenSize.minY)
    53. If snipper.ShowDialog() = DialogResult.OK Then
    54. Return snipper.Image
    55. End If
    56. End Using
    57. Return Nothing
    58. End Function
    59. Public Sub New(ByVal screenShot As Image)
    60. InitializeComponent()
    61. Me.BackgroundImage = screenShot
    62. Me.BackgroundImageLayout = ImageLayout.None
    63. Me.ShowInTaskbar = False
    64. Me.StartPosition = FormStartPosition.Manual
    65. Me.DoubleBuffered = True
    66. End Sub
    67. Public Property Image() As Image
    68. Get
    69. Return m_Image
    70. End Get
    71. Set(ByVal value As Image)
    72. m_Image = value
    73. End Set
    74. End Property
    75. Private m_Image As Image
    76. Private rcSelect As New Rectangle()
    77. Private pntStart As Point
    78. Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    79. MyBase.OnLoad(e)
    80. Dim m_MultiScreenSize As MultiScreenSize = FindMultiScreenSize()
    81. Me.Size = New Size(m_MultiScreenSize.maxRight - m_MultiScreenSize.minX,
    82. m_MultiScreenSize.maxBottom - m_MultiScreenSize.minY)
    83. Graph.CopyFromScreen(m_MultiScreenSize.minX, m_MultiScreenSize.minY, 0, 0, BitmapSize)
    84. End Sub
    85. End Class


    Hab nun das hier versucht:

    VB.NET-Quellcode

    1. Me.MaximumSize = New Size(m_MultiScreenSize.maxRight - m_MultiScreenSize.minX,
    2. m_MultiScreenSize.maxBottom - m_MultiScreenSize.minY)
    3. Graph.CopyFromScreen(m_MultiScreenSize.minX, m_MultiScreenSize.minY, 0, 0, BitmapSize)

    Funktioniert auch nicht

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Blackn0va“ ()

    Niemand eine Idee?

    Edit:

    Ich habs mit DPI und geräteunabhängige Pixel auch versucht, aber da b ekomm ich noch mehr Fehler als davor

    msdn.microsoft.com/de-de/libra…op/ff684173(v=vs.85).aspx

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Blackn0va“ ()

    Ich weiß nun wie man es hinbekommt das es nicht mehr zoomt auch bei hoher dpi einstellung.

    Anwendung rechtsklick, Haken bei "Skallierung bei hohem DPI-Wert Deaktivieren" -> läuft.

    Wie kann ich das nun in Visual Studio von vornherein machen das der Haken gesetzt ist/wird?
    Bilder
    • 2.JPG

      25,43 kB, 519×203, 114 mal angesehen
    @Blackn0va Das sind Randbedingungen, die das System für Dein Programm zur Verfügung stellt, die werden üblicherweise in der Registry abgelegt.
    Ohne eine Änderung sollte kein Eintrag da sein, danach ist einer da.
    Idenifiziere ihn und dann werden wir sehen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Kann ich die Standard einstellungen nicht in der Manifest - Datei mitgeben ?

    Ich habs schon mit dem hier versucht, aber leider ohne erfolg ..

    XML-Quellcode

    1. <asmv3:application>
    2. <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    3. <dpiAware>false</dpiAware>
    4. </asmv3:windowsSettings>
    5. </asmv3:application>


    Dann Installier ich nun die Anwendung bei mir aufm rechner und duchstöber mal die registry

    Edit: Also ich finde viel in der Registry, aber nicht wirklich bauchbares, dennoch bin ich der meinung das man das der Anwendung von vornherein klarmachen kann.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Blackn0va“ ()

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Blackn0va schrieb:

    Aber leider nicht bei windows 10 1703
    Was genau funktioniert da nicht?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die manifest datei wid Ignoriert.. und somit der hacken bei "skallierung bei hohem DPI wert" wieder verschwunden.

    Ich hab die Manifest datei selbst erzeugt mit rechtsklick auf dem desktop und hab sie dann in die Setup datei mit aufgenommen. Eine möglichkeit die Manifest datei generieren zu lassen habe ich nicht gefunden.

    Versucht habe ich es mit dem "Manifest Creator by himitsu", erfolglos.

    Inhaltd er Manifest datei :

    XML-Quellcode

    1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    2. <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    3. <assemblyIdentity
    4. version="1.0.3.5"
    5. name="FirmenName-Support-App.exe"
    6. type="win32"/>
    7. <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    8. <security>
    9. <requestedPrivileges>
    10. <requestedExecutionLevel
    11. level="asInvoker"
    12. uiAccess="false"/>
    13. </requestedPrivileges>
    14. </security>
    15. </trustInfo>
    16. <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    17. <application>
    18. <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    19. </application>
    20. </compatibility>
    21. <asmv3:application>
    22. <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    23. <dpiAware>False</dpiAware>
    24. </asmv3:windowsSettings>
    25. </asmv3:application>
    26. </assembly>
    @Blackn0va Von welcher Bildschirmauflösung reden wir?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Verstehe ich nicht die Frage.
    Bei allen auflösungen, wenn bei egal welche auflösung die windows skallierung Aktiv ist, wird die Anwendung falsch angezeigt, mein Ziel war es bis dato, der Anwendung per manifest datei zu sagen das er bitte den Haken bei "Skallierung bei hohem dpi wert deaktivieren" setzen soll, siehe Bild(6).

    oder Intepretiere ich die einstellung Falsch? Nur funktioniert die Anwendung so ohne Probleme ^

    Edit:
    So sollte es sein, wenn der haken gesetzt ist, kann ich die Skallierung bei windows hochdrehen wie ich will, es wird Ignoriert und nicht skalliert.

    Edit2: Am Einfachsten wäre es die Setupdatei zu extreahieren, den Haken setzen und die Setupdatei wieder zusammensetzen.. Nur ist das n icht sinn der Sache
    Bilder
    • 6.JPG

      22,73 kB, 353×232, 96 mal angesehen
    • 7.JPG

      82,25 kB, 2.157×376, 91 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Blackn0va“ ()

    @Blackn0va Und was war mit der Registry?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    In der Registry habe ich folgendes gefunden:

    XML-Quellcode

    1. [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide]
    2. "PreferExternalManifest"=dword:00000001


    jetzt hab ich die Manifest datei etwas verändert, jetzt setzt er mir den Haken nicht bei der DPI sondern sie Bild 12, jetzt blick ich nicht mehr durch..
    Bilder
    • 12.JPG

      24,52 kB, 425×287, 89 mal angesehen

    Blackn0va schrieb:

    jetzt blick ich nicht mehr durch..
    Probier da mal die Werte 0 bis 3 oder gar 7, falls das Bit-Felder sind.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!