|
APIs: Copier une image sur le Presse-Papier |
Author(s) Dev Ashish |
|
Copier une image sur le Clipboard.
Access ne nous permet pas de copier tous les type d'image depuis un
contrôle Image vers le Clipboard. Si l'image est incluse du genre embedded OLE, on
peut utiliser RunCommand acCmdCopy, mais si elle est en référence (link), ou
incluse dans un formulaire, il nous faire un effort supplémentaire pour les coordonnées
de l'image à envoyer au clipboard.
Plan d'exécution:
- Si l'image source (ctl.Picture) n'existe pas, le code étirera l'image de sorte
qu'elle remplisse tout le contrôle. Cela est nécessaire car on ne dispose d'aucun moyen
pour savoir si l'image ne remplis que partiellement ou ne dépasse les limites du
contrôle qui la contient.
- Si l'image source (ctl.picture) existe, il y a deux alternatives, dépendamment de
la dimension du contrôle:
(a) Si l'image source est plus grande que le contrôle, étirer (rapetisser) l'image
source aux dimensions du contrôle, de sorte qu'on ait toute
l'image.
(b) Si l'image source est plus petite, ne pas la modifier, de façon à conserver sa
résolution. Cela laissera un contour gris autour de l'image source copiée.
- Si le contrôle contient une référence à une image incluse ( OLE Embedded, tel que le
formulaire Employees dans Northwind), on place le focus sur le contrôle et exécute
RunCommand acCmdCopy.
Problèmes:
Il semble y avoir un petit pourtour ( deux pixels de large) autour de l'image lorsque
copiée. On recherche toujours la source de ce comportement. Entre-temps, on suggère
d'éliminer cette bordure à l'aide d'un logiciel d'édition d'images, si besoin est
d'éliminer cette fine bordure.
Avertissement:
Ce code enlève temporairement le "RecordSelector" du formulaire et il peut
également assigner la propriété SizeMode du contrôle d'image à "Stretched".
Ces propriétés sont remises à leur état initial lorsque la fonction termine.
Private Type RECT
Left As Long
Right As Long
Top As Long
Bottom As Long
End Type
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 apiGetDC Lib "user32" _
Alias "GetDC" _
(ByVal hwnd As Long) _
As Long
Private Declare Function apiReleaseDC Lib "user32" _
Alias "ReleaseDC" _
(ByVal hwnd As Long, _
ByVal hdc As Long) _
As Long
Private Declare Function apiCreateCompatibleDC Lib "gdi32" _
Alias "CreateCompatibleDC" _
(ByVal hdc As Long) _
As Long
Private Declare Function apiCreateCompatibleBitmap Lib "gdi32" _
Alias "CreateCompatibleBitmap" _
(ByVal hdc As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long) _
As Long
Private Declare Function apiDeleteDC Lib "gdi32" _
Alias "DeleteDC" _
(ByVal hdc As Long) _
As Long
Private Declare Function apiSelectObject Lib "gdi32" _
Alias "SelectObject" _
(ByVal hdc As Long, _
ByVal hObject As Long) _
As Long
Private Declare Function apiBitBlt Lib "gdi32" _
Alias "BitBlt" _
(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 apiDeleteObject Lib "gdi32" _
Alias "DeleteObject" _
(ByVal hObject As Long) _
As Long
Private Declare Function apiGetObjectBmp Lib "gdi32" _
Alias "GetObjectA" _
(ByVal hObject As Long, _
ByVal nCount As Long, _
lpObject As BITMAP) _
As Long
Private Declare Function apiOpenClipboard Lib "user32" _
Alias "OpenClipboard" _
(ByVal hwnd As Long) _
As Long
Private Declare Function apiEmptyClipboard Lib "user32" _
Alias "EmptyClipboard" _
() As Long
Private Declare Function apiSetClipboardData Lib "user32" _
Alias "SetClipboardData" _
(ByVal wFormat As Long, _
ByVal hMem As Long) As Long
Private Declare Function apiCloseClipboard Lib "user32" _
Alias "CloseClipboard" _
() As Long
Private Declare Function apiGetDeviceCaps Lib "gdi32" _
Alias "GetDeviceCaps" (ByVal hdc As Long, _
ByVal nIndex As Long) As Long
Private Declare Function apiGetSysMetrics Lib "user32" _
Alias "GetSystemMetrics" _
(ByVal nIndex As Long) As Long
Private Const CF_BITMAP = 2
Private Const IMAGE_BITMAP& = 0
Private Const SRCCOPY = &HCC0020
Private Const LOGPIXELSX = 88
Private Const LOGPIXELSY = 90
Private Const SM_CXSCREEN = 0
Private Const SM_CYSCREEN = 1
Private Const SM_CYCAPTION = 4
Private Const SM_CXBORDER = 5
Private Const SM_CYBORDER = 6
Private Const SM_CXDLGFRAME = 7
Private Const SM_CYDLGFRAME = 8
Private Const SM_CXFRAME = 32
Private Const SM_CYFRAME = 33
Function fImageToClipboard(frm As Form, _
imageCtl As Control) As Boolean
On Error GoTo ErrHandler
Dim hwnd As Long
Dim hdc As Long
Dim lngRet As Long
Dim hMemDC As Long
Dim hObject As Object
Dim blnBMPResize As Boolean
Dim lpRect As RECT
Dim lpObject As BITMAP
Dim hBitmap As Long
Dim intSizeMode As Integer
Dim blnRecordSelector As Boolean
Dim strPicture As String
Dim blnIsOLE As Boolean
Dim blnFileExists As Boolean
blnIsOLE = False
strPicture = imageCtl.Picture
If blnIsOLE Then
imageCtl.SetFocus
DoCmd.RunCommand acCmdCopy
Err.Raise vbObjectError + 65530
End If
blnRecordSelector = frm.RecordSelectors
frm.RecordSelectors = False
hwnd = frm.hwnd
hdc = apiGetDC(hwnd)
hMemDC = apiCreateCompatibleDC(hdc)
blnFileExists = (Not Dir(imageCtl.Picture) = vbNullString)
If blnFileExists Then
Set hObject = LoadPicture(imageCtl.Picture)
lngRet = apiGetObjectBmp(hObject.handle, Len(lpObject), lpObject)
End If
With lpRect
.Left = imageCtl.Left
.Top = imageCtl.Top
.Right = imageCtl.Width + imageCtl.Left
.Bottom = imageCtl.Top + imageCtl.Height
End With
With lpRect
,
If Not frm.BorderStyle Then _
.Top = .Top + apiGetSysMetrics(SM_CYCAPTION)
Select Case frm.BorderStyle
Case 1
.Left = .Left + apiGetSysMetrics(SM_CXBORDER)
.Top = .Top + apiGetSysMetrics(SM_CYBORDER)
Case 2
.Left = .Left + apiGetSysMetrics(SM_CXFRAME)
.Top = .Top + apiGetSysMetrics(SM_CYFRAME)
Case 3
.Left = .Left + apiGetSysMetrics(SM_CXDLGFRAME)
.Top = .Top + apiGetSysMetrics(SM_CYDLGFRAME)
End Select
.Left = ConvertTwipsToPixels(.Left, 0)
.Top = ConvertTwipsToPixels(.Top, 1)
.Bottom = ConvertTwipsToPixels(.Bottom, 1)
.Right = ConvertTwipsToPixels(.Right, 0)
End With
If blnFileExists Then
With lpRect
If .Right + .Left > lpObject.bmWidth Then
hBitmap = apiCreateCompatibleBitmap(hdc, _
.Right - .Left, .Bottom - .Top)
Else
blnBMPResize = True
intSizeMode = imageCtl.SizeMode
imageCtl.SizeMode = acOLESizeStretch
frm.Repaint
With lpObject
hBitmap = apiCreateCompatibleBitmap(hdc, .bmWidth, .bmHeight)
End With
End If
lngRet = apiSelectObject(hMemDC, hBitmap)
lngRet = apiBitBlt(hMemDC, 0&, 0&, .Right - .Left, _
.Bottom - .Top, hdc, .Left, .Top, SRCCOPY)
End With
Else
With lpRect
hBitmap = apiCreateCompatibleBitmap(hdc, .Right - .Left, _
.Bottom - .Top)
blnBMPResize = True
intSizeMode = imageCtl.SizeMode
imageCtl.SizeMode = acOLESizeStretch
frm.Repaint
lngRet = apiSelectObject(hMemDC, hBitmap)
lngRet = apiBitBlt(hMemDC, 0&, 0&, .Right - .Left, _
.Bottom - .Top, hdc, .Left, .Top, SRCCOPY)
End With
End If
Call apiOpenClipboard(hwnd)
Call apiEmptyClipboard
Call apiSetClipboardData(CF_BITMAP, hBitmap)
fImageToClipboard = True
ExitHere:
On Error Resume Next
Call apiCloseClipboard
If blnIsOLE Then _
Screen.PreviousControl.SetFocus
If blnBMPResize Then _
imageCtl.SizeMode = intSizeMode
frm.RecordSelectors = blnRecordSelector
Call apiDeleteObject(hObject)
Call apiDeleteDC(hMemDC)
Call apiReleaseDC(hwnd, hdc)
Exit Function
ErrHandler:
If Err.Number = 438 Then
blnIsOLE = True
Resume Next
Else
fImageToClipboard = False
Resume ExitHere
End If
End Function
Private Function ConvertTwipsToPixels(lngTwips As Long, _
lngDirection As Long) _
As Long
Dim lngDC As Long
Dim lngPixelsPerInch As Long
Const nTwipsPerInch = 1440
Const SM_CXSCREEN = 0
Const SM_CYSCREEN = 1
lngDC = apiGetDC(SM_CXSCREEN)
If (lngDirection = SM_CXSCREEN) Then
lngPixelsPerInch = apiGetDeviceCaps(lngDC, LOGPIXELSX)
Else
lngPixelsPerInch = apiGetDeviceCaps(lngDC, LOGPIXELSY)
End If
lngDC = apiReleaseDC(SM_CXSCREEN, lngDC)
ConvertTwipsToPixels = lngTwips / nTwipsPerInch * lngPixelsPerInch
End Function
|