Click to See Complete Forum and Search --> : PictureBox control


MazdaBoi
June 15th, 2001, 04:07 PM
Is there a way to, instead of using the LoadPicture command as follows:

Dim Picdata As String
Picdata = DownloadFile("FILENAME.JPG")
WriteBinaryFile(Picdata, "C:\DRUM.JPG")
pctGeneralPicture.Picture = LoadPicture("C:\DRUM.JPG")

to instead set the picture from an actual string of characters?

This question derives from the following situation: I'm reading 'files' off of a form of one touch memory... The 'file data' gets read into strings...

I'd like to eliminate the need to write out temporary binary files that I make out of the 'string data'... Instead, I would like the picturebox control to directly load the image data out of the variable that I have stuffed it into...

So, instead of going out to a file on the hard drive, it would just grab the information out of a byte or string array...

Dim Picdata As String ' or byte or whatever
Picdata = DownloadFile("FILENAME.JPG")
pctGeneralPicture.Picture = Picdata

Currently I am doing it with a temporary file, but as I said, I'd like to eliminate the 'middleman' as it were, if possible...

Thanks,
Brad

cksiow
June 22nd, 2001, 09:06 PM
If you don't intended to know how I get this done. just copy &
paste the code to get the result. But at least, you should beware
two things :

1. vbFileIO.ReadFileStr is just a function to read the file into a
string variable, but in you case, you don't need this as you
already got in directly from the internet (I assume).

2. If you want to exit the program, call GlobalFree API to free the
hGlobal. if not, you might get memory leak.

Okay, if you intended to know how it work, here it is :

Generally the picture box .Picture is IPicture interface of COM. the
LoadPicture function actually create a IPicture and set the .Picture
to the newly created .Picture. It always assume that the data is
in the file. Because you already got the data, so you need to do
to it manual, i.e. emulate LoadPicture which take in String
variable rather than File.

The first step is to allocate the memory and lock it in heap as,
first, the string variable is local and will go off as soon as you
leave the load procedure, second the string variable might be
UNICODE, that's why the following loop convert the string
variable to byte array.

After converting to byte array, we then move the data into the
global heap that we just allocate using RtlMoveMemory.


okay, we already setup the stream data properly, next, we are
going to use the COM function OleLoadPicture to create a new
IPicture. But before that, because OleLoadPicture need to have
IStream as it first parameter. Thus, we use the COM function
CreateStreamOnHGlobal to create a pointer of IStream.


right after this, we can use OleLoadPicture to create a IPicture
object using the IStream that we just created. the iID_IPicture is
the CSLID of the IPicture Interface.

after OleLoadPicture, we get a newly created IPicture, then we
can se the Picture1.Picture to the newly created IPicture.

did you see that the IPic variable give you the size of the picture
as well ?

private Declare Sub RtlMoveMemory Lib "kernel32" (Des as Any, Src as Any, byval Length as Long)
private Declare Function GlobalAlloc Lib "kernel32" (byval wFlags as Long, byval dwBytes as Long) as Long
private Declare Function GlobalFree Lib "kernel32" (byval hMem as Long) as Long
private Declare Function GlobalLock Lib "kernel32" (byval hMem as Long) as Long
private Declare Function OleLoadPicture Lib "olepro32.dll" (byval pStream as Long, byval lSize as Long, byval fRunmode as Long, RefIID as fGUID, iPic as IPicture) as Long
private Declare Function CreateStreamOnHGlobal Lib "ole32.dll" (byval hGlobal as Long, byval fDeleteOnRelease as Long, ppStm as Long) as Long


private Type fGUID
Data1 as Long
Data2 as Integer
Data3 as Integer
Data4(7) as Byte
End Type

Dim vbFileIO as new vbFileIO

private Sub Form_Load()
Dim iID_IPicture as fGUID
Dim iPic as IPicture 'IPicture requires a reference to "Standard OLE Types"
Dim IStream as Long
Dim streamstr as string
Dim hGlobal as Long
Dim mPtr as Long
Dim streamb() as Byte
Dim i as Long

vbFileIO.ReadFileStr "d:\windows\system\oobe\images\bgdiscov.jpg", streamstr
Size = len(streamstr)
ReDim streamb(Size - 1)

hGlobal = GlobalAlloc(2&, Size)
mPtr = GlobalLock(hGlobal)

for i = 1 to len(streamstr)
streamb(i - 1) = Asc(mid(streamstr, i, 1))
next i

RtlMoveMemory byval mPtr, byval VarPtr(streamb(0)), Size

CreateStreamOnHGlobal hGlobal, 0&, IStream

With iID_IPicture
.Data1 = &H7BF80980
.Data2 = &HBF32
.Data3 = &H101A
.Data4(0) = &H8B
.Data4(1) = &HBB
.Data4(3) = &HAA
.Data4(5) = &H30
.Data4(6) = &HC
.Data4(7) = &HAB
End With

'Create Picture object
result = OleLoadPicture(IStream, Size, 0, iID_IPicture, iPic)

'Return the new Picture object
set Picture1.Picture = iPic


End Sub

HTH

cksiow
http://vblib.virtualave.net - share our codes

[Cimperiali colorized and indented code for better reading]

nikidd
February 7th, 2003, 05:29 AM
The code you added here is fantastic. I tested it and it is great! Thank you very much :)