2020-04-12

VFP Paint Revisited - 2020


Here's a brand new version of VFPPAINT, a sample that I created using the GdiPlusX library that works much like MSPAINT, and creates a canvas that permits you to draw whatever you want with the mouse.

If you are not aware of what I'm talking about, you might be interested in checking this blog post..

VFPPAINT now has become much bigger than the original 50k SCX from the first version. Now it has become a VFP project, and received some important improvements, such as fast and reliable drawing, and the possibility to work with modal forms. many new and cool features were added too.

In this revamped version, I'm introducing the
   Paint Bucket - used to fill an area with single specific color. Select the bucket and position the cursor over the area to be filled and click with the Left mouse button to fill with the Primary color.

That's a cool feature that I introduced to GdiPlusX a long time ago, but forgot to document. I even think that the current release does not bring a sample dealing with it.





First of all, thanks for the positive feedback that many readers have sent, and all the suggestions.



Important requires VFP9 and GdiplusX to run.  
Please make sure that you have the latest version, because VFPPAINT uses some functions that were added recently.

http://www.codeplex.com/vfpx/wiki/view.aspx?title=gdiplusx&referringtitle=home


When you run VFPPAINT.scx it will ask you to select the folder where gdiplusx library is located.



What's new on this version:

1 - main screen may be modal, modeless, toplevel or inscreen - this was a problem in the first version. in that case, to obtain scrollbars in my canvas for the case that the image could not fit in the screen, I created a child form, that worked inside the main form. then the child form was configured to show scrollbars when needed. but working with this configuration, the main form had to be a toplevel form, and it was not possible to make that form modal.



Thanks to Carlos Alloatti and Malcolm Greene for their great "scrollablecontainer", I was able to use just a single control, and concentrate just on the drawing codes, I confess that it was a little bit complicated to control the form scrollbars and the image position in the original way. now this is all done by the scrollable container. Thanks very much Carlos for your support to make it work as I desired. Anyway, some tweaks were needed to be aplied in this control to make it behave exactly as I needed, and I created my customized version. Check the file SCONTAINERTWEAKS.TXT in the "source" folder.



2 - faster image drawing - I confess that the original version worked really sloooooow when direct drawing on the canvas. that's because vfp and gdiplusx has to work a lot in order to draw the image. After detecting the mouse position, cloning the original image for undo purposes, I used gdiplusx to obtain the pictureval of the bitmap, and then the image pictureval property was updated. obtaining the pictureval was the slowest operation. in this new version, I'm using gdi+ to draw du]irectly on the screen, using the hwnd of the form, when the left button of the mouse is pressed. only when the user releases the button or when he leaves the canvas surface is that the pictureval of the image object is updated, check it by yourself, this brought a huge performance gain !



3 - cut, copy and paste - these possibilities were added too. now you can select any portion of the image, cut or copy to the clipboard, and paste in any other application, or even inside vfppaint, moving pieces of images inside the canvas. it supports also that you paste any image from the clipboard. you can capture any screen using the prtscrn key and paste it there.



4 - drag and drop pieces of images. this brings the possibility to apply some effects in the whole image or just in the specified region.





5 - special color effects - there were lots of other cool things that I wanted to add, but no more space was available in the original form, so i've created a child form that agrupates some slidebars that will control the image colors, like: contrast, saturation, brightness, gamma, hue and adjusting each of the basic colors individually.





6 - other color effects - with just one click obtain monochrome, greyscale and invert the colors (negative)





7 - image transformations - another child form permits you to rotate the image by a desired angle, scale and shear vertically or horizontally.



8 - other tweaks, small fixes and optimizations. all methods were revised in order to enhance the performance and reliability.



Main features

- draw points, rectangles lines and ellipses with the mouse.

- text drawing, choose any font, size and style, and it will appear at the place that you click on the image. (drag and drop to choose the best place)

- choose any color, from the palette or directly from the loaded image or canvas and select the pen width that you want to draw.

