Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Drag and drop an image but save it in a table field (have some code) 1

Status
Not open for further replies.

Steve-vfp9user

Programmer
Feb 5, 2013
335
GB
Hello all

Firstly, credit to Cetin Basoz who posted the following in the Microsoft Developer Network (Visual Foxpro General) back in 2009:

Code:
Public oForm
oForm = Createobject("sampleForm")
oForm.Show()

Define Class sampleForm As Form
  Height=320
  Width=320

  Add Object myImage As Image With ;
    Left = 10,Top=10,Height=300,Width=300,OLEDropMode=1,Stretch=1

  Procedure myImage.OLEDragOver
    Lparameters oDataObject, nEffect, nButton, nShift, nXCoord, nYCoord, nState

    If m.nState = 0 And oDataObject.GetFormat( 15 )
      This.OLEDropEffects = 5
      This.OLEDropHasData = 1
    Else
      This.OLEDropEffects = 0
      This.OLEDropHasData = 0
    Endif
  Endproc

  Procedure myImage.OLEDragDrop
    Lparameters oDataObject, nEffect, nButton, nShift, nXCoord, nYCoord
    If oDataObject.GetFormat( 15 )
      Local Array laData[1]
      oDataObject.GetData(15,@laData)
      This.Picture = laData[1]
    Endif
  Endproc
Enddefine

The above creates a form which allows me to drag an image from a Windows Folder and drop it on the form where it displays perfectly.

I would like to take this one step further by storing the image dropped onto the form in a table field. I am fully aware that images can quickly add up to the 2GB limit in tables but I will be able to sort out something for that.

So using the above, is there a way to store the dropped image to a field (any name will do e.g. photo, image etc?)

