Tipp-Upload: VB 5/6 0397: Freihandauswahl Schere
von Zardoz
Über den Tipp
Dieser Tippvorschlag ist noch unbewertet.
Der Vorschlag ist in den folgenden Kategorien zu finden:
- Grafik
Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
Ausschnitt, Freihandform, Schere, Freihandauswahl, Zeichenprogramm, Ausschneiden, Bildausschnitt
Damit er übernommen werden kann, müssen noch Änderungen daran vorgenommen werden. Sofern Sie der Autor sind, können Sie sich anmelden, um die Liste einzusehen.
Der Vorschlag wurde erstellt am: 17.06.2010 19:00.
Die letzte Aktualisierung erfolgte am 17.06.2010 19:00.
Beschreibung
Der Tipp ermöglicht das Markieren, Ausschneiden und Einfügen eines
Bildausschnitts mit der Maus. Die Funktionalität ist der Freihandauswahl
von Zeichenprogrammen nachempfunden.
Schwierigkeitsgrad |
Verwendete API-Aufrufe: BitBlt, CombineRgn, CreatePatternBrush, CreatePolygonRgn, CreateRectRgn, DeleteObject, FrameRgn, GetRgnBox, OffsetRgn, PaintRgn, Polyline, SetBkMode, SetBrushOrgEx, SetStretchBltMode, SetWindowRgn, StretchBlt |
Download: |
' Dieser Source stammt von http://www.activevb.de ' und kann frei verwendet werden. Für eventuelle Schäden ' wird nicht gehaftet. ' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. ' Ansonsten viel Spaß und Erfolg mit diesem Source! ' ------------- Anfang Projektdatei Projekt1.vbp ------------- ' Die Komponente 'Microsoft Common Dialog Control 6.0' (COMDLG32.OCX) wird benötigt. ' --------- Anfang Formular "Form1" alias Form1.frm --------- ' Steuerelement: Menü "MenuFillClose" auf MenuCut ' Steuerelement: Timersteuerelement "Timer1" ' Steuerelement: Bildfeld-Steuerelement "Picture2" ' Steuerelement: Bildfeld-Steuerelement "Picture3" ' Steuerelement: Menü "MenuFill" auf MenuCut ' Steuerelement: Menü "MenuDrawClose" auf MenuCut ' Steuerelement: Menü "MenuCut" ' Steuerelement: Menü "MenuLoad" auf MenuFile ' Steuerelement: Bildfeld-Steuerelement "Picture1" ' Steuerelement: Standarddialog-Steuerelement "CommonDialog1" auf Picture2 ' Steuerelement: Menü "MenuEnd" auf MenuFile ' Steuerelement: Menü "MenuClose" auf MenuCut ' Steuerelement: Menü "MenuDraw" auf MenuCut ' Steuerelement: Menü "MenuFile" ' Freihandform Schere ' Copyright © 2010 by Zardoz Option Explicit Private SW1 As Long, SH1 As Long, XD As Single, YD As Single Private XMin As Single, YMin As Single, Breite As Long, Hoehe As Long Private Rgn2 As Long, flgDraw As Boolean Private NewBrush As Long Private OldBkMode As Long Private Z1 As Long ' Anzahl Polygonpunkte Private Figur() As PointAPI ' Liste Polygonpunkte Private Sub Form_Load() ' Einstellungen Dim Dat1 As String, i As Long With Me .ScaleMode = vbPixels .BackColor = RGB(102, 87, 65) .WindowState = vbMaximized .KeyPreview = True .Caption = "Freihandform Schere" If App.LogMode = 0 Then .Caption = .Caption & Space$(20) & "Compile me." End With Dat1 = App.Path & "\Bild1.jpeg" ' Bildpfad If Dir$(Dat1) = "" Then ' Existiert Datei? MsgBox "Datei nicht gefunden:" & vbCr & Dat1, vbExclamation + vbOKOnly, Me.Caption Unload Me Exit Sub End If With Picture3 ' Lupe .Visible = True .BorderStyle = vbBSNone .ScaleMode = vbPixels .TabStop = False .BackColor = vbBlack .Move 4, 4, 200, 200 .AutoRedraw = True End With With Picture1 ' Sichtbares Bild .BorderStyle = vbBSNone .ScaleMode = vbPixels .BackColor = vbBlack .TabStop = False .AutoRedraw = True .Visible = True End With Call LoadPicturefile(Dat1) ' Bild laden With Picture2 ' Zwischenspeicher für Grafik und verschiebbarer Ausschnitt .Visible = False Set .Container = Picture1 .BorderStyle = vbBSNone .ScaleMode = vbPixels .MousePointer = vbSizeAll .TabStop = False .BackColor = vbBlack .Move 0, 0, 16, 16 .AutoRedraw = True ' Muster zeichnen For i = 1 To .ScaleWidth * Sqr(0.5) Step 2 Picture2.Circle (8, 8), i, vbWhite Next i ' Brush für Animation erzeugen NewBrush = CreatePatternBrush(.Image.Handle) .ZOrder vbBringToFront End With flgDraw = False Timer1.Enabled = False Timer1.Interval = 100 End Sub Private Sub MenuClose_Click() ' Ausscnitt aus, nicht zeichnen Call CutOutClr End Sub Private Sub MenuDraw_Click() ' Ausschnitt zeichnen Timer1.Enabled = False Picture1.FillColor = vbBlack Picture1.FillStyle = vbFSSolid With Picture2 Call OffsetRgn(Rgn2, .Left, .Top) ' Maske verschieben .Cls ' Animierten Rahmen löschen .AutoRedraw = True ' Picture nach Image kopieren ' Bild Xor Ausschnitt Call BitBlt(Picture1.hdc, .Left, .Top, Breite, Hoehe, .hdc, 0, 0, vbSrcInvert) Call PaintRgn(Picture1.hdc, Rgn2) ' Maske zeichnen ' Bild Xor Ausschnitt Call BitBlt(Picture1.hdc, .Left, .Top, Breite, Hoehe, .hdc, 0, 0, vbSrcInvert) Call OffsetRgn(Rgn2, -.Left, -.Top) ' Maske zum Nullpunkt verschieben .Cls ' Image freigeben .AutoRedraw = False End With Picture1.FillStyle = vbFSTransparent Timer1.Enabled = True End Sub Private Sub MenuDrawClose_Click() ' Ausschnitt zeichnen und aus Call MenuDraw_Click Call CutOutClr End Sub Private Sub MenuFill_Click() ' Ausschnitt füllen Dim Num As Long On Error Resume Next With CommonDialog1 .Flags = cdlCCFullOpen Or cdlCCRGBInit .CancelError = True .ShowColor Num = Err.Number Err.Clear On Error GoTo 0 If Num = 0 Then ' Ausschnitt füllen Picture1.FillColor = .Color Picture1.FillStyle = vbFSSolid With Picture2 Call OffsetRgn(Rgn2, .Left, .Top) ' Maske verschieben Call PaintRgn(Picture1.hdc, Rgn2) ' Maske zeichnen Call OffsetRgn(Rgn2, -.Left, -.Top) ' Maske zum Nullpunkt verschieben .Move .Left + 4, .Top + 4 ' Ergebnis sichtbar machen End With Picture1.FillStyle = vbFSTransparent End If End With End Sub Private Sub MenuFillClose_Click() ' Ausschnitt füllen und aus Call MenuFill_Click Call CutOutClr End Sub Private Sub MenuLoad_Click() ' Dateiauswahl Dim Num As Long Call CutOutClr Picture2.Move 0, 0 With CommonDialog1 .Flags = cdlOFNFileMustExist Or cdlOFNReadOnly .Filter = "Pictures|*.jpg;*.jpeg;*.bmp;*.gif;.wmf|" .CancelError = True On Error Resume Next .ShowOpen Num = Err.Number Err.Clear On Error GoTo 0 If Num = 0 Then Call LoadPicturefile(.FileName) ' Bild laden End If End With End Sub Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) ' Ausschnitt aktiv? If Picture2.Visible = True Then Call MenuDrawClose_Click Else ' Beginn Ausschnitt markieren ReDim Figur(0) Z1 = 0 Figur(0).X = X Figur(0).Y = Y Picture2.Move 0, 0, SW1, SH1 Picture2.Cls ' Autoredraw-Bild anpassen Picture2.AutoRedraw = True With Picture1 ' Bild zwischenspeichern Call BitBlt(Picture2.hdc, 0, 0, SW1, SH1, .hdc, 0, 0, vbSrcCopy) ' Einstellungen für Linie .ForeColor = vbWhite .DrawStyle = vbDot OldBkMode = SetBkMode(.hdc, OPAQUE) End With flgDraw = True ' Zeichenmodus ein End If End Sub Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) ' Polygonkoordinaten beim Zeichnen protokollieren If Button = vbLeftButton And flgDraw = True Then ' Verhindern, dass über den Rand gezeichnet wird If X < 0 Then X = 0 ElseIf X >= SW1 Then X = SW1 - 1 End If If Y < 0 Then Y = 0 ElseIf Y >= SH1 Then Y = SH1 - 1 End If Z1 = Z1 + 1 If Z1 > UBound(Figur) Then ReDim Preserve Figur(Z1 + 40) End If Figur(Z1).X = X Figur(Z1).Y = Y ' Linie zeichnen Call Polyline(Picture1.hdc, Figur(0), Z1 + 1) Picture1.Refresh End If Call Zoom(X, Y) ' Lupe zeichnen End Sub Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) Dim Rgn1 As Long, Block As RECT If flgDraw = False Then Exit Sub ' Nicht im Zeichenmodus flgDraw = False ' Zeichenmodus aus Call SetBkMode(Picture1.hdc, OldBkMode) Picture1.DrawStyle = vbSolid ' Hintergrund wiederherstellen Call BitBlt(Picture1.hdc, 0, 0, SW1, SH1, Picture2.hdc, 0, 0, vbSrcCopy) Picture1.Refresh ' Auffrischen erzwingen If Z1 < 3 Then Exit Sub ' Zu wenig Punkte Rgn1 = CreatePolygonRgn(Figur(0), Z1 + 1, ALTERNATE) Call GetRgnBox(Rgn1, Block) With Block XMin = .Left YMin = .Top Breite = .Right - XMin + 1 Hoehe = .Bottom - YMin + 1 End With Erase Figur ' Speicher freigeben If Breite < 4 And Hoehe < 4 Then ' Ausschnitt zu klein (User von Maus abgerutscht :-)) Call DeleteObject(Rgn1) Else ' Ausschnitt ok Rgn2 = CreateRectRgn(0, 0, 0, 0) ' Leere Region erzeugen Call OffsetRgn(Rgn1, -XMin, -YMin) ' Region zum Nullpunkt verschieben Call CombineRgn(Rgn2, Rgn1, 0, RGN_COPY) ' Region kopieren With Picture2 .Move XMin, YMin, Breite, Hoehe ' Picturebox an Ausschnittgrösse anpassen .Cls ' Autoredraw-Bild anpassen ' Bildausschnitt auf Picture2 kopieren Call BitBlt(.hdc, 0, 0, Breite, Hoehe, Picture1.hdc, XMin, YMin, vbSrcCopy) Set .Picture = .Image ' Image nach Picture kopieren .Cls ' Image freigeben .AutoRedraw = False .Visible = True Call SetWindowRgn(.hwnd, Rgn1, True) ' Region übergeben End With Timer1.Enabled = True ' Animation einschalten End If End Sub Private Sub Picture2_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbRightButton Then ' PopupMenü aufrufen PopupMenu MenuCut Else ' Start Ausschnitt verschieben Picture2.MousePointer = vbDefault XD = X YD = Y End If End Sub Private Sub Picture2_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) ' Ausschnitt mit der Maus verschieben With Picture2 If Button = vbLeftButton Then .Move .Left + X - XD, .Top + Y - YD Picture1.Refresh End If Call Zoom(.Left + X, .Top + Y) ' Lupe zeichnen End With End Sub Private Sub Picture2_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) Picture2.MousePointer = vbSizeAll End Sub Private Sub Timer1_Timer() ' Animation Static Pos As Long Dim Pt1 As PointAPI If Me.WindowState = vbMinimized Then Exit Sub Pos = (Pos + 1) And 15 With Picture2 ' Koordinaten setzen Call SetBrushOrgEx(.hdc, Pos, Pos, Pt1) ' Rahmen zeichnen Call FrameRgn(.hdc, Rgn2, NewBrush, 1, 1) ' Alte Einstellungen setzen Call SetBrushOrgEx(.hdc, Pt1.X, Pt1.Y, Pt1) End With End Sub Private Sub Zoom(X As Single, Y As Single) ' Lupe zeichnen Dim SRR1 As Long, SHR1 As Long, OldMode As Long Dim SW3 As Long, SH3 As Long, Fkt As Single Fkt = 4 ' Vergrösserungsfaktor With Picture3 SW3 = .ScaleWidth SH3 = .ScaleHeight SRR1 = SW3 / Fkt SHR1 = SH3 / Fkt Picture3.Line (0, 0)-(SW3 - 1, SH3 - 1), vbBlack, BF OldMode = SetStretchBltMode(.hdc, COLORONCOLOR) Call StretchBlt(.hdc, 0, 0, SW3, SH3, Picture1.hdc, X - SRR1 / 2, Y - SHR1 / 2, SRR1, _ SHR1, vbSrcCopy) Call SetStretchBltMode(.hdc, OldMode) ' Fadenkreuz zeichnen .DrawStyle = vbDot OldMode = SetBkMode(.hdc, OPAQUE) Picture3.Line (SW3 / 2, 0)-Step(0, SH3 - 1), vbWhite Picture3.Line (0, SH3 / 2)-Step(SW3 - 1, 0), vbWhite Call SetBkMode(.hdc, OldMode) .DrawStyle = vbSolid .Refresh End With End Sub Private Sub CutOutClr() ' Ausschnitt löschen Timer1.Enabled = False If Picture2.Visible = True Then Picture2.Visible = False ' Rechteckform wiederherstellen Call SetWindowRgn(Picture2.hwnd, 0, False) End If If Rgn2 <> 0 Then Call DeleteObject(Rgn2) ' Region löschen Rgn2 = 0 End If End Sub Private Sub LoadPicturefile(Dat1 As String) ' Bild in Picturebox laden Dim TmpPic As StdPicture Me.MousePointer = vbHourglass DoEvents Set TmpPic = LoadPicture(Dat1) ' Bild laden With Picture1 ' Sichtbares Bild SW1 = CLng(.ScaleX(TmpPic.Width, vbHimetric)) ' Bildbreite SH1 = CLng(.ScaleY(TmpPic.Height, vbHimetric)) ' Bildhöhe .Move Picture3.Left + Picture3.Width + 4, 4, SW1 + .Width - .ScaleWidth, SH1 + _ .Height - .ScaleHeight .Cls .PaintPicture TmpPic, 0, 0 ' Bild zeichnen End With Set TmpPic = LoadPicture() ' Speicher freigeben Me.MousePointer = vbDefault End Sub Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) ' Abbruch über Esc-Taste If KeyCode = vbKeyEscape Then If Picture2.Visible = True Then Call CutOutClr Else Unload Me End If End If End Sub Private Sub MenuEnd_Click() ' Beenden über Menü Unload Me End Sub Private Sub Form_Unload(Cancel As Integer) ' Beim Beenden Speicher aufräumen Call CutOutClr Call DeleteObject(NewBrush) End Sub ' ---------- Ende Formular "Form1" alias Form1.frm ---------- ' --------- Anfang Modul "Module1" alias Module1.bas --------- Option Explicit ' Typen Public Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Public Type PointAPI X As Long Y As Long End Type ' Deklarationen ' gdi32 Public Declare Function BitBlt Lib "gdi32" ( _ ByVal hdcDest As Long, _ ByVal XDest As Long, _ ByVal YDest As Long, _ ByVal nWidth As Long, _ ByVal nHeight As Long, _ ByVal hDCSrc As Long, _ ByVal xSrc As Long, _ ByVal ySrc As Long, _ ByVal dwRop As Long) As Long Public Declare Function CombineRgn Lib "gdi32" ( _ ByVal hDestRgn As Long, _ ByVal hSrcRgn1 As Long, _ ByVal hSrcRgn2 As Long, _ ByVal nCombineMode As Long) As Long Public Declare Function CreatePatternBrush Lib "gdi32" ( _ ByVal hBitmap As Long) As Long Public Declare Function CreatePolygonRgn Lib "gdi32" ( _ lpPoint As PointAPI, _ ByVal nCount As Long, _ ByVal nPolyFillMode As Long) As Long Public Declare Function CreateRectRgn Lib "gdi32" ( _ ByVal x1 As Long, _ ByVal y1 As Long, _ ByVal X2 As Long, _ ByVal Y2 As Long) As Long Public Declare Function DeleteObject Lib "gdi32" ( _ ByVal hObject As Long) As Long Public Declare Function FrameRgn Lib "gdi32" ( _ ByVal hdc As Long, _ ByVal hRgn As Long, _ ByVal hBrush As Long, _ ByVal nWidth As Long, _ ByVal nHeight As Long) As Long Public Declare Function GetRgnBox Lib "gdi32" ( _ ByVal hRgn As Long, _ lpRect As RECT) As Long Public Declare Function OffsetRgn Lib "gdi32" ( _ ByVal hRgn As Long, _ ByVal X As Long, _ ByVal Y As Long) As Long Public Declare Function PaintRgn Lib "gdi32" ( _ ByVal hdc As Long, _ ByVal hRgn As Long) As Long Public Declare Function Polyline Lib "gdi32" ( _ ByVal hdc As Long, _ lpPoint As PointAPI, _ ByVal nCount As Long) As Long Public Declare Function SetBkMode Lib "gdi32" ( _ ByVal hdc As Long, _ ByVal nBkMode As Long) As Long Public Declare Function SetBrushOrgEx Lib "gdi32" ( _ ByVal hdc As Long, _ ByVal nXOrg As Long, _ ByVal nYOrg As Long, _ lppt As PointAPI) As Long Public Declare Function SetStretchBltMode Lib "gdi32" ( _ ByVal hdc As Long, _ ByVal nStretchMode As Long) As Long Public Declare Function StretchBlt Lib "gdi32" ( _ ByVal hdc As Long, _ ByVal X As Long, _ ByVal Y As Long, _ ByVal nWidth As Long, _ ByVal nHeight As Long, _ ByVal hSrcDC As Long, _ ByVal xSrc As Long, _ ByVal ySrc As Long, _ ByVal nSrcWidth As Long, _ ByVal nSrcHeight As Long, _ ByVal dwRop As Long) As Long ' user32 Public Declare Function SetWindowRgn Lib "user32" ( _ ByVal hwnd As Long, _ ByVal hRgn As Long, _ ByVal bRedraw As Long) As Long ' Konstanten ' StretchBlt() Modes Public Const COLORONCOLOR As Long = 3 ' PolyFill() Modes Public Const ALTERNATE As Long = 1 ' Public Const WINDING As Long = 2 ' CombineRgn() Styles Public Const RGN_COPY As Long = 5 ' Background Modes Public Const OPAQUE As Long = 2 ' ---------- Ende Modul "Module1" alias Module1.bas ---------- ' -------------- Ende Projektdatei Projekt1.vbp --------------
Diskussion
Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.
Folgende Diskussionen existieren bereits
Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.