参考oletodisk的实现方法,更新为在64位office上野可以运行,函数模块代码如下:

   1 Option Compare Database
2 Option Explicit
3
4
5 'DEVELOPED AND TESTED UNDER MICROSOFT ACCESS 97 through A2003
6 '
7 'Copyright: Stephen Lebans - Lebans Holdings 1999 Ltd.
8
9
10 'Distribution:
11
12 ' Plain and simple you are free to use this source within your own
13 ' applications, whether private or commercial, without cost or obligation, other that keeping
14 ' the copyright notices intact. No public notice of copyright is required.
15 ' You may not resell this source code by itself or as part of a collection.
16 ' You may not post this code or any portion of this code in electronic format.
17 ' The source may only be downloaded from:
18 ' www.lebans.com
19 '
20 'Name: GetContentsStream
21 '
22 'Version: 2.89
23 '
24 'Purpose:
25 '
26 '?) Export data inserted into OLE object field.
27 ' The original application that served as an OLE Server to insert
28 ' the object is NOT required.
29 '
30 ' 2) Perform an inventory of OLE field within an external table.
31 ' Returns inventory information including Linked path/filename if applicable.
32 '
33 '瓲
34 '
35 'Author: Stephen Lebans
36 '
37 'Email: Stephen@lebans.com
38 '
39 'Web Site: www.lebans.com
40 '
41 'Date: Nov 17, 2007, 12:34:56 PM
42 '
43 'Dependencies: StrStorage.dll(Standard Windows DLL - DOES NOT require Registration.
44 ' modGetContents Stream
45 ' modListTables
46 ' clsCommonDialog
47 ' cDIBSection
48 '
49 'Inputs: See inline Comments for explanation
50
51 'Output: See inline Comments for explanation
52 '
53 'Credits: Anyone who wants some!
54 '
55 'BUGS: Please report any bugs to my email address.
56 '
57 'What's Missing:
58 ' Enhanced Error Handling
59 '
60 'How it Works:
61 ' Keep reading!
62
63 ' Ver Jan 16 - 2008
64 ' Working on fixing Bug for embedded OT_STATIC MetafilePict
65 ' Added support for FoxitReader.Document embedded objects(PDF)
66
67 ' Ver Nov 17, 2007
68 ' Added support for WordPad documents.
69
70 ' Ver June 7, 2007
71 ' Added support for Kodak Imaging TIFF documents.
72
73
74 ' Ver March 20
75 ' Added support for PaperPort MAX documents and
76 ' HP DeskScan embedded images(Bitmaps).
77
78 ' This module exposes two functions.
79 'Public Function fGetContentsStream(ByRef arrayOLE() As Byte, _
80 'FileExtension As String, _
81 'Optional FileNamePackage As String = "") As Boolean
82
83 ' The first parameter, arrayOLE, is an array of Byte values that contain the entire
84 ' contents of an OLE object field. We pass the the first element of the
85 ' array be Reference, arrayOLE(0), which really means we are passing
86 ' the address of the start of the array.
87
88 ' The second parameter, FileExtension, is a empty string variable you pass that will
89 ' be filled in with the file extension of the extracted object.
90
91 ' The third parameter, FileNamePackage, is a empty string variable you pass that will
92 ' be filled in with the original file name of the extracted object when the object
93 ' was embedded as a Package.
94
95
96 'Have Fun!
97 '
98 '
99 '
100 ' ******************************************************
101
102
103 Private Type RECT
104 Left As Long
105 top As Long
106 right As Long
107 Bottom As Long
108 End Type
109
110 Private Type SIZEL
111 cx As Long
112 cy As Long
113 End Type
114
115 Private Type RGBQUAD
116 rgbBlue As Byte
117 rgbGreen As Byte
118 rgbRed As Byte
119 rgblReserved As Byte
120 End Type
121
122 Private Type BITMAPINFOHEADER '40 bytes
123 biSize As Long
124 biWidth As Long
125 biHeight As Long
126 biPlanes As Integer
127 biBitCount As Integer
128 biCompression As Long 'ERGBCompression
129 biSizeImage As Long
130 biXPelsPerMeter As Long
131 biYPelsPerMeter As Long
132 biClrUsed As Long
133 biClrImportant As Long
134 End Type
135
136
137 Private Type BITMAPINFO
138 bmiHeader As BITMAPINFOHEADER
139 bmiColors As RGBQUAD
140 End Type
141
142
143 Private Type BITMAP
144 bmType As Long
145 bmWidth As Long
146 bmHeight As Long
147 bmWidthBytes As Long
148 bmPlanes As Integer
149 bmBitsPixel As Integer
150 bmBits As Long
151 End Type
152
153 Private Type DIBSECTION
154 dsBm As BITMAP
155 dsBmih As BITMAPINFOHEADER
156 dsBitfields(2) As Long
157 dshSection As Long
158 dsOffset As Long
159 End Type
160
161
162 ' Here is the header for the Bitmap file
163 ' as it resides in a disk file
164 Private Type BITMAPFILEHEADER '14 bytes
165 bfType As Integer
166 bfSize As Long
167 bfReserved1 As Integer
168 bfReserved2 As Integer
169 bfOffBits As Long
170 End Type
171
172 Private Type METAFILEPICT
173 mm As Long
174 xExt As Long
175 yExt As Long
176 hMF As Long
177 End Type
178
179
180 Private Const CON_CHUNK_SIZE As Long = 32768
181 Private Const OBJECT_SIGNATURE = &H1C15
182 Private Const OBJECT_HEADER_SIZE = 20
183 Private Const CHECKSUM_SIGNATURE = &HFE05AD00
184 Private Const CHECKSUM_STRING_SIZE = 4
185 Private Const SIG_BMP = &H4D42
186
187
188 Private Type PT
189 width As Integer
190 Height As Integer
191 End Type
192 '
193 '
194 ' OBJECTHEADER : Contains relevant information about object.
195 '
196 Private Type OBJECTHEADER
197 Signature As Integer ' Type signature (0x1c15).
198 HeaderSize As Integer ' Size of header (sizeof(struct
199 ' OBJECTHEADER) + cchName +
200 ' cchClass).
201 ObjectType As Long ' OLE Object type code (OT_STATIC,
202 ' OT_LINKED, OT_EMBEDDED).
203 NameLen As Integer ' Count of characters in object
204 ' name (CchSz(szName) + 1).
205 ClassLen As Integer ' Count of characters in class
206 ' name (CchSz(szClass) + 1).
207 NameOffset As Integer ' Offset of object name in
208 ' structure (sizeof(OBJECTHEADER)).
209 ClassOffset As Integer ' Offset of class name in
210 ' structure (ibName + cchName).
211 ObjectSize As PT ' Original size of object (see
212 ' code below for value).
213 ' OleInfo(256) As Byte
214 End Type
215
216 '/* Object types */
217 Public Const OT_LINK As Long = 1&
218 Public Const OT_EMBEDDED = 2&
219 Public Const OT_STATIC = 3&
220
221
222
223 Private Type MSPHOTOEDITOR_CONTENTS_HEADER
224 bmBitDepth As Integer
225 bmWidth As Integer
226 bmHeight As Integer
227 End Type
228
229 ' Pass first element of Byte array - ex. a(0)
230 ' Pass size of array in bytes
231 ' Return length of valid data in the passed array of bytes
232 ' Array will contain complete CONTENTS Stream of Structured Storage
233
234
235 ' debugging with Visual C++
236 'Lib "C:\VisualCsource\SLStrucStorageContents\Debug\SSGetContents.dll"
237
238 Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
239 (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
240
241 Private Declare PtrSafe Function ShellExecuteA Lib "shell32.dll" _
242 (ByVal hwnd As Long, ByVal lpOperation As String, _
243 ByVal lpFile As String, ByVal lpParameters As String, _
244 ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
245
246 Private Declare PtrSafe Function LoadLibrary Lib "kernel32" _
247 Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
248
249 Private Declare PtrSafe Function FreeLibrary Lib "kernel32" _
250 (ByVal hLibModule As Long) As Long
251
252 Private Declare PtrSafe Function GetTempPath Lib "kernel32" _
253 Alias "GetTempPathA" (ByVal nBufferLength As Long, _
254 ByVal lpBuffer As String) As Long
255
256 Private Declare PtrSafe Function GetTempFileName _
257 Lib "kernel32" Alias "GetTempFileNameA" _
258 (ByVal lpszPath As String, _
259 ByVal lpPrefixString As String, _
260 ByVal wUnique As Long, _
261 ByVal lpTempFileName As String) As Long
262
263 Private Declare PtrSafe Function GetLongPathName Lib "kernel32.dll" Alias _
264 "GetLongPathNameA" (ByVal lpszShortPath As String, _
265 ByVal lpszLongPath As String, _
266 ByVal cchBuffer As Long) As Long
267
268 Public Declare PtrSafe Function GetFullPathName Lib "kernel32" _
269 Alias "GetFullPathNameA" _
270 (ByVal lpFileName As String, _
271 ByVal nBufferLength As Long, _
272 ByVal lpBuffer As String, _
273 ByVal lpFilePart As String) As Long
274
275
276
277
278 Private Const Pathlen = 256
279 Private Const MaxPath = 256
280
281 ' Structured Storage Signature = 'D0CF11E0
282 Private Const SSsig As Long = &HE011CFD0
283
284 ' Allow user to set FileName instead
285 ' of using API Temp Filename or
286 ' popping File Dialog Window
287 Private mSaveFileName As String
288
289 ' Instance returned from LoadLibrary call
290 Private hLibStrStorage As Long
291
292 ' * Move this into a class so we can init/destroy properly
293 Private ds As cDIBSection
294
295
296 Public Function fGetContentsStream(ByRef arrayOLE() As Byte, _
297 FileExtension As String, _
298 Optional FileNamePackage As String = "") As Boolean
299 ' arrayOLE must contain the entire contents of the OLE field.
300 ' Returns arrayOLE resized to fit and contain the
301 ' CONTENTS Stream of the OLE Structured Storage passed to this function.
302 ' Exceptions are for the "Package" type and Bitmap's embedded with MS Paint.
303
304 ' Hold working copy of arrayOLE
305 Dim arrayB() As Byte
306
307 ' Size of "Package"
308 Dim lPackSize As Long
309
310 ' File Extension of Package
311 Dim FileNamePackageExt As String
312 ' Original File Name and Path of Package
313 Dim FileNameandPathPackage As String
314
315 ' Current position in arrayOLE
316 Dim lPos As Long
317
318 ' Temp vars
319 Dim bCurValue As Byte
320 Dim iOffset As Integer
321 Dim i As Integer
322 Dim x As Long
323 Dim s As String
324 Dim blRet As Boolean
325 Dim lngRet As Long
326 Dim y As Long
327
328 ' Length of array returned from functions in Structured Storage DLL.
329 Dim lLen As Long
330
331 ' Access OLE Wrapper
332 Dim objHeader As OBJECTHEADER
333
334 ' Offset to start of structured storage file
335 Dim lOffSet As Long
336
337 ' Class name of embedded OLE object
338 Dim arrayClassName(0 To 1023) As Byte
339
340 ' OLE object temp vars
341 Dim sClassName As String
342 Dim sStreamName As String
343 Dim sBuf As String
344 Dim sExt As String
345
346 Dim mfp As METAFILEPICT
347 Dim bm As BITMAPINFOHEADER
348
349
350 On Error GoTo ERR_fGetContentsStream
351
352 ' Get Offset to start of Structured Storage
353 CopyMemory objHeader, arrayOLE(0), OBJECT_HEADER_SIZE
354 lOffSet = objHeader.HeaderSize + 24 + objHeader.ClassLen
355
356 ' If Linked object then exit
357 If objHeader.ObjectType = OT_LINK Then
358 fGetContentsStream = False
359 Exit Function
360 End If
361
362 ' Let's see if the StrStorage.DLL is available.
363 'blRet = LoadLib()
364 'If blRet = False Then
365 ' ' Cannot find StrStorage.dll file
366 ' fGetContentsStream = False
367 ' Exit Function
368 'End If
369
370 ' If OLE object was draged and dropped then
371 ' the ClassLen member with be a NULL string
372 'If objHeader.ClassLen > 1 Then
373 ' Convert byte Ascii data to VB string
374 sClassName = ""
375 For i = 0 To objHeader.ClassLen - 2
376 sClassName = sClassName & Chr(arrayOLE(objHeader.ClassOffset + i))
377 Next i
378 'Else
379
380 ' Add support for ClassLen = 0 - Drag and Dropped OLE object
381 'End If
382
383 ' Call seperate function if object is of type STATIC
384 If objHeader.ObjectType = OT_STATIC Then
385 sClassName = "OT_STATIC"
386 End If
387
388 ' Logic tree based on ClassName of embedded object
389 Select Case Left(sClassName, 7)
390
391 Case "OT_STAT"
392 ' Two possibilities.
393 ' Static MetafilePict or Static DIB
394 ' Standard OLE wrapper but it is always the same size
395 ' because the Class name is blank and Object name is always "Picture".
396 ' 29 Bytes Access OLE Header wrapper.
397
398 ' The following 12 Bytes are private header data
399 ' This brings us to offset 41.
400 ' The next 3 bytes will either be = "DIB or "MET"
401 ' DIB
402 ' After "DIB" + terminating NULL char we jump over next
403 ' 8 bytes of private data.
404
405 ' The next 4 bytes are the size of the Bitmap.
406 '
407 ' The next 40 Bytes are the BITMAPINFOHEADER structure
408 ' The next 4 bytes are always the value 40 - SIZEOF BITMAPINFOHEADER
409
410 ' The next X bytes are the BITMAPINFOHEADER
411
412 ' So once we get to the LONG SIZEOF bitmap data we can build
413 ' the disk basked BMP file.
414 ' The next X bytes are the actual Bitmap Data
415 '
416 '
417
418 ' Start of Package header
419 ' Jan - 2008 Offset out by 1 - was 41
420 lPos = 38
421 '' Skip nexy 4 bytes - Package size including padding
422 'lPos = lPos + 4
423 ' Skip next 2 bytes - Embedded constant - 2 ?
424 'lPos = lPos + 2
425
426 ' Checking for 0 so must initialize to any value but 0.
427 bCurValue = 1
428
429 Dim lSize As Long
430 Dim FileHeaderBM As BITMAPFILEHEADER
431
432 Dim sType As String
433 ' DIB or METAFILEPICT
434 Do While bCurValue <> 0
435 bCurValue = arrayOLE(lPos)
436 sType = sType & Chr(bCurValue)
437 lPos = lPos + 1
438 Loop
439
440 ' Jump over next 8 bytes of private data
441 lPos = lPos + 8
442
443 If sType = "DIB" Then
444 ' Get size of Bitmap Data
445 CopyMemory lSize, arrayOLE(lPos), 4
446 ' Make sure is less than arrayOLE
447 If lSize > UBound(arrayOLE) Then
448 ' Error
449 fGetContentsStream = False
450 Exit Function
451 End If
452 ' 14 is the size of the Bitmap disk File Header
453 ReDim arrayB(0 To lSize + 14 - 1)
454
455 ' Jump over 4 bytes of lSize
456 lPos = lPos + 4
457
458 ' Copy starting at end of BMP File Header(+14)
459 CopyMemory arrayB(14), arrayOLE(lPos), lSize
460
461 ' Are we 8 bits or less with a ColorTable
462 CopyMemory bm, arrayB(14), Len(bm)
463
464 Select Case bm.biBitCount
465
466 Case 24, 16
467 iOffset = 0
468
469 Case 8
470 ' Some apps mistakenly write &HFF here instead of 256(&H0100)
471 ' Further they only actually use 255 colors instead of 256
472 If bm.biClrUsed = 255 Then
473 iOffset = 255 * 4
474 Else
475 iOffset = 256 * 4
476 End If
477
478 Case 4
479 iOffset = 16
480
481 Case Else
482 iOffset = 0
483
484 End Select
485
486 ' Build BMP File Header
487 ' Signature
488 With FileHeaderBM
489 ' Signature
490 .bfType = &H4D42
491 ' Size of entire Bitmap disk file.
492 ' FileHeader + BitmapInfoHeader + ColorTable(if any) + Bitmap data bytes
493 .bfSize = Len(FileHeaderBM) + lSize
494 ' Offset from start of file to start of Bitmap data
495 .bfOffBits = Len(FileHeaderBM) + Len(bm) + iOffset
496 End With
497
498 ' Signature
499 CopyMemory arrayB(0), FileHeaderBM.bfType, 2
500 ' Size of Bitmap file
501 CopyMemory arrayB(2), FileHeaderBM.bfSize, 4
502 'CopyMemory arrayOLE(6), ByVal 0&, 4
503 ' Next 4 bytes Reserved
504 arrayB(6) = 0
505 arrayB(7) = 0
506 arrayB(8) = 0
507 arrayB(9) = 0
508 ' Offset to start of Bitmap data
509 ' Always File Header len(14) + BITMAPINFOHEADER len(40)
510 CopyMemory arrayB(10), FileHeaderBM.bfOffBits, 4 ' Add BMP File Header
511
512 ' Size our main array
513 ReDim arrayOLE(0 To UBound(arrayB))
514 ' Copy temp array to our main array
515 arrayOLE = arrayB
516 FileExtension = "bmp"
517 sExt = "bmp"
518
519
520 Else
521 ' METAFILEPICT
522 ' Get size of Bitmap Data
523 CopyMemory lSize, arrayOLE(lPos), 4
524 ' Make sure is less than arrayOLE
525 If lSize > UBound(arrayOLE) Then
526 ' Error
527 fGetContentsStream = False
528 Exit Function
529 End If
530 ' 8 is the length of the METAFILEPICT structure
531 ' because this OLE format only uses WORD(2 bytes)
532 ' for each structure element
533 ReDim arrayB(0 To (lSize - 8) - 1)
534
535 ' Jump over 4 bytes of lSize
536 lPos = lPos + 4
537
538 ' Fill in our public METAFILEPICT structure
539 CopyMemory mfp.mm, arrayOLE(lPos), 2
540 CopyMemory mfp.xExt, arrayOLE(lPos + 2), 2
541 CopyMemory mfp.yExt, arrayOLE(lPos + 4), 2
542
543 ' Jump over 8 bytes of METAFILEPICT structure
544 lPos = lPos + 8
545
546 ' Copy starting at end of BMP File Header(+14)
547 CopyMemory arrayB(0), arrayOLE(lPos), lSize - 8
548
549 ' Convert WMF to DIB
550 blRet = ds.WMFtoBMP(arrayB(), mfp.mm, mfp.xExt, mfp.yExt)
551 If blRet = False Then
552 fGetContentsStream = False
553 Exit Function
554 End If
555
556 ' ArrayB now contains the Byte data for the DIB
557 ' Create the disk Based Bitmap file
558
559 ' 40 is the size of the BITMAPINFOHEADER
560 ' 14 is the size of the Bitmap disk File Header
561 ReDim arrayOLE(0 To UBound(arrayB()) + 40 + 14)
562
563 ' Jump over 4 bytes of lSize
564 'lPos = lPos + 4
565
566 ' Copy starting at end of BMP File Header(+14) plus BITMAPINFOHEADER(+40)
567 CopyMemory arrayOLE(14 + 40), arrayB(0), UBound(arrayB()) + 1
568
569 ' Build BITMAPINFOHEADER
570 With bm
571 .biBitCount = 24
572 .biClrImportant = 0
573 .biClrUsed = 0
574 .biCompression = 0
575 .biHeight = ds.dib_height
576 .biPlanes = 1
577 .biSize = 40
578 .biSizeImage = UBound(arrayB()) + 1 '(ds.dib_width * ds.BytesPerScanLine) * ds.dib_height
579 .biWidth = ds.dib_width
580 .biXPelsPerMeter = 0
581 .biYPelsPerMeter = 0
582
583 End With
584
585 ' Copy BITMAPINFOHEADER
586 CopyMemory arrayOLE(14), ByVal bm, Len(bm) ' always 40 for this project
587
588 ' Build BMP File Header
589 ' Fill in our Bitmap FileHeader.
590 With FileHeaderBM
591 ' Signature
592 .bfType = &H4D42
593 ' Size of entire Bitmap disk file.
594 ' FileHeader + BitmapInfoHeader + ColorTable(if any) + Bitmap data bytes
595 .bfSize = Len(FileHeaderBM) + Len(bm) + bm.biSizeImage
596 ' Offset from start of file to start of Bitmap data
597 .bfOffBits = Len(FileHeaderBM) + Len(bm)
598 End With
599 ' Signature
600 CopyMemory arrayOLE(0), FileHeaderBM.bfType, 2
601 ' Size of Bitmap file
602 CopyMemory arrayOLE(2), FileHeaderBM.bfSize, 4
603 'CopyMemory arrayOLE(6), ByVal 0&, 4
604 ' Next 4 bytes Reserved
605 arrayOLE(6) = 0
606 arrayOLE(7) = 0
607 arrayOLE(8) = 0
608 arrayOLE(9) = 0
609 ' Offset to start of Bitmap data
610 ' Always File Header len(14) + BITMAPINFOHEADER len(40)
611 CopyMemory arrayOLE(10), FileHeaderBM.bfOffBits, 4 ' Add BMP File Header
612
613
614 FileExtension = "bmp"
615 sExt = "bmp"
616 End If
617
618 fGetContentsStream = True
619
620 Exit Function
621 ''''''''''''''''''''''''''''''''''''''''''
622 ''''''''''''''''''''''''''''''''''''''''''
623
624
625 Case "Package"
626 ' Copy of original file exists.
627 ' Please note all string values are terminated with the NULL char(0).
628 ' Standard OLE wrapper but it is always the same size
629 ' because the Class name and Object name are always "Package".
630 ' 36 Bytes Access OLE Header wrapper.
631
632 ' The following 28 Bytes are private header data
633 ' This brings us to offset 64.
634 ' Here is another part of the header info. The first 4 bytes
635 ' are the size of the package, including padding.
636
637 ' The next two bytes are always the integer value of 2.
638 ' I'll guess this is a constant value for embedded Packages.
639
640 ' The next X bytes are a copy of the original file name, including
641 ' teminating NULL character.
642
643 ' The next X bytes are a copy of the original file name including
644 ' path and teminating NULL character.
645 '
646 '
647 ' The next 4 bytes are unknown values. This Long value always seems to be 3.
648
649 ' The next 2 bytes, an Integer, contain the length of string
650 ' immediately to follow, which is a copy of the path string above.
651
652 ' The next X bytes are a copy of the original file name including
653 ' path and teminating NULL character.
654
655
656 ' The next 4 bytes, a Long, contain the actual file size of the original
657 ' embedded file.
658
659 ' The next x bytes contain the file that was originally embedded. This is an exact
660 ' copy of the original file.
661
662
663 ' Start of Package header
664 lPos = 64
665 ' Skip nexy 4 bytes - Package size including padding
666 lPos = lPos + 4
667 ' Skip next 2 bytes - Embedded constant - 2 ?
668 lPos = lPos + 11
669
670 ' Checking for 0 so must initialize to any value but 0.
671 bCurValue = 1
672
673 ' Package original File Name
674 Do While bCurValue <> 0
675 bCurValue = arrayOLE(lPos)
676 FileNamePackage = FileNamePackage & Chr(bCurValue)
677 lPos = lPos + 1
678 Loop
679
680 bCurValue = 1
681 ' Package original full path and File Name
682 Do While bCurValue <> 0
683 bCurValue = arrayOLE(lPos)
684 FileNameandPathPackage = FileNameandPathPackage & Chr(bCurValue)
685 lPos = lPos + 1
686 Loop
687
688 ' Unknown 4 bytes
689 lPos = lPos + 4
690
691 ' Integer - number of bytes of following string
692 ' which contains fill path and filename
693 CopyMemory iOffset, arrayOLE(lPos), 2
694
695 ' Jump over our iOffset
696 lPos = lPos + 2
697
698 ' Jump over 2 bytes - Unknown
699 lPos = lPos + 2
700
701 ' Jump over string
702 lPos = lPos + iOffset
703
704 ' Grab complete size of embedded file
705 CopyMemory lPackSize, arrayOLE(lPos), 4
706
707 ' Jump over lPacksize Offset
708 lPos = lPos + 4
709
710 ' Resize to fit embedded file
711 ' Error check
712 If lPackSize >= UBound(arrayOLE) Then
713 fGetContentsStream = False
714 Exit Function
715 End If
716
717 ReDim arrayB(0 To lPackSize - 1)
718
719 ' I just have never trusted overlapping memory locations
720 CopyMemory arrayB(0), arrayOLE(lPos), lPackSize
721 ReDim arrayOLE(0 To lPackSize - 1)
722 arrayOLE = arrayB
723 FileExtension = "pak"
724 sExt = "pak"
725 fGetContentsStream = True
726
727 Exit Function
728 ''''''''''''''''''''''''''''''''''''''''''
729 ''''''''''''''''''''''''''''''''''''''''''
730
731
732 Case "HP.Desk"
733 ' Scan HP DeskScan.2
734 sExt = "hpd"
735 sStreamName = "Ole10Native"
736 FileExtension = "bmp"
737 ''''''''''''''''''''''''''''''''''''''''''
738
739
740 Case "Visio.D"
741 ' MS Word document
742 sExt = "vsd"
743 sStreamName = "VisioDocument"
744 FileExtension = "vsd"
745 ''''''''''''''''''''''''''''''''''''''''''
746 ''''''''''''''''''''''''''''''''''''''''''
747 '''''''''''''''''''''''''''''''''''
748
749 Case "Paint.P" 'Paint.Picture
750 sExt = "bmp"
751 FileExtension = "bmp"
752
753 sStreamName = ""
754 ' Save off Bitmap file so we can simply exit
755 ' and return the original data minus the
756 ' Access OLE header and the 12 byte Checksum.
757
758 ' Delete Access OLE wrapper
759 y = objHeader.HeaderSize + 31
760 'copy back minus header and checksum
761 For x = 0 To UBound(arrayOLE) - (objHeader.HeaderSize + 31)
762 arrayOLE(x) = arrayOLE(y)
763 y = y + 1
764 Next x
765
766 ' Get Total Size.
767 ' For PaintBrushBitmap files it is an actual Disk based Bitmap file
768 ' not the MS Photo Editor private Bitmap or the PSP entire file.
769 ' It is the 3rd through 6th bytes that form the LONG value representing the
770 ' complete file size for the Bitmap.
771
772 CopyMemory x, arrayOLE(2), 4
773
774 ReDim Preserve arrayOLE(0 To x - 1) As Byte
775
776 ' Success!
777 fGetContentsStream = True
778 sExt = "bmp"
779 Exit Function
780 ''''''''''''''''''''''''''''''''''''''''''
781 ''''''''''''''''''''''''''''''''''''''''''
782
783 ' Need more work on error logic
784 Case Else
785 ' Not supported yet
786 Err.Raise vbObjectError + 566, "modGetContentsStream.fGetContentsStream", _
787 "Sorry...this OLE object contains an unsupported format" & vbCrLf & _
788 "Please select a different Record to Export"
789 ''''''''''''''''''''''''''''''''''''''''''
790 ''''''''''''''''''''''''''''''''''''''''''
791 'fGetContentsStream = False
792 'sExt = ""
793 'Exit Function
794
795 End Select
796
797 ' For any objects that we need to use the Structured Storage DLL's
798 ' to retrieve the contents of the OLE object then we need to
799 ' delete Access OLE wrapper of size objHeader.Size
800 ' lOffSet var is previously filled in:
801 'lOffSet = objHeader.HeaderSize + 24 + objHeader.ClassLen
802 ' MSPhotoEdScan.3 for some reason needs 4 bytes removed from
803 ' its offset to start of Structured Storage SIG.
804 ' I'll look in to it later and hardwire a fix for now.
805
806 If sClassName = "MSPhotoEdScan.3" Then lOffSet = lOffSet - 4
807 y = 0
808 For x = lOffSet To UBound(arrayOLE) - lOffSet
809 arrayOLE(y) = arrayOLE(x)
810 y = y + 1
811 Next x
812
813
814
815 'If sStreamName <> "CONTENTS" Then
816 ' ' Extract Office doc
817 ' lLen = ExtractOfficeDocument(arrayOLE(0), UBound(arrayOLE) - lOffSet, sStreamName)
818 'Else
819 '' Call our function in the StrStorage DLL
820 ' lLen = GetContentsStream(arrayOLE(0), UBound(arrayOLE) - lOffSet, sStreamName)
821 'End If
822
823
824 ' Need to log errors so that a Dialog is not popping up
825 ' for every record that errors
826 If lLen = 0 Then
827 Err.Raise vbObjectError + 526, "modGetContentsStream.fGetContentsStream", _
828 "Sorry...this OLE object does not have a CONTENTS Stream" & vbCrLf & _
829 "Please select a different Record to Export"
830 Exit Function
831 End If
832
833 ' Resize our returned memory
834 ReDim Preserve arrayOLE(0 To lLen - 1) As Byte
835
836
837 ' ***************************************************
838 ' DEBUG
839
840 'fGetContentsStream = True
841 'Exit Function
842
843
844 ' ***************************************************
845
846
847 ' Further processing is required for certain objects
848 Select Case sExt
849
850 ' Add Visio etc.
851 Case "doc", "xls", "ppt", "vsd", "rtf"
852 ' Do nothings as File Extension is already set.
853 ' Also arrayOLE is ready to be saved to disk
854 ''''''''''''''''''''''''''''''''''''''''''
855 ''''''''''''''''''''''''''''''''''''''''''
856
857
858 ' PDF
859 Case "pdf", "snp"
860 ' Do nothings as File Extension is already set.
861 ' Also arrayOLE is ready to be saved to disk
862 ''''''''''''''''''''''''''''''''''''''''''
863 ''''''''''''''''''''''''''''''''''''''''''
864
865 ' PDF
866 Case "tiff"
867 ' Remove header of 234 bytes
868 ' Remaining data ' is the complete TIFF file.
869 ' lLen is length of CONTENTS stream returned in GetContentsStream
870 ReDim arrayB(0 To lLen - (234 + 1)) As Byte
871
872 CopyMemory arrayB(0), arrayOLE(234), lLen - (234 + 1)
873 ReDim arrayOLE(0 To lLen - (1 + 234)) As Byte
874 CopyMemory arrayOLE(0), arrayB(0), lLen - (1 + 234)
875
876 ''''''''''''''''''''''''''''''''''''''''''
877 ''''''''''''''''''''''''''''''''''''''''''
878
879
880
881 ' PaperPort Document
882 ' 64 ByteHeader needs to be removed
883 Case "max"
884 ' Remove header of 64 bytes
885 ' Remaining data ' is the complete Bitmap file.
886 ' lLen is length of CONTENTS stream returned in GetContentsStream
887
888 ' April 18/2008
889 ' In some instances there is NO HEADER TO REMOVE
890 ' Examine first 3 bytes. If equal to MAX FILE SIGNATURE then DO NOT remove header!!!
891
892 If arrayOLE(0) = 86 And arrayOLE(1) = 105 And arrayOLE(2) = 71 Then
893 ' do nothing - DO NOT REMOVE HEADER
894
895 Else
896
897 ReDim arrayB(0 To lLen - (64 + 1)) As Byte
898
899 CopyMemory arrayB(0), arrayOLE(64), lLen - (64 + 1)
900 ReDim arrayOLE(0 To lLen - (1 + 64)) As Byte
901 CopyMemory arrayOLE(0), arrayB(0), lLen - (1 + 64)
902
903
904 End If
905 ''''''''''''''''''''''''''''''''''''''''''
906 ''''''''''''''''''''''''''''''''''''''''''
907
908 ''''''''''''''''''''''''''''''''''''''''''
909 ''''''''''''''''''''''''''''''''''''''''''
910
911
912
913 ' HP DeskScan stored as Bitmap
914 ' Header needs to be removed
915 Case "hpd"
916 ' Remove header of 4 bytes
917 ' Remaining data ' is the complete Bitmap file.
918 ' lLen is length of CONTENTS stream returned in GetContentsStream
919 ReDim arrayB(0 To lLen - (4 + 1)) As Byte
920
921 CopyMemory arrayB(0), arrayOLE(4), lLen - (4 + 1)
922 ReDim arrayOLE(0 To lLen - (1 + 4)) As Byte
923 CopyMemory arrayOLE(0), arrayB(0), lLen - (1 + 4)
924
925
926 ''''''''''''''''''''''''''''''''''''''''''
927 ''''''''''''''''''''''''''''''''''''''''''
928
929 Case "psp"
930 ' Paint Shop Pro
931 ' CONTENTS stream is the complete PSP file
932 ' plus an Header we
933 FileExtension = "psp"
934 ' Need to remove 36 Byte OLE/PSP header. Remaining data
935 ' is the complete original PSP file.
936 ' lLen is length of CONTENTS stream returned in GetContentsStream
937 ReDim arrayB(0 To lLen - 1) As Byte
938
939 CopyMemory arrayB(0), arrayOLE(36), lLen - 36
940 ReDim arrayOLE(0 To lLen - 1) As Byte
941 CopyMemory arrayOLE(0), arrayB(0), lLen - 1
942 'arrayOLE = arrayB
943
944 ' Added functionality to remove padding at end of file.
945 ' To calculate real PSP file size would involve basically
946 ' having to build a PP reader to parse all of the
947 ' blocks and their headers.
948 ' We'll cheat instead. The extra padding is at the
949 ' end of the fill and consists of all 0's.
950 x = UBound(arrayOLE)
951
952 Do While arrayOLE(x) = 0
953 x = x - 1
954 Loop
955
956 ' Bug
957 ' I canot remove all 0's at end of file
958 ' because last byte could legally be 0.
959 ' Let's leave the last 4 zero bytes
960 ReDim Preserve arrayOLE(0 To x + 4) As Byte
961 ''''''''''''''''''''''''''''''''''''''''''
962 ''''''''''''''''''''''''''''''''''''''''''
963
964
965 Case "bmp" ' I need to build a disk based BMP file
966 ' from the packed DIB contained in the array.
967 'MS Photo Editor
968 ' CONTENTS stream returns a packed DIB. A Header specifies Bitmap Height and Width and
969 ' Bits per pixel. At offset &h336 Dec822 BEGINS the Bitmap data. This offset is
970 ' calculated as follows:
971 ' 14 bytes FILEHEADER
972 ' 40 bytes BITMAPINFOHEADER
973 ' 768 bytes Color Table( 3 byte RGB triplet * 256)
974
975 ' So above looks exactly like a standard disk based Bitmap file.
976 ' Unfortuntately, it is not. First while the space is allocated
977 ' for the FILEHEADER and BITMAPINFOHEADER structures, they do
978 ' not contain valid data. For our purposes, only 3 values exist.
979 ' Get MS Photo Editor CONTENTS Stream header - 18 Bytes
980 ' The header contains the Image BitsperPixel, Width, Height
981 ' I have only seen 2 values in the the BitsperPixel byte.
982 ' 2 = 8 bits per pixel
983 ' 1 = 24 bits per pixel(I think greyscale
984 ' Jan/2006 Now I'm seeing a 3
985 ' Perhaps this means 24 Bits but not DWORD aligned
986 '
987 ' I need to test images of different BitsperPixel values.
988
989 Dim ph As MSPHOTOEDITOR_CONTENTS_HEADER
990 ' Fill our header
991 CopyMemory ph, arrayOLE(0), Len(ph)
992
993
994 ' Standard GDI Bitmap related structures
995 Dim MyBitmapInfoHeader As BITMAPINFOHEADER
996 Dim FileHeader As BITMAPFILEHEADER
997
998
999 ' Length of physical ColorTable
1000 ' which is the number of RGBQUADS
1001 ' required to hold the required number of colors.
1002 ' Only used for Bit Depths less than 16 bits.
1003 ' Note: The MS Photo Editor CONTENTS stream packs the
1004 ' Color Table using 3 byte RGB triplets instead of the
1005 ' 4 byte RGBQUADs specified for a disk based Bitmap file.
1006 Dim lngLenColorTable As Long
1007
1008 ' Init to 0
1009 lngLenColorTable = 0
1010
1011 ' Number of bytes for each complete row of the bitmap
1012 Dim BytesPerScanLine As Long
1013
1014 ' Start filling in our Bitmap related structures
1015 Debug.Print ph.bmBitDepth
1016 With MyBitmapInfoHeader
1017 If ph.bmBitDepth = 1 Then .biBitCount = 8
1018 If ph.bmBitDepth = 2 Then .biBitCount = 8
1019 If ph.bmBitDepth = 3 Then .biBitCount = 24
1020
1021 .biClrImportant = 0
1022 .biClrUsed = 0
1023 .biCompression = 0 'BI_RGB ' no compression
1024 .biHeight = ph.bmHeight
1025 .biWidth = ph.bmWidth
1026 .biPlanes = 1
1027 .biSize = Len(MyBitmapInfoHeader)
1028
1029 ' Each pixel is comprised of 3 bytes, Red, Green & Blue(RGB).
1030 ' Each row of pixels must end on a memory address evenly divided by 4.
1031 ' This is commonly refered to as DWORD aligned.
1032 BytesPerScanLine = (MyBitmapInfoHeader.biWidth * (MyBitmapInfoHeader.biBitCount / 8) + 3) And &HFFFFFFFC
1033
1034 ' Size of the Bitmap data only.
1035 .biSizeImage = (BytesPerScanLine * Abs(MyBitmapInfoHeader.biHeight)) ' 0 ' 0 OK for BI_RGB(uncompressed)
1036
1037 ' Most applications do not use these values
1038 .biXPelsPerMeter = 0
1039 .biYPelsPerMeter = 0
1040 End With
1041
1042 ' Calc color table size
1043 If MyBitmapInfoHeader.biBitCount = 8 Then lngLenColorTable = 256 * 4
1044 ' It's residing as RGB triplets not Quads in arrayOLE. We must translate this to
1045 ' RGBQUAD to reside on disk.
1046
1047
1048 ' Fill in our Bitmap FileHeader.
1049 With FileHeader
1050 ' Signature
1051 .bfType = &H4D42
1052 ' Size of entire Bitmap disk file.
1053 ' FileHeader + BitmapInfoHeader + ColorTable(if any) + Bitmap data bytes
1054 .bfSize = Len(FileHeader) + (Len(MyBitmapInfoHeader) + lngLenColorTable) + MyBitmapInfoHeader.biSizeImage
1055 ' Offset from start of file to start of Bitmap data
1056 .bfOffBits = Len(FileHeader) + (Len(MyBitmapInfoHeader) + lngLenColorTable)
1057 End With
1058
1059
1060 ' ********************************************************
1061 ' Trouble with structure alignment padding
1062 ' Copy our structures to our output array.
1063 ' Because of VB structure alignment pading
1064 ' we have to be careful and fill the structure
1065 ' members individually.
1066 ' Signature
1067 CopyMemory arrayOLE(0), FileHeader.bfType, 2
1068 ' Size of Bitmap file
1069 CopyMemory arrayOLE(2), FileHeader.bfSize, 4
1070 'CopyMemory arrayOLE(6), ByVal 0, 4
1071 ' Next 4 bytes Reserved
1072 arrayOLE(6) = 0
1073 arrayOLE(7) = 0
1074 arrayOLE(8) = 0
1075 arrayOLE(9) = 0
1076 ' Offset to start of Bitmap data
1077 CopyMemory arrayOLE(10), FileHeader.bfOffBits, 4
1078
1079 ' Must use second Byte array. Copying the Color Table is overwriting
1080 ' the start of the Bitmap data. The amount overwritten is equal to
1081 ' Len(FileHeader) + Len(MyBitmapInfoHeader)-18
1082 ' 18 bytes is the size of the private MS Photo Editor Header
1083 ' found at the very start of the CONTENTS Stream.
1084 ' Since the BM FileHeader = 14 Bytes and the BitmapInfoHeader
1085 ' = 40 bytes in length we need to move the Color Table and Bitmap data
1086 ' 54 - 18 = 36 bytes
1087 ' backwards in the current array. So we need to resize the array
1088 ' increasing by 36 bytes.
1089
1090
1091 ' Before we creating or Bitmap file we have an issue to resolve.
1092 ' MS Photo Editor stores the DIB as a Bottom UP DIB while most
1093 ' applications use Top Down and some apps will not even load Bottom Up format.
1094 ' Let's copy and mirror both the ColorTable and Bitmap data.
1095
1096
1097 '*** BUG ***
1098 ' I have run into a file where the size of the
1099 ' CONTENTS stream did not equal a packed DIB layout
1100 ' FILEHEADER + BitmapInfoHeader + ColorTable + Bitmap data
1101 ' To get around this let's try resizing arrayOLE
1102 ' based on the BitmapInfoHeader.
1103 'ReDim Preserve arrayOLE(0 To FileHeader.bfSize - 1) As Byte
1104
1105 If lngLenColorTable > 0 Then
1106 CopyMemory arrayOLE(Len(FileHeader) + Len(MyBitmapInfoHeader)), arrayOLE(18), 768 ' RGB TripletlngLenColorTable
1107 End If
1108
1109
1110 ' Now move the existing data back starting at the ColorTable
1111 ' if any and the Bitmap data.
1112 ' We can use CopyMemory as it is masquerading as RtlMoveMemory
1113 ' Copy ColorTable(if any)and move Bitmap data back 256 bytes to
1114 ' allow for the Bitmap file spec of 4 bytes per pixel(RGBQUAD)
1115 ' for each entry in the ColorTable.
1116
1117 ' * DWORD alignment issue. Bitmap data must be DWORD aligned. This simply
1118 ' means that each row of the Bitmap data must end on an address
1119 ' evenly divisable by 4. If it is not then you simply pad the row
1120 ' until it is. Since this is the MS published spec I just figured
1121 ' that MS Photo Editor would follow the spec. It does not.
1122 ' To get around this I will have to copy the data one row
1123 ' at a time from the OLE byte array.
1124
1125 Dim BPSLineNotAligned As Long
1126 BPSLineNotAligned = MyBitmapInfoHeader.biWidth * (MyBitmapInfoHeader.biBitCount / 8)
1127
1128
1129 ' Temp storage for copy of Bitmap data
1130 ReDim arrayB(0 To (MyBitmapInfoHeader.biHeight * BPSLineNotAligned) - 1)
1131
1132 CopyMemory arrayB(0), arrayOLE(822), (MyBitmapInfoHeader.biHeight * BPSLineNotAligned)
1133
1134 ' The offset to the start of the Byte RGB data from the start of the file.
1135 lOffSet = FileHeader.bfOffBits
1136
1137 ' Jan 5/2005 7:05 pm don't redim until after I copied arrayOLE to arrayB ********
1138 ReDim Preserve arrayOLE(0 To FileHeader.bfSize - 1) As Byte
1139
1140 ' For every row of Bitmap
1141 For x = 0 To Abs(MyBitmapInfoHeader.biHeight) - 1
1142 CopyMemory arrayOLE(lOffSet + (x * BytesPerScanLine)), _
1143 arrayB(UBound(arrayB) - ((x * BPSLineNotAligned) + BPSLineNotAligned - 1)), BPSLineNotAligned
1144 Next x
1145
1146
1147 ' Is there a Color Table?
1148 If lngLenColorTable <> 0 Then
1149
1150 Dim r As Byte
1151 Dim b As Byte
1152 Dim g As Byte
1153
1154 ' Need to fix RGB to BGR issue on RGB Triplet ColorTable data
1155 ReDim arrayB(0 To lngLenColorTable - 1)
1156 CopyMemory arrayB(0), arrayOLE(Len(FileHeader) + Len(MyBitmapInfoHeader)), 768
1157
1158 y = 0
1159 lOffSet = Len(FileHeader) + Len(MyBitmapInfoHeader)
1160
1161
1162 ' 2 Possiblities
1163 ' If ph.bmBitDepth = 2 then it's a normal Colortable
1164 ' If ph.bmBitDepth = 1 then it's a Greyscale Colortable
1165 ' which needs to be created
1166 If ph.bmBitDepth = 2 Then
1167
1168 For x = 0 To 768 - 4 Step 3 'Len(FileHeader) + Len(MyBitmapInfoHeader) To lngLenColorTable - 3 Step 3
1169 r = arrayB(x)
1170 g = arrayB(x + 1)
1171 b = arrayB(x + 2)
1172 arrayOLE(lOffSet + (y * 4)) = b
1173 arrayOLE(lOffSet + (y * 4) + 1) = g
1174 arrayOLE(lOffSet + (y * 4) + 2) = r
1175 arrayOLE(lOffSet + (y * 4) + 3) = 0
1176 y = y + 1
1177 Next x
1178
1179 Else
1180 For x = 0 To 255 Step 1 '768 - 4 Step 3 'Len(FileHeader) + Len(MyBitmapInfoHeader) To lngLenColorTable - 3 Step 3
1181 r = y 'arrayB(x)
1182 g = y 'arrayB(x + 1)
1183 b = y 'arrayB(x + 2)
1184 arrayOLE(lOffSet + (y * 4)) = b
1185 arrayOLE(lOffSet + (y * 4) + 1) = g
1186 arrayOLE(lOffSet + (y * 4) + 2) = r
1187 arrayOLE(lOffSet + (y * 4) + 3) = 0
1188 y = y + 1
1189 Next x
1190
1191
1192 End If
1193
1194
1195 End If
1196
1197
1198 ' Copy BitmapInfoHeader
1199 CopyMemory arrayOLE(Len(FileHeader)), MyBitmapInfoHeader, Len(MyBitmapInfoHeader)
1200
1201 ' Sat 6:17pm
1202 ' Change RGB triplet data to Quad RGB.
1203 ' put backin to see if we can handle both 8 bit and 24 bit
1204 If MyBitmapInfoHeader.biBitCount = 24 Then
1205
1206 Dim rquad As RGBQUAD
1207
1208 ' The Byte RGB data needs to be reversed to BGR
1209 lOffSet = FileHeader.bfOffBits
1210
1211 ' For every row of Bitmap
1212 For x = 0 To Abs(MyBitmapInfoHeader.biHeight) - 1
1213 ' For each pixel(triplet of RGB values)
1214 For y = 0 To MyBitmapInfoHeader.biWidth - 1
1215 With rquad
1216 .rgbBlue = arrayOLE(lOffSet + (y * 3))
1217 .rgbRed = arrayOLE((y * 3) + 2 + lOffSet)
1218
1219 ' Reverse B and R
1220 arrayOLE((y * 3) + lOffSet) = .rgbRed
1221 arrayOLE((y * 3) + 2 + lOffSet) = .rgbBlue
1222 End With
1223
1224 ' increment 3 bytes per pixel is built into the above logic
1225 Next y
1226
1227 ' increment bytes per row (3 bytes per pixel + padding to end up on DWORD alignment
1228 lOffSet = lOffSet + BytesPerScanLine
1229 Next x
1230
1231 End If
1232 ''''''''''''''''''''''''''''''''''''''''''
1233 ''''''''''''''''''''''''''''''''''''''''''
1234
1235 Case Else
1236 ' Unsupported Format
1237
1238 ''''''''''''''''''''''''''''''''''''''''''
1239 ''''''''''''''''''''''''''''''''''''''''''
1240
1241 End Select
1242
1243 ' Success
1244 fGetContentsStream = True
1245
1246
1247 EXIT_fGetContentsStream:
1248
1249 ' Add error handling
1250
1251 Exit Function
1252
1253 ERR_fGetContentsStream:
1254 MsgBox Err.Description, vbOKOnly, Err.Source & ":" & Err.Number
1255 fGetContentsStream = False
1256 Resume EXIT_fGetContentsStream
1257
1258 End Function

窗体代码如下:

  1 Option Compare Database
2 Option Explicit
3
4 Private Declare PtrSafe Function ShellExecuteA Lib "shell32.dll" _
5 (ByVal hwnd As Long, ByVal lpOperation As String, _
6 ByVal lpFile As String, ByVal lpParameters As String, _
7 ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
8
9 ' The following function will attempt to
10 ' extract and save the current OLE object to disk.
11 ' It will also launch whatever Application is currently
12 ' registered for this file type on your system.
13
14 Private Sub cmdSave_Click()
15 On Error GoTo Err_cmdSave_Click
16
17 Dim a() As Byte
18 Dim b() As Byte
19 Dim x As Long
20 Dim lTemp As Long
21 Dim sl As String
22 Dim blRet As Boolean
23 Dim sExt As String
24 Dim sFileExist As String
25
26 ' This is an optional param we pass to fGetContentsStream.
27 ' It will contain the original file name of the
28 ' object when embedded as a Package.
29 Dim PackageFileName As String
30
31 Dim iFileHandle As Integer
32
33 lTemp = LenB(Me.OLEPic.Value)
34 ReDim a(0 To lTemp - 1)
35 ReDim b(0 To lTemp - 1)
36
37 ' Copy the contents of the OLE field to our byte array
38 a = Me.OLEPic.Value
39
40 ' Make a copy of the original data
41 b = a
42
43 blRet = fGetContentsStream(a(), sExt, PackageFileName)
44 If blRet = True Then
45
46 If sExt = "pak" Then
47 ' If a file was dragged from the Explorer window
48 ' it will have a Package object Filename of NULL
49 ' inserted by Shell.DLL
50 ' Catch and give a temp file name
51 If Len(PackageFileName & vbNullString) < 3 Then
52 PackageFileName = "OLE-ExtractDraggedFromExplorer" & "." & "bmp"
53 End If
54
55 iFileHandle = FreeFile
56 sl = "H:\" & PackageFileName
57 sFileExist = Dir(sl)
58 If Len(sFileExist & vbNullString) > 0 Then
59 Kill sl
60 End If
61
62 Open sl For Binary Access Write As iFileHandle
63 Put iFileHandle, , a
64 Close iFileHandle
65 Else
66
67 iFileHandle = FreeFile
68 sl = "H:\" & sExt & UBound(a)
69 '& "." & sExt
70 sFileExist = Dir(sl)
71 If Len(sFileExist & vbNullString) > 0 Then
72 Kill sl
73 End If
74 Open sl For Binary Access Write As iFileHandle
75 Put iFileHandle, , a
76 Close iFileHandle
77 End If
78
79
80 Dim StartRegisteredApp As Boolean
81
82 'StartRegisteredApp = True
83 ' Do we open the exported OLE object in the
84 ' Application registered for this file type on this system?
85 If StartRegisteredApp = True Then
86 ' Some apps require vbNullString for the first parameter,
87 ' other apps require "open" for the first parameter
88 ShellExecuteA Application.hWndAccessApp, vbNullString, sl, vbNullString, vbNullString, 1
89 End If ' "open"
90 End If
91
92 ' Below is for debugging.
93
94 'iFileHandle = FreeFile
95 'sl = "C:\OLE-field-ALL" & ".dat"
96 'sFileExist = Dir(sl)
97 'If Len(sFileExist & vbNullString) > 0 Then
98 ' Kill sl
99 'End If
100 '
101 'Open sl For Binary Access Write As iFileHandle
102 'Put iFileHandle, , b
103 'Close iFileHandle
104 '
105 'iFileHandle = FreeFile
106 'sl = "C:\OLE-field-CONTENTS" & ".dat"
107 'sFileExist = Dir(sl)
108 'If Len(sFileExist & vbNullString) > 0 Then
109 ' Kill sl
110 'End If
111 '
112 'Open sl For Binary Access Write As iFileHandle
113 'Put iFileHandle, , a
114 'Close iFileHandle
115
116 Exit_cmdSave_Click:
117 ' Release structured storage library
118 Exit Sub
119
120 Err_cmdSave_Click:
121 MsgBox Err.Description
122 Resume Exit_cmdSave_Click
123
124 End Sub

类模块代码如下:

  1 Option Compare Database
2 Option Explicit
3
4
5 Private Type RECT
6 Left As Long
7 top As Long
8 right As Long
9 Bottom As Long
10 End Type
11
12 Private Type SIZEL
13 cx As Long
14 cy As Long
15 End Type
16
17 Private Type ENHMETAHEADER
18 iType As Long
19 nSize As Long
20 rclBounds As RECT
21 rclFrame As RECT
22 dSignature As Long
23 nVersion As Long
24 nBytes As Long
25 nRecords As Long
26 nHandles As Integer
27 sReserved As Integer
28 nDescription As Long
29 offDescription As Long
30 nPalEntries As Long
31 szlDevice As SIZEL
32 szlMillimeters As SIZEL
33 End Type
34
35
36 Private Type RGBQUAD
37 rgbBlue As Byte
38 rgbGreen As Byte
39 rgbRed As Byte
40 rgblReterved As Byte
41 End Type
42
43
44 'Private Enum ERGBCompression
45 Private Const BI_RGB = 0&
46 Private Const BI_RLE4 = 2&
47 Private Const BI_RLE8 = 1&
48 Private Const DIB_RGB_COLORS = 0 ' color table in RGBs
49 'End Enum
50
51
52 Private Type BITMAPINFOHEADER '40 bytes
53 biSize As Long
54 biWidth As Long
55 biHeight As Long
56 biPlanes As Integer
57 biBitCount As Integer
58 biCompression As Long 'ERGBCompression
59 biSizeImage As Long
60 biXPelsPerMeter As Long
61 biYPelsPerMeter As Long
62 biClrUsed As Long
63 biClrImportant As Long
64 End Type
65
66
67 Private Type BITMAPINFO
68 bmiHeader As BITMAPINFOHEADER
69 bmiColors As RGBQUAD
70 End Type
71
72
73 Private Type BITMAP
74 bmType As Long
75 bmWidth As Long
76 bmHeight As Long
77 bmWidthBytes As Long
78 bmPlanes As Integer
79 bmBitsPixel As Integer
80 bmBits As Long
81 End Type
82
83 Private Type DIBSECTION
84 dsBm As BITMAP
85 dsBmih As BITMAPINFOHEADER
86 dsBitfields(2) As Long
87 dshSection As Long
88 dsOffset As Long
89 End Type
90
91 Private Type METAFILEPICT
92 mm As Long
93 xExt As Long
94 yExt As Long
95 hMF As Long
96 End Type
97
98 ' From winuser.h
99 Private Const IMAGE_BITMAP = 0
100 Private Const IMAGE_ICON = 1
101 Private Const IMAGE_CURSOR = 2
102 Private Const IMAGE_ENHMETAFILE = 3
103
104 Private Const LR_DEFAULTCOLOR = &H0
105 Private Const LR_MONOCHROME = &H1
106 Private Const LR_COLOR = &H2
107 Private Const LR_COPYRETURNORG = &H4
108 Private Const LR_COPYDELETEORG = &H8
109 Private Const LR_LOADFROMFILE = &H10
110 Private Const LR_LOADTRANSPARENT = &H20
111 Private Const LR_DEFAULTSIZE = &H40
112 Private Const LR_VGACOLOR = &H80
113 Private Const LR_LOADMAP3DCOLORS = &H1000
114 Private Const LR_CREATEDIBSECTION = &H2000
115 Private Const LR_COPYFROMRESOURCE = &H4000
116 Private Const LR_SHARED = &H8000
117
118 Private Const vbSrcCopy = &HCC0020
119 Private Const SRCCOPY = &HCC0020 ' (DWORD) dest = source
120 Private Const WHITENESS = &HFF0062 ' (DWORD) dest = WHITE
121 Private Const BLACKNESS = &H42 ' (DWORD) dest = BLACK
122
123 ' Note - this is not the declare in the API viewer - modify lplpVoid to be
124 ' Byref so we get the pointer back:
125 Private Declare PtrSafe Function CreateDIBSection Lib "gdi32" (ByVal hdc As Long, pBitmapInfo As BITMAPINFO, ByVal un As Long, lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long
126 Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
127 Private Declare PtrSafe 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
128 Private Declare PtrSafe Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
129 Private Declare PtrSafe Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
130 Private Declare PtrSafe Function GetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBmp As Long, ByVal uStartScan As Long, ByVal cScanLines As Long, ByVal lpvBits As Long, ByRef lpbi As BITMAPINFO, ByVal uUsage As Long) As Long
131 Private Declare PtrSafe Function LoadImage Lib "user32" Alias "LoadImageA" (ByVal hInstance As Long, ByVal Name As Long, ByVal uType As Long, ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal fuLoad As Long) As Long
132 Private Declare PtrSafe Function apiGetObject Lib "gdi32" Alias "GetObjectA" _
133 (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
134 Private Declare PtrSafe Sub apiCopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
135 (Destination As Any, Source As Any, ByVal Length As Long)
136
137 Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
138
139 Private Declare PtrSafe Function apiGetDeviceCaps Lib "gdi32" _
140 Alias "GetDeviceCaps" (ByVal hdc As Long, ByVal nIndex As Long) As Long
141
142 ' Create an Information Context
143 Private Declare PtrSafe Function apiCreateIC Lib "gdi32" Alias "CreateICA" _
144 (ByVal lpDriverName As String, ByVal lpDeviceName As String, _
145 ByVal lpOutput As String, lpInitData As Any) As Long
146
147 Private Declare PtrSafe Function apiPlayEnhMetaFile Lib "gdi32" Alias "PlayEnhMetaFile" (ByVal hdc As Long, ByVal hEMF As Long, lpRect As RECT) As Long
148
149 'Private Declare PtrSafe Function SetWinMetaFileBits Lib "gdi32" _
150 '(ByVal cbBuffer As Long, lpbBuffer As Byte, _
151 'ByVal hdcRef As Long, lpmfp As METAFILEPICT) As Long
152
153 Private Declare PtrSafe Function SetWinMetaFileBits Lib "gdi32" (ByVal cbBuffer As Long, lpbBuffer As Byte, ByVal hdcRef As LongPtr, lpmfp As METAFILEPICT) As LongPtr
154
155
156 Private Declare PtrSafe Function apiDeleteEnhMetaFile Lib "gdi32" Alias "DeleteEnhMetaFile" _
157 (ByVal hEMF As Long) As Long
158
159 Private Declare PtrSafe Function apiCloseEnhMetaFile Lib "gdi32" Alias "CloseEnhMetaFile" _
160 (ByVal hdc As Long) As Long
161
162 Private Declare PtrSafe Function GetEnhMetaFileHeader Lib "gdi32" _
163 (ByVal hEMF As Long, ByVal cbBuffer As Long, lpemh As ENHMETAHEADER) As Long
164
165 Private Declare PtrSafe Function apiDeleteDC Lib "gdi32" _
166 Alias "DeleteDC" (ByVal hdc As Long) As Long
167
168 Private Declare PtrSafe Function apiCreateSolidBrush Lib "gdi32" Alias "CreateSolidBrush" _
169 (ByVal crColor As Long) As Long
170
171 Private Declare PtrSafe Function apiFillRect Lib "user32" Alias "FillRect" _
172 (ByVal hdc As Long, lpRect As RECT, ByVal hBrush As Long) As Long
173
174
175 ' Predefined Clipboard Formats
176 Private Const CF_TEXT = 1
177 Private Const CF_BITMAP = 2
178 Private Const CF_METAFILEPICT = 3
179 Private Const CF_SYLK = 4
180 Private Const CF_DIF = 5
181 Private Const CF_TIFF = 6
182 Private Const CF_OEMTEXT = 7
183 Private Const CF_DIB = 8
184 Private Const CF_PALETTE = 9
185 Private Const CF_PENDATA = 10
186 Private Const CF_RIFF = 11
187 Private Const CF_WAVE = 12
188 Private Const CF_UNICODETEXT = 13
189 Private Const CF_ENHMETAFILE = 14
190
191 ' Device Parameters for GetDeviceCaps()
192 Private Const LOGPIXELSX = 88 ' Logical pixels/inch in X
193 Private Const LOGPIXELSY = 90 ' Logical pixels/inch in Y
194
195 ' Handle to the current DIBSection:
196 Private m_hDib As Long
197 ' Handle to the old bitmap in the DC, for clear up:
198 Private m_hBmpOld As Long
199 ' Handle to the Device context holding the DIBSection:
200 Private m_hDC As Long
201 ' Address of memory pointing to the DIBSection's bits:
202 Private m_lPtr As Long
203 ' Type containing the Bitmap information:
204 Private m_bmi As BITMAPINFO
205 ' Holds current JPEG's FileName
206 Private m_CurrentJpegFileName As String
207 ' Array to hold original compressed Jpeg
208 ' to be used for BLOB storage in Table
209 Private bArray() As Byte
210
211 ' Temp var
212 Dim lngRet As Long
213
214
215
216 Public Function CreateDIB( _
217 ByVal lhdc As Long, _
218 ByVal lWidth As Long, _
219 ByVal lHeight As Long, _
220 ByVal lChannels As Long, _
221 ByRef hDib As Long _
222 ) As Boolean
223
224 With m_bmi.bmiHeader
225 .biSize = Len(m_bmi.bmiHeader)
226 .biWidth = lWidth
227 .biHeight = lHeight
228 .biPlanes = 1
229 If lChannels = 3 Then
230 .biBitCount = 24
231 Else
232 .biBitCount = 32
233 End If
234 .biCompression = BI_RGB
235 .biSizeImage = BytesPerScanLine * .biHeight
236 End With
237
238 'The m_lPtr is passed in byref.. so that it returns the the pointer to the bitmapinfo bits
239 'the m_lptr is then stored as a reference to the uncompressed image data
240 'the m_lptr is filled with image data when the ijlread method is invoked.
241 hDib = CreateDIBSection(lhdc, m_bmi, DIB_RGB_COLORS, m_lPtr, 0, 0)
242
243 CreateDIB = (hDib <> 0)
244
245 End Function
246
247
248 Public Function Create(ByVal lWidth As Long, ByVal lHeight As Long, Optional ByVal lChannels As Long = 3) As Boolean
249
250 CleanUp
251
252 m_hDC = CreateCompatibleDC(0)
253
254 If (m_hDC <> 0) Then
255 If (CreateDIB(m_hDC, lWidth, lHeight, lChannels, m_hDib)) Then
256 m_hBmpOld = SelectObject(m_hDC, m_hDib)
257 Create = True
258 Else
259 Call DeleteObject(m_hDC)
260 m_hDC = 0
261 End If
262 End If
263
264 End Function
265
266
267 Public Function Load(ByVal Name As String) As Boolean
268 Dim hBmp As Long
269 Dim pName As Long
270 Dim aName As String
271
272 Load = False
273
274 CleanUp
275
276 m_hDC = CreateCompatibleDC(0)
277 If m_hDC = 0 Then
278 Exit Function
279 End If
280
281 aName = StrConv(Name, vbFromUnicode)
282 pName = StrPtr(aName)
283
284 hBmp = LoadImage(0, pName, IMAGE_BITMAP, 0, 0, (LR_CREATEDIBSECTION Or LR_LOADFROMFILE))
285 If hBmp = 0 Then
286 Call DeleteObject(m_hDC)
287 m_hDC = 0
288 MsgBox "Can't load BMP image"
289 Exit Function
290 End If
291
292 m_bmi.bmiHeader.biSize = Len(m_bmi.bmiHeader)
293
294 ' get image sizes
295 Call GetDIBits(m_hDC, hBmp, 0, 0, 0, m_bmi, DIB_RGB_COLORS)
296
297 ' make 24 bpp dib section
298 m_bmi.bmiHeader.biBitCount = 24
299 m_bmi.bmiHeader.biCompression = BI_RGB
300 m_bmi.bmiHeader.biClrUsed = 0
301 m_bmi.bmiHeader.biClrImportant = 0
302
303 m_hDib = CreateDIBSection(m_hDC, m_bmi, DIB_RGB_COLORS, m_lPtr, 0, 0)
304 If m_hDib = 0 Then
305 Call DeleteObject(hBmp)
306 Call DeleteObject(m_hDC)
307 m_hDC = 0
308 Exit Function
309 End If
310
311 m_hBmpOld = SelectObject(m_hDC, m_hDib)
312
313 m_bmi.bmiHeader.biSize = Len(m_bmi.bmiHeader)
314
315 ' get image data in 24 bpp format (convert if need)
316 Call GetDIBits(m_hDC, hBmp, 0, m_bmi.bmiHeader.biHeight, m_lPtr, m_bmi, DIB_RGB_COLORS)
317
318 Call DeleteObject(hBmp)
319
320 Load = True
321
322 End Function
323
324
325 Public Property Get BytesPerScanLine() As Long
326 ' Scans must align on dword boundaries:
327 BytesPerScanLine = (m_bmi.bmiHeader.biWidth * (m_bmi.bmiHeader.biBitCount / 8) + 3) And &HFFFFFFFC
328 End Property
329
330
331 Public Property Get dib_width() As Long
332 dib_width = m_bmi.bmiHeader.biWidth
333 End Property
334
335
336 Public Property Get dib_height() As Long
337 dib_height = m_bmi.bmiHeader.biHeight
338 End Property
339
340
341 Public Property Get dib_channels() As Long
342 dib_channels = m_bmi.bmiHeader.biBitCount / 8
343 End Property
344
345 Public Property Get CurrentJpegFileName() As String
346 CurrentJpegFileName = m_CurrentJpegFileName
347 End Property
348
349 Public Sub PaintPicture( _
350 ByVal lhdc As Long, _
351 Optional ByVal lDestLeft As Long = 0, _
352 Optional ByVal lDestTop As Long = 0, _
353 Optional ByVal lDestWidth As Long = -1, _
354 Optional ByVal lDestHeight As Long = -1, _
355 Optional ByVal lSrcLeft As Long = 0, _
356 Optional ByVal lSrcTop As Long = 0, _
357 Optional ByVal eRop As Long) ' = vbSrcCopy)
358
359 If (lDestWidth < 0) Then lDestWidth = m_bmi.bmiHeader.biWidth
360 If (lDestHeight < 0) Then lDestHeight = m_bmi.bmiHeader.biHeight
361 Dim lngRet As Long
362 lngRet = BitBlt(lhdc, lDestLeft, lDestTop, lDestWidth, lDestHeight, m_hDC, lSrcLeft, lSrcTop, vbSrcCopy)
363 'lngRet = BitBlt(lhDC, lDestLeft, lDestTop, 640, 480, m_hDC, lSrcLeft, lSrcTop, vbSrcCopy)
364
365 End Sub
366
367 Public Function LoadJpegFileIntoArray() As Boolean
368
369 On Error GoTo Err_CmdLoad_Click
370
371 Dim blRet As Boolean
372
373 ' jpg_scale = 1
374 Dim strfName As String
375 strfName = Me.CurrentJpegFileName ' m_cDib.FileDialog 'c:\test2.jpg"
376 ' Read JPEG image
377
378 Dim lPtr As Long
379 Dim lSize As Long
380 Dim iFile As Integer
381 Dim sFile As String
382 'Dim bArray() As Byte
383
384 ' Copy the current Jpeg file data directly to the buffer
385 iFile = FreeFile
386 Open strfName For Binary Access Read Lock Write As #iFile
387 lSize = LOF(iFile)
388 ReDim bArray(0 To lSize - 1) As Byte
389 Get #iFile, , bArray()
390 Close #iFile
391
392
393 LoadJpegFileIntoArray = True
394 Exit_CmdLoad_Click:
395 Exit Function
396
397 Err_CmdLoad_Click:
398 LoadJpegFileIntoArray = False
399 MsgBox Err.Description
400 Resume Exit_CmdLoad_Click
401
402 End Function
403
404
405 Public Property Get JPegAsByteArray() As Variant
406 JPegAsByteArray = bArray
407
408 End Property
409
410 Public Property Get hdc() As Long
411 hdc = m_hDC
412 End Property
413
414
415 Public Property Get hDib() As Long
416 hDib = m_hDib
417 End Property
418
419
420 Public Property Get DIBSectionBitsPtr() As Long
421 DIBSectionBitsPtr = m_lPtr
422 End Property
423
424
425 Public Function DIBtoPictureData(ctl As Control)
426 Dim lngRet As Long
427 Dim ds As DIBSECTION
428
429 lngRet = apiGetObject(hDib, Len(ds), ds)
430
431 '.bfSize = Len(FileHeader) + Len(ds.dsBmih) + ds.dsBmih.biSizeImage
432
433 ' Update the Image Control display
434 ' We do this by simply copying the mBitmapAdd's contents to
435 ' the control's PictureData prop
436
437 Dim varTemp() As Byte
438 ReDim varTemp(ds.dsBmih.biSizeImage + 40)
439 apiCopyMemory varTemp(40), ByVal Me.DIBSectionBitsPtr, ds.dsBmih.biSizeImage
440 apiCopyMemory varTemp(0), ds.dsBmih, 40
441
442 ctl.PictureData = varTemp
443
444
445 End Function
446
447 Public Sub CleanUp()
448
449 If (m_hDC <> 0) Then
450 If (m_hDib <> 0) Then
451 Call SelectObject(m_hDC, m_hBmpOld)
452 Call DeleteObject(m_hDib)
453 End If
454 Call DeleteObject(m_hDC)
455 End If
456
457 m_hDC = 0
458 m_hDib = 0
459 m_hBmpOld = 0
460 m_lPtr = 0
461
462 m_bmi.bmiColors.rgbBlue = 0
463 m_bmi.bmiColors.rgbGreen = 0
464 m_bmi.bmiColors.rgbRed = 0
465 m_bmi.bmiColors.rgblReterved = 0
466 m_bmi.bmiHeader.biSize = Len(m_bmi.bmiHeader)
467 m_bmi.bmiHeader.biWidth = 0
468 m_bmi.bmiHeader.biHeight = 0
469 m_bmi.bmiHeader.biPlanes = 0
470 m_bmi.bmiHeader.biBitCount = 0
471 m_bmi.bmiHeader.biClrUsed = 0
472 m_bmi.bmiHeader.biClrImportant = 0
473 m_bmi.bmiHeader.biCompression = 0
474
475 End Sub
476
477
478 Private Sub Class_Terminate()
479 CleanUp
480 End Sub
481
482
483 Public Function FileDialog(LoadSave As Boolean) As String
484 ' Calls the API File Dialog Window
485 ' Returns full path to new File.
486 ' If LoadSave = TRUE then call File Load Dialog
487
488 On Error GoTo Err_fFileDialog
489
490 ' Call the File Common Dialog Window
491 Dim clsDialog As Object
492 Dim strTemp As String
493 Dim strfName As String
494
495 Set clsDialog = New clsCommonDialog
496
497 ' Fill in our structure
498 ' I'll leave in how to select Jpeg to
499 ' show you how to build the Filter
500 clsDialog.Filter = "JPEG (*.JPG)" & Chr$(0) & "*.JPG" & Chr$(0)
501 clsDialog.Filter = clsDialog.Filter & "Jpe (*.JPE)" & Chr$(0) & "*.JPE" & Chr$(0)
502 clsDialog.Filter = clsDialog.Filter & "Jpeg (*.JPEG)" & Chr$(0) & "*.JPEG" & Chr$(0)
503 clsDialog.Filter = clsDialog.Filter & "ALL (*.*)" & Chr$(0) & "*.*" & Chr$(0)
504
505 'clsDialog.Filter = clsDialog.Filter & "Gif (*.GIF)" & Chr$(0) & "*.GIF" & Chr$(0)
506
507
508 If LoadSave Then
509 ' Display the Open File Dialog
510 clsDialog.DialogTitle = "Please Select a JPEG File to Load"
511 clsDialog.ShowOpen
512 Else
513 clsDialog.DialogTitle = "Please Enter/Select a FileName to save the JPEG File"
514 clsDialog.ShowSave
515 End If
516
517 ' See if user clicked Cancel or even selected
518 ' the very same file already selected
519 strfName = clsDialog.FileName
520 If Len(strfName & vbNullString) = 0 Then
521 Set clsDialog = Nothing
522 Exit Function
523 '' Raise the exception
524 ' Err.Raise vbObjectError + 513, "clsPrintToFit.fFileDialog", _
525 ' "Please type in a Name for a New File"
526 End If
527
528 ' Return File Path and Name
529 FileDialog = strfName
530 ' Update our property
531 m_CurrentJpegFileName = strfName
532
533 Exit_fFileDialog:
534
535 Err.Clear
536 Set clsDialog = Nothing
537 Exit Function
538
539 Err_fFileDialog:
540 FileDialog = ""
541 m_CurrentJpegFileName = ""
542 MsgBox Err.Description, vbOKOnly, Err.Source & ":" & Err.Number
543 Resume Exit_fFileDialog
544
545 End Function
546
547
548
549 Public Function WMFtoBMP(bWMF() As Byte, mm As Long, xExt As Long, yExt As Long) As Boolean
550 Dim hEMF As LongPtr
551 Dim lngIC As Long
552
553 ' Instance of EMF Header structure
554 Dim mh As ENHMETAHEADER
555
556 ' Current Screen Resolution
557 Dim lngXdpi As Long
558 Dim lngYdpi As Long
559
560 ' Used to convert Metafile dimensions to pixels
561 Dim sngConvertX As Single
562 Dim sngConvertY As Single
563 Dim sngMetaResolutionX As Single
564 Dim sngMetaResolutionY As Single
565
566 Dim rc As RECT
567
568 Dim mfp As METAFILEPICT
569
570
571 ' Init our vars
572 CleanUp
573
574 ' Convert EMF byte array to memory EMF
575 With mfp
576 .hMF = 0
577 .mm = mm
578 .xExt = xExt
579 .yExt = yExt
580 End With
581
582 hEMF = SetWinMetaFileBits(UBound(bWMF) + 1, bWMF(0), 0&, mfp)
583 If hEMF = 0 Then
584 'Call DeleteObject(m_hDC)
585 'm_hDC = 0
586 WMFtoBMP = False
587 Exit Function
588 End If
589
590 ' Convert EMF size to pixels
591 '
592 lngRet = GetEnhMetaFileHeader(hEMF, Len(mh), mh)
593 If lngRet = 0 Then
594 WMFtoBMP = False
595 Exit Function
596 End If
597
598 With mh.rclFrame
599 ' The rclFrame member Specifies the dimensions,
600 ' in .01 millimeter units, of a rectangle that surrounds
601 ' the picture stored in the metafile.
602 ' I'll show this as seperate steps to aid in understanding
603 ' the conversion process.
604
605 ' Convert to MM
606 sngConvertX = (.right - .Left) * 0.01
607 sngConvertY = (.Bottom - .top) * 0.01
608 End With
609
610 ' Convert to CM
611 sngConvertX = sngConvertX * 0.1
612 sngConvertY = sngConvertY * 0.1
613 ' Convert to Inches
614 sngConvertX = sngConvertX / 2.54
615 sngConvertY = sngConvertY / 2.54
616
617
618 ' Get current Screen DPI
619 lngIC = apiCreateIC("DISPLAY", vbNullString, vbNullString, vbNullString)
620 'If the call to CreateIC didn't fail, then get the Screen X resolution.
621 If lngIC <> 0 Then
622 lngXdpi = apiGetDeviceCaps(lngIC, LOGPIXELSX)
623 lngYdpi = apiGetDeviceCaps(lngIC, LOGPIXELSY)
624 'Release the information context.
625 apiDeleteDC (lngIC)
626 Else
627 ' Something has gone wrong. Assume an average value.
628 lngXdpi = 120
629 lngYdpi = 120
630 End If
631
632 ' Convert the szlMillimeters to inches. This member
633 ' Specifies the resolution of the reference device, in millimeters.
634 ' Convert Inches to Pixels
635 'sngMetaResolutionX = (mh.szlMillimeters.cx * 0.01) / 2.54
636 sngMetaResolutionX = (mh.szlDevice.cx / ((mh.szlMillimeters.cx * 0.1) / 2.54))
637 sngMetaResolutionY = (mh.szlDevice.cy / ((mh.szlMillimeters.cy * 0.1) / 2.54))
638
639 Create CLng(sngConvertX * sngMetaResolutionX), CLng(sngConvertY * sngMetaResolutionY)
640
641 ' **********************
642 ' I have seen cases where the xExt and yExt values are not correct.
643 ' I may consider playing the MWF into an EMF DC so that
644 ' I could allow the GDI to determine the
645 ' actual extents of the Image. Next revision.
646
647
648 ' Case CF_ENHMETAFILE
649 ' If it is an Enhanced Metafile then we
650 ' Need to "PLAY" the Metafile
651 ' back into the Device COntext instead
652 ' of using the SelectObject API
653
654 rc.top = 0
655 rc.Left = 0
656 rc.Bottom = m_bmi.bmiHeader.biHeight
657 rc.right = m_bmi.bmiHeader.biWidth
658 lngRet = apiPlayEnhMetaFile(m_hDC, hEMF, rc)
659
660 ' Delete the EMF
661 lngRet = apiDeleteEnhMetaFile(hEMF)
662
663 ' Resize array
664 GetDIBBytes bWMF()
665
666 '// Success
667 WMFtoBMP = True
668 End Function
669
670
671
672 Public Function GetDIBBytes(bBytes() As Byte)
673 Dim lngRet As Long
674 Dim lSize As Long
675
676
677 lSize = m_bmi.bmiHeader.biSizeImage - 1
678 ReDim bBytes(0 To lSize) As Byte
679
680 apiCopyMemory bBytes(0), ByVal m_lPtr, m_bmi.bmiHeader.biSizeImage
681
682 End Function

可实现的功能如下:

点击保存后,可以将粘贴在OLE对象框内的图像保存在本地

access vba实现OLE对象保存到本地的更多相关文章

  1. iOS自己定义对象保存到本地文件

    我是将聊天记录存到本地,里边用到了自己定义的对象.把数据转成Data格式存到本地.在转Data格式的时候报错了.这时候须要先将自己定义对象进行归档才干够转Data格式. 方法例如以下: 一.在.h文件 ...

  2. 如何将Python对象保存在本地文件中?

    Python对象的永久存储 1.使用Python的pickle模块 import pickle class A: def __init__(self,name,a): self.name=name s ...

  3. C# 操作Access的Ole对象[转]

    原文链接 OLE对象数据类型 (1)OLE 对象用于使用 OLE 协议在其他程序中创建的 OLE 对象,如 Microsoft Word 文档. Microsoft Excel 电子表格.图片.声音或 ...

  4. Access OLE对象和附件的区别

    OLE 对象 来自 Office 和基于 Windows 的程序的图像.文档.图形和其他对象 最多可存储 2GB 数据(此大小限制适用于所有 Access 数据库).请记住,添加 2GB 数据会导致数 ...

  5. js实现字符串切割并转换成对象格式保存到本地

    // split() 将字符串按照指定的规则分割成字符串数组,并返回此数组(字符串转数组的方法) //分割字符串 var bStr = "www.baidu.con"; var a ...

  6. 如何把Excel中的单元格等对象保存成图片

    对于Excel中的很多对象,比如单元格(Cell),图形(shape),图表(chart)等等,有时需要将它们保存成一张图片.就像截图一样. 最近做一个Excel相关的项目,项目中遇到一个很变态的需求 ...

  7. JS截取页面,并保存到本地

    想截取浏览器上内容,并做成图片保存到本地. 可以使用html2canvas.js进行操作. <!DOCTYPE html> <html lang="en"> ...

  8. java后台中处理图片辅助类汇总(上传图片到服务器,从服务器下载图片保存到本地,缩放图片,copy图片,往图片添加水印图片或者文字,生成二维码,删除图片等)

    最近工作中处理小程序宝箱活动,需要java画海报,所以把这块都快百度遍了,记录一下处理的方法,百度博客上面也有不少坑! 获取本地图片路径: String bgPath = Thread.current ...

  9. C# 中从网络上下载文件保存到本地文件

    下面是C#中常用的从Internet上下载文件保存到本地的一些方法,没有太多的技巧. 1.通过  WebClient  类下载文件 WebClient webClient = new WebClien ...

  10. java 从服务器下载文件并保存到本地

    昨天在做一个项目时,用到了从服务器上下载文件并保存到本地的知识,以前也没有接触过,昨天搞了一天,这个小功能实现了,下面就简单的说一下实现过程: 1.基础知识          当我们想要下载网站上的某 ...

随机推荐

  1. Kali 配置Proxychains4

    Kali 配置Proxychains4 Proxychains4 是一款在 Linux 系统中广泛使用的代理工具,其全称为 ProxyChains.作为一款代理切换软件,Proxychains4 能够 ...

  2. Sdcb Chats 重磅更新:深度集成 DeepSeek-R1,思维链让 AI 更透明!

    Sdcb Chats 是一个强大且易于部署的 ChatGPT 前端,旨在帮助用户轻松接入和管理各种主流的大语言模型. Sdcb Chats 主要特性: 广泛的大模型支持: 已支持 15 种不同的大语言 ...

  3. Luogu P9646 SNCPC2019 Paper-cutting 题解 [ 紫 ] [ manacher ] [ 贪心 ] [ 哈希 ] [ BFS ]

    Paper-cutting:思维很好,但代码很构式的 manacher 题. 蒟蒻 2025 年切的第一道题,是个紫,并且基本独立想出的,特此纪念. 判断能否折叠 我们先考虑一部分能折叠需要满足什么条 ...

  4. AtCoder [ABC351E] Jump Distance Sum 题解 [ 绿 ] [ 数学 ]

    原题 场上差点就想出来了,就差一个旋转坐标轴了. 初步分析 首先来看如何判断两个点能不能走到,这可以看成下面的一张网格图,相同颜色的格子相互连通. 因此根据瞪眼法,可以把这些格子分为 $ (x_i + ...

  5. 【COM3D2Mod 制作教程(6)】实战!制作身体部分(下)

    [COM3D2Mod 制作教程(6)]实战!制作身体部分(下) 有了上一章制作帽子的经验,此时做头发很多就不必再重复赘述了,但如果用完全一样的流程和方法,把头发做好后直接装扮就会导致游戏报错,这就是我 ...

  6. C#长短链接服务器端WebApi作映射

    [HttpGet] public IHttpActionResult GetLongLink(string code) { if (string.IsNullOrWhiteSpace(code)) { ...

  7. 【文献阅读】 PVDF &阻尼&有限元建模

    1. 压电Damper原理 Piezoelectric Composite Materials - ScienceDirect 当振动传递到压电材料时,振动能量通过压电效应转化为电能,产生交流电压.所 ...

  8. pytest 框架使用规则

    使用pytest 注意 有时候常常会调用时文件未执行,就是没注意命名规范 如何调用-命令行调用 pytest 批量运行测试用例 单个用例调试成功后,接下来我们要进行所有脚本统一执行 我要执行testc ...

  9. (Python)用栈实现计算器的原理及实现

    前言 我们日常使用的计算器是怎么实现计算的呢?能自己判断运算符的优先级去计算,能处理括号的匹配,这些都是怎么实现的呢? 一个大家熟知的答案是用栈,好的,那么为什么要用栈?为什么栈能实现呢? 目录 前言 ...

  10. k8s:The connection to the server localhost:8080 was refused - did you specify the right host or port?

    前言 k8s 集群 node节点报错:The connection to the server localhost:8080 was refused - did you specify the rig ...