- select the shape or type of drawing in the graphical option buttons, and then go to the canvas (image object) and click the left mouse button.

- drag and drop is available for rectangles, lines and ellipses.

- basic undo features

- rotate and flip images

- resizing images

- printing and saving images

- scale, shear and rotate images

- apply image effects, like greyscale, saturation, contrast, brightness, and more



Basic commands

    load image to canvas
    save image in desired image format
    print image
    undo last changes



  pick color from palette
   clear entire canvas with selected color
  rotate left (whole or selected image)
  rotate right (whole or selected image)
   flip image horizontally (whole or selected image)
  flip image vertically (whole or selected image)

   no action

   draw points

   draw rectangle

   draw ellipse

   draw line

   fill rectangle

   fill ellipse

   draw string

   select a piece of the image, to be cut, copied, dropped or receive an effect

   pick color from canvas

   select font, size and type


   convert to greyscale

   convert to monochrome

   convert to negative


   calls child form that enables different kinds of resizing






   calls child form that allows scaling, shearing and rotating the image




   calls child form that allows several color effects to the image

    



   send the selected piece of image to the clipboard
   copy the selected piece of image to the clipboard
   paste image from the clipboard to the canvas

   paste special, allowing to choose the destination of the image

   paint bucket is used to fill an area with single specific color. Select the bucket and position the cursor over the area to be filled and click with the Left mouse button to fill with the Primary color.


All images are generated without disk access, using the new pictureval property of the image control. For this specific case, I didn't use the imagecanvas that ships with gdiplusx because I needed some extra customization. after the latest release of gdiplusx, getting the pictureval property of an image has became very simplified, with the new methods added to the image class - getpictureval and getpicturevalfromhbitmap.

As sometimes we need to work with an image that is bigger than our screen, the drawing canvas was put in a "in toplevelform" that has scrollbars.

Another cool feature is the "undo" possibilities. vfppaint stores the previous bitmap in a cache. this can be improved too, maybe you need to "undo" in higher level. for this, very few code is needed.

When drawing on the canvas, try dragging and dropping the objects. for this, the "undo" feature was highly used, because the shape is drawn, and when the user moves the mouse, it restores the original image from the buffer and draws again in the new position.


When a big sized image is loaded, first it asks if the canvas needs to be resized.



Scrollbars appear in the image to help dealing with it. in a first moment, I thought of using the very nice ctl32 scrollable container from Carlos Aloatti and Malcolm Greene, but I gave up because I needed the pictureval property, that is present only in the default image control. So, there are currently 2 forms in the screenshot below. one is a "in TopLevel" form that contains just one image object, and resides in the main VFPPAINT form. the other form is a "TopLevel form". The image object from the "child form" changes its size automatically, depending on the image dimensions. When this object is resized, the child form automatically resizes itself, and shows and adjusts the scrollbars if needed.





Resizing sample:


VFPPAINT also accepts that you pass an image file as a parameter. this way, you'll be able to open the form loading automatically the desired image to edit. run the form like this:

do form vfppaint with "eyes.gif"

In case you pass a gif image as a parameter, it will be automatically converted to 24bpp. that's because gifs are indexed images. a classic example of indexed images are monochrome. pure monochrome images use only 1 bit per pixel. So, in just one byte you can store information of 8 pixels ! in the case of gifs, they are usually 8 bits per pixel, so in one bit we can have a value that ranges from 0 to 255 - that's exactly the quantity of colors supported by GIFs! Unfortunately, the redistributable version of GDI+ has a limitation when working with images created in indexed pixel formats, such as 1bppindexed (0x00030101), 4bppindexed (0x00030402) and 8bppindexed (0x00030803). If you try to draw on this kind of images you'll always receive an error message when you'll create the graphics object, that permits to you to draw on the image. more detailed info about this can be found in this post: drawing on gifs or indexed pixel format images with gdi+  http://weblogs.foxite.com/vfpimaging/archive/2006/03/18/1302.aspx . That's why gifs are converted to a 24bpp format before initializing the painting possibilities.