Appreciate any guidance.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Well, you have is a picture file name in laData[1] (nothing else works in the picture property.

So you could store that file into a blob or memo. FILETOSTR or APPEND MEMO should by now have crossed your way.

Chriss
 
Chriss

I added the line (in bold) as below which has stored the image (albeit as a set of letters and number etc, but I get that)

Code:
Procedure myImage.OLEDragDrop
  Lparameters oDataObject, nEffect, nButton, nShift, nXCoord, nYCoord
  If oDataObject.GetFormat( 15 )
    Local Array laData[1]
    oDataObject.GetData(15,@laData)
    This.Picture = laData[1]

    [b]APPEND MEMO PHOTO FROM laData[1][/b]

  Endif
Endproc

I can now work on displaying that image once called upon.

I appreciate your post.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Looking into the memo you won't see the image, yes. That's just binary data.
It would be displayed as hexadecimals when you used a Blob field instead.

And since you now have the file in the memo you could also change the use of Picture to Pictureval.

Code:
If oDataObject.GetFormat( 15 )
    Local Array laData[1]
    oDataObject.GetData(15,@laData)
 
    APPEND MEMO PHOTO FROM laData[1]
    This.PictureVal = Photo
Endif



Chriss
 
Chriss

You mentioned:

And since you now have the file in the memo you could also change the use of Picture to Pictureval.

I've not done anything like this before so I'm not sure what the difference is.

I found some examples of showing an image on a form but they refer to the actual file location e.g. \myfolder\mypics\photonumber5.jpg

I am just trying to show the saved file (as already achieved) in my test table IMAGES with a memo field called PHOTO and show it on a form. I have:

[ul]
[li]Created a form[/li]
[li]Added an image box (named image1)[/li]
[li]Added the table IMAGES to the form[/li]
[/ul]

Then:

Code:
USE IMAGES SHARED
GO 1
DO FORM displayphoto

But the photo from my memo field doesn't show. I have of course, created a record and you can see the hexadecimals in the memo field PHOTO.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Use PictureVal, not Picture.

Did you write this before reading my advice?

.Picture[highlight #FCE94F]Val[/highlight] instead of .Picture can be used to show the picture file as it is in a blob or memo. So the solution is already there.

Test it with this code:
Code:
CREATE CURSOR imagememo (photo Memo)
APPEND BLANK
APPEND MEMO Photo FROM "fox.bmp"

* It also works with a Blob field, which is better suited for the case

CREATE CURSOR imageblob (photo Blob)
APPEND BLANK
APPEND MEMO Photo FROM "fox.bmp"


WITH _Screen
   .AddObject('image1','image')
   .image1.PictureVal = imagememo.photo
   .Image1.visible=.t.

   .AddObject('image2','image')
   .image2.top = 50
   .image2.PictureVal = imageblob.photo
   .Image2.visible=.t.

   .AddObject('image3','image')
   .image3.top = 100
   .image3.Picture = HOME()+"fox.bmp"
   .Image3.visible=.t.
ENDWITH

Chriss
 
Chriss

You asked,

"Did you write this before reading my advice?"

I may well have but keeping in mind, I did say I have never had to do anything like this before so I would ask for your patience. I am aware you're an expert and I am just a novice.

I'm grateful for your post and I'll look into it in due course.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Ther's no anger in that question. I just thought you might have figured out what I said already. And then decided to give an example anyway.

Chriss
 
Chriss

Thank you for your last post and I would never suggest that was the case. All MVP's are very valued together with the guidance they give.

As a result of your posts, I have now resolved my question.

With showing an image stored in a memo field, this is how it was achieved for anyone interested:

[ul]
[li]The image is stored in a table called IMAGES with several fields including IMAGE (M)[/li]
[li]Having already "drag and dropped" this image as previously shown above, it is stored in that MEMO field[/li]
[li]I created a form called "displayphoto" and placed an image control on it[/li]
[li]Inside that form's INIT procedure I have the following:[/li]
[/ul]

Code:
LPARAMETERS mimagerecno
GO mimagerecno
thisform.image1.PictureVal = images.photo

In part of my coding, a variable is assigned for the RECNO() of that image I want to recall.

To do so To recall any image it's as simple as:

Code:
* Other code....

mimagerecno=RECNO()

USE IMAGES SHARED
GO mimagerecno

DO FORM displayphoto WITH mimagerecno

I have added other command buttons which allow "Next", "Previous" and "Exit" so if there are any other images linked to the master record, then they are shown too.

Huge thanks to Chris Miller for the posts and apologies if my post caused any offence (that was never the intention).

Best wishes and stay safe.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Steve, before we excuse ourselves over and over let me just say it's never an issue if someone doesn't know something and it may sometimes be a challenge to my patience, but I never get impatient if something doesn't oome through, I'm just questioning myself.

Your solution works, obviously, I just don't know if it's really in the spirit of how Foxpro works. If something works on the current record of a current workarea, all it should need passedin is what could be missiing to it, but it's not the record number. It would also not be the id or the alias or workarea, as that's a given. I would make the image field name the parameter of a form intended to show the current record image. And that could also have a navbar that works with the current alias.

That's maybe redefining your intention, but I want to make a point about the principles of encapsulation and of single responsibility.

If the client opens a workarea, why should the form position on the record when the caller knows which record should be displayed? By opening the images table you make this knowledge and responsibility encapsulated in the caller. Of course the called form has to work on this too, if you overexaggerate the encapsulation principle the form could only display an image when you pass the image itself to it, that's keeping access to the data in the caller.

You may have done a form with a private data session that uses the same table in its data environment (aka DE) and therefore needs to know either id or recno of the image to display. So your construction is fine for that case, but then the caller doesn't need to open the images table or position on the record. It jsut needs to know a record number. That might come from a list of image names or thumbnails a user ppicks from.

You see, my spider senses tickle, because you GO to the record in both caller and callee.

I also basically thought how the most general image display form could work. And that might actually need no parameters if it worked based on the principle of current record in current workarea. The knowledge which table contains images then is encapsulated in the caller and you could perfect this encapsulation by not passing the recno (that's obviously just the current recno) but pass in the name of the image field. That would be a more sensible parameterization of a general image display form.

Maybe you only have one image table so that's constant, still I would consider keeping that open for the future where you may have other tables with images, maybe also coming from external and not having the images in a field called image.

That suggests a form with default datasession (DataSession property set to 1) and such an init routine:
Code:
Lparameters cImageFieldname

thisform.image1.PictureVal = &cImageFieldname
plus a check assuring the field cImageFieldname exists.

Or you make a specific field name like photo a requirement and then simply do
Code:
thisform.image1.PictureVal = photo

In oth cases you should store ALIAS() or SELECT(), the alias name or workarea number of the current workarea in a form property so the form could ensure it navigates in that alais, even if the form also uses other tables and selects them in their workarea.

Private datasessions are a good thing in themselves, so I don't urge youto that, but even in that case, I'd not rely on a fixed data environment opening a specific iimages table and pass in the recno, I'd then pass in dbfname and fieldname and id or recno. Then use the form init and not the datasession to open that dbf and position on the initial record pointer that can then be moved with a navbar.

So my design choices would be all or nothing:

Nothing: Either the form needs to know nothing at all and relies on the "contract" to display the photo field of whatever data is open in the current workarea. Advantages include you can SET FILTER and the display form would only navigate the images of the filtereed records. You can set an order before calling the diaplay form and its navigation using SKIP +/-1 would not need to know about any of this.

All: Or the form needs to know everything: Which dbf, which field, which record to start with. This way the private datasession would need to start empty and you USE a table with file name or table name (of a dbc table) is passed in. To make use of the form DE to open anything isn't necessary at all. If you'd still like to use DE you could use a DE class and pass the DE clasname to the form so it knwos which DEClass to make its own DEClass property.

Chriss
 
Chriss

Thank you for your comprehensive post and I take on board your points.

I'm only doing this for myself and happy that the solutions already given have assisted me in my quest. There is a lot more to dear old VFP9 I'm sure!

Best wishes.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top