|
|
|
|
|
|
Sie benötigen von einem vorhandenen Bild eine monochrome, also auf zwei Farben, reduzierte Version? Kein Problem - die API-Funktion DrawState erledigt das auf einfache Weise.
Sie benötigen lediglich eine der üblichen Zeichenflächen dazu, etwa ein Form, eine PictureBox oder ein UserControl. Die eine der beiden Farben ist in der Regel Weiß bzw. die gegebene Hintergrundfarbe, die andere Schwarz. Sie brauchen nur noch den "Pinsel" ("Brush") festzulegen, den die Funktion DrawState verwenden soll. Dies besorgt die API-Funktion CreateSolidBrush, der Sie einfach den gewünschten Farbwert übergeben. Sollte der Farbwert allerdings ein Systemfarbindex sein, etwa vbWindowText, muss dieser zuerst in einen echten Farbwert konvertiert werden (siehe: "Systemfarben-Dolmetscher"). Ach ja, neben den Pixel-Koordinaten der linken oberen Ecke, an denen das Bild ausgegeben werden soll, müssen Sie auch noch die Größe des Bildes, ebenfalls in Pixels, angeben. Die entsprechenden Umrechnungen erledigen die ScaleX- bzw. ScaleY-Methode des Zeichenflächen-Objekts. Dabei wird bei den Koordinaten der ScaleMode des Objekts und bei Breite und Höhe der Maßstab vbHimetric verwendet (siehe: "Hoch mal Breit"). Schließlich muss der "Pinsel" nach der Verwendung durch DrawState wieder entsorgt werden - mit der API-Funktion DeleteObject.
Private Declare Function CreateSolidBrush Lib "gdi32" _
(ByVal crColor As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" _
(ByVal hObject As Long) As Long
Private Declare Function DrawState Lib "user32" _
Alias "DrawStateA" (ByVal hDC As Long, ByVal hBrush As Long, _
ByVal lpDrawStateProc As Long, ByVal PicHandle As Long, _
ByVal wParam As Long, ByVal X As Long, ByVal Y As Long, _
ByVal Width As Long, ByVal Height As Long, ByVal Flags As Long) _
As Long
Private Declare Function OleTranslateColor Lib "oleaut32.dll" _
(ByVal lOleColor As Long, ByVal lHPalette As Long, _
ByRef lColorRef As Long) As Long
Public Sub PaintMonoPicture(Object As Object, _
Picture As StdPicture, Optional ByVal Left As Single, _
Optional ByVal Top As Single, Optional ByVal Color As Long)
Dim nColor As ColorConstants
Dim nLeft As Single
Dim nTop As Single
Dim nWidth As Single
Dim nHeight As Single
Dim nBrush As Long
With Object
nLeft = .ScaleX(Left, .ScaleMode, vbPixels)
nTop = .ScaleY(Top, .ScaleMode, vbPixels)
nWidth = .ScaleX(Picture.Width, vbHimetric, vbPixels)
nHeight = .ScaleY(Picture.Height, vbHimetric, vbPixels)
OleTranslateColor Color, 0, nColor
nBrush = CreateSolidBrush(nColor)
DrawState .hDC, nBrush, 0, Picture.Handle, 0, nLeft, nTop, _
nWidth, nHeight, DST_BITMAP Or DSS_MONO
DeleteObject nBrush
End With
End Sub
Das funktioniert so ganz gut. Nur, wenn Sie gar keine Zeichenfläche zur Verfügung haben, oder keine der vorhandenen verwenden wollen, und Sie lieber als Ergebnis ein neues, unabhängiges Picture-Objekt hätten? Dann können Sie natürlich eine Zeichenfläche (PictureBox oder UserControl, ohne Rahmen und gegebenenfalls unsichtbar) auf die passende Größe bringen, deren Eigenschaft AutoRedraw vor der Ausgabe auf True setzen, und das neue Picture-Objekt von der Image-Eigenschaft erhalten.
Eleganter, aber auch ein wenig aufwändiger, und unabhängig von einer dafür extra benötigten und zweckentfremdeten Zeichenfläche, lässt sich das rein per API-Funktionen erledigen. Im Prinzip funktioniert das genau so, wie oben gezeigt. Der Unterschied ist lediglich der, dass kein Steuerelement als Zeichenfläche benötigt wird, sondern vorübergehend eine virtuelle Zeichenfläche im Arbeitsspeicher angelegt wird.
Die folgende Funktion MonoPicture liefert ein monochromes Picture-Objekt. Sie übergeben ihr das zu konvertierende Picture-Objekt, sowie optional die Vordergrundfarbe (Color, Voreinstellung = vbWindowText) und die Hintergrundfarbe (BackColor, Voreinstellung = vbWindowBackground). Dazu können Sie auch noch optional angeben, ob das monochrome Bild anschließend noch invertiert werden soll (was allerdings wohl nur bei der Farbkombination Schwarz und Weiß sinnvoll erscheint). Und Sie können auch noch den Pfad einer Datei angeben, in der das neue Bild auch gleich gespeichert wird.
Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Private Declare Function BitBlt Lib "gdi32" _
(ByVal hDestDC 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 dwRop As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" _
(ByVal hDC As Long, ByVal nWidth As Long, _
ByVal nHeight As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" _
(ByVal hDC As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32" _
(ByVal crColor As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" _
(ByVal hDC As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" _
(ByVal hObject As Long) As Long
Private Declare Function DrawState Lib "user32" Alias "DrawStateA" _
(ByVal hDC As Long, ByVal hBrush As Long, _
ByVal lpDrawStateProc As Long, ByVal PicHandle As Long, _
ByVal wParam As Long, ByVal X As Long, ByVal Y As Long, _
ByVal Width As Long, ByVal Height As Long, _
ByVal Flags As Long) As Long
Private Declare Function GetObjectAPI Lib "gdi32" _
Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, _
lpObject As Any) As Long
Private Declare Function OleTranslateColor Lib "oleaut32.dll" _
(ByVal lOleColor As Long, ByVal lHPalette As Long, _
ByRef lColorRef As Long) As Long
Private Declare Function Rectangle Lib "gdi32" _
(ByVal hDC As Long, ByVal X1 As Long, ByVal Y1 As Long, _
ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function SelectObject Lib "gdi32" _
(ByVal hDC As Long, ByVal hObject As Long) As Long
Private Const DSS_MONO = &H80
Private Const DST_BITMAP = &H4
Public Function MonoPicture(Picture As StdPicture, _
Optional ByVal Color As Long = vbWindowText, _
Optional ByVal BackColor As Long = vbWindowBackground, _
Optional ByVal Invert As Boolean, _
Optional SaveToFile As String) As StdPicture
Dim nBackColor As Long
Dim nBitmap As BITMAP
Dim nBmpInvert As Long
Dim nBmpMono As Long
Dim nBrush As Long
Dim nDCInvert As Long
Dim nDCMono As Long
Dim nDCOrigin As Long
Dim nHeight As Long
Dim nObjBack As Long
Dim nObjInvert As Long
Dim nObjOrigin As Long
Dim nObjMono As Long
Dim nPicture As StdPicture
Dim nWidth As Long
OleTranslateColor BackColor, 0&, nBackColor
nDCOrigin = CreateCompatibleDC(0)
nObjOrigin = SelectObject(nDCOrigin, Picture.Handle)
GetObjectAPI Picture.Handle, Len(nBitmap), nBitmap
With nBitmap
nWidth = .bmWidth
nHeight = .bmHeight
End With
nBmpMono = CreateCompatibleBitmap(nDCOrigin, nWidth, nHeight)
nDCMono = CreateCompatibleDC(0)
nObjMono = SelectObject(nDCMono, nBmpMono)
SelectObject nDCOrigin, nObjOrigin
DeleteDC nDCOrigin
nBrush = CreateSolidBrush(nBackColor)
nObjBack = SelectObject(nDCMono, nBrush)
Rectangle nDCMono, -1, -1, nWidth + 2, nHeight + 2
SelectObject nDCMono, nObjBack
nBrush = CreateSolidBrush(Color)
DrawState nDCMono, nBrush, 0, Picture.Handle, 0, 0, 0, _
nWidth, nHeight, DST_BITMAP Or DSS_MONO
DeleteObject nBrush
If Invert Then
nBmpInvert = _
CreateCompatibleBitmap(nDCMono, nWidth, nHeight)
nDCInvert = CreateCompatibleDC(0)
nObjInvert = SelectObject(nDCInvert, nBmpInvert)
BitBlt nDCInvert, 0, 0, nWidth, nHeight, nDCMono, 0, 0, _
vbNotSrcCopy
SelectObject nDCInvert, nObjInvert
DeleteDC nDCInvert
Set nPicture = _
PictureFromHandle(nBmpInvert, vbPicTypeBitmap, True)
End If
SelectObject nDCMono, nObjMono
DeleteDC nDCMono
If Not Invert Then
Set nPicture = _
PictureFromHandle(nBmpMono, vbPicTypeBitmap, True)
End If
If Len(SaveToFile) Then
SavePicture nPicture, SaveToFile
End If
Set MonoPicture = nPicture
End Function
Beachten Sie bitte, dass das monochrome Bild anschließend in der gleichen Farbtiefe wie das Original vorliegt, und von Visual Basic mindestens als 256-Farben-Bild gespeichert wird. Eine Änderung der Palette und der Farbtiefe erfolgt bei diesem Verfahren nicht.
|
|
|