But the main thing is that this totally customizable. Study the technique that was used, and you'll see that there's not too much code there.




Download link
Download VFP PAINT REVISITED

17 comments:

  1. Just getting better Cesar? Great work, thanks

    ReplyDelete
  2. Cesar,

    From the captures I can see this is some unbelievable/fantastic job!!!  Congratulations!!!

    NOTE: The .ZIP/download is missing "System.PRG" thus the forms cannot be executed.
    Hi Kenneth,
    Thanks for the kind words!
    VFPPaint needs the GdiPlusX library to run. As I wrote in the post, you need to download it separately from the CodePlex VFPX website.
    Go to http://www.codeplex.com/VFPX/Wiki/View.aspx?title=GDIPlusX&referringTitle=Home then download the latest stable release of GdiPlusX. Unzip it. When you run VFPPaint, it will ask you to locate the file "System.prg" then, all you need to do is to point to the directory that contains the GdiPlusX files.
    I strongly recommend you to run the other samples for GdiPlusX, opening the "samples" folder, and runnning DEMO.PRG
    Hope this helps you to get started
    Regards
    Cesar

    ReplyDelete
  3. César Chalon,

    Parabens pelo VfpPaint, parece bem interessante.

    Um abraço
    Obrigado Rui ! Saudações !

    ReplyDelete
  4. Olá César...

    Que bom ter  'colegas' como vc no grupo foxbrasil. eheh
    Parabéns pela excelente ferramenta.

    Abraços.
    Obrigado Walber !

    ReplyDelete
  5. Cesar,


    This is simply astonishing work!  Tried the demo and was very impressed.  Thank you for the contribution to the VFP community!

    ReplyDelete
  6. Bonjour Cesar ,
    Impresionnant utilitaires surtout qu'on peux le lancer par  commande
    DO FORM vfppaint WITH "eyes.gif" pour l incorporer dans une applcvation VFP

    Merci Beucoup
    EL ABOUDI Ahmed,Casablanca Morocco

    Salut Ahmed,
    Merci Beaucup pour les mots aimables !

    ReplyDelete
  7. Hi Cesar,
        VFPPAINT app is cool. I will definitely integrate with my applications...I think its a must for graphic friendly and user friendly apps.

    I had a small question - Do i have to include your source files and  GDIPLUS source files in my project? Can u comment a bit on how to integrate it in my projects.

    Rgds
    Sanjay
    (Bangkok)

    Hi Sanjay,
    Yhanks for the kind words.
    Yes ! you need to include GdiPlusX files in your ptoject AND the files that I releases in the source for VFPPaint. Take care to do just one modification. In INIT() method, whene you have
    DO LOCFILE("System.prg")
    Please change to
    DO System.prg
    I hope to create an executable of VFPPaint in the future too, showing how you can add the GdiPlusX features needed, in order to save space. But this will be done not now, since GdiPlusX still needs to receive one last important update.
    Regards
    Cesar

    ReplyDelete
  8. Amazing what you've done with this. Great work.

    ReplyDelete
  9. Este artículo esta traducido al español en www.PortalFox.com en el siguiente enlace:


    -- VFP Paint Revisitado --

    http://www.portalfox.com/article.php?sid=2537



    ReplyDelete
  10. Hola Cesar,

    El proyecto VFP Paint, sale error cuando cargo images de tamaño grandes, por ejemplo de 2496 x 3440 pixeles este es un archivo .tif .

    Hay manera de cargar archivos de dimensiones grabndes?

    Gracias

    ReplyDelete
  11. Is there a way to locked down the Canvas so that it fits exactly on an 8 1/2 by 11 piece of paper? I'd like to use something like this to give a user the ability to create custom printable forms with their own images, etc. This tool looks like it would be perfect for the job.


    Thanks


    Ted

    ted@foxprosolutions.com

    ReplyDelete
  12. Hi..... i was working with VFP Paint (very very amazing tool), and made it some changes. I have a question? Is posible to save the file modified with the same name without show :
    1- File allrready exist
    2- Expecifing the path wher i want to save the file

    Very thanks for this great tool.....

    Hi Juan Pablo,
    Thanks for the kind words.
    For saving an image over an existing file, you need first to make sure the original file is not being used by GdiPlus. I suggest that for this case, you first make a copy of the original file, and make all the manipulations you need on it, and when you save it, save to the source file. After this, delete the temporary file.
    Another option that I imageine (not tested) is that you can load the original bitmap, then use the "Clone()" method to obatin an exact copy of the image, release the 1st object, and save the cloned image.
    Hope this helps!
    Saludos
    Cesar

    ReplyDelete
  13. Hi

    Is there any possibility to find out the real size of an image? I mean if i draw a line on the loaded image, how do I know the real size of the line, according to the image height, width and ppi ?


    Thanks

    ReplyDelete
  14. Hi Cesar

    I just download the application and i send you  some remarks/feedback:

    remarking is always most simple that coding...


    -add Free selection with mouse

    -I dont see the "gomme" and its zooms (4 differents areas in MSpaint)

    -add zooms 1x,2x,6x,8x)

    -Include the roundrect in drawing

    -Display before printing

    -see if the button print works well (i dont use the printer but it starts Snagit in my PC ??)

    -Add all attribute of picture(size,width,height,type,differents dates,...).

    -Use a contextuel menu on the area(edit,fliprotate,invert colors,...)

    -A help is needed on the menu

    -Scaling,resizing.....put textbox for value to input or to return with sliders.(small fonts)

    -The image must have 4 points to be resized manually with the mouse.


    -Why the form is modal ? use a level top form (2) ?


    -When i click on "selected region" and begin to select an area i obtain an error "member clondBMP unknown" (messagebox).


    Good luck and bravo for this work.

    ReplyDelete
  15. Hello Cesar:
    A fabulous tool! I have an app that is written in VFP6 that has image editing in it. I need to get this section of the app working in Windows 7. The current image editing will not work in Windows 7.
    Do you have an older version of VFPPaint that worked in VFP6? I realize some of the fabulous features may not work but I only need simple editing of adding lines and text to BMP and JPGs then be able to save the changes.
    Thanks for any help and thanks for making this work available to the FoxPro community!
    Best Regards,

    Jack Skelley
    Hi Jack,
    Unfortunately, VFPPaint works only on VFP9, preferrably SP2. To have it under previous versions, you would need to make a great effort, and use direct API calls or use GPIMAGE2.
    regards
    Cesar

    ReplyDelete
  16. when i run vfppaint in windows xp the image is shown but i try to run windows 7 the image  i selected is not showing. is there any files missing

    Rolando,
    Make sure to be using VFP9 SP2. There is a known problem with the Image object and Windows Seven. You have to install SP2.
    Hope that helps !

    ReplyDelete
  17. Hola Cesar, definitivamente tu aplicación esta super.
    He empezado a utilizarla en un pequeño proyecto de placas dentales

    Te escribo porque me he topado con un problema que llevo semanas en tratar de resolverlo pero no he encontrado nada que me ayude hasta el momento y como ultimo recurso pues he optado por escribirte ya que es obvio que pasas super ocupado.

    EL problema que tengo es que al abrir el VFPPaint desde otro formulario con esta instrucción:

    placa="c:\SICEX\TMP\"+SYS(2015)+".JPG"
    DO Form vfppaint WITH placa

    El VFPpaint lo muestra, pero al presionar cualquier botón ya sea para elegir un color o el lápiz y cualquier otro objeto, el VFP se queda pegado y mi aplicación no responde por un buen rato.
    Al cabo de unos dos minutos vuelve a responder pero en el VFP paint no se puede manipular la imagen.

    Me recomendaron registrar las dll de VFP pero no funciona
    Lo he probado en WinXp SP3, Win7 SP1 EN

    Tienes alguna idea de que pueda estar pasando?

    Quedare infinitamente agradecido si me sacas de este apuro

    Mil Gracias

    ReplyDelete