Moin,
Mir ist es jetzt schon häufiger untergekommen, dass ich in einem GDI+ Fenster gerne mit der Maus etwas bewegen und ggf. zoomen möchte (Linksklick -> Drag, Mausrad -> Zoom). Jedes Mal habe ich es wieder von neuem programmiert und mich geärgert, dass immer irgendwelche Zahlen nicht gestimmt haben (z.B. bleibt der Punkt unter der Maus beim Zoomen nicht an derselben Stelle, usw). Daher gibts jetzt eine UDF dazu die hoffentlich jedem weiterhilft der dasselbe Problem hat und ein wenig "interaktivere" GDI+ Anwendungen schreiben will. Da ist es nämlich immer schön, wenn der User ein wenig Spaß haben kann und nicht alles so furchtbar statisch ist.
Es ist eine sehr kurze (ca. 100 Zeilen [Edit: jetzt 140 [Edit2: jetzt 160]]) UDF geworden. Verbesserungsvorschläge / Korrekturen sind gerne gesehen.
Hier noch ein Minimalbeispiel, damit man schauen kann was die UDF eigentlich macht, und wie die Anwendung ist.
Es sind nur 3 Zeilen nötig um einem GDI+ Viewport eine Maussteuerung zu verpassen. Einfacher habe ich es nicht hinbekommen 
Für Einstellungen muss man in _GDIPlus_TransformCreate nachsehen welche Variablen es gibt, in den Kommentaren steht wofür sie verwendet werden.
#include '_GDIPlus_Transform.au3'
; Beispiel für ein simples GDI+ Fenster mit Maussteuerung
_GDIPlus_Startup()
Global Const $iW = 800, $iH = 500
Global Const $Rect1 = [10, 10, $iW / 2 - 20, $iH - 20]
Global Const $Rect2 = [$iW/2 + 10, 10, $iW / 2 - 20, $iH - 20]
Global $hGUI = GUICreate('Testfenster', $iW, $iH)
Global $hGFX = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global $hBMP1 = _GDIPlus_BitmapCreateFromGraphics($Rect1[2], $Rect1[3], $hGFX) ; Zwei unabhängige Zeichenflächen
Global $hBMP2 = _GDIPlus_BitmapCreateFromGraphics($Rect2[2], $Rect2[3], $hGFX)
Global $hBUF1 = _GDIPlus_ImageGetGraphicsContext($hBMP1)
Global $hBUF2 = _GDIPlus_ImageGetGraphicsContext($hBMP2)
Global $hBRU = _GDIPlus_BrushCreateSolid()
_GDIPlus_GraphicsSetSmoothingMode($hBUF1, 2) ; Verschiedene Buffer. Der Linke bekommt smoothing
Global $RandomObjects = 10, $iSelectedObject1 = -1, $iSelectedObject2 = -1
Global $RandomStuff1[$RandomObjects]
Global $RandomStuff2[$RandomObjects]
For $i = 0 To $RandomObjects - 1 Step 1
$RandomStuff1[$i] = RandomCircle()
$RandomStuff2[$i] = RandomCircle()
Next
Global $hTransform1 = _GDIPlus_TransformCreate($hGUI, $hBUF1, $Rect1[0], $Rect1[1], $Rect1[2], $Rect1[3])
Global $hTransform2 = _GDIPlus_TransformCreate($hGUI, $hBUF2, $Rect2[0], $Rect2[1], $Rect2[2], $Rect2[3])
$hTransform1.zoomMin = 0.01 ; kann sehr weit rauszoomen
$hTransform1.zoomMax = 100 ; und sehr weit reinzoomen (schau dir den Pixel bei 0/0 an. Im ToolTip sind die WorldSpace Koordinaten der Maus)
$hTransform2.zoomMin = 1 ; kann nicht verkleinert werden
$hTransform2.zoomMax = 2 ; nur faktor 2 vergrößerung erlaubt
$hTransform2.zoomStep = 1.05 ; kleine Schrittweite
$hTransform2.borderX = 100 ; man kann in X Richtung nicht außerhalb des ursprünglichen Rechtecks sein (WorldSpace Wert, keine "pixel")
$hTransform2.borderY = 100 ; man kann in Y Richtung um ein halbes Feld außerhalb sein.
$hTransform2.smoothZoom = 0 ; Deaktiviere smoothZoom
$hTransform1.moveButton = $_GDIPT_MIDDLE
GUISetState(@SW_SHOW, $hGUI)
While GUIGetMsg() <> -3
_GDIPlus_GraphicsClear($hBUF1, 0xFF202020)
_GDIPlus_GraphicsClear($hBUF2, 0xFF404040)
_GDIPlus_TransformBegin($hTransform1)
Draw($hBUF1, $RandomStuff1, _GDIPlus_TransformMouseGetPos($hTransform1), $hTransform1.Mouse.leftDown, $iSelectedObject1)
_GDIPlus_GraphicsFillRect($hBUF1, 0, 0, 1, 1, $hBRU) ; Testpixel zum anschauen
_GDIPlus_GraphicsFillRect($hBUF1, 100, 0, 1, 1, $hBRU) ; Testpixel zum anschauen
_GDIPlus_GraphicsFillRect($hBUF1, 0, 100, 1, 1, $hBRU) ; Testpixel zum anschauen
_GDIPlus_TransformEnd($hTransform1)
_GDIPlus_TransformBegin($hTransform2)
Draw($hBUF2, $RandomStuff2, _GDIPlus_TransformMouseGetPos($hTransform2), $hTransform1.Mouse.rightDown, $iSelectedObject2)
_GDIPlus_GraphicsFillRect($hBUF2, 0, 0, 1, 1, $hBRU) ; Testpixel zum anschauen
_GDIPlus_GraphicsFillRect($hBUF2, 100, 0, 1, 1, $hBRU) ; Testpixel zum anschauen
_GDIPlus_GraphicsFillRect($hBUF2, 0, 100, 1, 1, $hBRU) ; Testpixel zum anschauen
_GDIPlus_TransformEnd($hTransform2)
_GDIPlus_GraphicsDrawImageRect($hGFX, $hBMP1, $Rect1[0], $Rect1[1], $Rect1[2], $Rect1[3])
_GDIPlus_GraphicsDrawImageRect($hGFX, $hBMP2, $Rect2[0], $Rect2[1], $Rect2[2], $Rect2[3])
WEnd
_GDIPlus_BrushDispose($hBRU)
_GDIPlus_GraphicsDispose($hBUF2)
_GDIPlus_GraphicsDispose($hBUF1)
_GDIPlus_BitmapDispose($hBMP2)
_GDIPlus_BitmapDispose($hBMP1)
_GDIPlus_GraphicsDispose($hGFX)
_GDIPlus_Shutdown()
Func ToolTipPos(ByRef $hTransform)
Local $a = _GDIPlus_TransformMouseGetPos($hTransform)
ToolTip(StringFormat('x: % 6.2f\ny: % 6.2f', $a[0], $a[1]))
EndFunc
Func Draw($hGFX, ByRef $RandomStuff, $aPos, $bPressed, ByRef $iSelectedObject)
_GDIPlus_BrushSetSolidColor($hBRU, 0x20FFFFFF)
_GDIPlus_GraphicsFillRect($hGFX, 0, 0, $iW/2-20, $iH-20, $hBRU)
For $i = 0 To UBound($RandomStuff) - 1 Step 1
_GDIPlus_BrushSetSolidColor($hBRU, ($RandomStuff[$i])[3])
_GDIPlus_GraphicsFillEllipse($hGFX, ($RandomStuff[$i])[0] - ($RandomStuff[$i])[2], ($RandomStuff[$i])[1] - ($RandomStuff[$i])[2], 2 * ($RandomStuff[$i])[2], 2 * ($RandomStuff[$i])[2], $hBRU)
If $bPressed And ((($RandomStuff[$i])[0] - $aPos[0])^2+(($RandomStuff[$i])[1] - $aPos[1])^2)^0.5 < ($RandomStuff[$i])[2] Then $iSelectedObject = $i
Next
If Not $bPressed Then $iSelectedObject = -1
If $iSelectedObject <> -1 Then
Local $r = $RandomStuff[$iSelectedObject]
$r[0] = $aPos[0]
$r[1] = $aPos[1]
$RandomStuff[$iSelectedObject] = $r
EndIf
EndFunc
Func RandomCircle()
Local $a = [Random(0, $iW/2 - 20), Random(0, $iH-20), Random(5, 50), Int('0xFF' & Hex(Random(0, 0xFFFFFF), 6))]
Return $a
EndFunc
Alles anzeigen
Edit 16.02.23:
- Added: $Transform.Mouse [x, y, leftDown, rightDown, ctrlID]. Wird in TransformBegin automatisch aktualisiert und kann jederzeit abgerufen werden.
- Added: $Transform.borderX & $Transform.borderY. Damit setzt man fest wie weit das Verschieben außerhalb des eigentlichen Bereichs gehen soll.
- Added: $Transform.zoomMin & $Transform.zoomMax. Damit setzt man fest wie weit man hinein- bzw. herauszoomen kann.
- Added: $Transform.smoothZoom. Damit bestimmt man wie "weich" der Zoom sein soll. Ein Wert von 0 deaktiviert das Feature. Erlaubt sind alle positiven reellen Zahlen.
- Added: $Transform.containsMouse. Wird in TransformBegin automatisch gesetzt und gibt an ob die Maus im Viewport ist oder nicht.
- Added: _GDIPlus_TransformMouseGetPos. Gibt die Koordinaten der Maus in Weltkoordinaten an. (im Beispielskript im Tooltip angezeigt. Schaut euch die Testpixel z.B. bei 0/0 an)
Edit: 23.02.23:
- Added: $Transform.moveButton. Hier kann man $_GDIPT_LEFT, $_GDIPT_RIGHT, $_GDIPT_MIDDLE angeben.
- Added: $Transform.primaryDown. Hier kann man ablesen ob der bei moveButton gewählte Button gerade gedrückt ist.
- Updated: Beispielskript, zur besseren Demonstration wozu man die Weltkoordinaten verwenden kann (z.B. um Objekte mit der Maus zu verschieben)
- Beispiel, Links: Drag mit Mausradklick (middle), Objekte einzeln mit Linksklick auswählen und verschieben.
- Beispie, Rechts: Drag mit Linksklick, Objekte mit Rechtsklick verschieben. (Soll demonstrieren, dass man auch interaktive Sachen innerhalb einer Trafo machen kann).
lg
M