# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  [vb6]Alpha Image Control v2 - Final Update (15 Jan 2012)

## LaVolpe

*NOTICE :: NOTICE :: NOTICE*
Version 2 of the control came to an end. No new enhancements will be added to version 2. Bug fixes _may_ be applied as they are discovered. Support for version 2 will eventually cease.

Version 3 of the control will replace version 2 and will be DPI-aware. This will result in how images are loaded and displayed on a PC based on DPI settings (XP and above). In the case of icons/cursors, it may also result in which sized icon is displayed, based on current DPI settings. Externally, how you use this control will not change very much. Internally, a logical coordinate space will be used for all measurements and storage of properties, unlike the physical coordinate space now used. Like VB, this control will use twips internally. Externally to control users, pixels will still be used. DPI awareness will also be a customizable property. To properly support DPI-awareness,* binary compatibility will be broken*; hence a new version.
__________________________________________________________
15 Jan 2012. Minor patch applied. See change history below
----------------------------------------------------------

*Purpose*: A control that allows viewing & creating many image formats, particularly alpha-blended ones. 
This control is very similar in appearance and functionality to VB's Image Control. However, this control is super-sized. Requires GDI+ on the computer. Not a major issue nowadays. And GDI+ v1.0 can be redistributable if it doesn't exist. Advanced effects supported if system has GDI+ v1.1 installed (see posts #2 & 3 below).

*Image formats supported*: PNG (animated PNG too), TIFF (multi-page ones too), Icons, Cursors, Animated Cursors, JPEG, TGA, GIF (all frames), Bitmap, WMF, EMF, PCX, PBM, PGM, PPM, PAM, AVI, and those same formats contained inside MP3/WMA files, if they can be parsed out. 

*Image sources supported*: Files (unicode supported), arrays, stdPicture object, Clipboard object, Screen object (snapshots), OLE Drag/Drop Data object, this control's .Picture property, VB's LoadResData/LoadResPicture functions, bitmap/icon handles and URLs to images (unicode & async requests supported). Also can extract images from binaries such as exe, dll and ocx files. Supports loading images from strings containing Base64 encoding. Control can now be data-bound to a database table/field.
*See LoadPictureGDIp.rtf & SavePictureGDIp.rtf files included in zip*.

For more advanced users: special Pre & Post painting events allow you to modify the control's content during its rendering process. This literally allows the control to act as a blank canvas. Don't respond to those events & image renders as usual. Respond and you can change the background before image is rendered & even prevent image from rendering; you can also modify the control after the image is rendered but before it is displayed. Two of the sample projects use those events to show how powerful they are.

Unlike VB's image control, a few global methods are designed to allow you to draw directly to any DC you desire. TilePictureGDIplus will tile a source image and can fill a form very quickly. PaintPictureGDIplus will draw an image to any DC. The control, itself, has a method to draw itself to another DC also: PaintControlAsDrawnToHDC. Additionally, there are methods that can be used for non-drawing: the UnicodeFileDialog class can be used from your project; giving you a unicode-aware common dialog substitute. The global ConvertRGBtoARGB & ConvertARGBtoRGB methods are useful conversion utilities that also accept VB system colors (i.e., vbButtonFace). The global GetScaledContainerSize & GetScaledImageSize methods are useful for scaling a container to image or vice versa. As long as the global GDIplusTokenExists method returns true, you never have to create your own GDI+ startup/shutdown routines; the GDIplusTokenVersion method lets you know which version of GDI+ is running

*** Control performance is degraded while uncompiled*. *When compiled*, you will experience far better performance

Recommend you open the AICGlobals class and read the detailed comments for usage of the main functions. You can get more information about the control's properties, methods and events by reading the code or using your Object Browser (F2). 
See next post for a summary of the properties, methods, and classes this control exposes.

To add an image during design time, simply add a control to the form, right click on it, and select Properties. 
You can also double click on the "Custom" property sheet item.

*Look closely at the screenshot below. 
See toucan's shadow over the playing card? See the grid dots in the shadows? 
That's alpha-blending at work!!!
*


*Following is history of most recent changes. The control itself has complete change history included*
Any changes to the control may have spawned updates to 1 or more sample projects.


```
15 Jan 2012, version 2.1.32: Final update barring bugs
- UnicodeBrowseFolders class can now be created/called from within your projects
- Property page could return 32 & 48 sized associated icons in PNG format & shouldn't. Fixed
8 Jan 2012, v2.1.31
- property page for dragged/pasted files now coded to have them relate to associated icons, as appropriate
7 Jan 2012, v2.1.30
- can load icons associated with file system objects
- modified property page for associated icon selection
- added ASSOCIATEDICON structure, SHILIconSizeEnum & AssocIconTypeEnum enumerations
- added UnicodeBrowseFolders global class
- updated LoadPictureGdip & SavePictureGDIp RTF files
- fixes a logic error where control may not resize while it is hidden
- fixes issue where app may create metafile of text copied to clipboard & control loads that metafile instead of using the text to load an image
26 Nov 2011, v2.1.29
- Error converting black/white icons/cursors when loaded by handle. Fixed
16 Nov v2.1.28
- Allows saving unmodified AVI to other destinations (i.e., file, array, etc) 
- Found & fixed several minor bugs
  -- cFunctionsICO.HICONtoArray custom header changes prevented loading icons by handle
  -- cFunctionsPNM.LoadPNMResource invalid flag setting could invert PBM formats
  -- cFunctionsPNM.pvBuildPNM saved invalid token when writing 32 bpp alpha PAM formats
  -- cFunctionsTGA.SaveAsTGA could save image upside down
  -- cFunctionsPCX.SaveAsPCX could save image upside down
- Property page did not offer AVI as an image source
7 Nov v2.1.27
- test code from a few versions ago remained by mistake. Could crash project. Fixed
6 Nov v2.1.26
- error in MP3 tag parsing routine could occur with tags of less than 30 bytes. Fixed
3 Nov v2.1.25
- added WMA files as an image source
- enabled control to be bound to a database table/field. See LoadPictureGDIp.RTF for more
- added UpdateDataboundImage event to allow changing what will be saved before image written to database (databound control)
- rewrote the MP3 parsing logic; more robust & should properly handle v2,3,4 ID3 tags + unsynchronized tags
```

*For the 8 sample projects provided...*
1) Open the uncompiled alpha image project first (contained in the AlphaImgControl.zip file)
2) From the IDE menu: File | Add Project
3) Navigate to & select a sample project
4) Right click on it in the project explorer (treeview) & select: Set as Start Up
Now run the sample project. When done playing, remove the sample project, navigate to one of the others & run it.
Ensure you change the start-up project. You do not want the attached image control as the start-up project.

You will really like the "custom buttons" project. Shows how flexible this control really is.
Note: Sometimes I occasionally get an error when trying to load a sample project. This almost always happens after I've modified the uncompiled alpha image control. If that happens to you, simply close the sample project without saving changes, close the alpha image control project. Now try again.

*Tips*
1. Extract both zips, into same parent folder, using the "Use Folder Names" option
2. When recompiling this control over an existing, compiled, version always opt for Binary Compatibility from the project properties window, on the Component tab. See this thread for a bit more information on binary compatibility.  Binary compatibility if used allows already compiled/distributed apps using the control to continue using a newer version when it is distributed. I will make every effort in future revisions to maintain binary compatibility.

----------


## LaVolpe

Note that the control is basically a GUI wrapper of the GDIpImage class.

*The following is a summary of control properties/methods:*
:: listing replaced by the ControlProps.rtf file included with the project's zip file in post #1

*The following are custom events fired from the control:*
:: listing replaced by the ControlProps.rtf file included with the project's zip file in post #1

*The following are global functions that are not specific to any control:*
AsyncAbortDownloads: Aborts all active and/or queued async download requests
AsyncDownloadsEnabled: Returns whether async downloads can be performed
AsyncGetDownloadStates: Returns how many async requests  are in progress, waiting on replies, and/or queued
AVIEnabled: Property returns true if AVIs can be read (i.e., expected DLLs loaded)
CF_AlphaImageCtl: Returns the custom clipboard format used by this control.
ConvertBGRAtoRGB: Returns RGB format from GDI+ color format
ConvertRGBtoBGRA: Returns color format used by most GDI+ functions
GDIplusTokenExists: Returns whether GDI+ successfully loaded or not
GDIplusTokenVersion: Returns the GDI+ version loaded. v1.1 enables advanced effects
GetPixelGDIplus: Returns RGB color from a point within the image
GetScaledContainerSize: Returns container size needed to display scaled image at any rotation
GetScaledImageSize: Scales dimensions to another allowing consideration for rotation
LoadPictureGDIplus: Loads most image formats into a GDIpImage class
MergePictureGDIplus: Combines/overlays two or more images
PaintPictureGDIplus: Renders an image to any DC using various rendering styles
SavePictureGDIplus: Saves an image to a variety of destinations/formats using various rendering styles
SetPixelGDIplus:  Sets a point within the image to a user-defined color
TilePictureGDIplus:  Tiles an image to any DC or to a new GDIpImage class

*Objects you can create and use dynamically:*

UnicodeBrowseFolders Class: A unicode-aware "browse for folder" dialog class you can use from within your code.

UnicodeFileDialog Class: A unicode-aware Open/Save dialog class you can use from within your code.

GDIpEffects Class: A class used to create GDI+ image attributes and v1.1 effects 
--- Class has its own functions/properties to enable these attributes/effects
:: Image Attributes created with: GrayScale, GlobalTransparencyPct, LightnessPct, BlendColor, BlendPct, TransparentColor & TransparentColorUsed properties
:: Functions provided to create effects: Blur, HueSaturationLightness, Sharpen, BrightnessContrast, ColorBalance, ColorCurve, Tint, ToneLevel, & RedEyeCorrection properties (requires GDI+ v1.1)

GDIpImage Class: A class assigned to a control. Can also be created and used dynamically, just like a VB stdPicture object
--- Class has its own functions that allow some customizing...
AlphaMask: Gets/Sets the alpha values of an image
AnimationLoops: Returns number of loops from a loaded animated GIF/PNG resource, if provided by that resource
AsyncDownloadDone: Event that occurs when async download successful or fails
AsyncDownloadStatus: Property that returns whether download successful, failed, in progress
AsyncDownloadURL: Property returns URL passed to async download request. URL available until the ASyncDownloadDone event exits.
BitDepth: Returns the bit depth used by the image class. Optional Index parameter allows checking on other frames
ExtractImageData: Extracts image data to a byte array
FrameDuration: Returns the frame duration. Optional Index parameter allows checking on other frames.
Handle. Returns the GDI+ handle created from the loaded image
Height: Returns the image/segmented height in pixels. Optional Index parameter allows checking on other frames
ImageCount: Returns the number of frames loaded for this image
ImageFormat: Returns the image format (ImageFormatEnum value)
ImageGroup: Returns/sets the current Image group (Win7+ animated cursors)
ImageGroups: Returns the number of image groups for the loaded image
ImageGroupFormat: Returns the format of an Image Group. Binaries can have 3 different groups each their own format (bmp, ico, cur)
ImageIndex: Returns/sets the current image frame index
KeepOriginalFormat: Returns if original source data cached with the image or releases that data
Left: Returns the image's Left position. Useful for Segmented images, else will be zero
RegionFromImage: Returns a region containing just opaque pixels of the current image
Render: Draws the image to any hDC, using optional rendering styles and user-defined GDI+ objects
RenderSkewed: Draws the image to any hDC, using optional rendering styles and user-defined GDI+ objects. Rendered image is a parallelogram similar to GDI's PlgBlt API
SegmentImage: Removes/creates tiles within an image, offering more options than the AlphaImgCtl's related function
Segmented: Returns whether the loaded image has been segmented or not
Top: Returns the image's Top position. Useful for Segmented images, else will be zero
UsesTransparency: Returns whether current image frame contains transparency or not
Width: Returns the image/segmented width in pixels. Optional Index parameter allows checking on other frames

Note that this class is the control's Picture property. 
You have access to its properties and methods by referencing it.
Example:   MsgBox "Uses the Alpha Channel?: " & AlphaImgCtl2.Picture.UsesTransparency

----------


## LaVolpe

*Tips and comments regarding usage*

*MEMORY LEAKS!!!*
When control is *not compiled*, you can experience memory leaks and even random GDI+ crashes.
This can/will happen when you run your project, using the uncompiled control, and do not close your project normally. Whenever you hit END either as a result of a Debug message box option, clicking the blue square 'stop' toolbar button or actually executing an End statement in code, you are abnormally terminating your application. This results in the uncompiled control not having its class/usercontrol Terminate events triggered by VB. And guess where the clean up code is, it's in the Terminate events. This problem does not exist when the control is compiled.

*Scale Mode*
This control, like GDI and GDI+, requires dimensions and offsets in pixels not twips. Failiing to provide pixel sizes to the control can end up with unexpected results. For example, trying to call TilePictureGDIplus on a full-screen form and passing Me.ScaleWidth while form's scale mode is twips attempts to create a tiled image of ScreenSize*15 (1 twip ~ 15 pixels). This will most likely fail. Same issue if you are using the width/height of the AlphaImgCtrl. The dimensions of any control are in the scale mode of the control's container. Suggestion: Either ensure the control's container scale mode is pixels or use ScaleX,ScaleY to convert that scale mode to pixels. 
Tip: VB Frames do not have scalemode properties & the scalemode is always Twips. You will have to use ScaleX,ScaleY to convert a frame-contained control's dimensions to pixels.

*v1.1 of the GDI+ library*
Vista+ only. If you want to play with v1.1 of GDI+, this is how I managed it. This thread, reply #53, contains information on how to ensure v1.1 is used with your compiled application. The manifest can also be placed alongside your vb6.exe if named vb6.exe.manifest and v1.1 will be available during design time too. Note about the vb6.exe.manifest: if you have multi-boot system and XP & Vista installed VB6 to the same folder, that manifest will prevent VB from loading when you boot to XP. Simply rename the file

During runtime you can query the version loaded with GDIplusTokenVersion. During design-time, bring up the property pages of any alpha image control and click on the 2nd property page. If the Create command button is enabled, v1.1 is loaded.

*Sharing Images*
During run-time, you may want 2 or more controls to display the same image. By sharing images, you reduce resources since only 1 copy of the image data and only 1 GDI+ image handle is created, no matter how many controls are sharing that image.
To Share:  Set AlphaImgCtl2.Picture = AlphaImgCtl1.Picture
Applies to BkgImage property too: Set AlphaImgCtl2.BkgImage = AlphaImgCtl1.BkgImage

During design-time, if 2 or more controls will display same image, set the image in just 1 control. During run-time share the image, during Form_Load, as just mentioned. Each image assigned at design-time will be stored by _each_ control. Why store the same image multiple times?
When sharing. Some things effect all controls that share the image and these are:
-- Animating one, animates all controls sharing that image
-- If image contains multiple images (icon, cursor, gif, tiff), changing index or group changes all controls
-- If segmenting image, all controls show segmented image

*Animation*
Obviously animation means your image will change quite often, sometimes several times per second. 
There are some actions I would recommend against while animating.
- Don't use FastRedraw. Each time image frame changes, image drawn to offscreen DC first, then to DC. Waste of resources/time IMO
- Don't use HitTest type of lvicTrimmedImage. To determine trimming, image pixels must be pre-processed. Waste of time
- Don't use HitTest type of lvicRunTimeRegion. Whatever region you supplied may not align with new frame's image
- Avoid using AutoSize if not necessary. Each frame requires the control to be re-examined for possible resizing
- Avoid overlapping any control with the animating control. See performance below.
- If tracking MouseEnter/Exit, they can trigger if frame changes while cursor over image as hit test is adjusted for new image
- Don't separately animate 2 or more controls sharing the same image. You can create a race-condition and animation frames may skip. This is because shared images animate in their shared controls. While one control is changing frames, the shared controls also may be trying to change frames. Animating one, animates all shared controls. See 'Sharing Images' above.

*Memory Usage*
-- Avoid using KeepOriginalFormat when loading images during runtime. This is a parameter in LoadPictureGDIplus
By using that property, original image data is cached. For most cases I would think this is unnecessary. During design-time, all images are loaded with this property set to true so data can be saved in the control's property bag. Knowing this, and if you have no reason to ever extract the original data during runtime, you may wish to purge it during form load. To do so... AlphaImgCtl2.Picture.KeepOriginalFormat = False
-- Setting KeepOriginalFormat=False still allows you to extract image data, but the format will always be PNG except for bitmaps. Format will be bitmap. This also applies to the BkgImage property
-- The picture returned as a result of SavePictureGDIplus & MergePictureGDIplus default KeepOriginalFormat to True. You may want to reset that property after the image has been returned.
-- Share images when possible. See notes above
-- FastRedraw is nice to use/abuse, but only recommend using it for very large controls ( > 256x256) when special rendering is used: rotation, blending, etc, etc. On images < 256x256, rendering is generally very quick, regardless of special rendering used. When used, FastRedraw creates and maintains a separate DC and bitmap.
-- If your TIFF, GIF, PNG, icon or cursor has multiple images (ImageCount>1) and you are only ever going to display one. Setting KeepOriginalFormat=False will not only purge the original cached data (if any), but will also convert to single frame image. Just set the ImageIndex to the one you want to use before setting KeepOriginalFormat to False.
-- Setting WantPrePostEvents creates and maintains a separate DC and bitmap. If FastRedraw is also True, just one DC but 2 bitmaps are created.
-- Set WantMouseEvents to false unless needed. This property determines if mouse up/down/move/enter/exit events are trapped. Mouse Enter/Exit events cause creation/destruction of timers and extra system messages. You will still get click & double click events unless the control is disabled

*Performance*
- Compile the control. The control was designed to be a separate ocx, not to be merged inside a larger project.
- Actual-size image rendering is fastest because no scaling is required
- Avoid special rendering styles (grayscaling, blending, transparency, mirroring, rotation, v1.1 effects, etc)
- If you are going to use a large image always scaled at a specific size and never changed thereafter then 
a) Scale it in advance, save image to disk, and then supply that modified image instead
b) During runtime, create a copy of the image scaled along with any special rendering styles & use it: SavePictureGDIplus function
- If free-wheeling with scaling & rendering styles, consider using FastDraw property to speed up rendering. But see notes above regarding Animation
- Avoid overlapping images when possible. Each image control that needs to be repainted, causes a domino effect with all overlapping image controls both above & below it in the ZOrder. This is true for all window-less controls: label, image, line & shape controls also.

*Technical Support*
- I will make changes to include bug fixes and future enhancements for some time to come 
- I will not offer support to those that have customized my code for their use. If you tweak it, you fix it 
- I will not offer suggestions on how to modify the code for personal customization. I will consider enhancement requests
- I may offer suggestions for coding an outside routine that uses the control
- Any enhancements may result in the control breaking binary compatibility with previous versions of the control
- Know that the control exposes everything about the image, including the handle, effects and attributes it uses. Any enhancement I may decliine to include can be created from outside the control and implemented during Pre-Post render events. Additionally, if you can draw it to a DIB, you can load it into the control. So, you want to include an image format that isn't supported? Build a parsing routine and draw that format to a DIB, use LoadPictureGDIplus to load that DIB into the control. Want to include some filter like embossing? Get the pixels via the image handle, manipulate the pixels to another DIB, load that DIB into the control.

*Known Bugs*
- GDI+: 1 bpp PNGs may not render correctly
- There are several other GDI+ related bugs that are handled, overridden and processed manually vs. via GDI+
- GDI+: Not a bug. Some meta files will fail to load if GDI+ detects malicious code within the source
- VB: When the control is added to a container that has AutoRedraw=True and the container is custom painted by you (i.e., gradients) a black line may appear at top of the container. See posts 35 & 36 below for a description & workaround.
- VB: Whenever icons are loaded from a .Picture property or a stdPicture object, the control will report them as cursors. The GetIconInfo API is used to retrieve the icon from the handle provided by VB. That API seems to always return those handles as cursors vs. icons
- VB: Modal windows (MsgBox, InputBox, CommonDialog, etc) can negatively affect the control while control is uncompiled. These  include failed/incomplete rendering and missed events

----------


## petersen

GDI+ used to have a bug concerning 1-BPP image: 

-- If one passes a 1-BPP ColorType=0 PNG, with say blue color background or colored chessboard background, the resulting image would have ghost lines.

-- If one calls "GdipImageRotateFlip hImg, 6" on a 1-BPP image, the resulting image might have a thick black edge on the right side

You mentioned that "Now enables v1.1 GDI+ Effects (file version is 6.x)"; I wonder if the bug is still there with the new version?  Just curious.

----------


## Jordan

It's great to see this project rise from the ashes again. How different is this from the 2007 version?

Bugwise, nothing to report, though I have not run through it thoroughly yet.

I was just thinking up an imaginary control today where Alpha Image would play a key role. What I have in mind is a thumbnail image scroller with image fade-in and out on the edges, so as you scroll through the image list, a gradient transparency passes through the incoming and outgoing images.

This would require a feature that would provide variable transparency across an image, and markers that would indicate where transparency began and where it would end. For example, say an image was half way into the thumbnail scroller and the transparency gradient window is 20&#37; of the image. The transparency would begin at the 30% mark, and would fade into wholly transparent at the 50% mark.

Just a thought. Great work as always.

----------


## LaVolpe

> It's great to see this project rise from the ashes again. How different is this from the 2007 version? ...


Difference in this version is: written better, more flexible, more options, gets past more GDI+ "bugs"

Regarding your fading routine. This isn't exactly what you want, but I'm sure you can adapt it.
1) Add a picturebox to your form, set picbox ScaleMode to pixels
2) Add an AlphaImageCtl to the picturebox, place a picture in it 
3) Change AutoSize = lvicSingleAngle. Adjust control size now so it is completely visible in picturebox
4) Change picturebox's backcolor to any color you want or leave as is
5) Copy and paste this code. I've included the API declarations should you not have ready access to them


```
' declarations
Private Declare Function GdipCreateLineBrushFromRect Lib "gdiplus" (ByRef pRect As RECTF, ByVal Color1 As Long, ByVal Color2 As Long, ByVal Mode As Long, ByVal WrapMode As Long, ByRef lineGradient As Long) As Long
Private Declare Function GdipFillRectangle Lib "gdiplus" (ByVal graphics As Long, ByVal brush As Long, ByVal X As Single, ByVal Y As Single, ByVal nWidth As Single, ByVal nHeight As Single) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, hGraphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long
Private Declare Function GdipDeleteBrush Lib "GdiPlus.dll" (ByVal mBrush As Long) As Long
Private Type RECTF
    Left As Single
    Top As Single
    Width As Single
    Height As Single
End Type

Private Sub Form_Load()
      Me.ScaleMode = vbPixels
      AlphaImgCtl1.WantPrePostEvents = True
      ' don't set this during design-time. Newly discovered bug, I have to patch it this weekend
      ' Fixed bug in 30 Oct update. Can set this during design time if desired
End Sub
Private Sub AlphaImgCtl1_PostPaint(hDC As Long, Left As Long, Top As Long, Width As Long, Height As Long, HitTestRgn As Long)
    Dim hBrush As Long, size As RECTF, hGraphics As Long
    size.Width = AlphaImgCtl1.Width
    size.Height = AlphaImgCtl1.Height
    If GdipCreateFromHDC(hDC, hGraphics) = 0 Then
        If GdipCreateLineBrushFromRect(size, ConvertRGBtoBGRA(Picture1.BackColor, 0), ConvertRGBtoBGRA(Picture1.BackColor), 0, 0, hBrush) = 0 Then
            GdipFillRectangle hGraphics, hBrush, size.Left, size.Top, size.Width, size.Height
            GdipDeleteBrush hBrush
        End If
        GdipDeleteGraphics hGraphics
    End If
End Sub
```

Edited: FYI... The gradient fade is done overlaying a rectangle, that is filled with a gradient brush from (Color w/Alpha of zero) to (Color w/Alpha of 255). So instead of trying to fade the image into the backcolor, rather we are fading the backcolor into the image.

----------


## petersen

Feedback on a quick test:
Windows platform:  Vista 32-bit.

Test scope: After adding a new project and placing the control on the new form, begin the test by loading a different graphic file in turn, via "Browse" button on Property page.  No any other test conducted.

Bugs encountered:

(1) On PNG:  For BitDepth 1 and ColorType 0 with transparency, vertical ghost lines across the resulting image at certain regular intervals (however, for BitDepth 1 and ColorType 3 one, same with transparency, it is okay).

(2) On WMF: (a) If without "placeable" header (so-called "standard" one), resulting image appears as if "1x1" pixel size. (b) If with "placeable" header, resulting image is very much larger than it should be.  Remarks: "b" results seem to vary on different tries.

(3) On ANI:  Program crashed with a 32-BPP single-group ANI.

----------


## LaVolpe

Response to your quick tests
1) Limitation of GDI+, PNGs are not processed manually; all PNGs are loaded with GDI+. I'm not going to add code to manually parse PNG files. If this is important to a user, they can load the PNG via libpng or other methods into a DIB and send the DIB to an AlphaImgCtl
-- I do have manual routines that can read PNGs without any 3rd party DLLs. Also have routines that can write PNGs using zLIB and at better compression ratios than GDI+. Those will not be used in this project however.

2) If you can supply one for me to play with, I can try to code around those
b) To calculate the size of the WMF. I query the horizontal/vertical resolution the metafile was created in as reported by GDI+ and also the size reported by GDI+. The resolution and size are used in the following formula to calculate size in pixels: Size * 96 / Resolution
If GDI+ is reporting either size or resolution differently than what you expect, then so be it; out of my control. 
The constant 96 above was used as a suggestion by you to maintain constant size regardless of user's DPI screen settings. The formula I would normally use (similar to VB) is dependent on screen DPI and looks like: 
Size * (1440 / Screen.TwipsPerPixelX) / Resolution

3) I'll look into that, I believe I can get single-group ANI cursors from Vista in 32bpp formats. Sounds like an issue in my RIFF parsing maybe

Thanx for the bug reports

Edited: WMF/EMF details are not as familiar to me. I believe there are 4 types. If you post or point me to where I can get sample files like the ones you used for your tests. I can make the control more complete with regards to metafiles. Last but not least. Metafiles are scalable, for the purposes of this control, the actual size is only important if the control's AutoSize property is used and the Aspect property is ActualSize, otherwise, the actual size of any loaded image is irrelevant with regards to the scope of this control.

----------


## petersen

I attach two WMF files as requested - one with "placeable" header and one without.  A 32-BPP ANI is also included for your ready use.

I myself do not have much knowledge on EMF/WMF, but just enough to handle them (load and save).  In view of the lacking of published materials, the following are pertinent to getting a grip of WMF.

I would say WMF is a mess (like many things coming out from MS,  e.g. look at ICO header and look at Resource file structure for Cursor versus that for Icon, the original design was so loose).  As a result, we got 4 types of it as you said (I would say 5 actually, the 5th one being of a "bitmap" variation rather than GDI commands).

With a "standard" WMF file, what you get from calling GDI+ is basically your screen size.  Therefore, it was fully justifiable for Aldus to add a placeable header, in order to establish the intended image size with certainty.

' "Standard" metafile. 18 bytes.
Private Type METAHEADER
    mtType As Integer
    mtHeaderSize As Integer
    mtVersion As Integer
    mtSize As Long                ' Value of mtSize needs to be "x2", as it is in Words
    mtNoObjects As Integer
    mtMaxRecord As Long
    mtNoParameters As Integer
End Type

' "Aldus Placeable" header
Private Type PLACEABLE
    Key As Long
    handle As Integer
    Left As Integer
    TOp As Integer
    Right As Integer
    bottom As Integer
    Inch As Integer
    Reserved As Long
    Checksum As Integer
End Type

It is because of what is said in the previous paragraph, you will notice that the image returned from your Icon Resource Organizer is distorted, if you load the one without placeable header.  For a comparison, you can download a gadget of mine to try the same (where the size is halved intentionally),   Like you I am an amateur graphics lover, as such there might be some other materials of referecne value to you in the said gadget.  Just unzip it to a temp folder (there are 2 DLLs there, dispensing any or all of them would not affect the program running).   (Will remove URL a bit later today).

An explanation of "* 96/120" is in order.  On one hand, pixels are a device dependant scalemode, on the other hand, himetric is based on the metric system which is device independent. Therefore,  in order to arrive at the same pixel units irrespective of the DPI settings, we have to take into account of the DPI value in converting HiMetric to Pixel.

This morning I purposely powered off and on of my PC and I am able to re-produce all of what I said in my previous posting.  However, there is one point I want to bring to your attention: The test results of  "a" and "b" of "2" in my previous posting seem to vary on different tries, much depends on what has been loaded previously.

----------


## LaVolpe

Thanx for the info. Will be playing with this today/tonight. Already figured out the ani problem; If/Else logic error failed to size an array (easy fix). Will now work on the metafiles & post results & update project later.

Initial look at the 2 WMFs you gave me.  More research needed by me, not looking promising...
Placeable: 1.135 width:height ratio, using a 1000 v/h resolution
NonPlaceable: 1.56 width:height ratio and GDI+ converts to EMF using 93.78 v/h resolution

----------


## petersen

Re: For NonPlaceable, just a reminder -- see 4th ("With a "standard" WMF file ....) and 5th paragraphs of my previous posting.

----------


## LaVolpe

Gotcha. Decisions, decisions. The only way I'll know if the WMF is not placeable is to parse the header info (and not opposed to doing it)
I see where a default of 1/2 size could be useful or even using 1/8. What I see as a potential issue is the screen size. The width/height ratio of the non-placeable WMF will be same as the screen width/height ratio; therefore, giving a stretched vs scaled appearance. This is because non-placeable header's don't include image dimensions; therefore, the intended width/height ratio cannot be known.

----------


## petersen

Another reminder:

What is said in the last sentence of the last paragraph of my posting #9 is in fact a bug which you may want to address.   I would have it included as:

(4) On general:  .....

in my posting #7 if I knew it at that time.

----------


## LaVolpe

> Another reminder:
> 
> What is said in the last sentence of the last paragraph of my posting #9 is in fact a bug which you may want to address.   I would have it included as:
> 
> (4) On general:  .....
> 
> in my posting #7 if I knew it at that time.


Not sure I understand. Keep this in mind. During design-time...
1) If control has no picture assigned, any new picture will be shown actual size.
2) If control had picture, the replacement picture will be scaled to the control dimensions dependent on the Stretch property.

I am not exactly happy with that functionality and may revert to how VB does it: If Aspect=ActualSize, load image actual size else scale to Aspect property's setting. Still thinking on this. One thing I always disliked about VB is that loading a image into a VB image control during runtime, resized the image control unless Stretch=False.

*Edited*: Changed behavior
Design time: If Aspect=ActualSize, control will be resized to show entire image, regardless of AutoSize
Run time: The AutoSize & Aspect are honored. In same situation: Aspect=Actual Size and AutoSize=NoAutosize then image may be clipped if control is not big enough to display entire image. 
Changes made to imitate VB's Image Control behavior during design time. Note that VB's Image Control has only 2 settings: Stretch=False sizes control to image's dimensions.  Stretch=True sizes image to control's dimensions.

----------


## petersen

Regarding VB Image control, I generally leave the default as it is, unless I see there is a need (in rare occasions I do feel the need to change the default Stretch property).  

In the current case, somehow a practical arrangement should be made, e.g. there is no reason that when the user loads the first picture, the size is automatically fit to the originally coded size, wnen he/she loads a smaller one then the size no longer fits -- not every user is like you and me knowing why and how.

----------


## petersen

It appears to me that it would be nice if user can effect the settings you mentioned right on the Property screen as well (if this doesn't involve much coding overhead).

----------


## LaVolpe

> It appears to me that it would be nice if user can effect the settings you mentioned right on the Property screen as well (if this doesn't involve much coding overhead).


I'll take it into consideration. Look for control updates a bit later tonight to address wmf & ani cursor issues.

----------


## petersen

This one is just for reference, whilst we are here.

I didn't test any animated GIF file so far (because I stopped my quick test when I bumped into "(3)" mentioned in my posting #7),  so I've this evening made a few more clicks, specifically on animated GIF files, to complete the job.

I now upload a zip containing an animated GIF file, somewhat tricky and interesting. The Image control cannot animate it correctly, but neither can FireFox/IrfanView.  However, on the other hand,  Internet Explorer animates it perfectly right  (my own programs also).

----------


## petersen

To avoid misunderstanding, I can clearly see some white parts at scissors place during the animation (invoked via the checkbox Animate on the Property page), whereas the background should be the velvet.

----------


## LaVolpe

> To avoid misunderstanding, I can clearly see some white parts at scissors place during the animation (invoked via the checkbox Animate on the Property page).


Yep, me too. And on IE8 (Vista), same white space. I'm sure it isn't intended to show however the gif is poorly written then. It uses disposal code of 2 for the 2nd/3rd frames. Code 2 means to erase the area just drawn by the frame when that frame is disposed. Per GIF89A specifications



> Code 2 - Restore to background color. The area used by the graphic must be restored to the background color.


Frame2 has dimensions of 128x79. 
Frame3 has dimensions of 117x68. 
So, when Frame2 is disposed, a 128x79 area is erased and when Frame3 is drawn, it only covers 117x68; the "white space" you see is the difference. Frame2 probably should've had a disposal code of 3 or 1 instead of 2, both would have rendered it correctly.

If you'd like to discuss that GIF's formatting and specifications, PM me. I don't want to use this thread for that specific GIF. Don't want thread veering off on a tangent.

----------


## petersen

No, I don't want to enter into a discussion/debate; I just report the results of my "quick test".  Regarding the test of GIF animation, it was on IE7 (the one which shows velvet background alright).  To satisfy curiosity, I have now tested it on IE6 too, IE6 also displays velvet background alright.

Just a side issue talking of IE, the IT department of a sizeable hospital here advised all doctors to stick to IE6, avoid IE7 & 8.  

So, that is all from me about my quick test.  Nice talking to you.

----------


## petersen

Bug report.

A guy sent me a few animated GIF files (to ask some questions), one of them appears interesting to me because it somewhat resembles the above-said one in the arrangement of disposal methods used (but instead of To Background, To Previous).  So I fetched your new copy to try this one on it.  

As the frame displays do not appear alright, so I come back to report this one.  Unlike the file in my early posting, which a different browser/program may have a different practice to handle (that is why I didn't call it a bug), this one is certain (as the practice of all browsers/programs should be the same, so I call it a bug)..

Shown below is one of the animation frames - in the running rabbit place, one can see a rectangular area with distorted/lightened colors.

Zip containing the source GIF file is attached, hope it helps.

----------


## LaVolpe

Yep, you've discovered another GDI+ bug apparently or something wrong with my code.
I don't think it's my code simply because I'm asking GDI+ to move to the next frame and then render what it gives me. I'll look into it a bit further.  Maybe something to play with this weekend.

BTW: I ran your GIF in my personal animated GIF app (one I wrote) and it ran correctly. Agreed, no disposal code issues here.

Edited: I've got dozens upon dozens of GIFs (some badly coded) that I've collected when I wanted to learn the GIF format. I think I'll spend some time on this to see how many of those GDI+ failed to render correctly. I'd sure hate to have to supply my own GIF routines since GDI+ makes it sooooo easy. But if this is a bigger problem, then I may go that route.

Follow up: Frame disposal codes are: 1,3,3,3,3. The 1st 2 frames draw good; then bad after that. Now to look at other GIFs with multiple 3s placed consecutively. I may have to quick parse GIFs to determine disposal codes & decide whether or not to use GDI+ or manual rendering. Again, something to play with this weekend.

Edited: Another follow-up. Using v1.1 of GDI+ resulted in the same improper rendering.

----------


## petersen

> Edited: I've got dozens upon dozens of GIFs (some badly coded) that I've collected when I wanted to learn the GIF format ......


I got the impression (from past discussions) that you honestly adhere to what is stated in MS documentation / format specifications, which is good and necessary.  Unfortunately I found that often some judicial adjustment is necessary here and there.  Take GIFs for example (since we are talking of GIFs), I used to be serious to conduct a preliminary validation of the incoming file and would reject a file without a GIF trailer.  However, if other programs accept such a file (they do), then my clients might think it is something wrong with my program.  So, I have to relax that check (forget the laid down specification).  Just a mention.

----------


## LaVolpe

Well, with my personal GIF routines, I've relaxed some things too. But I won't work around a poorly coded GIF and allow well-coded/formatted ones to suffer.

Anyway. I think I've discovered what's different in your GIF and why GDI+ may have failed. I'll look more into it later:  local color table usage vs. global color tables. I know this is a bug regarding saving GIFs; didn't realize it may be a bug displaying them. Will be tweaking some code so I can scan 100's of files, looking for ones with local color table usage.  Consecutive code 3s isn't the problem, I've a few of those and they rendered fine with GDI+. Almost seems as if more than one local color table, it is an issue. I've found a couple of mine that have 1 local color table and it came out ok. Your gif has 4 local color tables starting with frame #2.

Edited: Follow-up. I searched over 5,000 gifs & could not find another one like yours. I did find many that used multiple local tables and all rendered ok. So I'm assuming the GDI+ bug comes in this category: multiple local tables and disposal code of 3. All the ones with multiple color tables I have have disposal codes of 1 or 2, not 3. I'm chalking this up to out of my control for now. Manually processing/displaying GIFs to handle a rare occurrence isn't a priority for me.

----------


## petersen

You mentioned the use of local palettes, so I took a look at them and I don't like them in the original file uploaded in the earlier posting.  They all use 256-color tables whereas each frame has not more than 8 colors.

I've now tidied up/simplified the said tables, so that each table does not contain more than 8 colors.  The result is a reduction of the file size from 13,523 to 10,189 bytes.  Just for a bit of fun only.

----------


## LaVolpe

That is one advantage of GIF. A table can be any bit depth between 1 and 8, so your table doesn't have to be a size typical with bitmaps, it can be: 2, 4, 8, 16, 32, 64, 128, 256

Also, if you are playing with your own GIF writer, I doubt all 4 tables are different. It might be better to use a global table for the last 4 frames and a local table for the first frame. The GIF will be smaller yet. In fact, GDI+ may even display it properly then too  :Wink: 

Edited: I wrote a GIF writer awhile back. I actually took the time to optimize the color tables per frame. If all colors could be squeezed into one table then one table used. Otherwise, it would create a table that a majority of the frames would use and set that one as global. The odd-ball frames would then have their own color tables as needed. This logic reduced GIF size very well. But a majority of GIFs out there are based on a single table and those can be optimized many times also. Example like yours: 256 palette, but far less colors used.

----------


## petersen

That rabbit GIF file which the guy sent me is from some site on the web.  As  it is supposedly a professional site, hence I am a bit surprised when I find such a sloppy palette table building.  

Actually, although we can limit the entries in a table to any number between 1 and 256, in VB6 world steps of 1, 4 and 8-BPP still have to be observed in the actual table size. There are constraints set by stuff like BITMAPINFOHEADER and GetDIBits.

We may have a 2-BPP PNG file (really coded 2-BPP), but when we process such a file, it is dealt with on a 4-BPP basis because of the above-said.  Also VB6 cannot directly handle some camera raw files which are often 48-BPP, not to say the 96-BPP and 128-BPP High Dynamic Range images such as HDR & EXR (C++ guys often deal with BPPs not usually seen in VB6).  

Nevertheless, for our purposes, VB6 is good enough to cover the commonly used images perfectly alright.

----------


## LaVolpe

> ...Actually, although we can limit the entries in a table to any number between 1 and 256, in VB6 world steps of 1, 4 and 8-BPP still have to be observed in the actual table size. There are constraints set by stuff like BITMAPINFOHEADER and GetDIBits.


Not really. The bitmap/dib table size is restricted, but not the GIF table size, other than what I mentioned earlier. The two have no direct relationship. If the GIF table size is 6 bits, then supply an 8 bit dib table and fill in just 64 of 256 dib colors. And if converting dib to GIF, simply keep track of how many color are used, if just 64, then GIF color table should be 6 bit, not 8 bit IMO.

----------


## petersen

You can save at 3 * (2 ^ BPP) in file alright, what I am talking about is whenever we process the image it is still on 1, 4 & 8-BPP basis, due to what is limited by BITMAPINFOHEADER and GetDIBits.  This is analogous to 2-BPP PNG case -- file size is smaller than 4-BPP, but requiring some overhead in handling.  Of course GIF is always 8-BPP.  Anyway, I do allow users to move up or down in steps of (2 ^ BPP) in my Animated GIF Editor.  I believe the redone tables in the "rabbit" file reflects that essence.

----------


## petersen

Just a reminder.  Some images can be big, e.g. TIFF and camera JPG are  notoriously so, hence you might want to set an allowable max to the Image control size.

----------


## LaVolpe

> Just a reminder.  Some images can be big, e.g. TIFF and camera JPG are  notoriously so, hence you might want to set an allowable max to the Image control size.


Worth thinking about... I was considering maxing it out at control's container size, but haven't decided how I wanted to implement it. VB will limit a control's size but that size can still be absolutely huge.


```
    UserControl11.Width = Screen.Width * 1000
    UserControl11.Height = Screen.Height * 1000
    
    Debug.Print "Widths - screen/control: "; Screen.Width \ Screen.TwipsPerPixelX; UserControl11.Width \ Screen.TwipsPerPixelX
    Debug.Print "Heights - screen/control: "; Screen.Height \ Screen.TwipsPerPixelY; UserControl11.Height \ Screen.TwipsPerPixelY
```

Edited: Would be nice of me to post the results, huh  :Wink: 
Widths - screen/control:  1920  16383 
Heights - screen/control:  1200  16383

And another thing to consider. If control size is adjusted by me because "it is too big"; that will have an effect on how the image is rendered within the control if the Aspect setting is not ActualSize or FixedSize.  Thinking....

Edited yet again. After playing around with this, I am going to restrict maximum control size to the screen size (in pixels of course)
Side note: The O/S has a max DIB size that is not documented, but a max size nonetheless. Since AutoRedraw obviously uses an offscreen DIB to cache the rendered state of the image, a large image may outsize the O/S max. If that is the case, the O/S will simply fail to create the DIB requested.  This error check has been in-place since the beginning: If O/S fails to create DIB then AutoRedraw is reset to False.

----------


## petersen

Just for info.

(i) For the earlier attached GIF file, you suspect that the incorrect animation on Image control has something to do with local palettes, I can confirm that it doesn't -- I put all frames to a global palette and the problem remains.

(ii) For years there had not been once that the earlier mentioned "to background" file failed to show alright on IE7, until today.  I guess MS has meanwhile dumped something to my machine,  kind of "auto-update" thing (despite I had already turned off auto-update), because when I re-test it again now, IE7 no longer shows it alright (scary, as if MS is ear dropping our conversation).  it remains alright on IE6 though, because that machine is not connected to web.  Because of this I have now revised my main program a little and removed the option to show animation in the manner as in IE.

(iii) In my programs, there are 4 options to show individual frames, against program's screen color, at frame's own transparent color if any, on a chessboard, and at frame's net size (for those less than background size).  There is also a summary of frames data.   If you are interested in one of my programs as a kind of 2nd reference when you test your GIF files, you can fetch a gadget at ...... (I will remove URL a bit later).  I have animated GIF submenu included in this gadget because a couple of years ago I had encountered an animated GIF file with over 1600 frames.

----------


## LaVolpe

Appreciate the offer. I have my own GIF parsing/rendering routines and I am 100&#37; confident they are written correctly.  As far as making assumptions about GDI+ and local color tables? That's all I can do, I don't know what methods it uses internally to do the job. Obviously it appears broken in this case.

----------


## Stidor

Hi LaVolpe!

Love the control, thank you for continuing to update it.

I seemed to have run into what may be a bug or glitch with the control. When I create a usercontrol, place your control on there and then create a function for drawing a line, I get a black line at the top of the control. It's quite weird. As soon as I remove your control it stops happening.


_(Notice the black line at the top?)_

Any ideas?

Please see attached project for example of glitch/bug or code below to replicate.



```
Private Sub UserControl_Initialize()

    Call Draw

End Sub
Private Sub Draw()

    With UserControl
        .Cls
        Line (0, 0)-(0, .ScaleHeight), vbBlue
    End With
    
End Sub

Private Sub UserControl_Resize()

    Call Draw
    
End Sub
```

Tested on two different Win7 x64 machines.

----------


## LaVolpe

Yes, it is a common bug with VB usercontrols. There is a workaround.
For others, this is the scenario.
1) Place AlphaImgCtrl in a picturebox. Set the picturebox AutoRedraw=True
2) Draw custom graphics to the picturebox, like a gradient background for example
3) Solid black line appears at top of the picturebox

BTW, it appears with all VB usercontrols where properties: Windowless=True & BackStyle=Transparent and the container's AutoRedraw=True

The fix: After you draw your background, then call: Set Picture1.Picture = Picture1.Image

Edited: You are adding my control to another usercontrol. Same principle should apply:
Set UserControl.Picture = UserControl.Image

----------


## Stidor

Ah I see. Thanks LaVolpe, first time I've come across it.

Will give your fix a test tonight, much appreciated.

----------


## LaVolpe

You're welcome. I only came to know this bug a couple years ago myself.

----------


## Stidor

Worked perfectly. Thanks again. :-)

What I'm planning (or rather hoping) is to replace my current image/picturebox control in my custom button. However I'm thinking this may not work. Will I be able to load in alpha images (pngs) into my custom button control's picture property during design time? Or am I going to have to load them from an external resource at run time?

I guess the better question is, does VB6 handle storing alpha images in control picture properties, and can this control load images from the property store?

----------


## LaVolpe

You will want to create a property page, similar to the one I use for the alpha image control. That property page will allow users to select non-vb supported file formats (i.e., png, tif, tga). You can then feed the file to the AlphaImgCtl within your 'button'.  To save the content of the file, store the file contents in a byte array. Save the byte array to your property bag during WriteProperties event. During ReadProperties, load the array from your propertybag and feed it to the AlphaImgCtl. You may want to look at how I do that in my control's Read/WriteProperties events

Another option, not very user friendly is to have them copy & paste the file path/name in a String public property and then load the file content from that.

Obviously you can't do this the easy way with a stdPicture object because user's will not be able to select non-vb supported image formats.

Edited. Give me a few minutes & I'll post a simple example and workaround for you. It's easier than it appears.
Ok, here we go....
1) In your usercontrol project, add a property page. Give it a more meaningful name as needed vs. PropertyPage1
2) Bring your usercontrol into design view. Find PropertyPages in the property sheet
3) Click the ellipse button (...) and select your new property page. Then close that window
4) Within the property page, simply add a button and leave it named command1 for this simple example
5) Also add 1 timer to the property page and leave its default settings
6) Copy & paste this code into the property page


```
Option Explicit

Dim cBrowser As UnicodeFileDialog
Dim cImage As GDIpImage

Private Declare Function GetParent Lib "user32" _
  (ByVal hwnd As Long) As Long

Private Declare Function SetWindowPos Lib "user32" _
  (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
  ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
  ByVal cy As Long, ByVal wFlags As Long) As Long

Private Declare Function PostMessage Lib "user32" Alias _
  "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
  ByVal wParam As Long, ByVal lParam As Long) As Long

Private Const HWND_TOP = 0
Private Const SWP_NOSIZE = &H1
Private Const SWP_HIDEWINDOW = &H80
Private Const WM_CLOSE = &H10

Dim hwndPP As Long

Private Sub PropertyPage_Paint()
   Dim lresult As Long
   lresult = GetParent(PropertyPage.hwnd)   ' Work back to the
   hwndPP = GetParent(lresult)              ' dialog window.
   lresult = SetWindowPos(hwndPP, HWND_TOP, 200&, 200&, &O0, &O0, _
      SWP_HIDEWINDOW Or SWP_NOSIZE)
End Sub

Private Sub Timer1_Timer()
   Dim lRet As Long
   Timer1.Enabled = False     ' You will not need the Timer again.
   Command1.Value = True      ' Click the CommandButton.
   If PropertyPage.Changed Then PropertyPage_ApplyChanges  ' Apply the new settings.
   lRet = PostMessage(hwndPP, WM_CLOSE, 0, 0) ' Close the dialog box.
End Sub

Private Sub Command1_Click()
    If cBrowser.ShowOpen(PropertyPage.hwnd) Then
        On Error Resume Next
        Set cImage = LoadPictureGDIplus(cBrowser.FileName, , True)
        If Err Then
            Beep ' image failed to load
        Else
            PropertyPage.Changed = True
        End If
    End If
End Sub

Private Sub PropertyPage_ApplyChanges()
    Dim bData() As Byte
    cImage.ExtractImageData bData
    PropertyPage.SelectedControls(0).Image = bData()
    PropertyPage.Changed = False
End Sub

Private Sub PropertyPage_Initialize()
    
    Set cBrowser = New UnicodeFileDialog
    With cBrowser
        .Filter = "All Files|*.*|" & _
            "Supported Formats|*.bmp;*.cur;*.ani;*.gif;*.ico;*.jpg;*.jpeg;*.emf;*.wmf;*.mp3;*.png;*.apng;*.tga;*.tif;*.tiff|" & _
            "Bitmap|*.bmp|Cursor|*.cur;*.ani|GIF|*.gif|Icon|*.ico|JPEG|*.jpg;*.jpeg|" & _
            "Metafile|*.emf;*.wmf|MP3|*.mp3|PNG|*.png;*.apng|Targa (TGA)|*.tga|TIFF|*.tif;*.tiff"
        .FilterIndex = 2
        .Flags = OFN_EXPLORER Or OFN_FILEMUSTEXIST
        .DialogTitle = "Select Image"
    End With
    Timer1.Enabled = False
    Timer1.Interval = 1

End Sub

Private Sub PropertyPage_SelectionChanged()
    PropertyPage.Changed = False
End Sub
```

7) You'll need a way to have the property page talk to your usercontrol to get/set properties. In this example, create a new property called image and copy/paste the relevant code from what I posted here:


```
Public Property Let Image(newValue As Variant)
    ' Write-only property
    On Error Resume Next
    Set AlphaImgCtl1.Picture = LoadPictureGDIplus(newValue)
    If Err Then
        ' probably should raise an Err here. Failed to load image
    Else
        ' refresh your control. New image was applied
        PropertyChanged "Image"
    End If
End Property

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
    Dim bData() As Byte
    bData() = PropBag.ReadProperty("Image", bData())
    On Error Resume Next
    Set AlphaImgCtl1.Picture = LoadPictureGDIplus(bData())
    If Err Then Err.Clear
    On Error GoTo 0
    ' read any other properties
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
    Dim bData() As Byte
    If AlphaImgCtl1.Picture.ExtractImageData(bData) Then
        PropBag.WriteProperty "Image", bData()
    End If
    ' write any other properties
End Sub
```

Note that the Image property above is for the example. You may want to change the property name or write your own. Whatever you decide upon, remember to make the appropriate change in the property page that calls it to get/set image data. The property does not need to be Public, but if not, other tweaks need to be made.

The hack to show the open file dialog window instead of the property page is described in this MSDN article. So if you actually want to design a property page to allow users to change other properties of the control, remove the timer-related code. This MSDN-suggested hack is only recommended if all you do is want to display a dialog box.

If you are new to property pages, they are not that difficult to use. Here is a great reference to assist if needed (in pdf format)

Last but not least. If you don't compile my control, you may get a registration error when trying to compile your control.

----------


## Stidor

Fantastic post LaVolpe, you've made it seem quite easy. Can't wait to give it a go when I get home from work this evening. I've never had a need to play with Property Pages so this should be a great learning exercise.

Thank you for the explanation and example code, much much appreciated.

----------


## Stidor

LaVolpe,

I appear to be getting a type mismatch error when trying to use;



```
LoadPictureGDIPlus(bData())
```

Is LoadPictureGDIPlus able to load from a byte array? I'm getting this error with your example code but was also getting it with my own code.

After looking at LaVolpeAlphaImg source code it does look like LoadPictureGDIPlus can import from a byte array. No doubt it's something simple I'm not seeing.

I'm even getting it with;



```
Set cImage = LoadPictureGDIPlus(cBrowser.FileName, , True)
```

----------


## LaVolpe

The control definitely can load a byte array. Ensure you are using Option Explicit atop your usercontrol and propertypage too. I'm guessing whatever is on the left side of the equal sign wasn't declared. It isn't the LoadPictureGDIplus function as I wrote it.  FYI: Why is there a capital P in the  Plus in LoadPictureGDIPlus? My function doesn't have a capital P. 

You might want to post a couple of snippets where you use those lines. Also include what type of object those lines are written in (form, uc, propertypage, class, etc).

Edited: Can you upload a clipped snap shot of your *expanded* project explorer tree? (top right treeview in IDE design window)

----------


## Stidor

> FYI: Why is there a capital P in the  Plus in LoadPictureGDIPlus? My function doesn't have a capital P.


Well don't I feel silly. Would you believe I had another function called exactly that already existing in my project. You have a very good eye LaVolpe.

My apologies.  :Blush:  Will refrain from posting late at night without looking at it again the next day with a fresh mind.

----------


## Stidor

Back again, hopefully this time with a legitimate issue. I seem to be having an issue transferring one image from a picturebox to an AlphaImgCtl. When I try I get an "invalid picture" error. Looking through your control source I see that via LoadPictureGDIplus it should be possible to load from a picturebox.picture?

*Update:* Ah! Upon further reading of your control source comments, I noticed the comment about loading from the handle instead. So basically I'm now using..

    Set AlphaImgCtl.Picture = LoadPictureGDIplus(PictureBox.Picture.Handle)

Which works just fine. :-) Thought I'd leave this post here in case anyone else finds it helpful.

----------


## LaVolpe

> ...*Update:* Ah! Upon further reading of your control source comments, I noticed the comment about loading from the handle instead. So basically I'm now using..
> 
>     Set AlphaImgCtl.Picture = LoadPictureGDIplus(PictureBox.Picture.Handle)


Glad you figured it out, some notes for clarification only

1) You can't do: Set AlphaImgCtl1.Picture = Picturebox1.Picture because the Picturebox object's .Picture property is a stdPicture class. The AlphaImgCtl object's .Picture property is a GDIpImage class. A type mismatch error should occur.

2) You can load a picturebox's picture a couple of ways
a) by handle as you described
b) also: Set AlphaImgCtl1.Picture = LoadPictureGDIplus(Picture1.Picture)

Edited: Note that by handle will fail if the picture is a metafile & transparency lost if transparent GIF. I'd recommend staying with option 2b above as a general rule.

----------


## petersen

Another bug?

I was doing something concerning some thumbnail stuff on my own program when I bumped into a likely GDI+ bug.  So I fetched a copy of Image control to see if it also applies there - it seems so.

Attached zip has 2 GIF sample files.  Note the characteristics of aaa1.gif file: the first frame is smaller than the background size, the first frame is non-transparent, there are some other frames with transparency.  And aaa2.gif, all frames are non-transparent.

----------


## LaVolpe

> Another bug?
> 
> I was doing something concerning some thumbnail stuff on my own program when I bumped into a likely GDI+ bug.  So I fetched a copy of Image control to see if it also applies there - it seems so.


Agreed another GDI+ bug in both cases. Appears GDI+ takes some shortcuts that do not render the GIFs correctly. I'll consider adding my own GIF routines, but not committed at this point.

FYI. If there has ever been any doubt that the Windows Picture & Fax Viewer uses GDI+, use that viewer to display those GIFs

*Edited*: I'm playing with the idea of using my own GIF routines. Not yet sure of how I want to go about this while maintaining the same methods I use for other image formats. Right now, I know I can do this a couple of ways to maintain those methods: a) create 1 large bitmap that will include all frames and then segment the image to produce frames or 2) create each frame, fully rendered, and add them to a multi-page TIF. Though either will work well and allow minimal 'special handling' for GIFs, I fear load time could be an issue since the entire GIF would have to be rendered to bitmap(s) initially. GDI+ is fast, but obviously, has its issues too. I still want to wrap a GDI+ handle around the GIF-data so I can continue to use all the other image processing methods/properties of the usercontrol; don't want to render individual GIF frames manually, per frame during animation, using GDI vs. GDI+.  Still thinking...

----------


## petersen

Yes GDIplus can be extremely efficient when selectively used.  For your reference, the craziest animated GIF file I've ever come across is with 1600+ frames; the background size is about a palm's size.

----------


## LaVolpe

As I'm contemplating taking over GIF rendering responsibilities vs. using GDI+, some other ideas hit me...
Whatever method I decide upon for GIFs can be used to support APNG (animated PNG) and MNG also. If I go that route, I will only support some subsets of MNG, specifically PNG & JPG most likely if I can find enough examples to play with.

Edited: I think I've discovered a really clever & fast way to load/render individual GIF/APNG/MNG frames while avoiding GDI+ bugs. Still working on it.
Update: Works fantastically. Will modify class to support APNG also, then post the updated control. MNG will wait a bit until I can find enough samples to play with. Expect the GIF/APNG updates 1st weekend of December.

----------


## petersen

Good luck and enjoy yourself.

----------


## Jonney

MNG Spec:
http://www.libmng.com/pub/mng/spec/

----------


## LaVolpe

Jonney, thanx for the specs link. I was aware of it, however, I haven't gone searching for MNGs at this point. 

*For all*: Updated project to support APNG and better GIF handling
Here are some sample APNGs you can play with.

http://www.spreadfirefox.com/node/1872
http://animatedpng.com/index.php/category/samples/
http://treebuilder.de/default.asp?file=89031.xml
also Google for APNG

Note about APNG. Rare. The following browsers/viewers are only ones I know of that support APNG
Mozilla Firefox 3, Opera 9.5, KSquirrel 0.7.2, XnView 1.92

And if you want to play with creating your own. Look at APNG's site: http://animatedpng.com/index.php/software/

----------


## tmighty

Great work! Thank you!

I don't have GDIPLUS.dll v 1.1. I am not sure why...
Can anybody please tell me where he/she got their v1.1 from (if you downloaded it later) and how you distribute it? Do you put the GDIPLUS.dll into your app directory?

----------


## tmighty

Sorry, I did not find a "Kill message" button. I found out that gdiplus v1.1 may not be distributed :-(

----------


## LaVolpe

Project updated to include the PCX image format. 1, 8, 24, 32 bit image support for displaying and 8, 24 bpp support for writing. 32 bpp support is included in the project but very few readers will recognize it. So I turned it off. If you wish to turn it on then see comments in cFunctionsPCX.SaveToStream

Also updated... can now save as WMF or EMF. Saving alphablended images to WMF may not produce best results. 

Hoping for a happy and prosperous New Year for all.

----------


## petersen

La Volpe,

As you know, I don't use Alpha Image Control myself (as I have my own stuff), nevertheless I have done some testings for you and provided some feedback and bugs reports per my postings earlier, as a matter of interest.

Following our discussion on PCX last night, I've now fetched the new copy and carried out some tests in selected areas.

Here is a particularly point I want to bring your attention to.  The screenshot below shows two images obtained from Alpha Image Control and from AZ Paint Pro program respectively.  The source image is a 32-BPP PNG, saved to 24-BPP PCX file.

(1) There is a discrepance between the image displayed and the image retrieved from the saved file using Alpha Image Control.  Despite the background used is White on loading the file and the display on screen showed the background being white, the saved file is invariably turned into using Black background.

(2) There is no option in Alpha Image Control to allow user to opt for a desired background color on loading a 32-BPP images. 

Whatever background color to use usually doesn't matter; however it matters in the case of 32-BPP images.  That is why programs such as AZ Paint Pro and IrfanView provide options for users to select a desired screen color to use (although the latter is basically a viewer program only).

Apparently Black is not a good background to use in this case - especially the jagged edges in the fishbow stand structure are conspicuously visible.

.

----------


## LaVolpe

There is an option to choose a background color. In the comments in the very first post I urge people to at least open the AICGlobals class and read the comments in that class for the few functions in that class.

Here are the comments in the SavePictureGDIplus call that pertains particularly to background color



> RenderingStyle :: Pass a filled RENDERSTYLESTRUCT or don't pass it if no special rendering style needed
>            - This function does not use rendering attributes utilized by any control maintaining the passed Picture object
>            - The BackColor member of the rendering style is used as follows
>                If BackColorUsed is True, the image will be filled with the BackColor member

----------


## petersen

La Volpe,

Please don't take it hard.  I've just pointed out a point which I considered worth pointing out.  If you don't like it, I would just stop here after this posting.

(A) You have ignored/overlooked a condition which has been clearly stipulated in my posting.  (i) My current background color is already what I have chosen to be, white, what else do I have to change?  (ii) What is better to guide the user to opt for a change than what is currently shwon on screen.  When the screen is already showing what I want it to look like, why should I select any option to change it still?  Common sense should prevail.



> (1) There is a discrepance between the image displayed and the image retrieved from the saved file using Alpha Image Control. Despite the background used is White on loading the file and the display on screen showed the background being white, the saved file is invariably turned into using Black background.


(B) Incidentally, I have just received a mail from someone who is also a graphics programmer (and VB fan) and with whom I have been communicating on this topic for fun.  What he says is self-explanatory.



> Contrary to my previous email, changing the background color of a 32bpp image in AZ Paint Pro all works OK even when made black.  So it takes the background color into account properly, unlike LaValpe's AlphaImage


The following image is what is meant in "B" above:
.

----------


## LaVolpe

This was your statement: There is no option in Alpha Image Control to allow user to opt for a desired background color on loading a 32-BPP images. 

That statement is false. I do not plan on changing the control for this item of interest. When saving to an image format that does not support transparency, transparency will be lost. To dictate the color you want to use to replace the transparency, use the options provided. My logic is not unlike other applications and is not unreasonable. Call it poetic license. I appreciate bug reports and will consider enhancements, but not this one because it is already addressed

----------


## petersen

Again, you are just "too quick".

I didn't say I make any change via an option provided in Alpha Image Control.  I changed the background color of the canvas, that is in this case the Form, to White (I may change it to say Black or Red). When I changed the background color of the Form to white, the image loaded shows what I wanted.  It is only the Save that fails to honour what I wanted.

I guess I should stop discussion now.

----------


## LaVolpe

Well, let me take 1 step back. The optional attributes you apply via the usercontrol (backcolor, grayscale, rotation, mirroring, transparency, blend, etc) are applied on the fly; they are not assigned to the image. Those attributes are maintained at the usercontrol not the image itself. The SavePictureGDIplus routine is passed an image class, not a usercontrol instance. The image class has no knowledge of what usercontrol(s) may be referencing it. Many usercontrols can share the same image class and each usercontrol can have different attributes applied. The only way the SavePictureGDIplus call can know of the attributes would be to pass that routine a usercontrol instance, not a GDIpImage class instance. But this isn't practical because the image class can be created on its own with the NEW keyword and will not have any control associated with it.

Here's what I will consider. Adding a SaveImage-like call in the usercontrol that will call the SavePictureGDIplus to produce a WYSIWYG result. That's an idea.

----------


## petersen

I can fully understand what you've explained.

But I have to put myself in an ordinary user postion.  Ordinary users wouldn't care and/or understand the code itself.  They just use it, and use it the way they are used to (or the way that the other programs/controls normally go).

The very purpose of my posting is to raise the point on a justified ground, whether your actual situation permits you to do something about it at the current moment (I can of course see that the code is far from a simple code), or indeed whether the point warrants a code modification at all, is entirely upto you to consider - but that is a separate issue.

----------


## LaVolpe

> But I have to put myself in an ordinary user postion.  Ordinary users wouldn't care and/or understand the code itself.  They just use it, and use it the way they are used to (or the way that the other programs/controls normally go).


I disagree 100&#37; with your statement. The ordinary user is a coder. The control is used in the coder's application they are designing. It is up to the coder to understand the controls they are using. By the word 'understanding' I specifically mean what options it offers and how to use it.  And in this case, it is pretty well documented within the code and it is open source.

For argument's sake. If someone wanted to save a stdPicture object in VB to a file, they'd use VB's SavePicture function, correct? Well what if that stdPicture was assigned to an image control that was stretched and had a border? Would VB save it in that scale and with a border? No. If VB could've offered 32bpp support for the stdPicture, what backcolor do you think it would have saved transparency as when saving to a format that doesn't support transparency? I believe the answer is black, same as other Microsoft products currently do: PhotoEditor & Paint. At best, VB might have offered an optional parameter for a backcolor, which is exactly what I did.




> When I changed the background color of the Form to white, the image loaded shows what I wanted. It is only the Save that fails to honour what I wanted.


By setting the BackColor & BackColorUsed values, the result is exactly as you wanted. Following is PNG saved to PCX  with white & black backcolors.


Again, it is not the control's responsibility to guess what the coder wants. It is the coder's responsibility to make the control do what he/she wants. The control has no knowledge of, nor does it care, nor does it need to care what its container's background state may be. That state is not part of the image, the image is rendered over it. Keep in mind that this is just a control, a tool for larger applications. Same applies to that stdPicture example above. If a coder wanted to save it in a different scale and style, they'd have to a) do it manually b) use one of the control's options to do it for them, if the option existed.

Obviously this control is not a stand-alone exe. It could be used as a key component for a larger application and offers a wide range of options that no other free control offers VB users. If someone wants to use it, it is their responsibility to play with and learn to use it, just like any other control in their toolbox. It appears you are comparing my control to a full application & that's like comparing the WinSock control to Mozilla. If I were to build an app that uses my control, I could replicate any 'paint-like' app and probably more because this control enables the coder to modify the image before, during, after drawing. Not only that, less code on my part is required because so many options have been included with the control. Its limitations are restricted only by the coder's imagination & experience, not by the control.

Edited: And to that point, I even took the time to create some sample projects people could use to play with the control and better educate themselves. Those can be found in the 1st posting.

----------


## petersen

If the following still cannot convince you to recognise that there are flaws in existence in Alpha Image Control, then I don't know what else to say.

Attached is a zip containing a 32-BPP PNG file (32bpp.PNG).

Image0 (first image shown) shows its image (using Black screen color, in order to be in line with the blackish background on saving PCX with Alpha Image Control).

Image1 (2nd image shown) shows what are the images in PCX, when saved with Alpha Image Control on one hand and AZ Paint Pro/IrfanView on the other.

Image2 (3rd image shown) shows what the images are in EMF, when saved with Alpha Image Contro, IrfanView and PNGnMNG2 respectively.

Readers who want to try save PCX using Alpha Image Control for
yourselves can refer the syntax given by La Volpe in Posting #28 at
http://www.vbforums.com/showthread.php?t=636793

(PNGnMNG2.zip containing PNGnMNG2.exe is available at
XXXX://XXX.XXX (removed now as origi...intended) XXXX
URL will be removed later today, latest tomorrow.
Just Open 32bpp.PNG, then click Save As EMF there)

.

----------


## LaVolpe

> If the following still cannot convince you to recognise that there are flaws in existence in Alpha Image Control, then I don't know what else to say.


I am not convinced. I have to repeat again, that if you don't use the backcolor options (saving transparency to format that doesn't support transparency), you will not get what you want. You tell the control what you want, it does not tell you what you want. Here is the same image rendered from png to pcx and to emf with the RenderingStyle parameter's BackColor & BackColorUsed properties set.


```
' Example saving to another format and loading it at afterwards
    Dim c As New GDIpImage
    Dim rs As RENDERSTYLESTRUCT
    rs.BackColor = vbWhite: rs.BackColorUsed = True
    SavePictureGDIplus AlphaImgCtl1.Picture, c, lvicSaveAsEMF, , rs
    AlphaImgCtl2.Picture = c 
' Example saving to file
    Dim rs As RENDERSTYLESTRUCT
    rs.BackColor = vbWhite: rs.BackColorUsed = True
    SavePictureGDIplus AlphaImgCtl1.Picture, "C:\MyImage.pcx", lvicSaveAsPCX, True, rs
```





> Readers who want to try save PCX using Alpha Image Control for yourselves can refer ...


Readers who want to try to use the control, read the comments, especially those in the AICGlobal class, and play with the control !

Your previous post does not mention how the EMF was saved. Is it transparent? Probably not & if it is, please post the emf here so I can see.  But *using the control properties provided to you*, you can reproduce the same images as your previous post. I have mentioned in post #1, at the very top, that I am working on revamping the SaveAs routines. If you do find an error, I'd be happy to address it. But you are not posting errors, you are posting examples of 'how not to use the control the way you want'. And to be clear about the PNG over backcolor... The backcolor is not part of the PNG, the control's backstyle is set to opaque

Edited: Just so one doesn't question my integrity, attached are examples of the saved images. And if someone still questions it, just do it yourself. The source image provided in previous post by Petersen, sample code provided by me above.

----------


## petersen

Why I have to bother myself again and again, if the other side does not follow the facts:

I have already presented so clearly all materials in posting above.

(1) PCX was obtained using exactly the command you gave, repeated here.

Readers who want to try save PCX using Alpha Image Control for
yourselves can refer the syntax given by La Volpe in Posting #28 at
http://www.vbforums.com/showthread.php?t=636793


(2) Correct EMF was obtainable from PNGnMNG2, repeated here

(PNGnMNG2.zip containing PNGnMNG2.exe is available at
XXXX://XXX.XXX (removed now as origi...intended) XXXX
URL will be removed later today, latest tomorrow.
Just Open 32bpp.PNG, then click Save As EMF there)


Edited:  For the benefit of general readers:  To understand why "Save PCX" had come up in the first place.  In the course of doing tests for Alpha Image Control, in Posting #26 of http://www.vbforums.com/showthread.php?t=636793, I specfically asked:



> .... how do I save a loaded image to a PCX file?


and the specific answer given in #28 is:



> SavePictureGDIplus AlphaImgCtl1.Picture,[path/filename], lvicSaveAsPCX, True
> 
> Change True to False for uncompressed. Supply path/filename


If you are interested in knowing how the subject matter has come about, browse the above link/thread, especially the later postings there.

----------


## LaVolpe

Petersen, At that point in time, I was just designing the pcx parser and you *KNOW* that. Things changed since that  posting. If you want to use the correct syntax use what I provided in my previous post.

If you don't want to use the control, then don't. You want to point something out that is wrong with the code, post the applicable code snippet, otherwise,  I'd very much appreciate if if you'd just stop posting erroneous stuff on this thread and stop trying to make a point that doesn't exist. I have no time for people that don't want to try to understand the code. Enough said.

----------


## petersen

If I recall correctly, you once explained that La Volpe means "The Fox" in Italian, now I can't help wondering whether in Indian it means "The Sacred Cow".  Only the day before you expressed apppreciation for my tesing in the above said link/thread, now you are so mad at my "not so pleasant" feedback whcih is just a continuation of the said testing.

Cheers.

----------


## LaVolpe

> Only the day before you expressed apppreciation for my tesing in the above said link/thread, now you are so mad at my "not so pleasant" feedback whcih is just a continuation of the said testing.
> 
> Cheers.


I'm not mad, I have told you no less than 2 times how to replicate the images you provided. You refuse to accept that advice and consistently harp on 'it doesn't do what AZ Paint or InfranView does'. Of course not, it isn't an application. It is a control. The control will do what those do if you pass it the right parameter information. This is now the 3rd of 4th time I've said that. Your feedback is not even constructive, I can deal with bug reports as history has proven. I can't deal with someone that apparently doesn't want to try to understand the control they are using and posting uneducated feedback.

----------


## petersen

Fair.  Let us put a stop here on the subject matter.

----------


## petersen

Take this as an independant issue (i.e.not to be related to the earlier subject)

Got an error message (screenshot attached) with the file (zip attached).

Debug line:    If inStream(UBound(inStream) - 768&) = 12& Then

----------


## LaVolpe

Thanks, that's something I will look into. I was sure I ran appropriate tests to prevent that, obviously not. It will wait until the save routines I'm designing are done.

And to the point of filling default background for formats that don't support transparency. That's on my list of things to do too. Bmp, Jpg are definite as they don't support transparency (except 32bpp bmp). PCX I'm still undecided with since it can support transparency, but not many viewers will display it. One of the options when saving to a particular format will be to dictate the bit depth as this will allow 32bpp to be saved with/without transparency or even bit reduced to paletted if desired using one of 4 palette options. I'm still not agreeable to having the control guess whether transparency should or should not be applied, simply because it permanently removes the option for the coder. Or... I am completely agreeable to default to 24bpp (or less) if format doesn't naturally support alpha channel (bmp, jpg, pcx for example) and let coder override for bmp/pcx. Converting WMF/EMF from 32bpp can produce horrible results if not rendered over a non-transparent background and that's going to be the coder's decision.

Last but not least, with every update comes more options. Included with the new SaveAs routines, will be option to save image rendered over an image background (tiled, stretched, clipped), a gradient/hatch brush, and/or solid backcolor.

----------


## petersen

When I was about to remove temp folder for Alpha Image Control, I spotted a 1-BPP file, hence just in time to do the above test.

The following are but for your reference:

Regarding PCX, I wouldn't give it the slightest thought about 32-BPP, as it is basically for legacy uses nowadays.

I don't come across any particularly dilamma situation regarding the transparency aspect.  My programs do show transparency for many formats (GIF, PNG, TGA, TIFF, J2K, JP2, ICO, CUR, ANI and 32-BPP BMP, the last one is for vb guys only).   In my own experience, three areas are comparatively tough (one is not difficult, one is difficult and one very difficult):

(A)  Taking the trouble to tell whether a simple transparency PNG has been faked by GDI+ as if reaal 32-BPP.  This one is not difficult at all, only causng some nuisance.

(B)  To allow user to enlarge a displayed GIF/Simple Transparency PNG on  chessboard, in a situation (1) Halftone is required, (2) use of GDI+ not allowed and (3) the chessboard grid size must maintain the same size as before.

(C)  In one of my programs, I have to allow users to edit 32-BPP images, e.g. rotate, resize and touch up alpha values, and after that allow them to save to various formats at will (e.g. user loads a 32-BPP PNG, rotates at 70 degree,  enlarges it by 2, then saves to a 32-BPP TGA).  This is comparatively much more difficult.  If GDI+ is used, obtaining un-premultiplied images is the key.

At the moment, I don't see you have any of "B" and "C" situations.

----------


## LaVolpe

Above
(A) Not an issue for me, I have routines that will identify via a 32bpp stream whether transparency is used and whether or not that stream is ARGB or pARGB

(B) GDI+ not allowed is not an option. This control is based on GDI+. GDI+ is redistributable if for some odd reason it doesn't exist. I have used GDI+ on Win95 and up. Yes, Win95. Regarding chessboard. Not an issue, since it isn't part of the control. The control will render over the chessboard background; therefore you can resize all you want without it affecting the background. Transparency with this control is not faked, it is rendered as-is.

(C) It is already there. The optional RenderingStyle parameter allows that. In your example, the image would be rendered resized & rotated simultaneously by GDI+, the resulting image would then be saved to TGA. Use negative angles for counter-clockwise rotation. 


```
    Dim RS As RENDERSTYLESTRUCT
        RS.Height = AlphaImgCtl1.Picture.Height * 2
        RS.Width = AlphaImgCtl1.Picture.Width * 2
        RS.Rotation = 70
    SavePictureGDIplus AlphaImgCtl1.Picture, "C:\MyPic.tga", lvicSaveAsTarga, True, RS
```

The main idea I had for this control was 1) show image formats VB won't, 2) make it enable tons of features/effects, 3) enable coder to do a lot with very little code. You can see how easy it is for the coder to do what you termed as 'much more difficult' by using just a few lines of code. The control has so many more options and only reading the comments/examples within AICGlobals class can one get a feel for the core functions and also press F2 and reading the usercontrol's property descriptions for that contrrol's properties/methods. I spent a lot of time adding those function descriptions & would expect those that want to play with the control to browse thru the ones they find of interest.

----------


## petersen

I can see you have the advantage since GDI+ is used throughout and you don't have to allow user to edit paint and alpha values of individual pixels.  As there are so many features and functions which can be included, a decision to provide what (and forego what) and how to best organize the arrangements need hard work still.

----------


## LaVolpe

Yes GDI+ is an advantage. My first image control I created used GDI+ sparingly and my own routines for a vast majority of the graphics including rotation, grayscaling, blurring, mirroring, etc, etc. I still have my own manual PNG reader/writer class I wrote that doesn't use GDI+ at all. I don't include those non-GDI+ routines any longer because 1) slower overall than GDI+ most of the time, 2) far less code needed for me, 3) wide-availability of GDI+, and 4) ease of use once one is comfortable with GDI+. Sure, it has its disadvantages also, but IMO those are far out-weighed by its advantages.

Edited: One disadvantage to GDI+ I really dislike is inability to set compression type of a PNG & various color depth formats. My manual PNG writer can out-perform GDI+ regarding file size, but not even close on speed. I can even create interlaced PNGs, but GDI+ can't/won't.

----------


## petersen

Most of my graphics programs started to build since 10 years ago when GDI+ was not common in users' machines, hence I had to do lots of detailed and dirty work, e.g. for anialiased line (guaranteed always smooth at any angle and brush size).  Gradually I found that I am using more and more GDI+ and I come to like it.  

Taken a quick look of your GDI+ call, the very long one, I can tell what you are doing and why you use that long one.

----------


## LaVolpe

You must be talking about GdipDrawImageRectRectI? Lots of parameters, but it does soooo much. That one function replicates many GDI calls, mainly due that attributes parameter. That one function can do same as these: BitBlt, StretchBlt, AlphaBlend. And with the use of the attributes parameter: grayscale, invert colors, blending, lightness/darkness, & TransparentBlt, color skewing/rotation, and many other color/matrix-related operations with just 1 API call. Lots of parameters, but oh so many options  :Wink:

----------


## petersen

Your subroutine with a long parameter list is Function Render, I meant.

Some of my GDI+ subroutines also use GdipDrawImageRectRectI, e.g. inside the one below, there is such a call.

Public Function ReadFileToDIB32_via_GDI(inFileSpec As String, inDIB As clsDIB, _
        Optional inIsTrueBPP32 As Boolean, _
        Optional ByVal inBkgdColor As Long = &HFFFFFF, _
        Optional ByVal inAlphaCutOff = 25, _
        Optional ByVal inTranspPercent As Long = 100, _
        Optional ByVal inRecreateDIB As Boolean = True, _
        Optional ByVal inDestX As Long = 0, _
        Optional ByVal inDestY As Long = 0, _
        Optional ByVal inDestW As Long = -1, _
        Optional ByVal inDestH As Long = -1, _
        Optional ByVal inHighQty As Boolean = True, _
        Optional ByVal inPageIndex As Long = 0) As Boolean

By a glance you are able to tell what I am doing there. In most cases I only need to pass first few parameters,  Note  inIsTrueBPP32 is passed ByRef, as its values is established within this subroutine (and the calling module uses that).   I only involve attributes when inTranspPercent is not 100.   If the incoming image is to be drawn on existing image in DIB, inRecreateDIB would be passed as False (actual use of True or False will be subject to certain condition).

My situation is diff to yours (e.g. mine has to go through edit of individual pixels), hence Resize and Rotation are in separate subroutines.  I guess in your case (I didn't look at in detail of yours), you must include Stretch and Rotate jobs in a single subroutine, because you don't use "un-premultiplied" image.

----------


## LaVolpe

GDI+ renders to 32bpp DIB in premultiplied pixels. When using GDI+ one does not need to be concerned with premultiplied or not. Only real exception is when extracting data from the GDI+ image, one must choose which color format they want, other than that, it isn't a concern for nearly all of the GDI+ calls.

Edited: A downside here is that once you render to GDI DC, you can never get true RGBA back from the DC, it will always be pRGBA.
As a simple test, I used GdipGraphicsClear on a new DIB passing a transparent white (&H00FFFFFF) and then retrieving the color from the DIB, what I got back was not &H00FFFFFF, it was &H00000000 (black) because of pre-multiplication; any fully transparent color becomes black.

The GDIpImage class does all the rendering in its Render function. Before rendering, it is just a matter of setting up the device context description beforehand. You tell GDI+ what smoothing/anti-aliasing quality you want to render in, what scale to render in, what angle to render at, and several other options. Once you define that, then you tell GDI+ to render & it does all the pixel X,Y translations while it renders.  Rotation with GDI+ is different. You don't manipulate pixels. Rather you tell GDI+ that the device context is rotated and GDI+ translates the pixels as it draws. I have in my possession very fast VB-only rotation code, but it is not faster than GDI+. I also have bilinear and bicubic Vb-only algorithms; again slower than GDI+

I think the old fashioned code is good to have for basic understanding of how rotation, scaling, etc, etc work. But I don't use any longer for reasons noted in previous post #77.

----------


## petersen

> GDI+ renders to 32bpp DIB in premultiplied pixels. When using GDI+ one does not need to be concerned with premultiplied or not.


In your case, yes.  However, in my case it is different -- on many occasions I must obtain an "un-premultiplied" image (through a trick of mine, GDI+ itself doesn't have that).  If later on I have to stretch the image, I pass the "un-premultiplied" image.  If further later on I have to rotate the image, I pass the processed "un-premultiplied" image again.  Why is that?

Take this as a simple example in my case:  User loads the image of a 32-BPP TGA, after drawing a red line on it, he resizes the image to 1.2 times.  After resizing, he decides to touch up some alpha values in some areas and a bit later he decides to write some text on the image as well.   Before he saves  the processed image a to 32-BPP PNG, he also decides to tilt the image by 45 degrees first.  --  It is in this kind of scenario that I must first obtain an "un-premultiplied" image every time I load the file.

Lucky that I didn't have GDI+ to use in earliers years, that provided me with a chance to build a good foundation, and even today I still have to use those subroutines under certain circustances, e.g. to draw a 45-degree-tilted and antialised ellipse  (draw on a pixel by pixel basis in that case).

With the "always monster size" digital camera JPG files nowadays, I found that GDI+ is a must for their thumbnail browsing, VB's ordinary way is simply not upto the job.

----------


## LaVolpe

Well, as with all things, there are usually workarounds...

For purists & special cases, not having original pixel data is not acceptable. If I render a PNG with transparent patterned background, I should be able to save as PNG with same background from that DC, correct?. I can't since it was rendered to GDI DC and all full transparency becomes black values. I can get original data from the source PNG but that isn't always doable (i.e., I need to scale the image then target & source images have different data). 

The workaround, and one that I will most likely employ while I'm updating this control, is rather simple. Using the same scenario from previous post. I can get original data after rendering this way: don't draw to GDI DC, draw to GDI+ DC (hGraphics). This requires creating a blank image, getting a GDI+ graphics object from that blank image, then rendering to it instead. This has a major advantage with viewers that don't support transparency or ignore the alpha channel... The transparent background will display &H00FFFFFF as full white instead of &H00000000 (premultiplied fully transparent white = black). And obviously, this means you'll always be rendering with original non-premultiplied data.

The only question I don't have an answer for yet is how the key GDI+ API (GdipCreateBitmapFromGraphics) is affected, if at all, when screen resolution is not 32bpp. Some testing needed by me.

----------


## petersen

Worthwhile to have a feedback:

Tested animation of all my collections of assorted animated PNG files, all okay.

----------


## petersen

In the previous link/thread, you asked about 4-BPP PCX, I've now obtained one (per ZIP attached).

Your Alpha Image Control cannot load it, but no run-time error this time.  On the other hand, there are some softwares which can load it perfectly right. The softwares include AZ Paint Pro, Irfanview, and AHA (I used AHA to test it because I got a good impression of it when I tested it's icon editor a few years ago).  PhotoShop7 cannot load it, but this is understandable as 4-BPP PCX is seldom seen and PhotoShop7 doesn't pay much attention to PCX (it cannot load uncompressed PCX).

Screenshots loaded images of AZ Paint Pro and IrfanView are appended below for your reference:

Edited: Have added a 2nd PCX in the ZIP.

----------


## LaVolpe

> In the previous link/thread, you asked about 4-BPP PCX, I've now obtained one (per ZIP attached).
> 
> Your Alpha Image Control cannot load it, but no run-time error this time.


Thanx for the sample, I'll look at it & make sure I can parse it. The control won't load it because I only support 1, 8, 24 & 32 bpp at this time. In the property page, you'll hear a beep if image fails to load. In code the LoadPictureGDIplus will return error. Since our last discussion, I also found 1 4bpp but am still concentrating on revamping my SaveAs routines. With 2 examples now, I should be able to add 4bpp support to PCX.

----------


## petersen

Since 4-BPP PCX is hard to come by (CGA & EGA no longer apply nowadays), would you please upload your 4-BPP one (I would like to take a look)?

----------


## LaVolpe

> Since 4-BPP PCX is hard to come by (CGA & EGA no longer apply nowadays), would you please upload your 4-BPP one (I would like to take a look)?


Will do, but will have to wait til later tonight. Its @ home & I'm not. Check back at this post after dinner time. I'll add it below.

Edited: Here are 2 4bpp pcx files.
Note: The one you provided reports as 4 bpp, 1 plane. Everywhere I've read says 4bpp should come in as 1bpp @ 4planes. The attached are 4planes, not 1 plane. But in reality, a parser can treat both as 16 colors and attempt to load it the best it can.

----------


## petersen

Thanks, both are of 1-bit-4-planes.  The one in my zip earlier is of 4-bit-1-plane, so it suits to complement.

I've now added another 4-bit-1-plane file to the said zip.  The newly added one is only different in image width.  What for?  To facilitate testing -- if byte alginment is not right, this one would not be displayed.  (Because of it, I myself have to revise my 4 BPP Read subroutine a little bit for my own programs).  So I thought it would be of use if you are going to implement 4-BPP PCX

Edited: Re your last message



> ....Everywhere I've read says 4bpp should come in as 1bpp @ 4planes....


That is the trouble.  Seems a lot, but most are just copycats, and narrative only.  In practice, I haven't come across any program actually praticing that.  Have you seen even a single one?  (If yes, please furnish the URL, I am curious)

On the other hand, I've seen good-quality shareware program(s) go for 4-bit-1-plane only, despite programs capable of saving 4-BPP are so rare.

----------


## petersen

I've found two such links mentioned earlier, in case you're interested:

XXX.batchconverter.com
XXX.coolutils.com/TotalImageConverter  (Auto 4-BPP if image is 4-BPP)

----------


## LaVolpe

Here's one that will save to 4 planes: http://www.ultimatepaint.com/download.php
The freebie version does pcx too

----------


## petersen

Thanks.  Indeed it does a great job for this particular function, 1-bit-4-plane.

Edited:  Just an observation:  This program (i.e. mentioned in #91) can load only 1-bit-4-plane PCX.  Those mentioned in #90 can load both 1-bit-4-plane and 4-bit-1-plane ones.

----------


## Catsmeat

Hello, new here. The control looks very nice and I got a noob question, will it work with Visual Basic 2010? If so, how do get it into the program and add it to my forms? If it doesn't work with VB 2010, is there something similar I could use? 

Thanks :Smilie:

----------


## LaVolpe

> Hello, new here. The control looks very nice and I got a noob question, will it work with Visual Basic 2010? If so, how do get it into the program and add it to my forms? If it doesn't work with VB 2010, is there something similar I could use? 
> 
> Thanks


Can't answer your question 'cause I don't own .Net (VB2010). Maybe another member can answer that question here? If not, you may want to google a bit searching for: VB6 ocx .Net

I don't even know if .Net supports *windowless* controls created in VB6, let alone whether it supports VB6 controls at all; though I'd assume it might.
You can always compile the ocx and see if you can add it to your .Net project.

----------


## Catsmeat

> Can't answer your question 'cause I don't own .Net (VB2010). Maybe another member can answer that question here? If not, you may want to google a bit searching for: VB6 ocx .Net
> 
> I don't even know if .Net supports *windowless* controls created in VB6, let alone whether it supports VB6 controls at all; though I'd assume it might.
> You can always compile the ocx and see if you can add it to your .Net project.


Ok, thanks for the info. Now I'm a little bit wiser. I'll keep on googling for an easy fix for a while=) If that doesn't work, I'll try to add the ocx thing. :Smilie:

----------


## petersen

La Volpe,

This is but for your reference, as you are using GDI+.

I believe the following would be accepted by you if someone says "For a JPG file, if VB LoadPicture() can load it alright, GDI+ shouldn't have a problem with it."

I've bumped into a case to prove that the above may not be true.  The Sample.jpg inside the ZIP can be loaded with LoadPicture(), but not GDI+.

Inside the ZIP, there is also a VB ready-to-run executable file for testing.  (1) Click Open submenu, in the File Dialog screen you don't see the thumbnail preview when you select the filename.  However, if you continue to just load the file, it would be loaded alright.  (2) Click File Browser submenu, go to the folder containing the subject JPG file (if you don't see the thumbnail displays/rectangles, click Refresh button in the File Browser screen), you don't see a thumbnail preview for the subject JPG file.  However, if you right click the thumbnail rectangle, the image is again loaded properly.   This is because,  in both "1" and "2" cases, GDI+ is used for the thumbnail preview, however, when you proceed to load the file, LoadPicture() is used and that succeessfully loads the image without any problem.

......(URL removed as originally intended) ....
(I will remove the URL later today, latest tomorrow)

Edited:  Further info. I've tested with IrfanView and PhotoShop7, same as VB LoadPicture(), i.e. no problem loading the JPG file.  However, failed on Alpha Image Control.

----------


## LaVolpe

I'll take a look at the file, but am not interested in messing with that attached app.
Interesting nonetheless. MS Paint couldn't load it either (doubt it uses GDI+). Windows Pic&Fax viewer couldn't, but I expect that since it uses GDI+. MS PhotoEditor & VB loaded it just fine.

If I was well versed in JPG format, I might be tempted to look into it further. But as it stands. I see I have just 2 basic choices at the moment.
1) Live with it
2) Attempt to load JPGs via LoadPicture then convert to GDI+ JPG that GDI+ can use

Edited: I think I can work around that issue. GDI+ reports the JPG as 8 bpp & that may be the key? Anyway, GDI+ loaded it, it just reports its bounds as 0x0. I can test for that situation, render it to a GDI+ bitmap & back to JPG to keep it as a JPG. Awkward workaround, but very doable.

*Follow-up*. I have it working now; it wasn't too bad  :Wink: .  The logic I used is as described above: Look for 0x0 successfully loaded JPG. If occurs, load to stdPicture & convert its handle to GDI+ JPG. End result is the image, but at 24bpp in this case, not 8 bpp. I'll be including that patch with the udpated control once I am happy with the new SaveAs routines. 
P.S. Now have working 4bpp PCX read & write routines also.

----------


## petersen

I've already traced to the cause, though of no use to you here.

Just for your info, the culprit is a zero entry in a tag "ED" (the tag and its entry length of 2 are perfectly valid, but GDI+ just wouldn't accept any zero entry).  When this particular tag is removed, GDI+ accepts the file alright.

----------


## petersen

You asked for 16-BPP PCX sample files a little while back; it is not until today that I've bumped into one.  It is a proper 4-bit 4-plane compressed PCX file.  

I now include this siad file in a zip, together with a viewer which is capable of loading it  (click Inquiry --> General Properties, you see 4-bit 4-plane).  IrfanView wouldn't reject the file but doesn't display its image correctly.

.... (removed as originally intended ....
(I will remove the URL a bit later today)

----------


## LaVolpe

Thanx Petersen. Now I can see if my educated guesses will work. I won't be able to download til later tonight when I get home from work. I already have 16bpp routines for TGA & ICO that should work with PCX, more or less.

Edited: Snaggd the image, haven't looked at it yet.
Ah, that was quick. It isn't a 16bpp image. It is 4bpp. The format says 4bpp x 4planes, but there isn't enough pixels to make it 16bpp. It is really 1bpp x 4planes. If you change the BitsPerPixel field in the image format, any viewer that can render 1bppx4planes would be able to load it. Simple math helps prove it.
The image reports 80 bytes per plane and has 4 planes. That equates to 320 bytes per line.
The image is 640 pixels wide. At 2 bytes per pixel (16bpp), the image would need 640*2 bytes or 1280 total bytes.
But at 4bpp (2 pixels per byte), the image would need 640\2 bytes (320 bytes) which is what exists in the format.

----------


## petersen

Yes, you're right.  I myself had been cheated.

I forgot the exact spot where I got it. But I remember it was in a PCX spec/tutorial site, the download zip contains this sample PCX and a subroutine in C.

Sorry that I didn't check it over first, accepting the face value of what was coded in the header (4 bits and 4 planes).  A quick check would have revealed it is a faked one (decompressed bytes are only 112000, a quarter of what they should be).

Edited:  Incidentally, I tried to revisit xxx.ultimatepaint.com/cgi-sys/suspendedpage.cgi, but the link is no longer valid (The Account Is Suspended, the screen shows).

----------


## LaVolpe

Actually, my routines (not yet updated here) read it fine as-is. That is because I've modified my routines a bit to allow for various ways PCX information is reported from what I've read on the web. The logic is basically this.
- 1 Plane = paletted: 1, 2, 4, 8 bpp. BitsPerPixel should always be 1,2,4,8 respectively
- 3 Planes = 24 bpp. BitsPerPixel may actually say 24 in some cases, but should say 8
- 4 Planes = 4 bpp or 32 bpp. 
... 4bpp: BitsPerPixel may say 1 or 4 (as is the case with the pcx file you recently got hold of)
... 32bpp: BitsPerPixel may say 8 or 32 (though not many viewers support 32bpp)

Along with the above assumptions, some sanity checks are employed to ensure the BytesPerPlane*NrPlanes >= image's expected scanwidth. Now those checks will fail to render a true 16bpp PCX correctly, but until I find several of them, I honestly don't care -- they may not even exist? And if they do exist, will they be 4x4 or 8x2? 

The true problem is interpretation. Some obviously feel that BitsPerPixel is literal & make this field read 1,2,4,8,24,32. While others interpret it to be BitsPerPixelPlane to be multiplied by number planes and then the only possible values would be 1,2,4,8. Though I haven't heard of, nor seen a 2 bit x 2 plane 4bbp image. Haven't seen a 2bpp image yet either; but coded for it.

The only issue I have with trying to support foul-ups, is that it is black and white to me. When I find the PCX format online that references ZSoft throughout, this is their description for the BitsPerPixel field, which clearly states BitsPerPixel is per plane not for the image itself.



> Number of bits to represent a pixel (*per Plane*) - 1, 2, 4, or 8

----------


## petersen

You and I are the last dinosaur in PCX world nowadays.  Since my first posting in the other thread, and following our recent discussions,  on and off I've played a little bit of it still.

For example, by changing the sequence of 16-color palette entries, the resultant file sizes can vary tremendously.  Per the attached zip, for a normally compressed file the size is 13k, but with a suitable arrangement in the sequence of palette entries (and with a good algorithm) it can be reduced to only 5k, on the other hand, an unsuitable change in sequence may result in 23k.

I think the above should be my last play of PCX.

----------


## LaVolpe

I'd think that palette order would optimize file size. Makes perfect sense to me.
Regarding 16pp. If I get truly interested enough, I'd create a 4x4 & 8x2 555-format 16bpp pcx and see if any of my few viewers can read it. If it can, I might support the one(s) recognized. But that will wait until I have time to play & feel like it  :Wink: 

FYI: With your zip... Using the badly compressed one, when saved via my current routines, it saved it at 10k. Not too bad. The palette is sorted numerically; otherwise no optimizations made. I don't plan on making it a goal of the AlphaImageCtrl to optimize palettes. The user will have the option to provide their own palette when saving, so I'll leave that to them.

----------


## petersen

Again, just for your info.

I've stumbled into a GDI+ bug again -- GdipGetImageThumbnail() fails to load an ordinary JPG file which otherwise is alright with LoadPicture(), AZ Paint Pro, IrfanView, MS Paint and PhotoShop etc.  I thus avoid using GdipGetImageThumbnail in any of my programs.

Unlike that per my Posting #98, this time I cannot trace to anything special about the subject JPG file.

----------


## LaVolpe

> Unlike that per my Posting #98, this time I cannot trace to anything special about the subject JPG file.  (If you are interested, I can supply you with the subject JPG).


Only if it doesn't load in the alpha image control. I also don't use the thumbnail function

----------


## jay55

Hi LaVolpe,

i'm a long time lurking fan of your work, great job, really.

i just looked into using your animated control and am having a problem displaying a gif.  code looks like this:



```
Private Sub Form_Load()
    AlphaControl.Animate lvicAniCmdStart, 1
End Sub
```

this form is being called from elsewhere as



```
Theform.Show
```

which then returns to doing work.  I tried inserting a DoEvents and Sleep(100) to get the animation going, but it doesn't work, only the first frame is shown.  the picture, an animated .gif, was pre-loaded through the property page.

any ideas?

J

----------


## LaVolpe

Jay, sorry I didn't notice your post earlier, been trying to wrap up this latest update. 
I admit that my animation class/methods can use a little work. I'm open to feedback/suggestions. 

Edited: I do see something I had to track down. When you called that method, the control did not know it was in runtime and that is wrong. The real patch, I'll include in the next minor update. But to get past the problem for now, try this instead. 


```
' in your form load... change to
    DoEvents ' should allow the control's internal Show event to trigger & set the flags appropriately
    AlphaControl.Animate lvicAniCmdStart
    AlphaControl.Animate lvicAniCmdSetLoopCount, 1 
    ' ^^ this sets the loop count, but must be called after animation starts. It think that is what you were trying to do?
```

For all.  *NEW VERSION OF CONTROL UPLOADED* to post #1
Any previous version is no longer compatible; way too many modifications and changes

----------


## Stidor

Hi LaVolpe,

Is there a process to updating your ActiveX control in a project that's already utilizing a previous version?

When I replace the LaVolpeAlphaImg.ocx file with a newly compiled one, I can no longer open the project. It basically errors out as if it can't find the control. I assume because the new version compiled has a new GUID.

Never really had to do this before for an ocx.

----------


## LaVolpe

> It basically errors out as if it can't find the control. I assume because the new version compiled has a new GUID.


That's the reason. For future versions, I'll make every attempt to keep it backward compatible. However, I have made so many modifications to this new update that it wasn't possible. It is a "new" control. The version in this is set a 2.0.0.  Future updates will be incremented 2.1.0 etc as needed. If for some reason I have to break compatibilty and create another version, it will be 3.0.0

I know it is a bit inconvenient, but in this case, there really wasn't much of a choice.

Edited: One way to try to overcome it, is to compile the control, add it to a new project and save it. Then go inside the vbp file via notepad and copy the reference (found near top of file). Then open your other project and find the reference & paste over it. You'll need to do this for both frm & vbp files.  Once done, open project in VB & press Ctrl+F5 and fix any changes in constant names, method parameters that cause an error. Press Ctrl+F5 again and again until no more errors.

Note. When compiling, you may want to add the version number at the end of the filename, i.e., AlphaImgCtrl2.ocx

----------


## Stidor

While playing around trying to get it to update I had actually done sort of what you have suggested.

I got a copy of the new GUID and pasted it into my current project's vbp file. (overwriting the old one)
Then I overwrote the LaVolpeAlphaImg.ocx file.

Voila. I don't know why but it's now working fine, I didn't have to change it anywhere else. This doesn't seem right though. Does it? I'm running through some tests and it seems to be working without any errors under the new v2 OCX.

----------


## LaVolpe

Give it a good test. Hint. If you were calling the SavePictureGDIplus function, look at those carefully. They had a few optional parameters. The new version got rid of one parameter. And if you supplied it, then that parameter may be shifted one to the right which will cause an error and/or unexpected effects. That is the only major issue related to functions that I can think of right now. You obviously did not dim a variable to one of the following; else errors should have been reported
- RENDERSTYLESTRUCT, no longer used & now is RENDERSTYLESTRUCT2
- MULTIPAGETIFFSTRUCT, structure changed
- MERGEINFOSTRUCT, structure changed
- lvicSaveAsTarga, changed to lvicSaveAsTGA

Dim a variable as SAVESTRUCT. If you get no errors, you are referencing the correct version. That structure didn't exist before.

----------


## Stidor

I don't believe I used any of those. At the moment I'm more or less only using it to display .png images in my controls. (Also slowly replacing all my other GDI related code that this control can now do instead)

Loving the load from URL addition to the control, also the mouse pointer/cursor properties. I hadn't updated in awhile so lots of new stuff for me.

Thanks a bunch LaVolpe, loving your work.

----------


## LaVolpe

> ...Also slowly replacing all my other GDI related code that this control can now do instead...


If you think whatever code you won't be replacing would be beneficial to the masses, submit its purpose here as a possible enhancement. I'm all for making the control more complete, but I'm not for making it a complete image processor.

----------


## LaVolpe

Bug report for WMF. Actually a GDI+ bug I think.
If interested, you can follow-up on my trial and error troublehsooting in this thread. But to make a long story short, GDI+ and VB6 don't play nice when GDI+ used to create a WMF.

I've fixed all the issues I knew about, but encountered a new one today. If the source image being converted to WMF consists of only black and white colors, then regardless of the bit depth of the source (1,4,8,16,24,32 bpp), the WMF during runtime has white become transparent.  I've included a patch in my local copy that appears to be ideal. Basically, the patch will ensure that if the scenario happens where only 2 colors are used (black and white) then black will be changed to a value of 1 vs. zero. This appears to work quite well.  I have a couple of other minor things to update too. Will wait til end of this week to post the patches. Want to see if I or you find any additional ones.

Edited: Similar issues existed with other formats

PCX & TIFF: If 1bpp image was not black and white, but say red & yellow, PCX/TIF displays all 1bpp as black & white.
The fix to that was to ensure the color depth was minimal 4bpp when 1bpp images were not black and white. 

ICO/CUR: VB-only. 1bpp color icon/cursor is not affected, but if a 1bpp black & white icon/cursor is loaded into a stdPicture object (.Picture/.Icon property), it is resized by VB to 32x32 regardless of image's actual size. This issue hasn't been addressed yet. It isn't VB, but rather one of the OLE APIs I use to create the stdPicture object. If the same icon is loaded via LoadPicture() and a file, no resizing occurs. Will be addressing this in next minor update. 
_Edited: Found fix for this issue_. Will include in next update

I discovered those annoyances a couple weeks ago.

----------


## petersen

> *Original post by La Volpe*
> PCX & TIFF: If 1bpp image was not black and white, but say red & yellow, PCX/TIF displays all 1bpp as black & white.
> The fix to that was to ensure the color depth was minimal 4bpp when 1bpp images were not black and white.


I haven't read your other comment lines yet, but regarding the above-quoted point it is my opinion (and practice) that:

(1) If an image has two colors which are not B&W, it shouldn't be saved as 1-BPP.

(2) To save as ICO file, if the image has 16 or below colors, but one or more of them are outside the 16 static colors, not to be saved as 4-BPP.  Some programs adhere to this and I myself had encountered at least two of them, e.g. WinZip Self-Extract (it disallows a non-standard 4-BPP icon file).

To exemplify the above practice, here is a PNGnMNG program, written in VB.  Its submenus under File main menu has the following (omong others): Save As BMP (Auto 32, 24, 8, 4 or 1), Save As PCX (Auto 24, 8 or 1) and Save As ICO (Auto 32, 24, 8, 4 or 1).  Now if you feed a 2-color image but with a non-B&W color, saved file is 4-BPP.  If you feed a 16-color image but with a color outside 16 static colors, saved ICO is 8-BPP.  Of course if you feed a 32-BPP image, the saved ICO will be 32-BPP even after the loaded image has been resized and/or rotated.

.....(removed as originally intended.....
(URL will be removed a bit later, latest by tomorrow).

----------


## LaVolpe

> (1) If an image has two colors which are not B&W, it shouldn't be saved as 1-BPP.
> 
> (2) To save as ICO file, if the image has 16 or below colors, but one or more of them are outside the 16 static colors, not to be saved as 4-BPP.  Some programs adhere to this and I myself had encountered at least two of them, e.g. WinZip Self-Extract.


1) Personal opinion. Why double the size of file if not needed? 1 bpp compresses to 8 pixels per byte vs. 2 pixels per byte for 4 bpp. Windows Bitmap supports 1 bpp non-B&W images. So do icons & cursors.  1 bpp means 1 or 2 colors, not B&W. But, if an image format always interprets 1bpp as B&W only (PCX,TIF), then there is an exception obviously.

2) Not sure I understand your statement. "Static colors"? Halftone? Some arbitrary palette? If I'm guessing at the context correctly, then adhering to palette colors for systems that cannot support more than 16 colors is a bit antiquated IMO; almost like ensuring our code meets Win3.1 standards.  However, because the user can supply their own palette, they can be guaranteed that no colors will be used outside of that palette. The user makes the determination, the code does not.

----------


## petersen

I don't want to enter into a debate, we may talk theory and MS rules and decrees the whole day, but the practices may still differ.  As I specified, there are programs still adhere to the old rules, and if I don't adhere to the same, my customers will blame me when they cannot load their icons to WinZip SelfExtract program (for shareware program installation use).  Over the years I had also encountered programs practicing the same as WinZip (through customers' feedback).

By 16 static colors, I meant the following 16 colors &HFFFFFF, &H808080, &HFF00FF, &HFF&, &HFFFF&, &HFF00&, &HFFFF00, &HFF0000, &HC0C0C0, &H0&, &H800080, &H80&, &H8080&, &H8000&, &H808000 and &H800000

I still adhere to the above on saving 4-BPP ICO, but laxed for other file formats.

----------


## LaVolpe

The static colors you mentioned are what I call the Halftones. The default palette types offered are halftones for 16 & 256 colors. 

The user (the coder, not a customer) has full control.
- If coder wants default colorless reduction, then if reduction results in 4bpp or 1bpp that's what they get, whether the palette contains halftones or not.
- If coder wants palette reduction to 256, 16 or b&W using default palettes, then the colors are guaranteed to be halftones
- Likewise, the coder can provide their own palettes

This control isn't the decision maker, other than ensuring the saved image can be read in the image format it is saved in. What colors, effects, sizes, etc, etc, are in the coders hands.  If someone wants to argue that the coder doesn't know whether an icon should be paletted in hafltones, or if WinZip will accept it if not, then the coder needs to do the research as you did.  The control offers a ton of flexibility, it forces nothing on the coder without offering other options/workarounds.

----------


## LaVolpe

I've been asked twice now... "How do you apply multiple version 1.1 effects to an image?" Honestly, I don't know the answer. Can it be done in one call? The key function only accepts one effects handle. So, I don't think it can be done in one call. But since this control exposes all, a little GDI+ knowledge and some fun, we can do it  :Wink: 

Note: *v1.1 of GDI+ required*. Vista or better. See posts #1 thru #3 for a bit more on v1.1 of GDI+
1. Add two alpha image controls to your form and one command button. Leave default control names
2. Place an image into the 1st alpha image control. Size 2nd control to 1st control's size
3. Copy and paste this code


```
Option Explicit

Private Declare Function GdipGetImageGraphicsContext Lib "gdiplus.dll" (ByVal pImage As Long, ByRef graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus.dll" (ByVal mGraphics As Long) As Long
Private Declare Function GdipGraphicsClear Lib "gdiplus.dll" (ByVal graphics As Long, ByVal pColor As Long) As Long

Private Sub Command1_Click()

    ' Tip. If the image is to be rotated, grayscaled, or any other non v1.1 effects, do that
    ' either first or last via a call to SavePictureGDIplus and filling out a SAVESTRUCT.

    Dim cFX As GDIpEffects
    Set cFX = New GDIpEffects
    ' create the v1.1 effects you want to apply
    cFX.CreateBlurEffect 2, True
    cFX.CreateBrightnessContrastEffect 40, -10
    cFX.CreateTintEffect 180, 40
    ' call this makeshift function & pass the effects in order that you want them applied
    Set AlphaImgCtl2.Picture = MultiEffectToImage(AlphaImgCtl1.Picture, cFX, lvicBrightnessContrastFX, lvicTintFX, lvicBlurFX)

End Sub


Private Function MultiEffectToImage(Source As GDIpImage, FXclass As GDIpEffects, ParamArray Effects() As Variant) As GDIpImage

    If GDIplusTokenVersion < 1.1 Then Exit Function ' need to have right version for effects

    Dim X As Long, Index As Long
    Dim hGraphics As Long
    Dim cImages(0 To 1) As GDIpImage
    Dim SS As SAVESTRUCT
    
    ' want a graphics object for this function to work. Can't have one if image is paletted.
    ' Need a copy anyway, so might as well just create a saved version in the right bit depth
    If Source.UsesTransparency Then SS.ColorDepth = lvicConvert_TrueColor32bpp_ARGB Else SS.ColorDepth = lvicConvert_TrueColor24bpp
    Set cImages(0) = New GDIpImage
    If SavePictureGDIplus(Source, cImages(0), lvicSaveAsPNG, SS) = False Then Exit Function
    Set cImages(1) = LoadPictureGDIplus(cImages(0)) ' copy the one we just made
    
    For X = 0 To UBound(Effects)
        ' now toggle between the two images, rendering the effects
        If GdipGetImageGraphicsContext(cImages(Index Xor 1).Handle, hGraphics) = 0& Then
            GdipGraphicsClear hGraphics, 0&
            cImages(Index).Render 0&, , , , , , , , , , , hGraphics, FXclass.EffectsHandle(CLng(Effects(X)))
            GdipDeleteGraphics hGraphics
        Else
            Exit For
        End If
        Index = Index Xor 1
    Next
    If X > UBound(Effects) Then Set MultiEffectToImage = cImages(Index)

End Function
```

*Edited*: Another version, no GDI+ knowledge needed. Just needed to put my thinkin' cap back on.


```
Private Sub Command2_Click()

    ' Tip. If the image is to be rotated, grayscaled, or any other non v1.1 effects, do that
    ' either first or last via a call to SavePictureGDIplus and filling out a SAVESTRUCT.

    Dim SS As SAVESTRUCT, cImage As GDIpImage
    Set SS.RSS.Effects = New GDIpEffects
    Set cImage = New GDIpImage
    ' create the v1.1 effects you want to apply
    SS.RSS.Effects.CreateBrightnessContrastEffect 40, -10: SS.RSS.EffectType = lvicBrightnessContrastFX
    SavePictureGDIplus AlphaImgCtl1.Picture, cImage, lvicSaveAsPNG, SS
    ' ^^ using PNG as destination to avoid issues if original image format doesn't support colors/effects
    
    SS.RSS.Effects.CreateTintEffect 180, 40: SS.RSS.EffectType = lvicTintFX
    SavePictureGDIplus cImage, cImage, lvicSaveAsCurrentFormat, SS
    
    SS.RSS.Effects.CreateBlurEffect 2, True: SS.RSS.EffectType = lvicBlurFX
    SavePictureGDIplus cImage, cImage, lvicSaveAsCurrentFormat, SS
    
    ' any other effects? If not, then...
    Set AlphaImgCtl2.Picture = cImage

End Sub
```

The above code is an example only. You should provide more error checking as needed/wanted.

And yet another method which is what I'd personally use if I wanted faster results.
1. Create a GDI+ bitmap 2x height and same width of source
2. Set clipping rect to top half, render source to top half using effects#1
3. Remove clipping rect & set new clipping rect to bottom half, clear bottom half, render top half with effects#2 to bottom half
4. Now continue toggling between top & bottom halves for remainder of effects, clear it before rendering
5. Create new GDI+ bitmap same size as source. Render last drawn half to it & clean up.
This method should be fastest I'd think. Oherwise, method 1 above will be faster than method 2 above because you aren't saving the image after each effect is rendered.

----------


## LaVolpe

Version 2.1 uploaded today. Some patches, but new enhancements:
- Added LoadPictureGDIp.rtf file & provides more detailed info regarding loading images
- Load images from within binaries (exe, dll, ocx)
- Save image or control as rendered to GDIpImage class
- Paint image or control as rendered to an hDC
- Added ImageGroupFormat to GDIpImage class to allow testing type of group when loading images from binaries

I still need to go back & start adding more comments/remarks to the latest additions. Will do when time permits.

----------


## LaVolpe

FYI: New bug found. When saving to a stdPicture object as a cursor, the image comes out as black and white. I believe this is a bug related to the OLE API I use. VB exhibits this same effect when you load a cursor during design time into an image control or picturebox. I have a workaround and will apply that in the next update at end of the week. Additioinally, I'll include any other patches that may be reported between now and then. 

One enhancement will be added for more advanced users. Currently, one has no way of creating a blank GDI+ bitmap, other than creating a DIB and passing it to the LoadPictureGDIplus routine. Unfortunately, if the DIB is 32bpp, the GDI+ bitmap/image will automatically be created with a format of 32bpp pARGB (pre-multiplied alpha). The added enhancement will allow you to create a bitmap of any bit depth, passing optional palette if desired, and configuring 32bpp GDI+ bitmaps as either RGB, ARGB, or pARGB. If creating a 24bpp or 32bpp bitmap, then it can be used to render to directly using the GdipGetImageGraphicsContext API. This new ability will be part of the SavePictureGDIplus function, not the LoadPictureGDIplus function. Choice made to maintain binary compatibility without adding a new function for this purpose.

----------


## jicxicmic

Hi,

First of all, Thanks for your work.

I'm using the abilility of your control to rotate/resize images to minimize the number of images of each product  I need on my aplication, also it enabled me to use .PNG format.

Basically I use your control to show the image on distinct forms, no problem at all.
There is an exception, that is msflexgrid. It only works with StdPicture, so I use your control to generate the proper image (resized and rotated), in that case, your control has visible=false , an here apears my problem. I couldn't find how to get it with transparent color.
I've use SaveImageAsDrawnToGDIpImage function to obtain the image, as SaveControlAsDrawnToGDIpImage(True) doesn't work if control is not visible.

Any Idea ?

Attached there is an small project where i test it

----------


## LaVolpe

I'll take a look, but keep this in mind... stdPicture doesn't support transparency except for GIF or Icon. This means that you'll need to save the image to stdPicture format as a GIF or Icon. Both may produce jagged edges on rotated images. GIF supports 256 colors only, icon is true color. SaveImageAsDrawn... will return image in PNG format; so this may help but with limitations noted above.


```
    Dim tStdPic As StdPicture
    Dim tAlphaImg As GDIpImage
    
    Set tAlphaImg = AlphaImgCtl1.SaveImageAsDrawnToGDIpImage()
    Set tStdPic = New StdPicture
    SavePictureGDIplus tAlphaImg, tStdPic, lvicSaveAsIcon
    ' tStdPic now has the stdPicture (icon)
    ' if having issues with lvicSaveAsIcon, then try lvicSaveAsGIF
```

Edited: I haven't looked at your zip file; will do that later tonight when I'm home.

----------


## jicxicmic

Hi LaVolpe,

I got working ussign PNG format (fantastic, I got  a lot better quality), I've  surprised, because i thought Image control doesn't support PNG, ( maybe is only LoadPicture function).

But my problem continues, SaveImageAsDrawnToGDIpImage doesn't keep the transparent color, and SaveControlAsDrawnToGDIpImage doesn't work if control is not visible. I've tested with a visible control and SaveControlAsDrawnToGDIpImage works just perfect.

Another question, I've noticed if I resize the image to small size, and latter I try to resize to bigger size, doesn't work properly (I got diferent sizes ???), I've so set to original size first, and after that set to the desired size. Is the way it is suposed I've to go ? (on my test I use a big image, so usually I reduce the size)
Example: Original image is 20.000 width, I resize to 1.500 and latter to 10.000 

Thanks in advance.

jicxicmic

----------


## LaVolpe

SaveControlAsDrawnToGDIpImage won't work with non-visible control. This is because the control needs VB to send the Paint event to the control. VB won't do that if the control is not visible or if the control is visible but not on the screen. Without the paint event, the control has no DC to draw to since it is windowless. I've tried all I can think of to force VB to send the event, but it won't in those scenarios.

Comments about your post. 
1. The image control does not support PNG. When you save the control or image to stdPicture, the returned image in the stdPicture is bitmap. But bitmap doesn't support transparency, GIF & ICO do.

2. SaveControlAsDrawnToGDIpImage does keep transparency because the image inside the returned GDIpImage class/object is PNG. However, saving the PNG to stdPicture is where you loose transparency.
Edited: Unless you also choose to include the container's background. In that case, transparency is lost because the control's container is not an alphablended bitmap.

Using your sample project, I think the workaround is to use the SAVESTRUCT. Modified your routines as follows. What do you think?


```
Private Sub Horizontal_Click()
    Dim Cx As Long, Cy As Long
    GetScaledImageSize AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 140, 140, Cx, Cy, , , False
    SaveOptions.Width = Cx: SaveOptions.Height = Cy
    LoadImageIntoControl
    SaveOptions.Width = 0: SaveOptions.Height = 0 ' reset; will use actual size if these are zero
End Sub

Private Sub Vertical_Click()
    SaveOptions.RSS.Angle = 90
    SaveOptions.RotatingCanGrowImage = True
    LoadImageIntoControl
    SaveOptions.RSS.Angle = 0 ' reset
End Sub

Private Sub LoadImageIntoControl()
    Dim tPic As StdPicture
    Image1.Picture = Nothing
    Set tPic = New StdPicture
    If SavePictureGDIplus(AlphaImgCtl1.Picture, tPic, lvicSaveAsBitmap, SaveOptions) Then
        Image1.Picture = tPic
    End If
End Sub
```

----------


## jicxicmic

Hi LaVolve,

I tryed but I don't understant how it works. Let me explain

Horizontal function:
it resize the image on both ways, (getting bigger and smaller than original), but I don't undertand how it works

GetScaledImageSize AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 140, 140, Cx, Cy, , , False

it is just to calculate Cx and Cy ? what are 140 ? I wanted 400 twips height, how to convert ?


Vertical function does rotation but not resize, I've mixed vertical plus horizontal functions and works ok.



```
Private Sub Vertical_Click()
    Dim Cx As Long, Cy As Long
    GetScaledImageSize AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 140, 140, Cx, Cy, 90, , False
    SaveOptions.Width = Cx: SaveOptions.Height = Cy
    
    SaveOptions.RSS.Angle = 90
    SaveOptions.RotatingCanGrowImage = True
    LoadImageIntoControl
    SaveOptions.RSS.Angle = 0 ' reset
    SaveOptions.Width = 0: SaveOptions.Height = 0 ' reset; will use actual size if these are zero
End Sub
```

I got a good image but there is a blank area on left and bottom sides as if resized image doesn't fit the painting area. Again, how I can select the desired size ?

Thanks

----------


## LaVolpe

GetScaledImageSize will return the value of the width & height of the image scaled to whatever dimensions are passed. That function accepts pixels & returns pixels, in fact the entire control uses pixels only, not twips.  So, I took the 140 in your example (140*14). If you want to use twips simply supply this value instead of 140:  1400\Screen.TwipsPerPixelX. That will convert twips to pixels for the control.
Edited. If you don't use GetScaledImageSize, then whatever width/height you supply in SaveOptions will result in the image being stretched to those dimensions. GetScaledImageSize is used to keep image's aspect ratio in tact.

In your example, the vertical function wasn't resizing. If you want to resize, set the SaveOptions Width & Height members to the size of the image you want, scaled or not.  The RotatingCanGrowImage member works like this: If set to true and you want the image sized say 100x50, then the image will be 100x50 rotated, but the overall size of the picture may be larger to enable a 100x50 rotation. If set to False, then the overall size of the picture will be 100x50 and the image will be rotated inside that 100x50 bounding rectangle. The actual image will be smaller than 100x50. Understand? If I'm not being clear, simply try it. Set the Angle at 45 degrees and save image with and without that member set to true to visually see the difference. Don't only pay attention to the size of the returned stdPicture, notice the size of the actual image also.

When using SaveImageGDIplus, the actual size of the image or the control is not important unless the SaveOptions Width & Height are zero & in that case, then the actual size of the image, not the control, is used.

In your case, since you are hiding the control, it is only serving the purpose of containing the image, similar to a hidden VB image control. If you have further questions, please repost your sample project and include a screen shot in that zip of what the end result should look like & I can offer a suggestion or two.

----------


## jicxicmic

Hi LaVolpe,

Had been very helpfull.

It is running perfect.

Thanks a lot.

----------


## LaVolpe

Control updated today. See Post#122 above for reasons.
The SavePictureGDIplus function can now create a blank GDI+ bitmap. The included SavePictureGdip.RTF file describes how this is accomplished.

Edited. Updated one more time on 4 Mar 2011 with minor corrections & one minor enhancement. See 1st post for more info

----------


## LaVolpe

*UPDATED 11 MAR 2011 to fix below issues*

Bug report regarding animation.

1. When the control is animating, some annoyances have been noticed and will be addressed. My initial plan for animation was to stop/pause animation when the control's visible property set to false and restart/resume when visibility returns. However....

a. When control is visible and animating, animation does stop when control's Visible property set to False. It does restart when Visible reset to True
-- This scenario does not apply if AnimateOnLoad=False. This will be fixed. Scenario must not be limited to that property, but rather the fact it is animating or not

b. When control's Visible property is set to False at design time and at runtime if AnimateOnLoad=True or animation started manually, the control will attempt to animate. It won't paint but will change frames. Got that half right but also half wrong.

c. The control has no way of knowing thru VB events that any parent/container objects it may exist in changes visibility to false. This results in the container not visible, but the control animating (not painting but changing frames).

d. The control actually doesn't even know if it is invisible on start up. The usercontrol's Show event triggers initially whether the control's Visible property is True or False. This means when control Visible=False, it will attempt to animate if AutomateOnLoad=True (not painting but changing frames)

2. The default minimal frame interval is set to 10 ms if no frame interval has been provided in the animated resource. This default is way too low and will be increased to 50-80 ms; not sure yet. 

3. Matter of education vs. bug. 

a) The more controls you load that are animating, the higher CPU usage goes. The faster the animation, the higher CPU usage goes. Loading a dozen or so animated gifs, all animating at ridculous fast speeds (say 10-20 ms) can eat up 80% or more CPU usage. If these were animating say 50-100 ms, cpu usage should drop to the teens or low-20s at most.

b) When control is inside a container (picturebox, frame or even the form itself), if the container is made invisible by setting its Visible property to false, the control is not notified and does not pause/stop animation. *Animation continues*. You should loop thru your controls in a container that becomes invisible and stop/pause animation manually. If container becomes visible again, loop true controls and start animation again as needed. 

Edited for paragraph 3b. What I wrote above is a good workaround to pause/stop animation when a control's container goes invisible, since you, the coder, dictate that.  To automate pause/resume due to visibility change, will take some thought. Theoretically, the control can exist in several layers deep of containers (i.e., picbox in a picbox within another picbox inside yet another picbox, etc, etc). If any of the control's containers go invisible, then animation should pause. I have an idea that does not include hard-referencing containers nor uses subclassing. If it pans out, I'll include it in the update that fixes annoyances noted above.

Another issue I've just discovered....
The AnimationFrameChanged event has a parameter called Index. That will cause problems if the AlphaImgCtl itself is an indexed control
Without being indexed, event looks like: Private Sub AlphaImgCtrl1_AnimationFrameChanged(Index As Long)
But with being indexed, event looks like: Private Sub AlphaImgCtl1_AnimationFrameChanged(Index As Integer, Index As Long)
In the latter case VB will give you an error. The simple workaround is to manually change the 2nd Index from Index to Frame or some other word besides Index. The workaround will be for v2.1.4 and earlier. When I update the control, Index will become Frame and binary compatibility will be maintained

Edited. Follow-up. I think I have all the workarounds and will post 11 Mar 2011.
1. When animating, animation pauses and resumes when visibility is toggled
2. When not visible, animation will not start. If AnimateOnLoad=True or a call to manually start animation while invisible, then animation starts when made visible
3. If any higher level container is made to be invisible, animation will pause until container becomes visible again; then it will resume
4. The default minimal frame rate if no rate is supplied by the image resource or by you, will be 75 ms. It is a constant in cAnimator class and can be modified by you if desired

----------


## LaVolpe

Potential mod forthcoming.

Problem: I found myself wanting to resize a WMF image. Ok, no biggie for 99.9&#37; of the cases. But I know that WMFs are vector graphics that can be resized without any distortion. In this case I wanted to resize a portion of the image to something like 8x without any alphablending effects or distortion. Not possible with the control's current code

Background. WMF/EMF are converted internally to PNG. This is to allow them to be rendered with special effects, rotation, mirroring and other effects that are not possible if the image is in metafile format. Resizing the image is the same as resizing a PNG in this case. That means you get good quality stretching but alphablending is used to produce the quality. The metafile, itself, is never used during resizing; whether or not it is maintained by the control. If not familiar with raster vs. vector, here is a perfect example of what I wanted but is not available with the control, as is.

Therefore, I am messing with ideas on how to use metafiles for resizing only but internally still maintained as PNG for special effect purposes. I think this will be an optional property on the usercontrol, named something like: UseVectorResizing. If used, and if ActualSize is false and only if metafile is cached by the control, then when control is resized the cached metafile will be reloaded via GDI+ to a temp image, rendered at the required size, then GDI+ temp image destroyed. This will obviously be a speed hit. Still entertaining ideas on this...

*Edited*: Though I realize this is a shortfall in my control, I may not be modifying after all, for this purpose. It can be handled with outside routines or even not using the control at all but using a graphics editor for this purpose. I want to avoid the control becoming a mini-graphics editing program and want to keep it just as a control; not an application. Even I need to re-evaluate my original intentions from time to time, so I don't get into the "_make this thing more than what it was intended to be_" mindset  :Wink:

----------


## paulsoulsby

Hi,

This project is amazing!!  I have a question about animations though:

I have a png sequence that I want to load into the control as an animation.  Can I do this easily, or will I need to create a single png with all the frames in a grid.  It's quite a long animation, so would take a while to do!

I've had a look at the animation example, but can't see how you actually load the animations!

Paul

----------


## LaVolpe

Paul, I see you have a few choices
1) convert to animated GIF. Not good choice since gifs don't support variable alpha blending your PNGs probably have
2) convert to animated PNG format. Post #53 has a link for such a utility. Never tried it though
3) convert all images to multipage TIFF (these can be animated too)
4) load all images in separate controls and create your own manual animation via a timer and hiding/showing 'frames'
5) convert to a single PNG and can easily be done with this control's MergePictureGDIplus function...

Example for #5. 
a. Add 1 alpha image control to your form and 1 command button
b. Leave all default values and paste below behind your button's click event


```
' I'm going to assume all your PNGs are same size and named similarly
' example file name: mySeq1.png
    Dim X As Long, PMS As PICTUREMERGESTRUCT
    Dim sPath As String, Cx As Long
   
    Const NrImages As Long = 8 ' change to actual number of your 'frames'
    sPath = App.Path & "\" ' change to where your 'frames' are located on disk & ensure trailing slash
    
    PMS.Pictures = NrImages         ' how many images
    ReDim PMS.MIS(1 To NrImages)    ' array of image classes
    
    With PMS.MIS(1)                 ' get first image & base overall new image off that
        Set PMS.MIS(1).Picture = LoadPictureGDIplus(sPath & "mySeq1.png", False)
        Cx = .Picture.Width
        PMS.CanvasHeight = .Picture.Height
        PMS.CanvasWidth = Cx * PMS.Pictures
    End With
    
    ' if you got an error above or get one below, check your path & filename you are trying to load
    
    For X = 2 To NrImages           ' process remaining images
        Set PMS.MIS(X).Picture = LoadPictureGDIplus(sPath & "mySeq" & X & ".png", False)
        PMS.MIS(X).RSS.Quality = lvicNearestNeighbor ' prevnets potential alphablending on frame edges
        PMS.MIS(X).Left = Cx * (X - 1) ' set offset to render to
    Next
    
    ' now test what was just done....
    Set AlphaImgCtl1.Picture = MergePictureGDIplus(PMS)
    Erase PMS.MIS                   ' free up some memory; destroy loaded images
    
    AlphaImgCtl1.Picture.SegmentImage NrImages, 1, , 50
    AlphaImgCtl1.AutoSize = lvicSingleAngle ' force control to size to actual size
    AlphaImgCtl1.AutoSize = lvicNoAutoSize ' remove auto-size during animation (performance reasons) 
    AlphaImgCtl1.Animate lvicAniCmdStart
    
    ' if it appeared find, unrem these next lines
'    AlphaImgCtl1.SegmentImage 0, 0 ' unsegment
'    SavePictureGDIplus AlphaImgCtl1.Picture, sPath & "AnimatedSeq.png", lvicSaveAsCurrentFormat
```

Note: Nice brain teaser and unfortunately, found a bug in the property page regarding segmented images (result of a previous patch). I'll have to fix that. If you opted for #5 above, you will have problems segmenting the image in the property page. You can segment it during runtime using similar code as I did above (SegmentImage method). I'll have a patch for the property page in a day or two (need to find some time to update it).

Edited: Regarding animation settings. Those can be done via code or via the property page. To show the property page for any of the controls, simply right click and select properties.

----------


## mOBSCENE

Hey LaVolpe,

When I put the project into my other project, LOOKS fine, but two small worries...

When I add the control to a form, the other controls get those ascending diagonal lines of doom. (But that's no big deal, I just update UC's.)

Here's the real problem...I can't add images! I get to the property pages, and I press Browse, and I get Runtime Error 2 "The common dialog box function failed during initialization."
It happens when I right click -> properties, and when I go through Custom! :x

o.o

Halp! :3

----------


## LaVolpe

1. Are you adding this control uncompiled or compiled to your project? 
2. Regarding the common dialog, it is an API version not the VB6 version. What operating system are you running?

----------


## mOBSCENE

Uhh...I'm adding it through the IDE as a .vbp file. That probably means uncompiled. :P

Operating System: Windows 7

----------


## LaVolpe

Recommed you compile the usercontrol project to an ocx. Then open a new project, open the components window (Ctrl+T) and look for it. It will be called 'LaVolpe's GDI+ Based Image Rendering Control'. Add it to a form and see if you have any issues. I don't own Win7, so I can't help there if that error continues, but am willing to research some guesses if that error continues.

----------


## mOBSCENE

Hmm...That means I'd have to give out the OCX with the program, yes?

----------


## LaVolpe

I mentioned in the 3rd post, page 1, that I did not write this control to be merged with other projects. I wrote it to be used as a stand-alone OCX. So either the answer is Yes, or if you want to troubleshoot it and tweak it to work inside your other project(s), have a go.

----------


## mOBSCENE

Ahh. I'll see what I can do. Thanks anyways, you're a great programmer.  :Big Grin:

----------


## LaVolpe

Thanx. Let me know if you discover the reason for that initialization error. Per MSDN, it is most likely due to low memory, but I think that is their default answer for everything  :Wink:

----------


## LaVolpe

Patch applied to fix issue noted in post #134 above.

----------


## mOBSCENE

I realized it has something to do with command dialogs of any sort in VB6. I have a hunch that it has SOMETHING to do with being on a 64bit computer. SysWOW64<->System32 and all that hogwash, probably.

EDIT:

I've also gathered that it works fine outside of the IDE. Like on your 32bppSuite. Works compiled, but not in the IDE. What is this bull?

----------


## LaVolpe

The control itself cannot do what you are looking for. GDI+ does not support perspective transformation. It would require a custom function/class to manually transform/move pixels from source to perspective destination. One idea may be worth investigating (assuming you can't find a good GDI+ example) is to paint each vertical column of pixels from source to destination, accounting for the destination height and column width relative to the source column. Basically like filling the destination with vertical stripes, but the stripes are relative to the 'stripes' in the original image.

The rotation you are discussing can be better visualized in the following link. You'll see 2 examples: a) non-perspective, i.e., parallelogram and b) perspective, i.e., trapezoidal with distortion. GDI+ does support parallelogram via its GdipDrawImagePointsRectI API/function

Though GDI+ can perspectively warp/sheer a path, it cannot with images. Converting all image pixels to points and warping the points, then going back to re-map those points to the original bitmap will be doable, but can be time consuming (slow)

Edited: forgot to include the link: http://www.flashandmath.com/advanced/card/math2.html

Edited yet again. Somehow the post I replied to is missing. Here is what it said



> Hi all.,
> 
> I would like to do a simple animation of a Poker card that rotates over the Y axis and then moves to a particular area of the screen (that has a backgound image).
> 
> Here is an quite good example created using Flash of what I have in mind:
> 
> http://englishblog.flepstudio.org/tu...rd-with-flash/

----------


## Bigweld

Hi Lavolpe,

Thanks for the quick and accurate response. Unfortunatly I'm not so good developer to code that kind of solution by myself.   :Cry: 

Anyway, Googling I found this code that actually do the effect that I looking for... BUT it is based on PictureBoxes and transparencies will not work
http://www.canalvisualbasic.net/foro...s-grados-2816/

I wondering if it can be modified by using some kind of custom PictureBox

Do you think that can be possible?

Thanks in advance

B.

----------


## LaVolpe

> ... Anyway, Googling I found this code that actually do the effect that I looking for... BUT it is based on PictureBoxes and transparencies will not work
> http://www.canalvisualbasic.net/foro...s-grados-2816/
> 
> I wondering if it can be modified by using some kind of custom PictureBox
> 
> Do you think that can be possible?


Actually conversion is extremely simple. The PlgBlt API used in that project is very similar to GDI+'s GdipDrawImagePointsRectI mentioned in my previous post.

Here's how to convert that project, using my image control
1. Add an AlphaImgCtl on the form
2. Search & replace everywhere, the following
... Find: Picture2.ScaleWidth Replace with: AlphaImgCtl1.Picture.Width
... Find: Picture2.ScaleHeight Replace with: AlphaImgCtl1.Picture.Height
... Find: Picture1.ScaleWidth Replace with: AlphaImgCtl1.Picture.Width
... Find: Picture1.ScaleHeight Replace with: AlphaImgCtl1.Picture.Height
3. Add this before exiting the DoRedraw routine: AlphaImgCtl1.Refresh.
Then within the DoReDraw routine, rem out or remove the following lines


```
 Picture1.Cls
 SetStretchBltMode Picture1.hdc, vbPaletteModeNone
 Call PlgBlt(Picture1.hdc, PtList(0), Picture2.hdc, 0, 0, Picture2.ScaleWidth, Picture2.ScaleHeight, 0, 0, 0)
 Picture1.Refresh
```

4. In Form_Load event, remove any code related to the pictureboxes. You can even remove the picboxes because they won't be used. 
Also add following before the line "Call DoRedraw", within that event


```
AlphaImgCtl1.WantPrePostEvents = True
```

5. Add this code to the AlphaImgCtl1_PrePaint() event


```
    Dim hGraphics As Long
    If AlphaImgCtl1.Picture.Handle Then
        GdipCreateFromHDC hDC, hGraphics
        If hGraphics Then
            GdipDrawImagePointsRectI hGraphics, AlphaImgCtl1.Picture.Handle, ByVal VarPtr(PtList(0)), 3&, 0&, 0&, _
                AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 2&, 0&, 0&, 0&
            GdipDeleteGraphics hGraphics
            Cancel = True 
        End If
    End If
```

6. Add the following API declarations to the form and then add an image to the AlphaImgCtl and play


```
Private Declare Function GdipDrawImagePointsRectI Lib "gdiplus" (ByVal graphics As Long, ByVal pImage As Long, ByRef pPoints As Any, ByVal Count As Long, ByVal srcX As Long, ByVal srcY As Long, ByVal srcWidth As Long, ByVal srcHeight As Long, ByVal srcUnit As Long, ByVal imageAttributes As Long, Optional ByVal pcallback As Long = 0&, Optional ByVal callbackData As Long = 0&) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, hGraphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long
```

What the above does is take advantage of the control's ability to allow you to draw the image vs. the control drawing the image. Let me know how things worked.

Edited: The line "AlphaImgCtl1.WantPrePostEvents = True" can be toggled true or false. Setting it to false prevents that event from being called. This way you can set it to true, automate the flip/rotation via a timer, then set it back to false after automation. Just thinking out loud.

Sorry if you saw this before I last updated. I forgot to give you the most important step: #5 above.

----------


## Bigweld

Hi Lavolpe,

I will try your suggestions and let you know how it goes. :Thumb: 

Thank you, very much! 

B.

----------


## LaVolpe

Here's a real simple sample

1. Start new project & on new form, add these controls
-- timer, 2 command buttons, 3 of my AlphaImgCtl controls
-- rename AlphaImgCtl2 to AlphaImgCtlFront & rename AlphaImgCtl3 to AlphaImgCtlBack
2. Load the attached card back in AlphaImgCtlBack & card front in AlphaImgCtrlFront
3. Make AlphaImgCtl1 the same size as AlphaImgCtlBack. Organize your controls so none overlap
4. Copy & paste the following code and play.


```
Option Explicit

Private Declare Function GdipDrawImagePointsRectI Lib "gdiplus" (ByVal graphics As Long, ByVal pImage As Long, ByRef pPoints As Any, ByVal Count As Long, ByVal srcX As Long, ByVal srcY As Long, ByVal srcWidth As Long, ByVal srcHeight As Long, ByVal srcUnit As Long, ByVal imageAttributes As Long, Optional ByVal pcallback As Long = 0&, Optional ByVal callbackData As Long = 0&) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, hGraphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long

Private Type POINTAPI
    x As Long
    y As Long
End Type
Private Const pi180 = 3.14159265358979 / 180
Private m_PtList(2) As POINTAPI

Private Sub Form_Load()
    Timer1.Enabled = False
    Timer1.Interval = 50 ' reduce to make flip faster
    Set AlphaImgCtl1.Picture = AlphaImgCtlBack.Picture
    Command1.Caption = "Flip"
    Command2.Caption = "Reset"
End Sub

Private Sub AlphaImgCtl1_PrePaint(hdc As Long, Left As Long, Top As Long, Width As Long, Height As Long, HitTestRgn As Long, Cancel As Boolean)
    Dim hGraphics As Long, tSourceImg As GDIpImage
    If AlphaImgCtl1.Picture.Handle Then
        GdipCreateFromHDC hdc, hGraphics
        If hGraphics Then
            ' decide which to use: card front or card back
            If Val(Timer1.Tag) > 90 Then Set tSourceImg = AlphaImgCtlFront.Picture Else Set tSourceImg = AlphaImgCtlBack.Picture
            GdipDrawImagePointsRectI hGraphics, tSourceImg.Handle, ByVal VarPtr(m_PtList(0)), 3&, 0&, 0&, _
                AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 2&, 0&, 0&, 0&
            GdipDeleteGraphics hGraphics
            Cancel = True
        End If
    End If
End Sub

Private Sub Command1_Click()
    If Timer1.Enabled = False Then ' abort if timer already running
        Timer1.Tag = "0"
        AlphaImgCtl1.WantPrePostEvents = True
        Timer1.Enabled = True
    End If
End Sub

Private Sub Command2_Click() ' set target to card back
    Set AlphaImgCtl1.Picture = AlphaImgCtlBack.Picture
End Sub

Private Sub Timer1_Timer()

 Timer1.Enabled = False ' turn off for now

 Dim x As Integer
 Dim NewX As Long, NewY As Long
 Dim SinAng1 As Double, CosAng1 As Double
 Dim SinAng2 As Double, SinAng3 As Double
 Dim Zoom As Double

 With AlphaImgCtl1.Picture
    m_PtList(0).x = -(.Width / 2)
    m_PtList(0).y = -(.Height / 2)
    m_PtList(1).x = .Width / 2
    m_PtList(1).y = -(.Height / 2)
    m_PtList(2).x = -(.Width / 2)
    m_PtList(2).y = (.Height / 2)
 End With
 
 Timer1.Tag = Val(Timer1.Tag) + 20
 
 Zoom = Tan(45 * pi180)
 SinAng1 = Sin(90 * pi180)
 CosAng1 = Cos(90 * pi180)
 
 x = CInt(Timer1.Tag) ' draw card front normal, not mirrored
 If x > 90 Then x = 180 - x
 
 SinAng2 = Sin((x + 90) * pi180) * Zoom
 SinAng3 = SinAng1 * Zoom
 
 For x = 0 To 2
    NewX = (m_PtList(x).x * SinAng1 + m_PtList(x).y * CosAng1) * SinAng2
    NewY = (m_PtList(x).y * SinAng1 - m_PtList(x).x * CosAng1) * SinAng3
    m_PtList(x).x = NewX + (AlphaImgCtl1.Picture.Width / 2)
    m_PtList(x).y = NewY + (AlphaImgCtl1.Picture.Height / 2)
 Next
 
 
 If Timer1.Tag = "180" Then ' done rotating/flipping
    AlphaImgCtl1.WantPrePostEvents = False ' disable event
    Set AlphaImgCtl1.Picture = AlphaImgCtlFront.Picture ' assign to card front
 Else
    AlphaImgCtl1.Refresh ' update screen
    Timer1.Enabled = True ' continue timer
 End If

End Sub
```

Here are the images. Right click and "Save As" if needed

----------


## Bigweld

Hey! This is working great!!!
Thank you, very much 

PS: Do you have the complete set of card images? They look awesome

----------


## Jonney

> Hey! This is working great!!!
> Thank you, very much 
> 
> PS: Do you have the complete set of card images? They look awesome


Lavolpe, You are excellent to push AlphaImage forward into ultra powerful and widen usage range.
*Only unexpected,Nothing impossible*

----------


## LaVolpe

> Hey! This is working great!!!
> Thank you, very much 
> 
> PS: Do you have the complete set of card images? They look awesome


No, just did a quick google using "cardback png". Found those and thought they'd be ideal cause of their high quality and shows that transparency is not an issue with the control

----------


## Bigweld

Hi Lavolpe,

I have found several fancy decks on internet.
Thank you, very much!

B. :Thumb:

----------


## VbNetMatrix

first, THANKS... and many thanks again! to you Lavolpe,

great work!!!

About thoses "Crash" you're talking about in uncompiled mode,
I'm not sure it's related, but I had a LOT of thoses...
then I started to look in the code and I found that many function DONT return any value...

some function even does:

callingfunction1() = callingfunction2()
and both of them doesn't return any value.

I've changed that, some function, I replaced with Sub and some function now return something...

and my uncompiled  project didn't crash in last 5 days...
could be related... could be not...  

I also have a Class for RGB Color, I thought it would be worth sharing with you
it's very simple actually:

' 32 x 1 = 32 bits
Private Type Long32
  ColorValue As Long
End Type

'  4 x 8 = 32 bits
Public Type typRGBA
  Red   As Byte
  Green As Byte
  Blue  As Byte
  Alpha As Byte
End Type

Public Function rColorToRGBA(ByVal plngColor As Long) As typRGBA
  Dim lngRGB As Long32

  ' Copy value to a User Defined Type
  lngRGB.ColorValue = plngColor

  ' Now we can make a direct bitwise copy to another UDT of the same size.
  LSet rColorToRGB = lngRGB
End Function

Public Function rRGBAToColor(ByRef pRgba As typRGBA) As Long
  Dim lngRGB As Long32

  ' Copy value to a User Defined Type
  LSet lngRGB = pRgba

  ' Now we can make a direct bitwise copy to another UDT of the same size.
  rRgbToColor = lngRGB.ColorValue
End Function

I also would like to offer my help if you want,  I would very much give you a web site so you can develop your work more...  just tell me if you're insterested we could manage to contact each others.

regards.

----------


## VbNetMatrix

oh well...  did I forgot to include the BGR to RGB translation!!
since normal color are RGB
Ex.:  lngColor = rgb(1,2,3)
       typMyBGRA = rColorToRGB(lngColor)
result: typMyBGRA.red = 1: typMyBGRA.green  =2: typMyBGRA.blue =3: typMyBGRA.alpha =0

but PNG use BGR (blue and red switched), so to translate back and forth between  rgb to brg, use the following:

Public Function SknBgrToRgb(ByRef typMyBGRA As typRGBA) As typRGBA
  Dim retValue As typRGBA

  retValue.Red = typMyBGRA.Blue
  retValue.Green = typMyBGRA.Green
  retValue.Blue = typMyBGRA.Red
  retValue.Alpha = typMyBGRA.Alpha

  SknBgrToRgb = retValue
End Function

----------


## LaVolpe

Thanks for the input, but I'll keep my color conversion/assignment routines. This one line toggles from BGRA to RGBA and vice versa:


```
newColor =  (oldColor And &HFF00FF00&) Or ((oldColor And &HFF&) * &H10000) Or ((oldColor And &HFF0000) \ &H10000)
```

----------


## VbNetMatrix

> Thanks for the input, but I'll keep my color conversion/assignment routines. This one line toggles from BGRA to RGBA and vice versa:
> 
> 
> ```
> newColor =  (oldColor And &HFF00FF00&) Or ((oldColor And &HFF&) * &H10000) Or ((oldColor And &HFF0000) \ &H10000)
> ```


Yes it's one of the best method on the net...
 a little bit slower then mine (yes I know, Bitwise operator are very fast, but direct 32 bit assignment is faster, test it if you want)

and what about my web site proposition?  I really think it could be beneficial for your excellent project.  I'm not asking anything in return, you'll have full control over your web page.

also... I found a bug, I'm not sure it's  control related or gdi related...
it is when doing an "objImage.Render" of a PNG onto a FORM object.
when the form got his MaxButton property to FALSE.

when image is bigger then a certain size,  the X position from the source is wrong and we got 1 pixel offset on the destination.

I made a project who reproduce it...  where can I send it for your own analyse?

keep  up the good work.

----------


## LaVolpe

> ...also... I found a bug, I'm not sure it's  control related or gdi related...
> it is when doing an "objImage.Render" of a PNG onto a FORM object.
> when the form got his MaxButton property to FALSE.
> 
> when image is bigger then a certain size,  the X position from the source is wrong and we got 1 pixel offset on the destination.
> 
> I made a project who reproduce it...  where can I send it for your own analyse?


I'm always interested in bug reports. Please post a sample project or code that reproduces the problem.

Edited: Note that the control defaults to centering the image in the control. If the control size changes and proportional Aspect is used, it is possible the image can be 1 pixel off depending on whether the control's bounds are even or odd. To prevent this, opt for Left alignment vs centered. Other factors may apply to like: mirroring or 180 degree rotation.

----------


## VbNetMatrix

> I'm always interested in bug reports. Please post a sample project or code that reproduces the problem.


Like I said,  this is a "rare" bug and hard to reproduce.  posting code
might not work as the format and size of the png seem to decide if it occur or not.

I posted an exemple on a web site for you to download it.  This exemple is enable to reproduce it,  all comment are in the form load.
if you ENABLE the MAX button, the bug doesn't happen... (strange)

http://www.vbnetmatrix.com/download/lavolpe/bugdemo.zip

----------


## LaVolpe

It is actually a VB-bug. I've discussed this previously. The bug is identified in post #3 (1st page) and discussed in posts #35 & #36, also on the 1st page, with the workaround. Though pictureboxes are specifically addressed, bug can apply to any VB container, i.e., the form.

----------


## afdoal

Mr. lavolpe...

how to integrated ListView n LavolepeImageList???
Lavolpe ImageList
http://www.Planet-Source-Code.com/vb...69621&lngWId=1

please help me....  :Confused:  :Confused:  :Confused:

----------


## LaVolpe

> Mr. lavolpe...
> 
> how to integrated ListView n LavolepeImageList???
> Lavolpe ImageList
> http://www.Planet-Source-Code.com/vb...69621&lngWId=1
> 
> please help me....


You cannot. That was mentioned in the comments/feedback section of that link. That control was designed for users of custom drawn controls (i.e., buttons, grid controls, image controls, etc) where the image is not assigned to a property, but drawn manually on the control. Hope that answers your question. I've stopped supporting all code on PSC when I left PSC. I won't be making any changes to that project nor re-creating it.

----------


## LaVolpe

*Updated 1 Jun 2011*

- Added support for creating animated GIFs
- Added support for creating multi-image icons/cursors
- Added support for creating PNG-embedded icons/cursors (Vista and above can read these)

See the comments/examples in AICGlobals.SavePictureGDIplus class and also the SavePictureGDIp.rtf file

----------


## VbNetMatrix

Thanks Lavolpe for the bug explanation,

I'm sorry I missed it in the forums I'll look more into it.

regards

----------


## Bigweld

Hi Folks,

I recently recieved a requiriment that should be addressed with rotated transparent text in different angles even with different font sizes and colors.

Does anyone has ideas on how to accomplish that?

I saw this code http://www.vbaccelerator.com/codelib...o/sidelogo.htm
but unfortunatly it seems that could not handle transparencies and font colors.

Thanks in advance

B.

----------


## LaVolpe

> ...I recently recieved a requiriment that should be addressed with rotated transparent text in different angles even with different font sizes and colors.
> Does anyone has ideas on how to accomplish that? ...


Please do not post questions here not directly related to my project. Your question should be posted in the graphics or vb portion of the forums. Thank you.

----------


## Bigweld

Hi All,

Sorry. You are right. Is there any way to remove it from the current thread?
Thanks

B.

----------


## LaVolpe

Don't worry about it. It'll serve as a reminder for others. I think I read somewhere that the 'privilege' of deleting your posts was tied to some magic number of overall posts one has made as a forum member. Anyway, here's the "how to" if you are enabled to.

----------


## Bigweld

Hi Lavolpe

I'm trying to present images using AlphaImgCtl controls dynamically generated.
The last dynamically created image should be presented at the top in the zOrder but I could not get it.
Regardless the ZOrder I set, the  firt presented image remains at the top and the rest are presented behind it.

There is the code that I made:

a) This is the part that dynamically creates the set of images to be used. This set is not visible to the user while the program runs.



```
Sub LoadDeck()

Dim f           As Byte
Dim Lavolpe(51) As AlphaImgCtl

For f = 0 To 51
   Set Lavolpe(f) = Controls.Add("LaVolpeAlphaImg.AlphaImgCtl", "Lavolpe" & CStr(f))
   Lavolpe(f).Picture = LoadPictureGDIplus(CARD_BASE_PATH & CStr(f) & PNG_EXTENSION)
Next

End Sub
```

b) This is the part that uses the previous generated controls and then sets the image according the desired index when necessary.



```
Sub ShowCard(OffsetMultiplier As Byte)
   
   Static z  As Byte
   Dim a     As AlphaImgCtl
   
   Set a = Controls.Add("LaVolpeAlphaImg.AlphaImgCtl", "c" & CStr(z), Me)

   With a
      .Top = CARD_INITIAL_POSY - (POSY_CARD_OFFSET * OffsetMultiplier)
      .Left = 527
      .Width = 180
      .Height = 270
      Set .Picture = Lavolpe(m.CardID).Picture
      .ZOrder z
      .Enabled = True
      .Visible = True
   End With
   z = z + 1
 
 End Sub
```

Would you like to take a look to it, please?
Not sure if there is an issue of the AlphaImgCtl or mine

Thanks in advance

B.

PS: Its seems like the 'delete post' option is not avalible. I see just the 'edit post' option while trying to remove my previous post. Sorry.

----------


## LaVolpe

You have to understand the ZOrder method. Your z variable is useless. The only two values allowed for the ZOrder method are: vbSendToBack or vbBringToFront.

Edited: Has nothing to do with the Alpha Image Control. The ZOrder method is one that all VB controls have, including usercontrols created with VB. The control itself does not process that, VB does for the control.

----------


## Bigweld

Thank you, for pointing me the error.
B.

----------


## LaVolpe

FYI: Small enhancement added today... The Interpolation property.
By default the image quality is always highest possible. It will render with high-quality bicubic interpolation whenever the image is rotated or scaled to a different size than the original. There may be cases when a lower quality rendering is desired. Basically lower quality means faster renders, while higher qualities mean slower renders. Now you have that option to render at any of the other 5 quality settings offered.

----------


## LaVolpe

A question came up recently how one can use rotation to animate a "knob" manually. Here's one idea.

1. Add an AlphaImgCtl to your form
2. Assign that control a nice picture of a knob or something circular
3. If the picture is not circular 
-- change the control's .AutoSize property to lvicMultiAngle & control will resize itself
-- change the control's .AutoSize property to lvicNoAutoSize & adjust size as needed
-- set the control's .Rotation property to several settings at 45 degree intervals to ensure image is not cropped at those angles
-- if image is cropped at a certain angle, enlarge your control size a bit & repeat previous 2 steps
4. Paste this code in your form


```
Private m_StartAngle As Single

Private Sub AlphaImgCtl1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        With AlphaImgCtl1
            ' want zero degrees due North, so passing an offset of -90
            m_StartAngle = CalculateAngle(X - .ScaleWidth \ 2, Y - .ScaleHeight \ 2, -90)
        End With
    End If
End Sub

Private Sub AlphaImgCtl1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        ' want zero degrees due North, so passing an offset of -90
        X = CalculateAngle(X - AlphaImgCtl1.ScaleWidth \ 2, Y - AlphaImgCtl1.ScaleHeight \ 2, -90)
        Y = (X - m_StartAngle)
        If Y Then
            AlphaImgCtl1.Rotation = AlphaImgCtl1.Rotation + Y
            m_StartAngle = X
            ' perform whatever action the knob would do: change sound volume, rotate some other image, etc
        End If
    End If
End Sub

Private Function CalculateAngle(ByVal X As Single, ByVal Y As Single, _
                    Optional AngleOffset As Single, Optional AngleStep As Single = 1!) As Single
    
    ' returns a Degree vs Radian usable for properties that require angles in degrees vs. radians
    
    ' X & Y must be offset from a reference point
    '   -- the reference point is usually the center of whatever you want rotated
    '   -- So X may be: X - CenterPoint
    '       and Y may be: Y - CenterPoint
    ' AngleOffset is used to change what 0 degrees is relative to
    '   -- by default, 0 degrees is due West
    '   -- if you want due North to be 0 degrees, then pass AngleOffset as -90
    '   -- Why -90? If 0 is really due West then due North is 90 (clockwise rotation), 
    '       so to make due North zero, we need to subtract 90 
    ' AngleStep is used to restrict returned degrees to a fixed step value
    '   -- If you want the degrees to be returned in increments of 10, then pass 10
    '   -- If AngleStep is 10, then degrees < 10 will be returned as zero, < 20 returned as 10, etc
    
    Dim Radian As Single
    Dim xDiff As Single
    Dim yDiff As Single
    Dim Angle As Single
    
    Const PI As Single = 3.14159265358979
    
    xDiff = -X
    yDiff = -Y
    
    If Abs(xDiff) < 0.00000001 Then xDiff = 0!
    If Abs(yDiff) < 0.00000001 Then yDiff = 0!
    
    If xDiff <> 0! Then
        Radian = Atn(yDiff / xDiff)
        If xDiff < 0 Then Radian = Radian + PI
    Else
        If yDiff < 0 Then
            Radian = 3! * PI / 2! '90
        Else
            Radian = PI / 2! '270
        End If
    End If
    
    If Radian < 0! Then Radian = Radian + PI * 2!
    Angle = Radian * (180! / PI) + AngleOffset
    If Angle < 0! Then Angle = Angle + 360!
    
    ' restrict rotation to n degree increments
    If AngleStep Then
        CalculateAngle = Int((Angle \ AngleStep) * AngleStep)
    Else
        CalculateAngle = Angle
    End If

End Function
```

5. Now run your form, hold mouse down on the control and start rotating it.

Edited: Using above code, you will notice that sensitivity to changes is greater while mouse is closer to center of control and less sensitive the further away the mouse is from that center.

Edited yet again. For those that use the above logic, the assumption is that the image is rendered center of control. If image is rendered top left, adjust the center point in MouseDown & MouseMove

If you get an error saying .ScaleWidth & .ScaleHeight are not supported, you are using a previous version of the control.

----------


## Jonney

> A question came up recently how one can use rotation to animate a "knob" manually. Here's one idea.
> 
> 1. Add an AlphaImgCtl to your form
> 2. Assign that control a nice picture of a knob or something circular
> 3. If the picture is not circular 
> -- change the control's .AutoSize property to lvicMultiAngle & control will resize itself
> -- change the control's .AutoSize property to lvicNoAutoSize & adjust size as needed
> -- set the control's .Rotation property to several settings at 45 degree intervals to ensure image is not cropped at those angles
> -- if image is cropped at a certain angle, enlarge your control size a bit & repeat previous 2 steps
> ...


Good algorithm (CalculateAngle) for rotation using 'knob' manually. But we can resize AIC & rotate pic at the same time with a bit of modification of CalculateAngle (using xDiff and center position of AIC to determine the zoom changes).
One annoying thing is GDI+ doesn't draw Anti-aliasing for two edges of a rotated pictures.

----------


## LaVolpe

Another nice routine.

version 1.1 of GDI+ library has some niffty effects but not available to v1.0 of GDI+. One such effect is a blur. v1.1 has a true gaussian blur routine. If you want a blur routine for v1.0, the following may be useful. It is not a true blur but produces good results.

You'll need these 2 GDI+ API delcarations


```
Private Declare Function GdipGetImageGraphicsContext Lib "gdiplus.dll" (ByVal pImage As Long, ByRef graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus.dll" (ByVal mGraphics As Long) As Long
```

1. On a new form, add 2 AlphaImgCtl controls and 1 command button
2. Add an image to AlphaImgCtl1
3. Make the AlphaImgCtl2 same size as AlphaImgCtl1
4. Copy & paste following code. Run project & click on the button. Play with different blur depths


```
Private Sub Command1_Click()
' modified from this source: http://www.autohotkey.net/~tic/Gdip.ahk

    Dim tImg As GDIpImage
    Dim SS As SAVESTRUCT, hGraphics As Long
    
    ' create a new blank image same size as source image & place in 2nd image control
    SS.ColorDepth = lvicConvert_TrueColor32bpp_pARGB
    SS.Width = AlphaImgCtl1.Picture.Width
    SS.Height = AlphaImgCtl1.Picture.Height
    Set tImg = New GDIpImage
    SavePictureGDIplus Nothing, tImg, , SS
    Set AlphaImgCtl2.Picture = tImg
    
    ' create new temp blank image a fraction size of source image
    ' change the percentage to smaller values for greater effect & higher for lesser effect
    SS.Width = AlphaImgCtl1.Picture.Width * 0.33
    SS.Height = AlphaImgCtl1.Picture.Height * 0.33
    If SS.Width = 0 Or SS.Height = 0 Then
            MsgBox "Blur depth is too great"
            Exit Sub
    End If
    Set tImg = New GDIpImage
    SavePictureGDIplus Nothing, tImg, , SS
    
    ' render the source image onto temp image at fraction of size
    GdipGetImageGraphicsContext tImg.Handle, hGraphics ' function only works for 24bpp & above
    AlphaImgCtl1.Picture.Render 0&, , , SS.Width, SS.Height, , , , , , , hGraphics, , lvicHighQualityBicubic
    GdipDeleteGraphics hGraphics
    
    ' render temp image to full size and update 2nd control
    GdipGetImageGraphicsContext AlphaImgCtl2.Picture.Handle, hGraphics
    tImg.Render 0&, , , AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, , , , , , , hGraphics, , lvicHighQualityBicubic
    GdipDeleteGraphics hGraphics
    AlphaImgCtl2.Refresh
    Set tImg = Nothing

End Sub
```

----------


## LaVolpe

FYI. Updated version posted today. 

- Fixed couple minor errors in ICO & GIF creation routines
- Added ability to load image from Base64 encoded string
- Added AlphaMask & RenderSkewed functions to GDIpImage class (see class comments)
- Updated couple sample projects using newly added functions (see Change History on post #1)

----------


## astronald

WOW lavolpe
Good day
Very good and interesting your project, excuse my question, is there any way to remove the rest of the form and only leave the control and also encourage you, thank you for your answer

----------


## LaVolpe

astronald, welcome to the forums.

The zip file containing the control. Unzip it to a folder and open the .vbp file. Compile it. It will become a stand-alone OCX that you can add to your toolbox whenever you want. Should I update the control and you re-download, be sure to compile future revisions with binary compatibility. There is a link in post #1 I point people to, to better understand binary compatibility if this is a new topic to you.

The zip file containing the sample projects are there just for educational purposes. They have no bearing on the actual control.

----------


## astronald

:Smilie:  :Smilie:  :Smilie: 

Thanks Lavolpe, I liked the clock project would be done without you see the gray background of the form, thanks again for your help.

 :wave:  :wave:

----------


## cheesebrother

I have a memory leak in my project which is loading and unloading alpha image controls in a control array.  It seems as though every time I add another object to the array it will add two gdi objects however when I unload an object either one or no gdi objects will go away. Ive attached a simple project which shows the problem.

----------


## LaVolpe

> I have a memory leak in my project which is loading and unloading alpha image controls in a control array...


*Edited*: For others reading this post. If you read my "Memory Leak FAQ", linked in my signature below, you'll know what we are talking about, regarding GDI counts.

I can't reproduce the problem. Well, I can sort of

1. My baseline GDI count is 513 let's say. That's the count before running the project
2. I run the project (ensuring no other VB MDI child widows open). Count = 525
3. I add 5 new controls & count rises to 534
4. I then remove those 5 controls & count drops to 529

It does appear 1 leak per object. But it isn't & here's why:
5. Close form normally. Count now reads: 513

When VB loads DLLs/OCXs. It doesn't exactly clean up memory right away when the instance of it is removed. I can't tell you the intricacies of how VB's garbage collection works because I don't know. However, the fact that the GDI count did not change from starting the project to ending the project, indicates no leaks. Agreed?

----------


## cheesebrother

Thanks. I can see what you're saying. Great control.

----------


## LaVolpe

> Thanks. I can see what you're saying. Great control.


You're welcome & thanks for the compliment.

FYI: Using your sample code, you can reduce memory usage. Add this before making your control visible


```
Set object(object.UBound).Picture = object(object.LBound).Picture
```

When you dynamically load a control that already contains a picture, that picture's data & GDI+ objects are replicated not shared. You can verify this by printing out the object(object.UBound).Picture.Handle property. Using the above tweak, all is shared. However, in post #3 back on page #1, read the gotchas about sharing multi-image formats

----------


## shaneshock@nate.com

Hello
 I've been using LaVolpeAlphaImg.

 To become a better control
 I hope the following features are added.

 1. picturebox, grid control with the features that happens when you come to a top layer
 2. Png in the form to apply full-screen window (like the splash window)

 Pay as you think, if this feature has to pay.
 Have a nice day.

----------


## cheesebrother

There is one other thing that i've been trying to do.  Is there a way to have vb compile the alpha image control pictures without putting them in a resource file?  I tried running my program on another computer and got an error that said "Component 'LaVolpeAlphaImg3.ocx' or one of its dependancies not correctly registered: A file is missing or invalid."

----------


## LaVolpe

> To become a better control
>  I hope the following features are added.
> 
>  1. picturebox, grid control with the features that happens when you come to a top layer
>  2. Png in the form to apply full-screen window (like the splash window)


#1. Have no idea what you are suggesting. Are you asking for a picturebox control version of the Alpha Image Control? If so, won't happen. This control cannot be made to be a container of other controls, especially windowed controls.

#2. Not sure what you meant there either. If you want the control & image to size to the form, simply change the control's dimensions in the form's resize event. Also set the Aspect & AlignCenter properties for the stretching/alignment of the contained image, as desired.

----------


## LaVolpe

> There is one other thing that i've been trying to do.  Is there a way to have vb compile the alpha image control pictures without putting them in a resource file?  I tried running my program on another computer and got an error that said "Component 'LaVolpeAlphaImg3.ocx' or one of its dependancies not correctly registered: A file is missing or invalid."


The pictures assigned to a control during design time are stored in the hosting form's .frx file & compiled within your app when app is compiled. That isn't the reason for your error. You can't just copy the ocx to another pc and expect it to work, the ocx needs to be registered on that other pc. Suggest creating a proper install setup.exe for your application

----------


## cheesebrother

Okay, I'll need to learn how to do that.  Sorry to bother you.

----------


## astronald

Thanks Lavolpe, I liked the clock project.
would be without you see the gray background of the form, thanks again for your help.

----------


## LaVolpe

> Thanks Lavolpe, I liked the clock project.
> would be without you see the gray background of the form, thanks again for your help.


If you are asking how to make something like a clock widget that would show up on the desktop and without a form's background showing thru, that is a project all in itself. I'll give you these hints. But for assistance you should post your questions in the graphics or VB6 portion of the forums, not here in the codebank or in this thread. This is all the help I'll provide since your question isn't related to how my project works.

1. Use SetLayeredWindowAttributes & UpdateLayeredWindow APIs to draw your clock on a transparent form. The form should be made an owned window to the desktop if clock is to appear on the desktop

2. This usercontrol cannot be used as is because of how UpdateLayeredWindow works. But you can still draw the clock parts to the form every second (if second hand is displayed) or every minute if no second hand used. The usercontrol's PaintImageAsDrawnToHDC function would be helpful here or accessing the Picture property's .Render function directly.

Search the forums for examples of the 2 APIs I mentioned. Good luck.

----------


## mjohnlq

Hi. I use the control, but found some problem.
please see the attachment.

I read the contact.jpg use GDIpImage.
But I get the different color value in point (x,y) = (0,64) form photoshop or paint.

use GDIpImage, I get
 'Red:255;Green:255;Blue:251;Alpha:255
when use photoshop or paint or other soft ,I get 
 'Red:255;Green:255;Blue:255;Alpha:255

Plese help me see what's wrong?

Thanks!

----------


## LaVolpe

> Hi. I use the control, but found some problem.
> please see the attachment.


Forgot the attachment. If you include the jpg, also tell me whether the control is showing the image actual size or not. Also show the code you are using the extract the color

----------


## mjohnlq

Hi, LaVolpe,
I found the problem.   
It's my mistake,  (x, y) should be (y, x).
now, the value is the same with other software.
Thanks!

----------


## LaVolpe

Updated control. See 1st post
- Can now create animated PNG 
- Prevented control from trying to process 64bit binaries for images
- GDIpImage.AnimationLoops property returns animated PNG loop count
- New control method Animate2 is class-based version of older Animate method
- Added ability to do a screen capture to 24bpp bitmap

Edited: To test animated PNGs without using my control, use FireFox to open the animated PNG file

----------


## mjohnlq

Hi. 
 When AlphaImgCtl1.WantPrePostEvents = True, then AlphaImgCtl can't resize correct.

//////////////////////////////////////////////////////////////
Option Explicit

Private Sub Form_Load()
    AlphaImgCtl1.WantPrePostEvents = True
End Sub

Private Sub Form_Resize()
    AlphaImgCtl1.Move Me.ScaleLeft, Me.ScaleTop, Me.ScaleWidth, Me.ScaleHeight
End Sub
///////////////////////////////////////////////////////////////

Above code can't run correct,  if AlphaImgCtl1.WantPrePostEvents = false then it is correct.


Please see the attachment!

Thanks!

----------


## LaVolpe

> Hi. 
>  When AlphaImgCtl1.WantPrePostEvents = True, then AlphaImgCtl can't resize correct.


Thanx for the bug report. An undiscovered bug that's persisted through last several versions. 

I think I know what is happening and will look into it. In the mean time, setting WantPrePostEvents  in the property sheet instead of form_load will have expected results

Update: Figured out the problem... logic error. I never coded for scenario where WantPrePostEvents without an image assigned to the control - not enough foresight there. Requires tweaks in 2 routines & will upload patch by Aug 17th after a bit more testing

----------


## mjohnlq

Hi
SaveControlAsDrawnToGDIpImage

e.g
///////////////////////////////
    Set AlphaImgCtl2.Picture = AlphaImgCtl1.SaveControlAsDrawnToGDIpImage(True)
//////////////////////////////

Above Code is invalid.

And  SaveImageAsDrawnToGDIpImage may have the same problem.

Thanks!

----------


## LaVolpe

> Set AlphaImgCtl2.Picture = AlphaImgCtl1.SaveControlAsDrawnToGDIpImage(True)
> 
> Above Code is invalid.


Can you be more specific? What's invalid about it? If the following resolves the issue, please let me know also

If AlphaImgCtl2 isn't showing the complete image, try this:


```
AlphaImgCtl2.AutoSize = lvicSingleAngle
Set AlphaImgCtl2.Picture = AlphaImgCtl1.SaveControlAsDrawnToGDIpImage(True)
```

Also note that AlphaImgCtl1 must be visible

*Edited*: If there is no image assigned to the usercontrol, there is a check for that to abort the routine. I can see where this may not be desirable. I'll include that modification also. Simply remove the following line from the usercontrol's SaveControlAsDrawnToGDIpImage function:
_If m_Image.Handle = 0& Then Exit Function_

The same scenario for SaveImageAsDrawnToGDIpImage does not apply. That function relates to the loaded image only, not any background graphics. Therefore if no image loaded, SaveImageAsDrawnToGDIpImage will abort

----------


## mjohnlq

Hi.
Please see the attachment, the copy button has no effect.

Thanks!

----------


## LaVolpe

> Please see the attachment, the copy button has no effect.


Now I understand. Thanx for the example. Need to think this over a bit.

AlphaImgCtl1 is user-drawn in that example. The PrePaint event draws the image itself then tells the control to not draw its copy. So, that does explain why no graphics were returned to AlphaImgCtl2 since AlphaImgCtl1 was told not to draw the image

I'll be considering this. The following scenarios are possible along with what I consider commonsense responses

*I.* If WantPrePostEvents is True then graphics may or may not be user-drawn

a. If the control is told to abort painting by passing the PrePaint event's Cancel parameter as True
-- SaveControlAsDrawnToGDIpImage has no choice but to return the graphics as drawn by the user since the control will not be drawing the image. This will include any background fill/graphics since the user dictates everything

b. If the control is NOT told to abort painting then 
-- SaveControlAsDrawnToGDIpImage should function as intended

*II.* If WantPrePostEvents is False then no user-drawn graphics to worry about
-- SaveControlAsDrawnToGDIpImage should function as intended

*III.* The SaveImageAsDrawnToGDIpImage function is not affected. It uses the control's image and any image properties (i.e., rotation, grayscaling, etc)

----------


## mjohnlq

Hi.

GDIpImage.Render may have problem.

I want use  GDIpImage.Render to draw a jpg's right-bottom corner in a  picturebox, but I found there has some Offset.
I didn't know why.

Please see the attachment.

Thanks!

----------


## LaVolpe

> ...but I found there has some Offset.
> I didn't know why.


Double check the parameter values you are passing. You are trying to render a 400 pixel wide image 30x larger than actual size.


```
passing DestWidth & DestHeight as: k.Height * 30, k.Width * 30
```

If you want to render the bottom right corner, I would suggest setting the SrcX, SrcY, SrcWidth & SrcHeight parameters vs rendering the entire image to some large negative offset.

Bottom line. I don't see anything incorrect with the .Render function at this time. Appears the parameter values are the error.

----------


## mjohnlq

Hi.

Thanks for your suggestion.

I want use  GDIpImage to enlarge and shrink a picture as photoshop do.

But the problem is still exist.

The method2 is what I did as your suggestion.

Please see the attachment.

----------


## LaVolpe

> ... but I found there has some Offset.
> I didn't know why.


Ignore previous replies, I now see what you are talking about.
I had to change the picturebox's backcolor to dark so the offset was obvious. 

I'm looking into it and it isn't an issue with the control; but may be some GDI+ anomaly. Hopefully will know more later.

Follow-up. Increasing the zoom factor also increases the unwanted offset. Obviously a factor of 1 has no offset, where a factor of 50 has quite a big offset. This is definitely GDI+ related, not control related. Still looking...

Update. Figured out I think. The offset you see appears to be directly proportional to the zoom factor. If you are zooming 30x then you'll see an offset of 15 pixels. Haven't played with zoom values < 1 (i.e., .5). This 'bug' also seems to apply *only if the X and/or Y coords are less than zero*; no offsets seen with X,Y => 0

The following adjusts the X,Y coords by half the zoom & appears to render well. However, flaky in my opinion & not 100&#37; sure it works in all cases. I'll do a bit more research and see if I can find some sort of GDI+ setting that will prevent these offsets.


```
    Const zoom As Single = 30
    Dim X As Long, Y As Long
    Dim m_Effects As New GDIpEffects
    Dim k As GDIpImage
    Set k = LoadPictureGDIplus(App.Path & "\contact.jpg")
    Picture1.Cls
    X = Picture1.ScaleWidth - k.Width * zoom
    Y = Picture1.ScaleHeight - k.Height * zoom
    If X < 0& And zoom > 1 Then X = X + zoom / 2
    If Y < 0& And zoom > 1 Then Y = Y + zoom / 2
    k.Render Picture1.hDC, X, Y, k.Width * zoom, k.Height * zoom, , , , , , m_Effects.AttributesHandle, , 0, RenderInterpolation.lvicNearestNeighbor
```

*Final Update*: Ok, I've found what I believe is the answer. There is another GDI+ setting that can be used & appears to solve the problem. No need to adjust X,Y coords based on zoom factor.
1. Add this API declaration to your GDIpImage class, at very top of class after the _Option Explicit_ line


```
Private Declare Function GdipSetPixelOffsetMode Lib "gdiplus" (ByVal graphics As Long, ByVal PixOffsetMode As Long) As Long
```

2. In the GDIpImage.Render method, add call to that API as described below. Note you'll find two places in that routine with identical lines of code. Add the new call to both sections of the code.


```
...
        Else
            Call GdipSetInterpolationMode(hGraphics, Interpolation + 2&)
        End If
' insert new call here:
        Call GdipSetPixelOffsetMode(hGraphics, SmoothingModeAntiAlias)
```

This will be added to the latest modifications when I post them this weekend. Need to test a few things first.

----------


## mjohnlq

Hi
Thank your very very much.

I has another question.

I found photoshop's cursor can be very large if set the pen's width....

I want change the cursor's size too.  But widows's cursor size is fixed to 32 x 32, it' is very bad. I don't know how photoshop can change cursor's size.

I found some other post of you that can  use CreateIconFromResourceEx to create a cursor, but it can't change cursor's size too.

Now, I found GDIpImage can save a .ico to .cur, I want set my cursor use the ico,  the ico's size is 16 x 16, and i want change it to a 32 x32 cursor.

below is what i do, but has problem.

Please see the attachment.

//////////////////////////////////////////////

Private Sub SetCursor_Click()
    Dim k As New GDIpImage
    Set k = LoadPictureGDIplus(VB.LoadPicture(App.Path & "\1.ico"))   ' (VB.LoadResPicture(101, vbResIcon)).

    Dim m As New StdPicture

    'I want change the ico's size from 16  x 16 and then set the cursor's hot spot , how can I do?

    '    k.Width = 32  'I Can't change it
    '    k.Height = 32 'I Can't change it

    SavePictureGDIplus k, m, lvicSaveAs_HCURSOR
    Me.MousePointer = MousePointerConstants.vbCustom
    Set Me.MouseIcon = m
End Sub

//////////////////////////////////////////////////////

could you help see what's is wrong with me?

----------


## LaVolpe

To set a cursor's hotspot, pass a SAVESTRUCT in the last optional parameter of SavePictureGDIplus

Using sample code from your test5 zip


```
    Dim SS As SAVESTRUCT
    SS.CursorHotSpotX = newHorizontalHotSpotValue
    SS.CursorHotSpotY = newVerticalHotSpotValue
    SS.Width = 32: SS.Height = 32
    SavePictureGDIplus k, m, lvicSaveAs_HCURSOR, SS
```

*Edited*: Note that because this is being resized, will most likely cause alphablending during resizing. stdPicture object's cannot accept alphablended images and any resized cursor pixels not fully opaque or fully transparent will be turned to fully transparent. This will have the effect of losing some detail in the cursor. To overcome this problem, recommend also setting the SS.AlphaTolerancePct value to 25 which produces good quality complex-to-simple transparency reduction. stdPicture icons/cursors only support simple transparency. The SavePictureGDIp.rtf document included with the project attempts to explain that. The SS.AlphaTolerancePct member was designed for such cases: stdPicture icons/cursors, GIFs, & metafiles

Another option instead of using the SS.AlphaTolerancePct member is to use the SS.RSS.Quality member and set it to  lvicNearestNeighbor. But I think the quality of stretching will be less professional than using the SS.AlphaTolerancePct member

----------


## mjohnlq

Hi, LaVolpe

  Thanks very much.
  But I still have questions:

1. If I needn't stretch the icon, 
   can GDIpImage let me not stretch the 16 * 16 icon , only add the icon size to 32 * 32?  because i need show a small cursor as photoshop do.
   if stretch the icon, the cursor is twice the size, this is not what i want.

2.  If I need stretch the icon,
   set SS.Width = 128: SS.Height = 128, the width has no effect. 
   the width and the height is always 32. 
   So how Can I show a very big cursor like photoshop?

3. If the Icon is stretch,
    SS.CursorHotSpotX = 0
    SS.CursorHotSpotY = 0
   is not right, it has some offset.
  in test5, when the mouse move to the title, the cursor still didn't restore.

Thanks!

----------


## LaVolpe

mjohnlq, regarding the offsets when zooming... I found a final solution I believe. See post #204 where I included the patch.

Note: That issue had nothing to do with negative X,Y offsets. What was really the issue, as proven by some of my testing, was using nearest-neighbor interpolation along with stretching/zooming. What GDI+ was doing was pre-sizing the output image size based on bicubic/bilinear interpolation. That means the overall image is expanded by the 1/2 the zoom factor in all directions which is typical for that interpolation model. But when GDI+ rendered the image, it clipped the 'blurred' portion which made it look as though image was rendered offset by a few pixels. It was actually clipped. By providing the new GDI+ setting, the issue no longer exists. Just FYI

And regarding the cursor not staying custom when you move to the titlebar.... The custom cursor only applies to the client area of your form, not the titlebar, menubar, or borders. If you want cursor to apply to entire form, use Screen.MouseIcon instead of Me.MouseIcon

----------


## LaVolpe

mjohnlq, regarding cursors sizes....

VB is to blame here.

The icon you provided in your zip contains just one 16x16 icon. However, when you load an icon/cursor into a MouseIcon property, it seems to always come out visually as 32x32 regardless of what its original size is.  

But that is just an illusion. VB is doing something behind the scenes. The stdPicture object (Me.MouseIcon) is really 16x16 !!!! Don't believe it, then try this:

Debug.Print ScaleX(Me.MouseIcon.Width, vbHimetric, vbPixels)

Also note that VB and cursors/icons behave slightly different when app is compiled. You may want to test a 16x16 & 32x32 MouseIcon image from a compiled test app.

----------


## mjohnlq

Thanks Very much!

----------


## LaVolpe

Updated version posted today. 

Updates are to address issues discovered by mjohnlq. Refer to posts 195-204 for more details.

----------


## mjohnlq

hi.

Other software can read cursors in attachment, but GDIpImage can't.
You can use prjTheBasics to test it.

Thanks!

----------


## LaVolpe

> Other software can read cursors in attachment, but GDIpImage can't.


Actually it can read them, but are aborting because they are not formatted correctly.

Those cursors have the height set at zero within the icon directory entry. Not sure if you are well versed on icon file structure. Anyway, zero equates to 256 for icons/cursors & those cursors are 32x32 except one which is 16x16. I have included patches for mal-formatted image data in other image formats; so I'll include a patch for these types of icons/cursors too

I'll tweak the project to handle these situations when possible. Since all icons/cursors are really bitmaps with masks, that bitmap information also has dimensions. I can bounce the bitmap dimensions up against the icon structure dimensions and internally modify the icon structure as needed. Bottom line, with a properly written icon, the icon structure should be correct, but the bitmap data should always override the icon structure info.

Thanx for the sample icons. I don't expect this tweak to be implemented before the weekend & hope that's not an issue for you.

----------


## mjohnlq

Yes, the format  of the cursor files is  invalid !
I think it is needn't modify the codes for these invalid  format cursor file.

Thanks verh much!

----------


## LaVolpe

> Yes, the format  of the cursor files is  invalid !
> I think it is needn't modify the codes for these invalid  format cursor file.


I'll modify the code because Windows has no issues displaying them and I'd like to at least be able to do what Windows does. The modification is relatively simple

----------


## mjohnlq

Hi.

I have another two cursor file, their format is valid. 
But AlphaImgCtl maybe show incorrect.

in attachment.
1. "See in other soft.png" is when the two cursors show in other software.
2. test6 is test show the cursor files use  AlphaImgCtl .

you can see, AlphaImgCtl  can't show complete.

Thanks very much!

----------


## LaVolpe

> Hi.
> 
> I have another two cursor file, their format is valid. 
> But AlphaImgCtl maybe show incorrect.


Ok, that's a logic bug. I'll look into it -- gotta be something wrong with my mask processing section

Though... When looking at the icon/image in Windows Explorer or on my desktop, it is displayed like the AlphaImgCtl. If I were to load the cursor into a VB Image control, it is displayed like in your png snapshot. Interesting

Update: I will need to handle black&white cursors/icons a bit differently. I can now render the exact same image as shown in your png snapshot & VB's image control. However, in reality, 1 bit cursors/icons that use an XOR mask (as does your cursor), what you get depends on what the cursor is currently rendered over. See attached. For my control, the assumption for drawing is that cursor will be over a white background.

In above image, the top 4 boxes is the same cursor, in VB's Image Control, drawn over colored squares. The bottom image is modified code to handle B&W cursors/icon processing differently, more correct. Modified code not yet posted.

*Final update*. Had to handle the AND & XOR masks manually to guarantee I could draw the icons exactly correct. I'll include the patch in the next update, expected end of August.

----------


## VB_Rocks

Hello Keith,

I have a feature request:

Would it be possible to add an option for Green Screen removal?  Where a photo is taken against a green or blue screen and you can convert the background to transparent?

Lots of controls have the ability to replace a color or make it transparent, but to do true ChromaKey you would need to be able to supply a color and then be able to convert that color in addition to a range of lighter and darker colors to transparent.

Sound like something that is possible? 

Also, any thoughts on watermark options?  The ability to set a font, color, style, position, transparency and rotation would be really nice addition as well.

Regards,

----------


## LaVolpe

Regarding green screen ability -- already there but will make the color 100&#37; transparent throughout. The two properties you'll need to set are: TransaprentColor and TransparentColorMode
For example using vbGreen
AlphaImgCtl1.TransparentColor = vbGreen
AlphaImgCtl1.TransparentColorMode = lvicUseTransparentColor

Not sure if the above is what you truly meant.

Regarding watermarks. They can be done a few ways & I don't intend to build a specific function for that. In fact, the control is already setup for such things

1. To use an image as a watermark, some sample code exists in the AICGlobals.MergePictureGDIplus function

2. A text watermark isn't specifically addressed but not that difficult either if one is comfortable with GDI+. Creating text with a rotated font and whatever attributes you want with GDI+ is simple. The string can be rendered in the control's PostPaint event. Or, if the control is hosting a 24/32bpp image, you can grab an hGraphics object from it's handle (AlphaImgCtl1.Picture.Handle) via the GdipGetImageGraphicsContext API and draw the GDI+ string directly to the image itself.  There are other options that come to mind also.

----------


## VB_Rocks

Well not exactly what I was talking about.

In photography, you can shoot a subject or a product in front of a green-screen then use software to remove the background and make it transparent.

Typically the green-screen is a bright neon green and unlikely the subject will have this color of green.

However, due to shadows and lighting, the green may be a little lighter or a little darker in certain spots.  Thus the software allows you to select the base color of green then has a choke value, typically between 0 and 255 that allows you to remove the base green plus shades of the green both lighter and darker.

I have attached an example photo with the green screen and one that has been removed using software to remove the green screen.

The original is of a model taken in front of a green screen in .jpg format, with the green background removed with a choke value of 55 and saved in .png format with all green removed.

As you can see there are some color variations in the green background, this is due to lighting and shadows in the studio.

I also resized the .png file so it would fit the file limits of this forum.

----------


## LaVolpe

VB_Rocks. though the control isn't directly set up to do what you are suggesting, it can be done outside of the control.  Using your JPG source as an example, try this...

1. New form, add AlphaImgCtl and assign your JPG to that control
2. Add a command button to the form & this code


```
Private Declare Function GdipCreateImageAttributes Lib "gdiplus.dll" (ByRef imgAttr As Long) As Long
Private Declare Function GdipSetImageAttributesColorKeys Lib "gdiplus.dll" (ByVal mImageattr As Long, ByVal mType As Long, ByVal mEnableFlag As Long, ByVal mColorLow As Long, ByVal mColorHigh As Long) As Long
Private Declare Function GdipDisposeImageAttributes Lib "gdiplus.dll" (ByVal imgAttr As Long) As Long
Private Declare Function GdipGetImageGraphicsContext Lib "gdiplus.dll" (ByVal pImage As Long, ByRef graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus.dll" (ByVal mGraphics As Long) As Long

Private Sub Command1_Click()
    
    Dim hAttributes As Long, hGraphics As Long, tImg As New GDIpImage
    Dim lBaseColor As Long, lLow As Long, lHigh As Long, lChannel As Long
    Dim SS As SAVESTRUCT
    
    AlphaImgCtl1.BackColor = vbWhite
    AlphaImgCtl1.BackStyleOpaque = True

    ' set up structure for a blank 32bpp image same size as original
    SS.ColorDepth = lvicConvert_TrueColor32bpp_ARGB
    SS.Width = AlphaImgCtl1.Picture.Width
    SS.Height = AlphaImgCtl1.Picture.Height
    If SavePictureGDIplus(Nothing, tImg, , SS) = False Then Exit Sub ' create blank image
    ' now get a handle to its DC (hGraphics)
    If GdipGetImageGraphicsContext(tImg, hGraphics) = 0& Then
    
        ' assign base color; we'll use top left corner for simple example & ensure in GDI+ color format
        lBaseColor = ConvertRGBtoARGB(GetPixelGDIplus(AlphaImgCtl1.Picture, 0, 0))
        
        ' create an attributes handle
        If GdipCreateImageAttributes(hAttributes) = 0& Then
            ' adjust the range to 1/8th above & below base color. 1/8th is +/- 32
            ' assign darker color to lLow & lighter color to lHigh
            lLow = &HFF000000: lHigh = lLow
            
            lChannel = (lBaseColor And &HFF&)
            If lChannel > 31 Then lLow = lLow Or (lChannel - 32)
            If lChannel < 224 Then lHigh = lHigh Or (lChannel + 32) Else lHigh = lHigh Or &HFF&
            
            lChannel = (lBaseColor And &HFF00&) \ &H100&
            If lChannel > 31 Then lLow = lLow Or (lChannel - 32) * &H100&
            If lChannel < 224 Then lHigh = lHigh Or (lChannel + 32) * &H100& Else lHigh = lHigh Or &HFF00&
            
            lChannel = (lBaseColor And &HFF0000) \ &H10000
            If lChannel > 31 Then lLow = lLow Or (lChannel - 32) * &H10000
            If lChannel < 224 Then lHigh = lHigh Or (lChannel + 32) * &H10000 Else lHigh = lHigh Or &HFF0000
            
            ' create the attributes
            If GdipSetImageAttributesColorKeys(hAttributes, 1&, 1&, lLow, lHigh) = 0& Then
            
                ' draw source image to new image while applying attributes
                AlphaImgCtl1.Picture.Render 0&, , , , , , , , , , hAttributes, hGraphics
                Set AlphaImgCtl1.Picture = tImg
            End If
            
            GdipDisposeImageAttributes hAttributes ' clean up
        End If
                
        GdipDeleteGraphics hGraphics ' clean up
        
    End If
    
End Sub
```

Note that the removal of green isn't 100&#37; perfect but I suspect that is more of an issue of using a JPG as a source. JPGs lossy color compression wouldn't be ideal whereas a PNG source would be ideal IMO.

----------


## Jonney

> VB_Rocks. though the control isn't directly set up to do what you are suggesting, it can be done outside of the control.  Using your JPG source as an example, try this...
> 
> Note that the removal of green isn't 100% perfect but I suspect that is more of an issue of using a JPG as a source. JPGs lossy color compression wouldn't be ideal whereas a PNG source would be ideal IMO.


Look like the Green part has range e.g.RGB(118,165,110),G(Green) is always bigger than R & B. Can we do pixel by pixel replacement with White (255,255,255) if G is bigger than R and B?

----------


## LaVolpe

> Look like the Green part has range e.g.RGB(118,165,110),G(Green) is always bigger than R & B. Can we do pixel by pixel replacement with White (255,255,255) if G is bigger than R and B?


I don't think pixel by pixel tweaking is preferred due to lack of speed.
My intention was simply to show a way this can be done even though the control doesn't support it directly. I doubt a JPG would really be used as a source. Saving a JPG over an over again at less than 100&#37; quality will degrade the image to a point where *no* threshhold will be satisfactory. My opinion of course - JPGs bad choice where original color data is important.

----------


## DarkOnMatrix

The Alpha Imagen Control is perfect, but i think that have a litte problem, when we assign the control to download an image from the Internet, if the image is too large or the internet connection is very slow, freezes the program control until the image downloads completely.

I think this is a problem, as for example in a project where it is assigned to control download multiple images from the Internet in a form, this would not be shown until control download all ...

Regards...

----------


## LaVolpe

DarkOnMatrix. Good point. I'll experiment a bit and update this posting when I know more.
There are callback options available when using APIs to grab internet data. The VB6 usercontrol can do this for us easily but is not unicode compliant & too bad; would've been very easy to provide async data.

Update #1. Very doable to allow async vs sync downloads. The issue is assignment of a GDIpImage object if async is used. The LoadPictureGDIplus function returns a GDIpImage class object containing the picture. But if async is used, the function will return immediately without any image assigned. So, how are you going to know that the image finished downloading? How are you going to be able to abort the download if you wanted to? I'm looking at those scenarios now. An immediate option is to create a new AsyncDownload class that has events. You would pass this class as the SourceImageData parameter of LoadPictureGDIplus. That class would have events that told you whether or not the image downloaded, progress, option to abort, and a few other properties. When finished downloading, then you'd be able to assign a GDIpImage class to the picture. Still thinking this over....  Nah, I think I have a clever way to get around those problems, maybe.

Update #2. Pretty dang close to a solution.

Update #3. Aug 29. Successfully created a multi-threaded asynchronous solution that works in a test executable. Need to test it a bit more & if still successful, will incorporate it into the control.

Side note & logic bugs. 
1. InternetCheckConnection used to test net connection & will always fail if going thru proxy. Not reliable
2. INTERNET_OPEN_TYPE_DIRECT flag used in InternetOpen call & will cause failure if going thru proxy. Don't use that flag
3. Only 3 protocols supported: http, ftp, gopher (though I think gopher no longer supported in Vista or Win8). Will add code to support file:\\

----------


## mjohnlq

> Ok, that's a logic bug. I'll look into it -- gotta be something wrong with my mask processing section
> 
> Though... When looking at the icon/image in Windows Explorer or on my desktop, it is displayed like the AlphaImgCtl. If I were to load the cursor into a VB Image control, it is displayed like in your png snapshot. Interesting
> 
> Update: I will need to handle black&white cursors/icons a bit differently. I can now render the exact same image as shown in your png snapshot & VB's image control. However, in reality, 1 bit cursors/icons that use an XOR mask (as does your cursor), what you get depends on what the cursor is currently rendered over. See attached. For my control, the assumption for drawing is that cursor will be over a white background.
> 
> In above image, the top 4 boxes is the same cursor, in VB's Image Control, drawn over colored squares. The bottom image is modified code to handle B&W cursors/icon processing differently, more correct. Modified code not yet posted.
> 
> *Final update*. Had to handle the AND & XOR masks manually to guarantee I could draw the icons exactly correct. I'll include the patch in the next update, expected end of August.



Hi. LaVolpe.

The cursor's effect Looks very good!

Thanks very mush!

----------


## LaVolpe

Control updated today & binary compatibility still maintained.

Fixed icon issues noted in posts 212-216 above
Added async download capability per request. See post 224 above

----------


## cheesebrother

Hi, I want to let you know about a bug I found while using the control.  The control will clip its picture when you set the rotation to -89.1.  I can reproduce this every time by putting a 20*400 bitmap into it and setting the correct rotation.

----------


## LaVolpe

> Hi, I want to let you know about a bug I found while using the control.  The control will clip its picture when you set the rotation to -89.1.  I can reproduce this every time by putting a 20*400 bitmap into it and setting the correct rotation.


Bug reports always welcomed. Can you provide more details on the control's properties? Besides the Rotation property being -89.1, what is the Aspect and AutoSize properties set to? When I pasted a simple 20x400 image into the control, no clipping appeared. Here are the properties I used
Rotation: -89.1
AutoSize: lvicMultiAngle
Aspect: lvicActualSize

*Edited*: I think I see what you are talking about, by changing the AutoSize property to lvicSingleAngle
Here is a temporary solution. Haven't tested it yet and need to ensure it doesn't affect other functions relying on this one:
- modCommon.GetScaledCanvasSize
- Replace these 2 lines


```
    a = (Int(Angle) Mod 360!) + (Angle - Int(Angle))
    If a < 0# Then a = a + 360#
```

- With these few lines


```
    If Angle < 0! Then
        a = 360! + (Angle Mod 360)
    Else
        a = Angle Mod 360
    End If
```

Also note that original code wouldl break if passing a value outside of +/- 720 degree angles. I'll have to reduce angles internally to max range of +/- 359.9999 to handle all scenarios. In doing so, internally all negative values will also be converted to positive values with addition of 360 degrees. Like I said, the above 'patch' is temporary but may fix both issues.

Also the modCommon.GetScaledImageSizes function will need a similar patch

----------


## cheesebrother

Yes, I got the problem when the control's AutoSize property was set to IvicSingleAngle and the Aspect was set to IvicActualSize.  Thanks for the little fix, I tried it and it works well.

----------


## LaVolpe

> Yes, I got the problem when the control's AutoSize property was set to IvicSingleAngle and the Aspect was set to IvicActualSize.  Thanks for the little fix, I tried it and it works well.


Cool. I'll include the patch later this week. Trick was to do calculations based off of angles rounded up/down as needed vs. actual angle when rotating in fraction of degrees

BTW. While testing, I discovered another minor bug. If image is mirrored both vertically and horizontally, drawing it at angles other than 90 degree increments may fail (believe this to be a GDI+ bug). I do have a fix for that now also & will include it with the patch for the bug you discovered.

----------


## Jonney

> Control updated today & binary compatibility still maintained.
> 
> Fixed icon issues noted in posts 212-216 above
> Added async download capability per request. See post 224 above


When async downloading, I can't do other things... But I don't worry much because of most of people won't use much of this function.

----------


## LaVolpe

> When async downloading, I can't do other things... But I don't worry much because of most of people won't use much of this function.


When downloading asynchronously, you will be able to do other things.

When wanting to download a URL asynchronously ensure you pass the last parameter of LoadPictureGDIplus as False. Otherwise, synchronous downloads will be performed (default behavior).

If you are passing that last parameter as False, then maybe async downloads are not supported. Test the global AsyncDownloadsEnabled property and see if it returns true or false. The control will fall back to sync downloads if that property returns false

Edited: Simple example. You'll see the caption changing while download is occurring. If async download is not enabled, msgbox displays & project unloads

1. Add AlphaImgCtl to form & a timer
2. Copy & paste this code. The image downloaded is one from post #220 above.


```
Option Explicit

Private Sub AlphaImgCtl1_AsyncDownloadDone(Success As Boolean, ErrorCode As Long)
    Timer1.Enabled = False
    If Success Then
        Me.Caption = "Done. Success"
    Else
        Me.Caption = "Error: " & ErrorCode
    End If
End Sub

Private Sub Form_Load()
    Me.Show
    DoEvents
    If AsyncDownloadsEnabled = False Then
        MsgBox "Async downloads not enabled", vbInformation
        Unload Me
        Exit Sub
    End If

    Dim sURL As String: sURL = "http://www.vbforums.com/attachment.php?attachmentid=85501&stc=1&d=1313972675"

    Timer1.Interval = 100
    Timer1.Enabled = True
    AlphaImgCtl1.AutoSize = lvicSingleAngle
    Set AlphaImgCtl1.Picture = LoadPictureGDIplus(sURL, , False)

End Sub

Private Sub Timer1_Timer()
    Me.Caption = Timer
End Sub
```

*Note*: When a modal window is displayed (i.e., a message box), and your project is not compiled, it affects raised events from the control. So, no AlphaImgCtl1_AsyncDownloadDone event is triggered. When ocx is compiled, image will still be displayed while modal window is active, but event not received. When ocx is not compiled, image data is not even processed...

If within your code & you have doubt whether the image was loaded or not during the display of a modal window, you can query the GDIpImage class' AsyncDownloadStatus property after that modal window is closed. Example:


```
    If AlphaImgCtl1.Picture.AsyncDownloadStatus = lvicAsync_Ok Then
        ' image assigned
    ElseIf AlphaImgCtl1.Picture.AsyncDownloadStatus = lvicAsync_Invalid Then
        ' failure - reason would have been passed to the AsyncDownloadDone event
    else 
        ' any other value indicates download is not complete. lvicAsync_WaitingOnReply may indicate destination not responding
    End If
```

The above will only work when the control is compiled. And here is why it doesn't work when control is not compiled
Step 1: cAsyncClient initiates downloads and is owned by a GDIpImage class
Step 2: When download done, raises event to owner GDIpImage class & passes collected image data
Step 3: GDIpImage class processes image data as needed
Step 4: If GDIpImage class is owned by AlphaImgCtl, then it raises its AsyncDownloadDone event to that control
Step 5: AlphaImgCtl raises its AsyncDownloadDone event to its host (your form) when it gets the GDIpImage event

When modal window is displayed while events are being raised...
a. When control is uncompiled, step 2 is broke due to VB blocking events and Steps 3-5 never get executed
b. When control is compiled but project is not, Step 5 is broke due to VB blocking events
c. *When project is compiled, no steps are broke, no workarounds needed*

I can see where this could be an issue when designing one's app & insisting on using the uncompiled control. So, I'll include a patch that will know to re-execute Step 2. That patch will be executed with a query to the AsyncDownloadStatus property, similar method as sample code above shows.

----------


## Jonney

> When downloading asynchronously, you will be able to do other things.
> 
> When wanting to download a URL asynchronously ensure you pass the last parameter of LoadPictureGDIplus as False. Otherwise, synchronous downloads will be performed (default behavior).
> 
> If you are passing that last parameter as False, then maybe async downloads are not supported. Test the global AsyncDownloadsEnabled property and see if it returns true or false. The control will fall back to sync downloads if that property returns false


Thanks. I missed the last parameter of LoadPictureGDIplus. 
How about Moving Public Property AsyncDownloadsEnabled to AlphaImgCtl? It looks weird because of this is only Public Property in AICGlobles.

----------


## LaVolpe

> How about Moving Public Property AsyncDownloadsEnabled to AlphaImgCtl? It looks weird because of this is only Public Property in AICGlobles.


The async downloads can be done with a GDIpImage class also, not just the Alpha Image Control, i.e., ....


```
Private WithEvents myImage As GDIpImage

Private Sub Command1_Click()
    Dim sURL As String: sURL = "http://www.vbforums.com/attachment.php?attachmentid=85501&stc=1&d=1313972675"
    Set myImage = LoadPictureGDIplus(sURL, , False)
End Sub

Private Sub myImage_AsyncDownloadDone(Success As Boolean, ErrorCode As Long)
    If Success Then
        Me.Caption = "Done. Success"
    Else
        Me.Caption = "Error: " & ErrorCode
    End If
End Sub
```

----------


## LaVolpe

Control updated today.

- Fixes a rotation calculation error. See posts 228-231 above for more info
- Added IDE patch when using uncompiled control & async download events blocked by a modal window you have displayed from your project. See post 233 for more info
- Added 2 new global asynchronous download support functions:
:: AsyncGetDownloadStates returns count of *all* downloads in progress, waiting on reply, and/or queued
:: AsyncAbortDownloads aborts *all* active and/or queued downloads
- Added AsyncDownloadURL property to the GDIpImage class. This property available until the class' AsyncDownloadDone event is triggered and exits.

The LoadPictureGDIp.rtf file has a section that discusses async downloads. Suggest reading that too

----------


## LaVolpe

Found minor logic bug this morning. 

*Where*: modCommon module, CreateSourcelessHandle function
*Observation*: Converting EMF/WMF to bitmap can result in a single black edge on the right and/or bottom side of the image when there shouldn't be one
*Cause*: Rendering from _single_ variable-type dimensions to _long_ variable-type dimensions creates rounding error that could result in unwanted black edge(s). 
*Solution*: Use same variable type dimensions. Will upload patch by weekend

----------


## LaVolpe

Control updated today.

- Fixes rounding error noted in previous post #237
- Added new grayscale property enumeration item: Black and White

About the Black and White grayscale option. It uses luminance to determine pixel color. This method would render a pure black and blue image as all black due the low luminance of both black and blue. This new option uses GDI+ color matrix to generate the colors and no consideration is given to other colors in the image. It is a simple formula, controlled by GDI+, that looks like:
Color = IIF( (redWeight * red + greenWeight * green + blueWeight * blue) >= 127.5, vbWhite, vbBlack)

Note: The above algorithm/formula is common in many graphics programs, including MS Paint, affects any image consisting mostly of Blue, Green and/or Red. Various methods exist to negate this problem, including diffusion and methods similar to the one described below. Any single method for conversion to black and white probably won't be acceptable for every situation; also applies to converting/reducing image colors to 4, 16 or 256 colors

However, if saving the same blue & black image via the SavePictureGDIplus function and passing the SaveStruct.ColorDepth as black and white, luminance is not the decision factor by itself. The function used processes each pixel and the pixel's luminance, in relation to all other pixels in the image, determines pixel color (in this case, blue would become white & black remains black). 

So, bottom line, you have two black and white options to choose from. One is immediate via the GrayScale property and is somewhat limited, and the other is available only when saving images using the SaveStruct.ColorDepth member. Both methods can return radically different results as one is based on fixed RGB ratio to white; while the other fixed RGB ratio between darkest & lightest colors in image. Both are completely different algorithms

Additionally, you always have the option of providing your own custom functions by accessing the pixels from the image's GDI+ handle

Within the modCommon module, you'll find the function: CreateGDIpAttributeHandle
In that function is a constant named BWLuminanceRatio which can be modified to adjust the ratio/cutoff between what will be black and what will be white. Recommend setting somewhere between .4 & .5 (smaller value more white & larger value more black). The min/max values are between 0 & 1 inclusively. Can also achieve ratio modifications thru code by adding/removing lightness from the image: LightnessPct property

Example of differences. When image is not mostly a prime color, results are similar; otherwise, can be quite different

----------


## LaVolpe

Minor patch uploaded today.

While playing with inverting black & white images that used the LightnessPct or BlendPct properties, wasn't getting the expected results. Found logic bug in the color matrix calculations when inverting colors. Fixed now, I believe

----------


## Cube8

After your last update, the TransparencyPct property is not working at all. No matter what I type, it behaves as if it was 100.

----------


## LaVolpe

> After your last update, the TransparencyPct property is not working at all. No matter what I type, it behaves as if it was 100.


Ugh, thanx. Simple fix for me. Unfortunately, that portion of the matrix was moved into a section that is activated only if other parts of the matrix are valid. Bad on me. I'll move it out of that section where it should've been. Will update it today. 

*Edited*: Patch uploaded now

----------


## LaVolpe

Updated control today. Enhancement-only updates

- New BorderShape property allows borders to have round corners vs. just sharp corners

- Can now drag & paste files from Explorer when zip/compressed files are viewed as "Compressed Folders" (XP and above)

- If dragging multiple files onto control (OLEDropMode=vbOLEDropAutomatic), each file will be processed, as needed, until image successfully loaded. Same logic used if pasting multiple files and loading image via the Clipboard. Previous behavior was to process only the 1st file, do or die

Edited: After playing around with the rounded borders, I can see where non-blended corners may be more desirable than blended corners. The next update will offer a choice between blended & non-blended
As for the size of the rounded corners, I chose to replicate VB's shape control with rounded corners and the results should be nearly identical. If anyone wishes to apply their own border shape, its just a matter of using the Pre-PostPaint events and assigning a clipping region during PrePaint and drawing the custom border in PostPaint. To assist in that regard and to prevent you from having to offset the image and/or adjust dimensions of control to accommodate a 1-pixel border, I'll also include an optional UserDefinedBorder member of the BorderShape property

Another enhancement update coming 1st/2nd of October & will include these options
- BorderShape property: will include rough & blended rounded corner border options. Will also include a UserDefined setting as described above
- Gradient background: For images that use transparency, the control's background can be gradient filled in 8 directions, using 2 colors
: New GradientForeColor will be provided. Gradients start with this color and end with the control's BackColor property
: Horizontally left to right, Vertically top to bottom, Diagonally from top/left to bottom/right, Diagonally from bottom/left to top/right
: To reverse above 4 directions, just swap out GradientForeColor & BackColor properties

----------


## cheesebrother

Hi, another bug.  I noticed as i was using the control that the Mouse Enter event would fire like crazy sometimes. After looking into it I've found that every timer the control's picture is changed (even if the mouse is already over the control) the Mouse Enter event will fire.  If I make so that the control's picture changes in the Mouse Move event the Mouse Enter event will fire every time.

----------


## LaVolpe

> Hi, another bug.  I noticed as i was using the control that the Mouse Enter event would fire like crazy sometimes...  If I make so that the control's picture changes in the Mouse Move event the Mouse Enter event will fire every time.


Yep, by design. But as I just revisited that routine, I can't tell you for sure why I designed it that way.... Thinking on this and unless I can rediscover why I coded it that way, I'll remove it in next update due this weekend.

If you wish to remove that for right now, rem out the following lines in the Set Picture property


```
        If Not m_MouseTracker Is Nothing Then           ' fire mouse leave event if needed
            Call m_MouseTracker.ReleaseMouseCapture(True, ObjPtr(Me))
            Set m_MouseTracker = Nothing
        End If                                          ' assign new image & set render flags
```

Edited: I may have been thinking in the context of the image vs. the control. Yes, I'm tap dancing a bit. I do agree that the current logic can be counter-productive in this case & will re-work the logic a tad.

Note: That if you set the HitTest property to other than default, you can experience this situation also because the HitTest area can change when the image changes. That is by design also and, in my opinion, is still applicable and sound logic

----------


## cheesebrother

> Yep, by design. But as I just revisited that routine, I can't tell you for sure why I designed it that way.... Thinking on this and unless I can rediscover why I coded it that way, I'll remove it in next update due this weekend.
> 
> If you wish to remove that for right now, rem out the following lines in the Set Picture property
> 
> 
> ```
>         If Not m_MouseTracker Is Nothing Then           ' fire mouse leave event if needed
>             Call m_MouseTracker.ReleaseMouseCapture(True, ObjPtr(Me))
>             Set m_MouseTracker = Nothing
> ...


Thanks for the fix, in a program that i'm making it will be much appreciated.  I also had a suggestion for a possible addition to the control.  What if you made it so that a user could crop the picture?  It would go something along the lines of this - AlphaImageCtl1.Picture.CropImage(X as integer, Y as integer, Width as integer, Height as integer).  It would be a lot like segment image except it would give the user all of the control in the world.

----------


## LaVolpe

Regarding cropping: Well, you can already do that with existing methods:

1. Set AutoSize property so no AutoSizing takes effect & size control to the dimensions of the cropping, i.e., Width, Height
2. May want to set the AlignCenter property to False in this case, so image is drawn at 0,0
3. Set the XOffset & YOffset properties as needed, i.e., (-X, -Y)

The above steps can be placed in a simple user-defined sub within your project. Also by setting these properties during design time, you can see what the cropped image will look like in advance

Edited: A simple user-defined cropping routine


```
Option Explicit
' in this example, the control's parent scalemode is pixels

Private Sub AlphaImgCtl1_Click()
    CropImage AlphaImgCtl1, 30, 30, 100, 100
End Sub

Private Sub CropImage(theImage As AlphaImgCtl, X As Long, Y As Long, _
                        Width As Long, Height As Long)
    
    ' the AlignCenter property should already be set to False for better runtime visual change
    With theImage
        .SetRedraw = False
        .AlignCenter = False
        .AutoSize = lvicNoAutoSize
        ' ensure X, Y are pixel scalemode 
        .SetOffsets -X, -Y
        ' ensure X, Y, Width, Height are appropriate container scalemode
        .Move .Left + X, .Top + Y, Width, Height
        .SetRedraw = True
    End With
        
End Sub
```

Edited yet again. The above code works extremely well if Aspect is actual size; otherwise, it doesn't because resizing the control changes the dimensions of rendered image which means it isn't really designed to crop while stretched or scaled without a lot of extra calculations from you, including drawing in the PrePaint event (or saving the image to a new GDIpImage object with scaled dimensions ahead of time)

I'm not sure about hardcoding function in the control. In the mean time, this solution should work perfectly, since it doesn't mess with any control settings or rendering options, but does require using the advanced PrePaint & PostPaint events. It also give the coder better control since the cropping area/shape is user-defined and not restricted to rectangular. If one can build a region, one can crop


```
Private Declare Function CreateRectRgn Lib "gdi32.dll" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function SelectClipRgn Lib "gdi32.dll" (ByVal hDC As Long, ByVal hRgn As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long

Dim bCropping As Boolean

Private Sub AlphaImgCtl1_Click()
    bCropping = Not bCropping
    AlphaImgCtl1.WantPrePostEvents = bCropping
    AlphaImgCtl1.Refresh
End Sub

Private Sub AlphaImgCtl1_PrePaint(hDC As Long, Left As Long, Top As Long, Width As Long, Height As Long, HitTestRgn As Long, Cancel As Boolean)
    ' obviously, one would have a way of caching whether cropping is in effect and what those dimensions were
    ' and also devised simple method to determine if cropping was applicable to this control instance
    If bCropping Then
         Dim hRgn As Long
         hRgn = CreateRectRgn(30, 30, 100, 100) ' relative to the control dimensions (in pixels)
         SelectClipRgn hDC, hRgn
         DeleteObject hRgn
    End If
End Sub

Private Sub AlphaImgCtl1_PostPaint(hDC As Long, Left As Long, Top As Long, Width As Long, Height As Long, HitTestRgn As Long)
    ' same notes from the PrePaint event apply
    SelectClipRgn hDC, 0& ' remove any selected clipping region
End Sub
```

----------


## cheesebrother

> Regarding cropping: Well, you can already do that with existing methods:
> 
> 1. Set AutoSize property so no AutoSizing takes effect & size control to the dimensions of the cropping, i.e., Width, Height
> 2. May want to set the AlignCenter property to False in this case, so image is drawn at 0,0
> 3. Set the XOffset & YOffset properties as needed, i.e., (-X, -Y)
> 
> The above steps can be placed in a simple user-defined sub within your project. Also by setting these properties during design time, you can see what the cropped image will look like in advance


Great, I tried the cropping routines and they work quite well. I just had one problem with it. Is it possible to give another alpha image control the cropped picture? I tried doing this, "Set AlphaImgCtl2.Picture = AlphaImgCtl1.SaveImageAsDrawnToGDIpImage" but it gave the whole picture to the receiving control. Thanks.

----------


## LaVolpe

> ...Is it possible to give another alpha image control the cropped picture?


This should work ok. I can think of a couple of other alternatives too, but not without making you declare a bunch of APIs


```
        Dim PMS As PICTUREMERGESTRUCT
        With PMS
            .CanvasHeight = 100 ' crop width
            .CanvasWidth = 100 ' crop height
            .Pictures = 1
            ReDim PMS.MIS(0 To .Pictures - 1)
            .MIS(0).Left = -30 ' crop left * -1
            .MIS(0).Top = -30 ' crop top * -1
            Set .MIS(0).Picture = AlphaImgCtl1.SaveImageAsDrawnToGDIpImage()
        End With
        Set AlphaImgCtl2.Picture = MergePictureGDIplus(PMS)
```

P.S. I'm going to include your suggestion in update this weekend. The function will be called SetClipRect vs. CropImage
By including that new function, users won't have to mess with the Pre/PostPaint events

----------


## LaVolpe

Control updated today for the following reasons

1. Added gradient background option. Gradients start with the GradientForeColor property & end in BackColor property. GradientStyle property has 4 directions. To reverse those directions, simply swap GradientForeColor & BackColor property values and you'll have a total of 8 direction options. In order for gradients to be enabled, the BackStyleOpaque property must also be true

2. The rounded corner border option now allows choice between blended and non-blended corners

3. New SetClipRect function added to the control. This function will clip the rendered output without modifying the image itself or any control properties. Border, if used, is always exempt from clipping

4. The control could fire a MouseExit/MouseEnter event whenever image changes & mouse is over the control. This behavior is not desirable if you are changing images on mouse events. Control no longer fires them in this specific case, unless the HitTest property setting results in a MouseExit event

Gradient examples:

----------


## cheesebrother

Thanks, I have everything working and it now does all that I want (at the moment).  By the way the new gradient thing for the control is beautiful.

----------


## LaVolpe

> By the way the new gradient thing for the control is beautiful.


Thanx, but I already found an anomaly with the GDI API used to create the gradients. It can fail in a specific situation & will replace that routine with one that uses GDI+ instead. Testing same scenarios with GDI+ did not fail where the GDI API did fail.

----------


## LaVolpe

Control updated today to fix a gradient anomaly, a bonehead mistake, and for enhancements...

- Added BkgImage property. BkgImage will paint over solid/gradient background (if applies) and under the control's Picture property
- Added BkgImageStretch property. BkgImage will be clipped in the control or stretched
- Added AsyncDownloadDoneBkgImg event to support async download of BkgImage
- Added SetFixedSizeAspect method to enable aspect of fixed-size during runtime
- Modified main property page to allow insertion of BkgImage
- Rewrote gradient routine to use GDI+ vs. msimg32.dll
- Bonehead mistake: last update somehow broke the PrePaint event (mistakenly deleted a line of code)

Example of layered backgrounds:
The following image has a gradient background and the new BkgImage property (semi-transparent bubble png) drawn over the gradients, then the actual control's Picture (my avatar) drawn over the BkgImage.

1. The BkgImage property is limited in how it is drawn. It is either drawn clipped by the control (if applicable) or stretched to the control's dimensions. Since the BkgImage property is a GDIpImage class, you have full access to it for other properties, like setting the ImageIndex and/or segmenting it if desired. If you desire a specifically, run-time, drawn image that is rendered with custom attributes/effects, sizes, etc, you'll want to create a new image and assign it to the BkgImage property; i.e., use SavePictureGDIplus, MergePictureGDIplus or maybe TilePictureGDIplus

2. The right-side image above was done using the PrePaint event. The PrePaint & PostPaint events will always give you far more control. Sample code looked like this:
- AlphaImgCtl1 had my avatar in it. WantPrePostEvents property is True
- AlphaImgCtl2 was hidden and had a 48x48 blue tile in it
- PrePaint & PostPaint events are runtime events only, so image not displayed as drawn while in design


```
Private Sub AlphaImgCtl1_PrePaint(hDC As Long, Left As Long, Top As Long, Width As Long, Height As Long, HitTestRgn As Long, Cancel As Boolean)
    Dim xOffset As Long
    If AlphaImgCtl1.Border Then xOffset = 1
    TilePictureGDIplus AlphaImgCtl2.Picture, hDC, xOffset, xOffset, _
        AlphaImgCtl1.ScaleWidth, AlphaImgCtl1.ScaleHeight, _
        AlphaImgCtl2.Picture.Width, AlphaImgCtl2.Picture.Height
End Sub
```

----------


## xnipher

hi lavolpe.

Thanks for creating a great control for vb6.

I want to ask if how can i move the Alpha Image Control to Back of Textboxes?

----------


## LaVolpe

Are you asking how you can draw an image on a textbox? If so, it isn't that easy. Here's an example on vbAccelerator

Otherwise, the control is windowless. Being windowless, it can never be placed above a textbox. It will always be behind a textbox or any other windowed control

----------


## xnipher

thanks about that.

Is there any way i can make it a "windowed" control?

----------


## LaVolpe

> Is there any way i can make it a "windowed" control?


Yes, but you'll lose its transparency  and/or alphablending ability and then you'll have to draw the control's background manually.  If wanting to play with that idea, open the control in design view and find its Windowless property & change it to False. Also change the BackStyle property to Opaque. But you'll have to do the background drawing via the PrePaint event....

Here's how the control accomplishes transparency. It relies on Windowless being true & of course, BackStyle being Transparent. By being windowless, the control borrows its container's device context (DC) to draw on. Since VB knows this, every time whatever is behind the control changes, VB sends the control a snapshot of what is under it. The control then copies that and draws whatever it wants on top of that and then paints it back to the container's DC. Because VB sends the control this information, the control never has to guess or determine when it should be updated, VB informs it. Niffty, easy (more or less) and perfect transparency effects. 

Unfortunately, making the control windowed breaks all of this. By being windowed, the control does not use the container's DC. It has its own or is given one on the fly, as needed. The control will never have any knowledge of what is behind it on the container. You will have to basically draw, yourself, whatever is behind it, onto the control. Also, the control will never know that anything behind it was changed and will only  rederaw itself when told do via a Refresh command or when it becomes covered/uncovered by other windows.

What you are asking for is basically a transparent picturebox. There is no simple way to create a transparent windowed control. There are methods to fake/simulate transparency and some work well, while others not so much. In either case, those methods rarely update themselves. Rather the owner of the project back-paints onto the control or sends the control some static bitmap to use as a background. Searching for transparent picturebox or transparent textbox may prove useful or fruitless

----------


## xnipher

> Yes, but you'll lose its transparency  and/or alphablending ability and then you'll have to draw the control's background manually.  If wanting to play with that idea, open the control in design view and find its Windowless property & change it to False. Also change the BackStyle property to Opaque. But you'll have to do the background drawing via the PrePaint event....
> 
> Here's how the control accomplishes transparency. It relies on Windowless being true & of course, BackStyle being Transparent. By being windowless, the control borrows its container's device context (DC) to draw on. Since VB knows this, every time whatever is behind the control changes, VB sends the control a snapshot of what is under it. The control then copies that and draws whatever it wants on top of that and then paints it back to the container's DC. Because VB sends the control this information, the control never has to guess or determine when it should be updated, VB informs it. Niffty, easy (more or less) and perfect transparency effects. 
> 
> Unfortunately, making the control windowed breaks all of this. By being windowed, the control does not use the container's DC. It has its own or is given one on the fly, as needed. The control will never have any knowledge of what is behind it on the container. You will have to basically draw, yourself, whatever is behind it, onto the control. Also, the control will never know that anything behind it was changed and will only  rederaw itself when told do via a Refresh command or when it becomes covered/uncovered by other windows.
> 
> What you are asking for is basically a transparent picturebox. There is no simple way to create a transparent windowed control. There are methods to fake/simulate transparency and some work well, while others not so much. In either case, those methods rarely update themselves. Rather the owner of the project back-paints onto the control or sends the control some static bitmap to use as a background. Searching for transparent picturebox or transparent textbox may prove useful or fruitless



It seems that i can't find the Windowless Property of Alpha Image Control.

----------


## LaVolpe

> It seems that i can't find the Windowless Property of Alpha Image Control.


1. Open the alpha image control project
2. In the project treeview, double click on AlphaImgCtl (AlphaImgCtl.ctl)
3. You'll now see a gray square. In the property sheet you see its core properties.

----------


## LaVolpe

Just a coding note... Updates expected to be posted around end of October
Now is the time to offer any additional suggestions/ideas

1. Will recognize the PNM family of image formats (pbm, pgm, ppm) for reading and writing
-- will not support rare multiple image formats, though first image will always be processed

2. Planning to include PAM format also, but not having much luck finding a variety of sample images

3. Extracted 32bpp bitmaps from binaries (dll/exe/etc) did not honor alpha channel. Will be fixed

4. Extracted PNGs from binaries (as icon resources) were not being created correctly. Will be fixed

5. Will minimally support AVI (image only) for reading only. I will not include a SaveAs method to AVI
-- these can be added via file name or extracted from dll/exe (i.e., Shell32.dll)
-- I will recommend you do not distribute AVI sources to be used with this control. AVI requires that the destination pc has appropriate video decompressors installed to read your AVI. Uncompressed or RLE AVIs are an exception since any pc should be able to read those
-- I will include a method of converting AVI to animated PNG or animated GIF. This would allow you to distribute AVI frames that can be displayed on your pc to other pc's. However, I'd suspect the GIF/PNG file may be significantly larger than source AVI. And color loss may occur with AVI to GIF, but no color loss with AVI to PNG

----------


## LaVolpe

Updated control today, to address enhancements/issues noted in previous reply.

See post #1, 1st page, for more info

----------


## pelermeler

Hallo Master,

Could you fix the *HitTest* problem please?
I want to use this control as a custom shape button, but the HitTest is not working correctly.

ps: I've been using your AlphaImageControl.ocx (v1.0) for my projects. THANK YOU!  :Big Grin:

----------


## LaVolpe

You'll have to give me more details, or better yet, whip up a quick sample project & post it so I can test it. Be sure to provide details.

----------


## pelermeler

The problem is even if I set the .HitTest to lvicTrimmedImage, the AlphaImgCtl_MouseEnter() event is still fire even the mouse is in the transparent pixels area.

attached is the sample project, images and AlphaImageControl v1.0 I'm using

(the sample project also need alpha image project v2.1.23 which I don't included)

Sample.rar

----------


## LaVolpe

I don't use WinRar, zip would be better. Let me explain trimmed image better and it may answer your question.

There are 4 hit test settings available
1) lvicPerimeter: The entire control
2) lvicEntirelImage: The image bounds, including any buffered/transparent pixels that may exist
3) lvicTrimmedImage: Any excess buffered/transparent pixels are trimmed off the image by creating a tight rectangle around the image.
4) lvicRunTimeRegion: Passing a valid region handle will result in this setting

In other words, the hit test is *always rectangular*, except for the 4th option which is user-defined.

Attached image explains the difference between the 1st 3 hit test options. Any mouse actions within the thick rectangle bounds will be registered; whether they are over transparent, partially trannsparent or opaque pixels.

I think what you are looking for is a shaped region that includes only non-transparent areas. That option is not offered with the control. However, nothing saying you can't create your own and pass that.

----------


## pelermeler

Well... with that explaination there's no problem then  :Big Grin: 
Thank you for your effort to give such detail explanation, you are a good person.

By the way, do you still have a source code of Alpha Image Control v1.x? The control name is aicAlphaImage. I could use some code in there to make my dream come true  :Stick Out Tongue: 

Sample.zip

----------


## LaVolpe

Though I do have the source for my older control, it was based off of my old c32bppDIBsuite project. This version of the control is based nearly 100&#37; off of GDI+. So, you'd need to do a lot of tweaking to get the routines for shaping a region around a GDI+ bitmap. 

To make it easy on you & anyone else that wants to do what you are trying to do, I'll simply post what you need here. It could probably be optimized a bit more, but as is, it is super fast.

1. Strongly recommend the AlphaImgCtl's AlignCenter property is *FALSE*, or if rotating make AutoSize property single angle. Otherwise, you will have to offset the created region so it aligns with a center-drawn image in the control

2. If you are using anything but actual size images, or mirroring/rotating, you'll want to draw the control to a temporary GDIpImage object and process that. Example provided

3. The control does not copy the region you pass as the HitTest property. But it owns it, so you *must not delete* the region

4. Here are the API declarations you'll need


```
Private Declare Function ExtCreateRegion Lib "gdi32" (lpXform As Any, ByVal nCount As Long, lpRgnData As Any) As Long
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
```

5. Here is a routine that is designed to be used with my control


```
Private Function CreateShapedRegion(imgBytes() As Byte, Width As Long, Height As Long, Optional OpaquenessTolerance As Long = 255) As Long

    ' returns a Windows region handle, or zero if failure
    ' the imgBytes array must be one returned from GDIpImage.AlphaMask function
    ' the OpaquenessTolerance must be a value between 0 and 255
    '   if the pixel opaqueness is < OpaquenessTolerance then that pixel not included in the region

    Dim X As Long, Y As Long, a As Long, lAppendFlag As Long
    Dim r() As RECT, rIndex As Long, rCount As Long
    
    If UBound(imgBytes) <> Width * Height - 1& Then Exit Function
    ' array returned from GDIpImage.AlphaMask (byte aligned mask), top down format
    rCount = Height                             ' initialize with arbitrary count of RECT structures
    ReDim r(-2 To rCount - 1&)                  ' 1st 2 RECTs are used as the region's 32 byte header
    r(-1).Left = Width                          ' set invalid max value
    
    For Y = 0& To Height - 1&
        lAppendFlag = 0&                        ' reset for each row
        For X = 0& To Width - 1&
            If imgBytes(a) < OpaquenessTolerance Then ' pixel excluded from region
                If (lAppendFlag And 1&) Then    ' currently appending
                    r(rIndex).Right = X         ' close out the RECT
                    rIndex = rIndex + 1&        ' increment
                    If rIndex = rCount Then     ' redim if needed
                        rCount = rCount + Height
                        ReDim Preserve r(-2 To rCount - 1&)
                    End If
                    lAppendFlag = lAppendFlag Xor 1& ' reset
                End If
            ElseIf (lAppendFlag And 1&) = 0& Then
                r(rIndex).Left = X              ' starting new RECT
                r(rIndex).Top = Y: r(rIndex).Bottom = Y + 1&
                lAppendFlag = 3&                ' appending and a new row will be added to region
            End If
            a = a + 1&                          ' move array pointer along
        Next
        If (lAppendFlag And 1&) Then            ' handle situations where last pixel in row terminates a RECT
            r(rIndex).Right = X                 ' close out the RECT
            rIndex = rIndex + 1&                ' increment index & redim if necessary
            If rIndex = rCount And Y < Height - 1& Then
                rCount = rCount + Height
                ReDim Preserve r(-2 To rCount - 1&)
            End If
        End If
        If (lAppendFlag And 2&) Then            ' row added: update region bounds
            With r(rIndex - 1&)
                If .Right > r(-1).Right Then r(-1).Right = .Right
                If .Left < r(-1).Left Then r(-1).Left = .Left
            End With
        End If
    Next
    
    If rIndex Then                          ' we have rectangles; therefore, a region to be created
        r(-1).Top = r(0).Top                ' r(-1) is the overall bounds of the region
        r(-1).Bottom = r(rIndex - 1&).Bottom
        With r(-2)
            .Left = 32&                     ' length of region header in bytes
            .Top = 1&                       ' required cannot be anything else
            .Right = rIndex                 ' number of rectangles for the region
            .Bottom = .Right * 16&          ' byte size used by the rectangles
        End With                            
        
        ' call function to create region from our byte (RECT) array
        CreateShapedRegion = ExtCreateRegion(ByVal 0&, (rIndex + 2&) * 16&, ByVal VarPtr(r(-2).Left))
    End If
    
End Function
```

6. Here are 2 examples of usage


```
    ' if needing to render the image (as drawn) before creating a region
        Dim b() As Byte, hRgn As Long
        Dim tImg As GDIpImage
        Set tImg = AlphaImgCtl1.SaveImageAsDrawnToGDIpImage()
        If tImg.AlphaMask(b(), False) Then
            hRgn = CreateShapedRegion(b(), tImg.Width, tImg.Height, 128)
            If hRgn Then AlphaImgCtl1.HitTest = hRgn
        End If
        
    ' if using actual size image, no rotation nor mirroring
        Dim b() As Byte, hRgn As Long
        If AlphaImgCtl1.Picture.AlphaMask(b(), False) Then
            hRgn = CreateShapedRegion(b(), AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 128)
            If hRgn Then AlphaImgCtl1.HitTest = hRgn
        End If
```

*Edited*: In playing with above code, found a bug that will have to be addressed.
When form is displayed and if control's Visible=False or control is hidden off the viewable form, SaveImageAsDrawnToGDIpImage will fail. This is due to a flag that is only set when the control is first painted & of course, if it isn't visible, it'll never get painted so flag is never set. Same problem will apply to PaintImageAsDrawnToHDC

----------


## pelermeler

WOOOWWWWW  :Eek Boom:  (mind-blowing)

I think I'm gonna start experiencing Insomnia  :Big Grin: 

THANK YOU  :Alien Frog:

----------


## LaVolpe

Hope all works well for you. Note that if you set the Border property, or toggle the Border property, you may need to offset your region by 1 pixel both vertically & horizontally. I didn't include that possibility in the routine I provided in post #266. If this is the case, you can always use the OffsetRgn API to adjust for that 1 pixel

My gut reaction was that if you are wanting a shaped region, a border wouldn't be in use anyway


```
Private Declare Function OffsetRgn Lib "gdi32.dll" (ByVal hRgn As Long, ByVal X As Long, ByVal Y As Long) As Long
```

Edited: Since I discovered 2 new bugs (minor), I'll be updating the control. I'll also include the shaped region function in the GDIpImage class. This can reduce your overall code to just the following, after it has been updated:


```
    Dim hRgn As Long
    hRgn = AlphaImgCtl1.Picture.RegionFromImage(128)
    If hRgn Then AlphaImgCtl1.HitTest = hRgn
```

----------


## pelermeler

Ooo My GOD...

Just when I 'm about to ask for more pointers about shape area HitTest, you already did it. THANK YOU!  :Big Grin: 

I don't know if it's a bug or not, 
If I call a *MsgBox* on _Form_Load()_, AlphaImgCtl fail to draw properly, even if I call *.Refresh* method. But it can be fix if I toggle *.Visible*.

----------


## LaVolpe

> I don't know if it's a bug or not, 
> If I call a *MsgBox* on _Form_Load()_, AlphaImgCtl fail to draw properly, even if I call *.Refresh* method. But it can be fix if I toggle *.Visible*.


No, not a bug. It is a known issue that applies only while the control is uncompiled.

Actually any modal windows (MsgBox, CommondDialog, InputBox, etc) displayed while the control is uncompiled has the possibility of events not being sent to the control. These events can effect drawing, async downloads, and your form receiving events from the control. This is all the result of blocking actions IDE creates for uncompiled code

----------


## k_zeon

Hi LaVolpe. I have a situation where a scanner is outputting tiff images with compressed Jpeg. Have been trying GDI+ but to no avail. Also tried your user control and this too failed.

Then i tried the Freeimage.dll and this appears to work. 
I am able to input compressed jpeg tif and load into a dib , then put this dib into a picture box.
Is it possible that something can be done with GDI+ or will this not be possible.

Many thanks

----------


## LaVolpe

> I have a situation where a scanner is outputting tiff images with compressed Jpeg. Have been trying GDI+ but to no avail.


Can you upload a sample tiff? I'll have to do a bit of playing and maybe some research too

Edited: Forget about the sample image. It's not gonna happen. The TIFF compression options that GDI+ supports are noted below. I suspect that if a different compression other than that listed, GDI+ isn't supporting it. A manual parsing/uncompression method would need to be employed or use of 3rd party tools.
- CCITT3
- CCITT4
- LZW
- RLE
- None

Edited yet again. Further reading on the net hints that lossy compressed tiffs may be supported in Win7 and Vista if current service packs are up to date -- don't know for sure.

And a quote from another forum (not verified as accurate)



> ... By the way GDI+ reads some of tiffs compressed by JPEG, i suppose it depends on color depth or something else.


It does seem that the newer version of jpeg compression could be easily parsed out. But to get an idea at how messed up jpeg compression within tiff is/was, here is an interesting link

----------


## cromit

Hello,
this image control is realy amazing, very powerful.
Now i want to do some tests.
I want to use a picture from a standard vb6 PictureBox control, like:
    Set AlphaImgCtl1.Picture = PictureBox1.Picture
but i am not successful.

Can you help?

Many thanks.

----------


## LaVolpe

> I want to use a picture from a standard vb6 PictureBox control, like:
>     Set AlphaImgCtl1.Picture = PictureBox1.Picture
> but i am not successful.
> 
> Can you help?
> 
> Many thanks.


Take a few moments and read over the 2 RTF files that were included in the zip file you downloaded


```
Set AlphaImgCtl1.Picture = LoadPictureGDIplus(PictureBox1.Picture)
```

----------


## LaVolpe

Control updated today - enhancements only. The following have been added.

1. WMA music files can be selected as source for images. These files, much like MP3 files, can contain embedded images that may be extracted.
*Edited*: Will wait for a bit before updating again. Found a WMA where Windows Media Player placed a WM/Picture tag in a block I wasn't parsing. I've modified my version to ensure all images were parsed & when updated, the control will include this new tweak

2. Control is now databound-capable. This means you can tie the control to a field within a database, assuming that field contains image data. The control can be bound during design-time with a configured Adodc (ADO data control). During run-time, it can be bound by an Adodc or ADO recordset. This control is not compatible with VB's DAO Data control. The LoadPictureGDIp.rtf file contains information on how to set the databound control's DataSource property during design-time and run-time; not as straightforward as one would think.

See post#1 for more

----------


## LaVolpe

Control patched today. A logic bug in the mp3 tag parser could occur for tags less than 30 bytes. You should immediately download the updated/patched control if you were already using v2.1.25 posted on 3 Nov.

----------


## VbNetMatrix

Hi Lavolpe, 

thanks for all recent update.  I found what seem to be a bug with the alpha transparency of PNG file.
If you get a 1x1 pixel png of color RED and you  STRETCH it to 200x1 pixel, you'll get a line of 200x1 pixel of RED... wich is normal.

now, I take a 1x6 pixel RED with the following alpha transparency:

1x1: 15&#37;
1x2: 30%
1x3: 45%
1x4: 60%
1x5: 75%
1x6: 90%

(in other word I got a 1x6 red line going to the White)

and I stretch it to 200x6 pixel and it give a reversed pattern from Y1 to Y6 starting red at X1 and ending transparent at X200

in other word the pattern is reversed from top to bottom from x1 to x200 instead of staying the same pattern (but stretched)

what do you think ?

----------


## LaVolpe

> ...
> what do you think ?


My brain hurts. 
Maybe a picture is worth a 1000 words, along with the source image uploaded too  :Wink: 

Edited:
Here's what I did and I get what I expected: a 6-pixel high line stretched to 200x wide. When zoomed in using PaintBrush or other app, one can clearly see the 6 bands; nothing unexpected. Maybe, however you created the line, you were thinking transparency, but the method you used was thinking opacity? Or when you loaded/saved the PNG, it was done upside down?


```
    Me.ScaleMode = vbPixels
    Dim ss As SAVESTRUCT, tImg As New GDIpImage
    ss.Width = 1: ss.Height = 6 ' create 1x6 blank image
    ss.ColorDepth = lvicConvert_TrueColor32bpp_ARGB
    SavePictureGDIplus Nothing, tImg, , ss
    SetPixelGDIplus tImg, 0, 0, vbRed, 255 * 0.85  ' set colors from 15&#37; transparency
    SetPixelGDIplus tImg, 0, 1, vbRed, 255 * 0.7   ' to 90% transparency
    SetPixelGDIplus tImg, 0, 2, vbRed, 255 * 0.55  ' note this function uses opacity
    SetPixelGDIplus tImg, 0, 3, vbRed, 255 * 0.4   ' vs transparency; therefore
    SetPixelGDIplus tImg, 0, 4, vbRed, 255 * 0.25  ' 15% transparent = 85% opaque
    SetPixelGDIplus tImg, 0, 5, vbRed, 255 * 0.1
    SavePictureGDIplus tImg, tImg, lvicSaveAsPNG    ' convert to PNG
    aicLine.Picture = tImg                          ' apply image over white bkg
    aicLine.BackColor = vbWhite: aicLine.BackStyleOpaque = True
    aicLine.Interpolation = lvicNearestNeighbor     ' shows bands better (no blending)
    aicLine.Aspect = lvicStretch                    ' stretch image now
    aicLine.Move aicLine.Left, aicLine.Top, 200, 6
```

----------


## VbNetMatrix

'm very sorry, I should have compiled the latest version before posting that bug that annoyed me for month...

you already fixed it.  (I still got the old version though if you need it to see my problem)

however your answer raised another one in my head.  You're talking like if opacity and transparency is not the same ?

Maybe I don't use the proper term.  The zoomed picture you provided is a good exemple.
it's a red pixel wich you applyed a transparency layer, therefore changing the opacity of the red pixel from top to bottom.  am I not correct ?

----------


## LaVolpe

> however your answer raised another one in my head.  You're talking like if opacity and transparency is not the same ?


Opacity = the degree to which light is not allowed to travel through a material
Transparency = the physical property of allowing light to travel through a material
Definitions provided from wikipedia, but almost any source will give similar definitions

They are opposites. 100&#37; opacity is 0% transparency & 100% transparency is 0% opacity.
One could argue that they are the same when opacity or transparency is 50%, same as gray is both black & white

P.S. If you find a bug, especially one that annoys you, don't wait a month. I'm very receptive to bug reports  :Thumb:

----------


## VbNetMatrix

Well...  in my photo software program there is only 1 setting and it's called transparency, and I never saw a program with "both" feature, so I'm guessing it's 2 way of talking of the same thing but with different effect in mind...




> P.S. If you find a bug, especially one that annoys you, don't wait a month. I'm very receptive to bug reports


I Know you're very receptive to bug report, I just hate forum.  I loved forum the way back in the '90 because they remembered exactly wich post you didn't read....  forum today don't do that and you're always trying to get where you where last time and it's time consuming for the least to say...

and I got very limited time  :Wink: 

I'm surprised though that when I mentionned that bug you didn't answer me to check if I had the latest version.  I mean, it make sense to me that if you already fixed the bug, you knew about it... unless it was a logic bug that you fixed and you never saw it in action...  

in any case, as always, thanks for your GREEEEEEEAT product and continue your good work!

I have some product too (not related to graphic though) on Vb6 but I never posted them because I thought I was the only one still programing on Vb6...  maybe I shall do like you ...  but I'm affraid I would not have as many time as you for the bug report (and documentation) ...  :Wink:  

take care.

----------


## LaVolpe

> Well... in my photo software program there is only 1 setting and it's called transparency, and I never saw a program with "both" feature, so I'm guessing it's 2 way of talking of the same thing but with different effect in mind...


Agreed. Even in my code I use both terminology. For example, there is the TransparencyPct, TransparentColor & TransparentMode properties. And in the SetPixelGDIplus & GetPixelGDIplus functions, an opacity parameter is used. 

But within my routines, the formula to determine the alpha value depends on whether an opacity value is expected or a transparency value is expected. A fully opaque pixel has an alpha value of 255 out of 255 while a fully transparent one has a value of 0 out of 255
To change pixel's opacity percentage (0-100&#37 :Wink: , we can simply use something like this: Alpha=255*(pctOpacity/100)
But if talking about transparency, then the formula is tweaked just a bit:  Alpha=255*((100-pctTransparency)/100)
In either case, I think it is important to not confuse the two terms, opacity & transparency are antonyms not synonyms.




> ...
> I'm surprised though that when I mentionned that bug you didn't answer me to check if I had the latest version.  I mean, it make sense to me that if you already fixed the bug, you knew about it... unless it was a logic bug that you fixed and you never saw it in action...


You mentioned you downloaded most recent version, so any bugs in prior versions are history. Whatever the problem was, obviously it was corrected either because I found the bug or because of re-writing routines which I will do from time to time. This control is a year old now and when I see some code that could be much more efficient, I'll take the time to tweak it or re-write it. That could be how the previous bug, you were describing, got fixed.

----------


## VbNetMatrix

in any case, good control!  and good work  :Wink: 

the current revision is .26, the control with the bug was .16
not so far away  :Wink:  (other version number was same)

----------


## LaVolpe

> in any case, good control!  and good work


Thanks. I found another bug in the cFunctionsICO class. It will fail to use any icon that is loaded by handle or stdPicture containing an icon. I inadvertently broke that part of the class couple revisions ago; will be patched this weekend. Been wanting to update some of the sample projects to include some of the latest enhancements

----------


## VbNetMatrix

cool that you can fix it that fast...

----------


## VbNetMatrix

I noticed something, it's not a bug per say...  more a typo error.

The TOP property in the control is named "TOp"

 :Wink: 

I can live with it, maybe it's an Easter egg...  :Wink: 

also I was wondering if theses 2 commands following each other should work like on the VbPictureBox object  (meaning change size and retain it):

because as soon as it execute the second line, it revert to his original size...  :Frown: 

  AlphaImgCtl1.AutoSize = lvicSingleAngle
  AlphaImgCtl1.AutoSize = lvicNoAutoSize

----------


## LaVolpe

> I noticed something, it's not a bug per say...  more a typo error.
> The TOP property in the control is named "TOp" 
> 
> ... also I was wondering if theses 2 commands following each other should work like on the VbPictureBox object  (meaning change size and retain it):
> 
> because as soon as it execute the second line, it revert to his original size... 
> 
>   AlphaImgCtl1.AutoSize = lvicSingleAngle
>   AlphaImgCtl1.AutoSize = lvicNoAutoSize


The TOp is annoying to me too. It's something I keep meaning to find & fix, but reverts back to TOp everytime I change it to Top. I'll find it & fix it once for all; probably a typo in the module somewhere.

Regarding changing size...
AlphaImgCtl1.AutoSize = lvicSingleAngle may have no effect, depending on the current control size & image size. Regardless, changing .AutoSize to lvicNoAutoSize will have no effect because the control will not resize again with that setting.

If you are attempting to resize the control based on the current image...
AlphaImgCtl1.Aspect = lvicActualSize
AlphaImgCtl1.AutoSize = lvicSingleAngle
If those properties were set during design-time, control will be self-sizing to whatever image is assigned during run-time

More details would be helpful

Edited: If you are discussing design-time, then what you are experiencing is by design. I've built the control using VB's image control as the model. If the Aspect property is lvicActualSize, then assigning a new image to the control will show the image actual size, regardless of the .AutoSize property. This is similar to VB's image control's Stretch property. If that property is False, any new image you assign to VB's image control will result in actual size image; otherwise, the control does not resize. At run-time, the behavior is not the same. The resizing of the control is completely dependent upon the .AutoSize property.

----------


## VbNetMatrix

I don't think I made myself understandable about that Autosize problem.

I'll post an exemple soon, but it doesn't react the way you explained it "should"

That seem to confirm I have a problem.

as for the TOp property, I know how to fix.  I had a similar problem in past.
You'll have to Edit the file from external source (Ex.: Notepad++) as Vb won't allow this change to occurs because it is case insensitive, therefore he doesn't see the difference.  Or, you can (in Vb) temporarely change the property to a different name (let's say "TopB")  and then, remove the added caracter.  it will then understand the change.

----------


## VbNetMatrix

Here I made a list, all you have to do is Change the "TOp" in the Declaration.  Vb will correct it automatiquely all others place it appear.

here the list of Declaration with line number, use an external editor like Notepad++:

AlphaImgCtl.cls
79, 84 (Public Definition)

AicGlobals.ctl
100, 113  (struct definition)

GDIpImage.cls
434, 438, 440 (Public Property Get)

I fixed my side, it worked.

BIG WARNING THOUGH:
if compatibility is activated, UNREGISTER the file BEFORE compiling or you'll damage your registry.
fortunately, I knew how to fix manually but it was messy...
That's probably why Vb didn't wanted to allow the modification from inside IDE.

----------


## LaVolpe

> BIG WARNING THOUGH:
> if compatibility is activated, UNREGISTER the file BEFORE compiling or you'll damage your registry.


Not willing to break binary compatibility for such a small thing. I'll let others decide to do that for themselves. 
Edited. I figured out how to make it stick without breaking compatibility. Next time I patch the control; I'll get that done too


*For All*: Uploaded patches today. Summary of changes

- Loading/saving of icons, pcx, tga, pnm, & pam files had a few logic flaws

- Can now save loaded AVIs to file, array, clipboard & another GDIpImage class. However, no support provided for creating AVIs

- Added a new RTF file that some may find useful: ControlProps.rtf

- Updated some of the sample projects (minor updates overall)

----------


## VbNetMatrix

sharing your finding could be nice, it's not the first time myself I'm faced with this problem.

----------


## LaVolpe

> sharing your finding could be nice, it's not the first time myself I'm faced with this problem.


Can't do that. My app lied to me. Once I recompiled, using binary compatibility, it once again reverted to TOp vs Top. It's just the way it will remain until a revision forces me to break binary compatibility. As I said before, not willing to break compatibility for a simple typo on my part.

P.S. Looking at the PDF source documentation & considering using them as a multi-image source. Will be playing with this over the next couple weeks as I find some time.

----------


## Cube8

Regarding the "TOp" problem.
I've been in the same situation sometimes, but my case was about hWnd. Some people prefer it "hwnd" (small "w"), while I prefer it like this: "hWnd".
Normally, if you change the letter case in one part of the project, VB will change it everywhere. Unfortunately, there have been cases where tha change wasn't preserved after I reloaded the project.

What I do is: do a search & replace of _TOp_ to _Top_, activating the case-sensitivity checkbox and setting it to search the whole project. Then, I save it, close VB and re-open it. *Binary compatibility will not break just for changing the letter case, because COM is not case-sensitive.* A very easy way to understand how it is possible, is late-binding, where we can type the procedure name using any combination of small and capital letters and it will still execute.

All you need to do after that is un-register and re-register the control.

----------


## LaVolpe

> All you need to do after that is un-register and re-register the control.


Individual responsibility. Re-registering it will likely create a new GUID. New GUID may prevent pre-existing apps using the control to not be able to use the control once it is re-registered. Fixing it in my project is doable, but when recompiled using binary compatibility, it will revert to TOp unless one of the steps mentioned earlier, is performed. When & if I do make changes to break compatibility with earlier versions, I will fix the typo

----------


## Cube8

You misunderstood. I meant registering with regsvr32. The GUID is already inside the ocx.

The reason for un-registering and then re-registering (_regsvr32 /u_ and _regsvr32_ respectively) is because the control's interface is cached somewhere in the system and we force it to rebuild it.

----------


## LaVolpe

Control patched today.

Error found and corrected. When loading black/white icons/cursors by handle or stdPicture, calculation error wrote color table offset by 8 bytes resulting in incorrectly colored image.

----------


## SeoChamber

sorry to be such a noob.. but I just downloaded and compiled the ocx and then added it to a new project.  What Id like to do now is to be able to feed the control a string variable which contains the binary data (in string format ... as if you would open a .gif file in notepad++).  Can this be done?  Also, is GetPixel, SetPixel available on the control as well?

Thanks!

----------


## LaVolpe

> sorry to be such a noob.. but I just downloaded and compiled the ocx and then added it to a new project.  What Id like to do now is to be able to feed the control a string variable which contains the binary data (in string format ... as if you would open a .gif file in notepad++).  Can this be done?  Also, is GetPixel, SetPixel available on the control as well?


1) String containing binary data. I wouldn't suggest that. There is always possibility that bytes can be converted incorrectly depending on how you are loading the string.  The simple answer is no. The control only accepts 3 types of strings: a) file path/name, b) url, c) Base64 encoded string

What you can do is convert the string to a byte array first, then send that:


```
Dim bData() As Byte
bData() = StrConv(imageString, vbFromUnicode)
```

2) GetPixel/SetPixel. Yes. They are global functions found in the AICGlobals class. These functions are available when an alpha image control is added to any form. Those functions are: GetPixelGDIplus & SetPixelGDIplus

----------


## mahdix18

You are the best *LaVolpe*

----------


## k_zeon

Hey LaVolpe. You are the best person when it comes to Graphic usercontrols. I have a question. I am looking for a small simple usercontrol that i can display a bitmap or jpeg and mask a color. do you know of any such control. ( if not would you be able to create of advise code to use)
I know your Alpha Control can do this but dont need all the bells and whistles.
Many thanks

----------


## LaVolpe

> I am looking for a small simple usercontrol that i can display a bitmap or jpeg and mask a color. do you know of any such control.


I don't know of any, but it wouldn't be hard for you or someone else to create. I am not interested in creating specific, user-defined controls. 

1) TransparentBlt API can draw a bitmap to a device context while masking a color
2) You many not even need a control, consider using a picturebox

If you have any questions regarding what I just mentioned, you should ask those questions in the appropriate forum. Please do not use this thread to continue this topic. This thread is for the Alpha Image Control, not some other control or non-related topics.  Thank you.

----------


## canon1995

Please, can you explain how to load picture by code, without "CUSTOM" menu? Thank you.

----------


## LaVolpe

In the zip file you downloaded, open the LoadPictureGDIp.RTF file. There are several examples on how to load an image during run time.  Also in several of the sample projects, examples exist. The function you will use is called: LoadPictureGDIplus(). During design time, the "Custom" property page is the only way.

----------


## canon1995

> In the zip file you downloaded, open the LoadPictureGDIp.RTF file. There are several examples on how to load an image during run time.  Also in several of the sample projects, examples exist. The function you will use is called: LoadPictureGDIplus(). During design time, the "Custom" property page is the only way.


Oh, Thank you!

----------


## MarkCrum

Hey Lavolpe, I am a big fan and thank you so much for your gifts of knowledge!

I have a question, I would like to bring your control to the top of the zOrder but can't seem to. I am limited in knowledge of how this works. Is there a way to bring it to the front and maintain it's transparency appeal?

Just to clarify the reason: I would like to use the control as a button for a slider control or (on the form itself) so code can move it around when you left click on it and drag. So I must be able to load my image with transparency. I know I can place it on a PictureBox but the pictureBox background is square. Seeing the picbox behind the image control is undesirable.

Thank you in advance for replying

Mark

----------


## LaVolpe

Mark, thanx for the compliments. This is a windowless control. As such, its ZOrder will never be higher than any windowed control (i.e., button, slider, etc). The ZOrder does work in relation to other windowless controls (i.e., image, line, shape, label). Gotta think in terms of ZOrder, that this control is the same as a label, line, shape, etc.  

The control cannot be made windowed and maintain its variable-level transparency. If a control only needed to have simple transparency (either 100&#37; opaque/transparent); then it would be possible with the help of the usercontrol's MaskPicture property. But I won't modify the control for that limited purpose. There are examples of creating shaped usercontrols out & about.

*Edited*: Here's an idea you may be able to use. I won't discuss it further in this thread, but could address it if I saw it in the appropriate VB or graphics portion of the forums. With Win2K and above, we have the ability to create layered windows that can be shaped from any image. This layered window could be a form in your project. The image for that window can be loaded with my control, or not. By using the APIs SetLayeredWindowAttributes & UpdateLayeredWindow you can create a shaped form that appears when the drag operation begins, move the form while dragging, then unload the form when the drag stops.

----------


## MarkCrum

Thanks... hmmm, might look into that. I did find a very suitable situation. Using your 32dbb DIB Suite from Planet Source, (which I have been using in the Frame and Button control that created) I use the image classes to create the image and rener it to the UserControl hdc. I sort of rig portions of the control in a modular rect manner like, border area, body, caption area, header, and such... THis has been a great way to deal with images and seems to be quite fast. So I just used that, stretched the image and set the corners to the closest rounded edge that is pretty close (as long as the object is not elliptical) and it works pretty well.

Here is a question that could save me a bunch of research if you would as I do not have the newer Os's? Using that older Dib Suite, should I expect any problems with Win7, Vista, or any other up-coming versions? Also, have you updated that since 2009's version on Planet Source Code?

Thanks you really are a great teacher!

Mark

----------


## MarkCrum

Oh, I had to chuckle, I feel like I am chatting with VB Royalty!! I can't begin to really thank you enough for the great work and your willingness to share your knowledge. Just thought I'd put that out there! Thanks!!!

----------


## LaVolpe

Mark, the DIB suite is fairly stable. I don't expect it should have any major issues. PSC has the most current version & it won't be updated. This control was based off of that to begin with. The major differences between the two are pretty much enhancements to this control:
- reads more formats; writes to more formats
- handles a few more rarer GDI+ bugs
- based on GDI+ images, DIB suite based on DIBs/GDI but preferred GDI+ for PNG/TIFF 
- more graphical options
- the DIB suite was written to support Win95 also; this is really not but can be
- the DIB suite has 1 major advantage over this control and that regards writing PNGs. This control uses GDI+ only; whereas, the suite has code to manually create PNG with various compression algos & more options

*Now back to your issue*. If your image does not contain significant levels of transparency, i.e., simple transparency mostly, you can mimic what I suggested with already built-in methods, and with very good results:

1. Use a picturebox instead of my control for that floating window. Properties include AutoRedraw=True, BorderStyle=0
2. From the control/image class containing your picture, call the RegionFromImage method to return a windows region
3. Apply that region to the picturebox. Do not destroy the region in this case


```
' api you'll need
Private Declare Function SetWindowRgn Lib "user32.dll" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long

' shaping the picturebox
:: draw the image onto the picturebox or put my control in the picturebox at 0,0 coords, then...
SetWindowRgn  Picture1.hWnd, AlphaImgCtl1.Picture.RegionFromImage(), True
' Image must not be resized. If it must be resized; you'll need to save it first to the new size. 
' RegionFromImage uses actual size image only

' should you need to restore picturebox
SetWindowRgn Picture1.hWnd, 0&, True
```

The 1st parameter of the RegionFromImage method can be adjusted to allow/remove more semi-transparent pixels. See the comments for that function. Those that are allowed will not be semitransparent; they will be converted to 100&#37; opaque. That parameter, whatever setting, ensures variable transparency is treated as simple transparency.

Apologize a bit. Should've thought about this solution earlier; but honestly, I just forgot I added that method to the control a couple versions ago.

----------


## VbNetMatrix

Hi Lavolpe!

Happy NEW YEAR for you!!!

when crashing celebration will be over  :Wink: , could you tell me how you set up the Interpolation ?

By default it's set on AUTO,  but how this AUTO mode is decided ?  Because in all my project I have to fix it manually, I'm guessing my kind of project is not standart

Any documentation on this ?  Would help me understand, maybe I'm doing something wrong.

regards.

----------


## LaVolpe

The ControlProps.rtf that came with your zip should answer your question

----------


## VbNetMatrix

Ok I read....

now got 2 questions...

You're using lvicHighQualityBicubic when sizing is using.

if user is sizing 2 sides (height and width) it make sense.
However, if user size only 1 side (eitheir Height or Width), 
lvicHighQualityBicubic is prone to error (I think) because in that case
(when user is sizing only 1 side) the desired effect is probably not
what lvicHighQualityBicubic is doing.

exemple:  you got a 1pixel width (many pixel height) using some transparency and you want to make a BORDER of a frame...
in that case, lvicNearestNeighbor would be more appropriate.

Do you think it's worth including this "thinking" into the Auto mode decision ?

I can provide a physical exemple if my speech wasn't understandable.

question 2:  Do you got something equivalent to LINE and CIRCLE ?  if so, where is the doc about theses functions ?  thanks.

(you're still the best, you very much inspired me in 2011 and I'm thinking about releasing my Access Database component in 2012, I just need to buil a website for it)

----------


## LaVolpe

1) Maybe an example could help better describe the problem. Also include the Aspect & AutoSize properties you are using for the control.

2) GDI+ has API calls to draw a line and circle if you wish to draw them via GDI+. But you can also use the WantPrePostEvents property to draw the lines & circles yourself. The custom button sample project is an example of using that property and responding to the PrePaint & PostPaint events. You should also look at that RTF file again for more information on those events

----------


## VbNetMatrix

1.
http://vbnetmatrix.com/download/lavo...erpolation.zip

You want to check out Middle part (Left Middle, Top Middle, Right Middle and Bottom Middle)
they are the part that are stretched.  Corner are not stretched.

2. Will check that out... thanks for the info.
Would GDI+ be Faster ? for drawing line ??
because if I go to all the fuss ans wuzz to Prepaint postpaint and iT's slower, ... no need to reinvent the wheel, do I ?

what do you think ?

----------


## LaVolpe

1. Ok, I see what you are talking about. No, I do not agree the logic needs to be changed. You are stretching an image that is 1 pixel in width or height. Different interpolation algorithms will render different results. The "auto" selection may not be ideal for every possible situation, but it will be for a majority of the cases. Since the control allows you to opt for different interpolations, I think that is good. Keep in mind, most people will not be using this control to stretch a 1 pixel image, they will be using it to display pictures vs. lines

2. Regarding drawing lines or circles. The Pre/PostPaint events really are not slow. When the property is set, a bitmap is created that lasts until WantPrePostEvents is set to false or the control is destroyed. Unless the image is nearly full screen, you shouldn't see any differences in speed.

Now it all depends on the quality you want for your circles and lines. A circle drawn with VB or GDI32 apis will not be alpha blended but are far easier to use. If you want smoother/blended edges for circles and diagonal lines, GDI+ may be ideal. You will still use Pre/PostPaint events, create a GDI+ DC, create a GDI+ brush and/or pen, set the interpolation for that DC, then draw a GDI+ line or circle. Browsing the graphics portion of the forum could be useful if you are not familiar with GDI+. This is one of my favorite GDI+ sites, but it is not really friendly to VB language. If I see questions regarding GDI+, I usually try to help, but won't use this thread for a GDI+ tutorial.

----------


## VbNetMatrix

"Keep in mind, most people will not be using this control to stretch a 1 pixel image"

1. Yeah I know what you mean, that's why I said "changing the logic for that particular case"  maybe it wasn't phrased that way but that's what I meant.  Most people will not use the control that way, it's true.  But thoses who will are expecting that result, right?  meaning, a simple test inside control

If (Streched X AND NOT Streched Y) or (Streched Y AND NOT Streched X) then
 Interpolation =3
else
 Interpolation =0 'Auto
end if

But now that I'm aware of the problematic, it's probably simpler to SET my control in the begining... I'm agreeing with you...  But since people using that particular mode of stretching are probably seeking for that kind of effect it seem pertinent to insert the logic...


2. Why hDc of the control is available only at postpaint event ?  can't we write directly on the control ???  I failed to find a Gdi Exemple that would allow me to paint directly on the control without hDc.  I probably missed something.

and yes, my control is fullscreen, so yes I think best way would be to use GDI...  or learn more about creating a png directly using your control...

thanks.  I would never say enough how much your control is apreciated.

----------


## LaVolpe

> 2. Why hDc of the control is available only at postpaint event ?  can't we write directly on the control ???  I failed to find a Gdi Exemple that would allow me to paint directly on the control without hDc.  I probably missed something..


The control is windowless, it gets it DC from its container only during the control's Paint event. During the paint event, it then sends you the DC thru the Pre/PostPaint events if requested. But it really isn't the actual DC because that DC is clipped and offset; so a temporary DC is sent instead that will cause problems if you draw outside of the actual control which is possible if the real DC was sent. There is no DC to draw on directly.

----------


## VbNetMatrix

ok, so if I understand correctly from previous post...

1. the control is windowless because otherwise it wouldn'T allow full transparency
2. a windowless control obviously doesn't have a direct DC
3. if using the dc from pre/post paint event, I draw OUTSIDE the control, it can be dangerous ?  like crashing issue ?

4. is there any way to temporary "CreateDc" using GDIpImage and  SAVESTRUCT ?  (I'm probably just half stupid)

----------


## LaVolpe

1) Yes regarding variable translucency. If GIF-like transparency, no blending, then that can be done a few different ways. But that would remove semi-transparency effects

2) No, it can. But I chose not to for 2 reasons: a) uses less resources, b) I'd still have to get VB to paint the container's bkg to the DC

3) No, crashing is not the issue. When VB sends the control a DC, it is clipped and offset so that 0,0 coords of the DC line up with the control and the width/height of the DC is the 'dirty' area to be painted by the control. The DC is actually the entire container. Now if someone were to mess with the DC and remove or adjust the clipping region contained in it, the entire container becomes the drawing area instead of just the area occupied by the control. Also, it would be possible to inadvertently corrupt the DC. This is the reason I do not send users the actual DC, but I send them an offscreen DC which I then paint to the container

4) Don't understand. Maybe you can describe what you are trying to do that the control isn't allowing you to do

----------


## VbNetMatrix

2.  b) ??  I didn't understood what you meant about the Vb Paint.

3. clever... I like it...  it's like when I use a control to Subclass, if it crash in the Subclass only my control crash and not the full app.   :Wink:  and I can still Debug...

4.) I need to use direct drawing function like MoveToEx and LineTo (Api)
wich I failed to perform...   So I probably misunderstood you properly when you said I could use Gdi+ function...  I looked up the web site you gave, but I have no idea where to start my search so unless I read all the 563 pages bible on GDI (Wich is very interesting by the way) I don't know where to look or even what I'm looking for...  

I need to draw a New GdiIpImage that is 1024x768 (screen size) in size
with transparency.  So unless I figure out how to perform that many SetPixelGDIplus in less then 3 second, I need to find another way... 

one thing that could help was if I had an already prepared Array of pixel like a BitBmp map I could use and only change the part I need to...  wich is adding some line...

now the problem lie in the fact that I don't know the Size Screen of all client and it's possible it would not always be 1024x768...

one possible solution if I can't find another way would be to limit my program to a few different size, and prepare semi transparent background image that I would just load and then make the change (still need to draw line in it) on the fly...

any thought, suggestion, protocol and documentation would be great.  You are still the one knowing this control more then anybody...

thanks for all..

----------


## canon1995

Hi LaVolpe! You are the best programmer I ve ever seen in my life! Thank you and Happy New Year! I have a problem, can you help me, please?
So, I have a module:

vb Code:
Public Declare Function ExtractAssociatedIcon Lib "shell32.dll" Alias "ExtractAssociatedIconA" (ByVal hInst As Long, ByVal lpIconPath As String, lpiIcon As Long) As Long
Public Declare Function DrawIcon Lib "user32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal hIcon As Long) As Long
Public Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long
and Form Code:

vb Code:
Private Sub Command1_Click()
CommonDialog1.ShowOpen
Dim sPath As String, hIcon As Long, nIcon As Long
sPath = CommonDialog1.FileName
hIcon = ExtractAssociatedIcon(App.hInstance, sPath, nIcon)
DrawIcon Picture1.hdc, 0&, 0&, hIcon
AlphaImgCtl1.PaintImageAsDrawnToHDC (Picture1.hdc)
DestroyIcon hIcon
End Sub
So, what is wrong in it? Or how can I paint associated icon to AlphaImgCtl1(hdc)? Please, can you help me to correct it? Thanks!

----------


## LaVolpe

> Or how can I paint associated icon to AlphaImgCtl1(hdc)? Please, can you help me to correct it? Thanks!


Set AlphaImgCtl1.Picture = LoadPictureGDIplus(hIcon)

Edited: P.S. I've already built a routine into the control that will load associated icons. It will be available in the next update which is waiting on DPI awareness code I haven't completed yet

----------


## canon1995

> Set AlphaImgCtl1.Picture = LoadPictureGDIplus(hIcon)
> 
> Edited: P.S. I've already built a routine into the control that will load associated icons. It will be available in the next update which is waiting on DPI awareness code I haven't completed yet


Understood. Thank you. 
Oh, it will be great!

----------


## VbNetMatrix

canon1995:

I don'T understand why you're using a picturebox ??  You want to Erase the TRANSPARENCY of the Icon ??  You don't need a Picturebox unless that's what you want to do...

see LoadPictureGDIp.rtf,  look for:
"Binaries. Binaries such as exe, dll and ocx can contain bitmaps, icons, cursors"
and also check for "Section IV"

can you tell us more what you're trying to do ?
might be easier to extract the icon in ICO file and then Load them from Lavolpe component...

----------


## VbNetMatrix

sorry Lavolpe, there were no answer when I started writing...

if you got time, can you help me with my last question ?

----------


## VbNetMatrix

Lavolpe:
concerning canon1995 issue, while trying to write him an exemple code, I ran into something strange with an EXE file.  If you want to check it out for your next to come
quote:
  "built a routine into the control that will load associated icons"

http://vbnetmatrix.com/download/lavolpe/Strange.zip

----------


## canon1995

> canon1995:
> 
> I don'T understand why you're using a picturebox ??  You want to Erase the TRANSPARENCY of the Icon ??  You don't need a Picturebox unless that's what you want to do...
> 
> see LoadPictureGDIp.rtf,  look for:
> "Binaries. Binaries such as exe, dll and ocx can contain bitmaps, icons, cursors"
> and also check for "Section IV"
> 
> can you tell us more what you're trying to do ?
> might be easier to extract the icon in ICO file and then Load them from Lavolpe component...


I dont want to Erase Transparency. This code works to get icon from file to Picture1. It was posible only to get icon to Picture.hdc or Form.hdc, but now it's posible to load it to Lavolpe control.

----------


## LaVolpe

> I need to draw a New GdiIpImage that is 1024x768 (screen size) in size
> with transparency.  So unless I figure out how to perform that many SetPixelGDIplus in less then 3 second, I need to find another way...


Drawing onto the full-size image is possible but requires a bit more forethought. You can get a DC related to the actual image and draw directly to it. That does permanently change the image. Here's some sample code that will create a full screen image and draw a diagonal, blended, line from top left to bottom right. For future questions about these GDI+ APIs and other ones you may be interested in, you should post those questions in the VB or graphics portion of the forum. This is because you are now entering a different topic area that isn't directly related to the control.

You'll need a DC to the control's image after you create the full screen image. Then you'd set the interpolation on that DC and draw your lines & circles


```
' apis for this exercise
Private Declare Function GdipGetImageGraphicsContext Lib "GdiPlus.dll" (ByVal pImage As Long, ByRef graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long
Private Declare Function GdipDrawLineI Lib "GdiPlus.dll" (ByVal graphics As Long, ByVal pen As Long, ByVal x1 As Long, ByVal y1 As Long, ByVal x2 As Long, ByVal y2 As Long) As Long
Private Declare Function GdipCreatePen1 Lib "GdiPlus.dll" (ByVal pColor As Long, ByVal nWidth As Single, ByVal unit As Long, ByRef pen As Long) As Long
Private Declare Function GdipDeletePen Lib "GdiPlus.dll" (ByVal pen As Long) As Long
Private Declare Function GdipSetInterpolationMode Lib "GdiPlus.dll" (ByVal hGraphics As Long, ByVal Interpolation As Long) As Long
Private Const UnitPixel As Long = 2&

' sample of creating a blank image
    Dim ss As SAVESTRUCT, tGDIpImage As GDIpImage
    ' change ss.Width/Height as needed
    ss.Width = Screen.Width \ Screen.TwipsPerPixelX
    ss.Height = Screen.Height \ Screen.TwipsPerPixelY
    ss.ColorDepth = lvicConvert_TrueColor32bpp_ARGB
    ' create a blank image of desired size & color depth
    Set tGDIpImage = New GDIpImage
    SavePictureGDIplus Nothing, tGDIpImage, , ss
    ' assign the image to the control & resize the control
    Set AlphaImgCtl9 = tGDIpImage
    AlphaImgCtl9.AutoSize = lvicSingleAngle
    
' sample of drawing a line on the actual image
    Dim hGraphics As Long, hPen As Long
    ' get the DC for the image
    If GdipGetImageGraphicsContext(AlphaImgCtl9.Picture.Handle, hGraphics) = 0 Then ' ok
        ' create a blue pen, 2 pixels in width
        If GdipCreatePen1(ConvertRGBtoARGB(vbBlue), 2, UnitPixel, hPen) = 0 Then ' ok
            ' set interpolation mode.
            ' Note that if using my RenderInterpolation enum, you need to add 2.
            ' DO NOT use .lvicAutoInterpolate
            GdipSetInterpolationMode hGraphics, RenderInterpolation.lvicHighQualityBicubic + 2
            ' draw the line & clean up
            GdipDrawLineI hGraphics, hPen, 0, 0, AlphaImgCtl9.ScaleWidth - 1, AlphaImgCtl9.ScaleHeight - 1
            GdipDeletePen hPen
        End If
        GdipDeleteGraphics hGraphics
    End If
    AlphaImgCtl9.Refresh    ' view the changes
```




> now the problem lie in the fact that I don't know the Size Screen of all client and it's possible it would not always be 1024x768...


That's easy enough: 
screenCx = Screen.Width\Screen.TwipsPerPixelX
screenCy = Screen.Height\Screen.TwipsPerPixelY

Note that you probably won't get full screen anyway. Any taskbars take away from the available screen size. If your form is not borderless, then your form's borders, titlebar, menubar take size away too. If you want to get the total available size your maximized form will display, use this instead. Form's scalemode must be twips else use ScaleX/ScaleY as needed

maxWidth = Me.ScaleWidth\Screen.TwipsPerPixelX
maxHeight = Me.ScaleHeight\Screen.TwipsPerPixelY

----------


## VbNetMatrix

> I dont want to Erase Transparency. This code works to get icon from file to Picture1. It was posible only to get icon to Picture.hdc or Form.hdc, but now it's posible to load it to Lavolpe control.


well...  picturebox DOESN'T support transparency... that's why we need Lavolpe excellent OCX.  If you load ANYTHING inside picture box, you're loosing the transparency.  Vb6 Doesn't support it.  If you would copy any picture box content to Lavolpe component, you'll never get transparency back.

that's what I meant.  Sorry for the confusion.

----------


## VbNetMatrix

Lavolpe:

part 1: Excellent, I'll try that...

part 2: no, no...  what I meant was that since the Screen size was variable, I would prefer not to use external png file to load because it mean my program might be useless in futur if screen resolution go haywire!  (lol)  I'm well aware of how to make setting size issue and scalemode and other setting to get back the size...  and yes my form is full screen, no border and TopMost

thanks for everything... I'll test the code...  and about the warning, I'm taking note of it, but I asked it here because I thought there would be a simple way to do a line in your control using an internal function I didn'T know about...  Since you know the component very well, it seem obvious for me to ask if there were such internal function as drawing line...  do You think it's worth exploring to add it in the future ? (Since internally you already got the DC ?)  Or at least, tell me where to look inside the component to get the DC and I'll try to modify my version of it to make some test ?

thank for everything.

----------


## VbNetMatrix

rofl...

I was using:
Private Type POINTAPI
  x As Long
  y As Long
End Type
Private Const PS_SOLID = 0
Private Declare Function CreatePen Lib "gdi32" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, lpPoint As POINTAPI) As Long
Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long

  lngPenHandle = CreatePen(PS_SOLID, 1, vbRed)
  lngRetValue = SelectObject(picGrid.hdc, lngPenHandle)

and MoveToEx  and LineTo  function...


I didn'T know there where GdiEquivalent... that's all I was missing.  Thanks for bringing the light Lavolpe, you're the best.

----------


## LaVolpe

> ... do You think it's worth exploring to add it in the future ? (Since internally you already got the DC ?)  Or at least, tell me where to look inside the component to get the DC and I'll try to modify my version of it to make some test ?


I am against modifying the control to make it become a graphics application. It's purpose has always been to display images like an image control, not to act as a Paint application. However, since I foreseen questions like this, I have exposed everything one needs, either directly or indirectly, to draw to the control or the image. This must be done outside the control by the user -- just my rule. As mentioned in post #3, I will not support modifying the control for specific customer needs; nor offer sample code to do so. If you do decide to tweak the control; I will not offer any support in fixing it... you break it, you fix it. Again, just my rules

As mentioned before, you can use Pre/PostPaint events to draw directly to the control since that event passes you a typical hDC that can be used with MoveToEx, BitBlt, LineTo, etc. Any drawing you do is on the control, not the image. You can even use GDI+ APIs to draw blended shapes to the control. That does require you to create a GDI+ hGraphics object from the passed hDC from those events: GdipCreateFromHDC

----------


## LaVolpe

> Understood. Thank you.


Are you good to go now? Didn't want to lose you in the last volley of replies

----------


## VbNetMatrix

ok, Here something odd...

    'Assign the image to the control & resize the control
    Set AlphaImgCtl9 = tGDIpImage
    AlphaImgCtl9.AutoSize = lvicSingleAngle

AlphaImgCtl9 size is Changed properly, but property: 
AlphaImgCtl9.Width and AlphaImgCtl9.Height

are the OLD size...

normal or not ?

I replaced it with:
    aImg.Width = typGDIpImage.Width
    aImg.Height = typGDIpImage.Height
    Set aImg.Picture = typGDIpImage


2.:
Quote "As mentioned before, you can use Pre/PostPaint events"

how do I fire them ?  and what if I need to fire them BEFORE the control is shown ?

----------


## LaVolpe

> 1. ok, Here something odd...
> 
> 2. Quote "As mentioned before, you can use Pre/PostPaint events"


1) the control's .Width & .Height values are in the control's container's scalemode. The .ScaleWidth & .ScaleHeight properties are always in pixels and is same as AlphaImgCtl9.Picture.Width & .Height when control is same size as the its image. The typGDIpImage .Width & .Height properties are the actual image's width/height in pixels.

2) Set the WantPrePostEvents property to true. You then have to respond to the PrePaint and/or PostPaint events of the control to draw onto the control. The custom button sample project has an example and the ControlGDIp.rtf file has some documentation. PrePaint fires before image is drawn to control; PostPaint fires after image is drawn but before control is visibly updated

----------


## VbNetMatrix

1. ok, and in that case, what the height and width represent ?
2. I turned WantPrePostEvents to True, but Prepost doesn't fire...  that's why I asked "How do I fire them"

----------


## canon1995

> Are you good to go now? Didn't want to lose you in the last volley of replies


All is OK! I understood all.

----------


## LaVolpe

> 1. ok, and in that case, what the height and width represent ?
> 2. I turned WantPrePostEvents to True, but Prepost doesn't fire...  that's why I asked "How do I fire them"


1) depends on the context
AlphaImgCtl1.Width is the width of the control in its container's scalemode
AlphaImgCtl1.ScaleWidth is the width of the control in pixels less border if used
AlphaImgCtl1.Picture.Width is the control's image's width in pixels

2) From that sample you sent me, pick one of the AlphaImgCtrl6 controls; doesn't matter which index. Change WantPrePostEvents to true. Copy and paste this code & you'll see it fires. Look at ControlPropsGDIp.rtf for more info


```
Private Sub AlphaImgCtl6_PostPaint(Index As Integer, hDC As Long, Left As Long, TOp As Long, Width As Long, Height As Long, HitTestRgn As Long)
    Debug.Print "postpaint for index "; Index
End Sub
Private Sub AlphaImgCtl6_PrePaint(Index As Integer, hDC As Long, Left As Long, TOp As Long, Width As Long, Height As Long, HitTestRgn As Long, Cancel As Boolean)
    Debug.Print "prepaint for index "; Index
End Sub
```

----------


## VbNetMatrix

1. thanks a lot...  crystal clear now...  but that doesn'T explain how the container can be smaller then the picture...


2.  You're talking about the Icon Bug file I sent you in regard to Canon1995 ?
I don't have anymore the other bug file...  oh... the square box thing... I got this one

added: That kind of strange, it wasn't firing on my other project...   :Frown:

----------


## LaVolpe

> 1. thanks a lot...  crystal clear now...  but that doesn'T explain how the container can be smaller then the picture...
> 
> 
> 2.  You're talking about the Icon Bug file I sent you in regard to Canon1995 ?
> I don't have anymore the other bug file...  oh... the square box thing... I got this one
> 
> added: That kind of strange, it wasn't firing on my other project...


1) Sure it can. If you put at 1024x1024 control on a 32x32 container, the control will be bigger than the container, clipped by the container, but bigger. Likewise, an image can be bigger that the control. If not scaled/stretched, it will be clipped

2) No. I was talking about your sample project regarding the Auto-Interpolation issue

----------


## VbNetMatrix

2. ok got it...  made it work...  doesn't know what was wrong in my other try though... will check that...

1. Maybe we have different terminology...

for me:
Container:  the OCX object that Hold the image.
Control: the image itself I guess in the case of the Lavolpe OCX.

If you put a 1024x1024 control on a 32x32 container, you'll be enable to see only 32x32 of that control, right ?  because the rest will be clipped inside...

Now, this is not what is happening with your control.

I got a 1024x1024 image loaded and I see it ALL (Full screen) but when I check the ocx (container) width, I got 512

wich doesn't quite add up to my reality because if the container was "really" smaller, I should only be enable to see as big as the container ?

Where do I not understand ?

----------


## LaVolpe

The control's container is the object where the ocx is placed into: form, picturebox, frame, etc
The control is the ocx

The value of the ocx/control's width is decided by the container's scalemode. If it is returning 512 and you are absolutely positive you can see the entire 1024x1024 image, then I assume your container is using a custom scalemode: Debug.Print Me.ScaleMode (replace Me with whatever the controls' container is)

----------


## VbNetMatrix

I use Pixel (3) scalemode...  I always do in every graphics programs, it's more practical...   want my code ?
(oh and YES, I use the "original" Lavolpe, not modified, not broken... just in case)

----------


## LaVolpe

> I use Pixel (3) scalemode...  I always do in every graphics programs, it's more practical...


Then I have know idea why AlphaImgCtlx.Width would return 512 in your case. You'd have to troubleshoot that. It has nothing to do with the control. A control's .Width property is provided by VB.

----------


## VbNetMatrix

ok, I found the reason to my Size Bug...  it was in the code... but I'm not sure it's supposed to react that way...

Part1:
  'aImg (Lavolpe component) on the form is 400x400 when form is loaded...

  'From Post #328
  ' sample of creating a blank image
  Dim typSaveStruct As SAVESTRUCT
  Dim typGDIpImage As GDIpImage

  'Create a blank image of desired size & color depth
  typSaveStruct.Width = 1024
  typSaveStruct.Height = 768
  typSaveStruct.ColorDepth = lvicConvert_TrueColor32bpp_ARGB
  Set typGDIpImage = New GDIpImage
  SavePictureGDIplus Nothing, typGDIpImage, , typSaveStruct



This work:
Part2a
  'Assign the image to the control & resize the control
  Set aImg = typGDIpImage
  aImg.AutoSize = lvicSingleAngle

  debug.print aImg.Width   '=1024
  debug.print aImg.Height  '=768

This Strange:
Part2b
  'Assign the image to the control & resize the control
  Set aImg.Picture = typGDIpImage
  aImg.AutoSize = lvicSingleAngle

  debug.print aImg.Width   '= 400
  debug.print aImg.Height  '= 400

I know that the default property is Picture, but why specifying picture DIRECTLY is causing a problem in the refresh of the container property ?
is it by design ?

----------


## canon1995

LaVolpe, Sorry, but I have a problem again. It concerns my previous post(321). I got icon in AlphaImgCtl1, but now I need to save it to file, but I can't understand how. Sure I have read "SavePictureGDIplus" manual. And is it posible to load it again to control after programm reload automaticaly?

----------


## LaVolpe

> LaVolpe, Sorry, but I have a problem again. It concerns my previous post(321). I got icon in AlphaImgCtl1, but now I need to save it to file, but I can't understand how. Sure I have read "SavePictureGDIplus" manual. And is it posible to load it again to control after programm reload automaticaly?


If you just want to save the picture to file in the same image format (no format conversions):
SavePictureGDIplus AlphaImgCtl1.Picture,  "C:\MyImages\filename.ext", lvicSaveAsCurrentFormat

If you want the image to be part of your program, you will want to do 1 of these 2 things:
1) Add it to an Alpha Image Control during design time via the Custom property page
2) Add it to a resource file and use LoadPictureGDIplus during form_load. The LoadPictureGDIp.rtf has examples of loading image from resource files

If I am not understanding the question correctly, let me know

----------


## LaVolpe

> ok, I found the reason to my Size Bug...  
> 
> This Strange:
> Part2b
>   'Assign the image to the control & resize the control
>   Set aImg.Picture = typGDIpImage
>   aImg.AutoSize = lvicSingleAngle
> 
>   debug.print aImg.Width   '= 400
>   debug.print aImg.Height  '= 400


I cannot reproduce the problem. My results are always 1024,768
If Aspect property is not ActualSize then _aImg.AutoSize = lvicSingleAngle_ has no effect because the image is being scaled or stretched to the current control dimensions. Suggest ensuring Aspect & AutoSize properties are reset back to zero before loading a new image into the control; then set those properties as needed?

----------


## canon1995

> If you just want to save the picture to file in the same image format (no format conversions):
> SavePictureGDIplus AlphaImgCtl1.Picture,  "C:\MyImages\filename.ext", lvicSaveAsCurrentFormat
> 
> If you want the image to be part of your program, you will want to do 1 of these 2 things:
> 1) Add it to an Alpha Image Control during design time via the Custom property page
> 2) Add it to a resource file and use LoadPictureGDIplus during form_load. The LoadPictureGDIp.rtf has examples of loading image from resource files
> 
> If I am not understanding the question correctly, let me know


Perfect! I got it. Thank you!

----------


## LaVolpe

> Perfect! I got it. Thank you!


Until I post an update with the associated icon routines which would allow you to select such an icon during design view, here's yet another option

1) Build simple test project & include Alpha Image Control (AIC) & button
2) In button click event, extract icon, add it to AIC & save it to file
3) In your real project, now you can load it, from the file, within the custom property page

----------


## canon1995

> Until I post an update with the associated icon routines which would allow you to select such an icon during design view, here's yet another option
> 
> 1) Build simple test project & include Alpha Image Control (AIC) & button
> 2) In button click event, extract icon, add it to AIC & save it to file
> 3) In your real project, now you can load it, from the file, within the custom property page


I'am doing it the same way. I don't need to load it via custom menu because this icon often changes. I'am waiting for update.

----------


## LaVolpe

> ...but now I need to save it to file, but I can't understand how. Sure I have read "SavePictureGDIplus" manual.


Hmmm, just looked at that rtf file. You know, I don't explain anywhere in there how to simply save an image to file or array if you are not going to use any of the image modification/conversion options. Will have to remedy that. Thanx

----------


## canon1995

> Hmmm, just looked at that rtf file. You know, I don't explain anywhere in there how to simply save an image to file or array if you are not going to use any of the image modification/conversion options. Will have to remedy that. Thanx


Thats why i can't to understand Save function. So, I'am waiting for next update. Thanks you too.

----------


## VbNetMatrix

alhough not explained per say (I had to dig up a lot) you made an excellent exemple of all saving and conversion in your sample program called: prjSaveAs.vbp

about post 348:  I think I found what cause the problem with the size...
I changed the size of the picture while the form was hidden and the size of the component change only after the refresh (Show) of the picture...

is that normal behavior ?

----------


## LaVolpe

> about post 348:  I think I found what cause the problem with the size...
> I changed the size of the picture while the form was hidden and the size of the component change only after the refresh (Show) of the picture...
> 
> is that normal behavior ?


Maybe  :Smilie:  ... a bit of tap dancing
The Show event of the usercontrol activates when it is first shown. Well on hidden forms or if the control's visible property is false, then that event won't trigger. The sizing routines of the control occur in the Shown event. I can see where this could be a problem for controls on hidden forms or controls that remain visible=false for whatever reasons. I will modify the control to account for this case, but it will not be automatic. If anyone needs to reference properties of a hidden/invisible control after loading an image, they should load the image, set whatever properties are desired then call the control's .Refresh method.

The Refresh method will need to be modified. Here it is. Just copy & paste to replace. Will be in next update


```
... removed. May be a VB bug & will be auto-corrected via code. See post 370 next page for more
```

----------


## VbNetMatrix

The modification doesn't seem to work...

here a project exemple...
http://vbnetmatrix.com//download/lav...apDanceBug.zip

also, You didn'T gave confirmation you saw that strange thing on ICON extraction, (just want to know if I can erase the file)

http://vbnetmatrix.com//download/lavolpe/Strange.zip


thanks for everything

----------


## LaVolpe

Just download both files. Will get back to you after I've had a chance to review them

Edited; That was easy. Simply call aImg.Refresh after you are done setting properties and before you read the properties:


```
....
  aImg.AutoSize = lvicSingleAngle
  aImg.Refresh    ' view the changes <<<< moved this here
  If (aImg.Width = 400) Then
    Stop  'Not supposed to happen...
  End If
```

I'll look at the other project today or tomorrow... Done.

What is the issue? Are you wondering why there are like several images in a single image? If so, that is not uncommon. What you are looking at is a bitmap that contains several mini-images. The app loads that resource then BitBlt's the image from it that it wants to be used for whatever purposes; probably a toolbar. The shell32.dll does something very similar too. As I said, this is not uncommon.  If you tweak your code a bit, you'll see what I'm talking about. The difference with the shell32.dll is that it stored a 32bpp alpha bitmap whereas your depends.exe did not.


```
Private Sub Form_Load()
  Me.ScaleMode = 3  'Pixel
  
  'LoadIconX App.Path & "\depends.exe"
  LoadIconX "C:\windows\system32\shell32.dll"
End Sub

Public Sub LoadIconX(ByVal pstrFileName As String)
  Dim objGDIpImage As GDIpImage
  
'  Set objGDIpImage = New GDIpImage
  Set objGDIpImage = LoadPictureGDIplus(pstrFileName, True)
  
  objGDIpImage.ImageIndex = 20 ' this is the specific one I was talking about
  
  AlphaImgCtl1.Width = objGDIpImage.Width
  AlphaImgCtl1.Height = objGDIpImage.Height
  Set AlphaImgCtl1.Picture = objGDIpImage
End Sub
```

P.S. Please do remove that sample project since it contains an executable & forum policy prohibits that.

----------


## VbNetMatrix

project2:

sorry for the Exe, it was the only way to show you that extract icon on an Exe can something lead to confusion...

I was not wondering why there was several icon...
You mentionned in a post early that you were working on extracting icon function,  I was merely showing you an exe that could cause conflict in that area if you were not expecting that kind of result...

Maybe I overthought here, I just wanted to be usefull so you take that particular case into consideration.


download files are removed.

Project1:



```
I have trouble following your logic in the last modification:

  If (m_RenderFlags And render_Shown) = 0& Then
    Call sptSetUserMode
    m_RenderFlags = m_RenderFlags Or render_Shown
    Call sptGetScaledSizes(False)
    m_RenderFlags = (m_RenderFlags And Not render_Shown)
  Else
    'Previous Code was here
    m_RenderFlags = (m_RenderFlags And Not render_NoRedraw)
    Call sptGetScaledSizes(False)
    UserControl.Refresh
  End If
```

could you explain a bit ?  thanks

----------


## LaVolpe

Long story short: the m_RenderFlags variable can contain up to 30 values. While the control is in use, several of those values get turned on or off depending on situations within the control. Those values are simply flags. The sptGetScaledSizes function will not resize the control unless the render_Shown flag is turned on. That flag is only turned on during the control's first paint event after the show event fires.

So, what that code is doing is testing to see if that render_Shown flag is set or not. If not, then we set it so the sptGetScaledSizes function will not fail. Then we unset the flag because it isn't really suppose to be set yet per my code's logic.  There are a lot of other things going on in that sptGetScaledSizes function & that function can call other functions. 

Basically, the Refresh method now knows whether it was called before the show event occurs or not. And fixes the sizing issue if the show event did not occur. But the Refresh method needs to be called by you. This is not unusual. Many controls you find, for whatever reasons, do not necessarily apply the changes you make to them until after you Refresh that control.

And regarding that depends.exe app. That isn't an issue. Extracting an icon from the resources of an executable is not necessarily the same result as extracting the associated icon for that exe.

----------


## VbNetMatrix

Excellent information, Thank, that's what I was looking for...
raise a second question though...

if I understood properly the explanation you gave, in my case, the only thing the Refresh will do is Force a Resize...

so code like



```
  aImgGrid.Width = typGDIpImage.Width
  aImgGrid.Height = typGDIpImage.Height
  Set aImgGrid.Picture = typGDIpImage
```

instead of


```
  Set aImgGrid.Picture = typGDIpImage
  aImgGrid.AutoSize = lvicSingleAngle
  aImgGrid.Refresh
```

Would have the same effect ?

----------


## LaVolpe

Yes, more or less. If rotation is used or Aspect was not ActualSize, then you could get different results. Also note that you do not need to Refresh if the control and its container are not hidden

----------


## VbNetMatrix

> 26 Nov 2011, version 2.1.29: Bug reports welcomed, enhancement requests will be considered


Well...  your component is Excellent, no doubt...  and I hope you'll consider my formal enhancement request below:

I'm not trying to turn your component into a Graphical Program. I'm trying to use it to replace the Vb6 PictureBox wich can't read PNG.  I made some game in past that use the Vb6 Picture Box and some Bitblt call to add a small picture over a bigger picture.  (I use 2 bitblt call and a mask to make it transparent)

I would like my game to be converted to use png instead of bmp.
It seem that everything I tried failed and I was wondering if adding a bitblt function that would use as input source a GDIpImage and as dest the component itself.

something like:



```
Public Function BitBltDc(ByVal plngPosX As Long, ByVal plngPosY As Long, ByVal plngWidth As Long, ByVal plngHeight As Long, ByVal phwnSrcDC As Long, ByVal plngSrcPosX As Long, ByVal plngSrcPosY As Long, ByVal dwRop As Long) As Long
  Dim lngRetValue As Long
  Dim lngDestDc As Long
  Dim booWasSet As Boolean
  
  booWasSet = False
  If m_DC Is Nothing Then
    Set m_DC = New cDeviceContext
    booWasSet = True
  End If
  
  m_DC.UpdateDC True                          ' put 24bpp bitmap into DC & usercontrol to that DC
  lngDestDc = m_DC.DC                         ' DC we use to paint on
  
  lngRetValue = BitBlt(lngDestDc, plngPosX, plngPosY, plngWidth, plngHeight, phwnSrcDC, plngSrcPosX, plngSrcPosY, dwRop)

  If (booWasSet <> False) Then
    Set m_DC = Nothing
  End If
  
  BitBltDc = lngRetValue
End Function
```

I tried this, with and without refresh...  the call to Bitblt is returning 1 (meaning it worked) but nothing appear on the image.

and voila, I plea guilty because I reeeeaaaaally would like you to help me out on this because I failed to make it work.

If you don't want to integreate this kind of function inside your component, I would understand, but some pointers to show me where I failed would be nice.

Bitblt is the only FAST drawing method that would solve all my problem (speed) using your component.

and the reason why I can't use separate image and overlay them like you did with the Clock Exemple, it's because I need to DRAG the image when I overlay too much component over, draging become slow.  With Bitblt, the other image would be part of the current image and there will be no speed loss.

 :Frown: 

plzzzz!

btw, do you got a donation link ?


added:
Thanks for your answer...  I rarely use stretch and never used rotation yet...  but it's good to know...

dang I waited 2 hours for your answer and it was there but it was on a "new page" and I didn't saw it... pressing refresh every 5 minutes! lool...

----------


## LaVolpe

The GDIpImage class (the control's .Picture property) has a Render method. That method is very similar to BitBlt, StretchBlt and VB's PaintPicture: AlphaImgCtlx.Picture.Render... It appears your code sample is modifying my control & since I won't support that, my advice stops right here.

----------


## VbNetMatrix

Hi Lavolpe.

I have the most respect for your work and your code.  I'm sorry if I offended you.
I read your rules in the begin of forum and although you "will not support custom change"
I know you have arbitration privilege to accept or not modification or suggestion enhancement request.

What I merely show in that code is that I learned enough with your component to understand better what kind of modification "could" be done if that was your wish.

but I understand your relunctancy to do so.

.Render seem to be the solution to my problem though...
just wish I learned about it 25 post ago...   :Wink: 

kind regards, you're still the best...

and what about that donation page, you got one ??

----------


## VbNetMatrix

sugestion enhancement:

When control aspect is scaled and you change the WIDTH or HEIGHT (not both) of the control, 
would be nice if the other side (HEIGHT or WIDTH) would be changed too.
The control image is scaled properly, there is no bug, but when we scale we are ofen left to change the other size of the control to manually adapt to the actual size of the image.

----------


## VbNetMatrix

The objGDIpImage.Render 
require a DC (didn't find the full explanation of the syntax) but I assume it's the Source Dc...

since my other source is also another Lavolpe Component...  I'm still stuck

Not having a Dc for your component by choice, I understand, you made it clear why you choosed to NOT add the DC public.  and it make perfectly sense too.

but I need to .render (bitblt) 1 Lavolpe Component over another Lavolpe Component.
and because you're the Guru of that component, I'm asking kindly for your help ...

any Idea "HOW" I can do what I'm required to do ?
just some pointer would be nice...

----------


## LaVolpe

Regarding setting the width or height & have the other change automatically. Nope. What if someone does want a non-proportional sizing? Then they would have no way of doing that.

.Render in a BitBlt manner can be done at least 2 ways. 

1. Extract the goldfish png from the animation sample project
:: add that project to the alpha image control project & open its main form
:: display the custom property page for the control that has the goldfish
:: right click on the displayed image in that property page & choose to export the image to file
:: close that project & done
2. Start a new project. Add 1 alpha image control, 1 command button, 2 pictureboxes, 1 timer
3. Rename Picture2 to: picBuff
4. Add the Goldfish png to the AIC
5. Copy & paste this code


```
Option Explicit

Private tileCx As Long
Private tileCy As Long
Private Const tileCount As Long = 20
Private tileIndex As Long

Private Sub Command1_Click()
    tileIndex = 0
    Timer1.Interval = 50: Timer1.Enabled = True
End Sub

Private Sub Form_Load()
    Me.ScaleMode = vbPixels
    Timer1.Enabled = False
    With AlphaImgCtl1 ' the goldfish png is 20 horizontal frames
        .Visible = False
        tileCx = .Picture.Width \ tileCount
        tileCy = .Picture.Height
    End With
    With picBuff
        .Visible = False
        .BorderStyle = 0
        .AutoRedraw = True
        .BackColor = vbBlue
        .Move 0, 0, tileCx, tileCy
    End With
    With Picture1
        .BorderStyle = 0
        .Move 10, 10, tileCx, tileCy
    End With
    With Command1
        .Move 10, Picture1.Top + Picture1.Height + 10, tileCx, 35
        .Caption = "Start Animation"
    End With
    
End Sub

Private Sub Timer1_Timer()
    picBuff.Line (0, 0)-(picBuff.ScaleWidth, picBuff.ScaleHeight), picBuff.BackColor, BF
    AlphaImgCtl1.Picture.Render picBuff.hDC, , , tileCx, tileCy, _
        tileCx * tileIndex, , tileCx, tileCy, , , , , lvicNearestNeighbor
    Picture1.PaintPicture picBuff.Image, 0, 0
    tileIndex = tileIndex + 1
    If tileIndex = tileCount Then tileIndex = 0
End Sub
```

2. Similar, but we'll use the SegmentImage method to break the image up into 20 images. This doesn't actually modify the image, just the way it is used. This option only works if your image can be viewed as several tiles, all the same size, combined to a single image


```
Option Explicit
Private Const tileCount As Long = 20

Private Sub Command1_Click()
    AlphaImgCtl1.ImageIndex = 1
    Timer1.Interval = 50: Timer1.Enabled = True
End Sub

Private Sub Form_Load()
    Me.ScaleMode = vbPixels
    Timer1.Enabled = False
    With AlphaImgCtl1
        ' the goldfish png is 20 horizontal frames
        .SegmentImage 1, tileCount
        .AutoSize = lvicSingleAngle
        .Refresh
        .AutoSize = lvicNoAutoSize  ' else control size will be checked every frame
        Set .Container = Picture1
        .Move 0, 0
        .Visible = True
    End With
    picBuff.Visible = False ' not used in this example
    With Picture1
        .BorderStyle = 0
        .Move 10, 10, AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height
        .BackColor = vbBlue
    End With
    With Command1
        .Move 10, Picture1.Top + Picture1.Height + 10, AlphaImgCtl1.Picture.Width, 35
        .Caption = "Start Animation"
    End With
   
End Sub

Private Sub Timer1_Timer()
    AlphaImgCtl1.ImageIndex = AlphaImgCtl1.ImageIndex + 1
End Sub
```

*Edited*: A 3rd method that combines the 2 above
Note that the AIC won't be used, but one needs to be on the form. In this example we are using a GDIpImage class directly


```
Option Explicit
Private Const tileCount As Long = 20
Private m_Image As GDIpImage

Private Sub Command1_Click()
    m_Image.ImageIndex = 1
    Timer1.Interval = 50: Timer1.Enabled = True
End Sub

Private Sub Form_Load()
    Me.ScaleMode = vbPixels
    Timer1.Enabled = False
    Set m_Image = LoadPictureGDIplus("C:\goldfish.png") ' change filename as needed
    ' the goldfish png is 20 horizontal frames
    m_Image.SegmentImage tileCount, 1
    With picBuff
        .Visible = False
        .BorderStyle = 0
        .AutoRedraw = True
        .BackColor = vbBlue
        .Move 0, 0, m_Image.Width, m_Image.Height
    End With
    With Picture1
        .BorderStyle = 0
        .Move 10, 10, m_Image.Width, m_Image.Height
    End With
    With Command1
        .Move 10, Picture1.Top + Picture1.Height + 10, m_Image.Width, 35
        .Caption = "Start Animation"
    End With

End Sub

Private Sub Timer1_Timer()
    picBuff.Line (0, 0)-(picBuff.ScaleWidth, picBuff.ScaleHeight), picBuff.BackColor, BF
    m_Image.Render picBuff.hDC
    Picture1.PaintPicture picBuff.Image, 0, 0
    m_Image.ImageIndex = m_Image.ImageIndex + 1
End Sub
```

----------


## VbNetMatrix

WouHou!

nice coding...  I'm in love now....




> Regarding setting the width or height & have the other change automatically. Nope. What if someone does want a non-proportional sizing? Then they would have no way of doing that.


Since the part that are not exposed to the image remain "transparent" with nothing inside...  I'm not quite sure why someone would need that.  But your logic can be applied to almost anything... "what if someone want it"
That raise this question: Got any idea how I could get the real "size" of the image once I stretched one side  in SCALE mode ?

and THANKS YOU very much for that bit of code, I'll try it as soon as possible...  (now I have to go for some errand so I'll be less demanding   :Wink:

----------


## LaVolpe

> That raise this question: Got any idea how I could get the real "size" of the image once I stretched one side  in SCALE mode?


Kinda out of luck there. Within the control the m_Size.Width & m_Size.Height are the scaled sizes the control uses to render the image. Those values are not exposed to the user.

The values also may not be exactly as one would expect. For example. If the AutoSize & Aspect properties are zero and the control is smaller than the image, then the m_Size.Width & m_Size.Height will be the actual image size. However, the image is clipped by the smaller control and whether or not AlignCenter is True/False, Rotation is used or not, the size of the visible non-clipped portion of the image can be different. The coordinates where the image is rendered also are not exposed. They are dependent on rotation, the optional XOffset & YOffset properties, AlignCenter property, and the scaled image

You can estimate the size of the image by using the global GetScaledImageSize function. Calculating the scaled size is complicated. The control's sptGetScaledSizes function is where it all happens.

----------


## LaVolpe

> about post 348: I think I found what cause the problem with the size...
> I changed the size of the picture while the form was hidden and the size of the component change only after the refresh (Show) of the picture...
> 
> is that normal behavior ?





> Maybe  ... a bit of tap dancing
> The Show event of the usercontrol activates when it is first shown. Well on hidden forms or if the control's visible property is false, then that event won't trigger. The sizing routines of the control occur in the Shown event....


The change to the Refresh method I suggested will NOT be included in the next update. This sizing issue should be automatic, not up to the user to "fix" by a call to Refresh. I see where the problem is and will patch it.

----------


## VbNetMatrix

cool, perfect...

I really like the big help you provided in the last few days... 
it was nice of you because it was a little bit outside of the normal requirement for your control.

it really helped me!

thanks

----------


## LaVolpe

Control updated today. See post #1 for more info. Significant changes:

- added ability to load icons associated to system file objects
- added a unicode-capable 'browse for folder' dialog class
- fixed minor resizing issue noted in previous few replies above
- updated the SavePictureGDIp & LoadPictureGDIp RTF files

Edited. Patched again 8 January, 1 day later. 
When I added associated icon capability, I didn't include that ability for dragged/pasted files onto the property page. Done.

----------


## VbNetMatrix

7 Jan 2012, version 2.1.30

To Patch The control for replacing "TOp" to "Top" without losing binary compatibility, follow theses step:

1. Exit Vb6
2. Open the Following file in Notepad++ (Google it if you don't have a notepad that allow you to see line number)

Files:
AICGlobals.cls
AlphaImgCtl.ctl
GDIpImage.cls
modCommon.bas

Make a Search to Replace "TOp" with "Top" in thoses files

Save, 
recompile...

voilà....   :Wink: 


AICGlobals.cls
line: 100, 113

AlphaImgCtl.ctl
line: 79, 83, 1835

GDIpImage.cls
line: 435, 439, 441

modCommon.bas
line: 4758, 4763, 4766, 4769

----------


## kontolimansyah

@ LaVolpe : Thx 4 the update  :Thumb: 
@ VbNetMatrix : welldone for the "TOp" trick  :big yellow:

----------


## LaVolpe

Hot patch until next update is released. If using one of the generic folder icons provided from the property page at design-time, it is possible that the 32x32 & 48x48 sizes will be saved in PNG format. The alpha image control & Vista+ can read PNG formats in icons, but XP and lower cannot. Also, the 16x16 icon for an "opened" folder is not returned. Suggest making these corrections:

What? The property page: *ppgCustom*
Where? *LoadSampleImage* 

Actions made to only ppgCustom.LoadSampleImage
1) Find & delete this line: MIS.Image(8 + icSize).IconEmbeddedAsPNG = True
2) Find & delete this line: MIS.Image(8).IconEmbeddedAsPNG = True
3) Find this line: If cboLoadType.ListIndex = 2 Then
4) Add these 3 lines directly after that line:


```
MIS.Image(3).IconEmbeddedAsPNG = True
MIS.Image(7).IconEmbeddedAsPNG = True
MIS.Image(11).IconEmbeddedAsPNG = True
```

5) Find this line: AI.IconType = AI.IconType Or lvicAssocIconOpened
6) Add this after that line: AI.DesiredSize = lvicSHIL_Small_16
Done

Senior-moment here. I added the UnicodeBrowseFolders class to the project but forgot to make it public so you can use it from within your code. So, open that class in IDE. In the property sheet, find the Instancing property & change its value to 5 - MultiUse

Edited: Apologize for the inconvenience. Supporting associated icons required significant code modifications throughout and there is a chance, other minor bugs may pop up due to those modifications.

----------


## VbNetMatrix

good work finding theses out Lavolpe.

thanks


kontolimansyah: thanks.  I wanted to include my Autofix program but EXE are not allowed  :Wink:   would have been of good use for Lavolpe Hot Patch though... would be simpler...

----------


## LaVolpe

*NOTICE :: NOTICE :: NOTICE*

Version 2 of the control came to an end & final update posted today. No new enhancements will be added to version 2 -- ever. Bug fixes _may_ be applied as they are discovered. Support for version 2 will eventually cease.

Version 3 of the control will replace version 2 and will be DPI-aware. This will result in how images are loaded and displayed on a PC based on DPI settings (XP and above). In the case of icons/cursors, it may also result in which sized icon is displayed, based on current DPI settings. Externally, how you use this control will not change very much. Internally, a logical coordinate space will be used for all measurements and storage of properties, unlike the physical coordinate space now used. Like VB, this control will use twips internally. Externally to control users, pixels will still be used. DPI awareness will also be a customizable property. To properly support DPI-awareness,* binary compatibility will be broken*; hence a new version.

When version 3 is available, I'll start a new thread for that control and I'll link the two threads to each other. For the most part, I will stop responding on this thread at that time. Since the functionality of the two versions will be nearly the same, any questions pertaining to one version will apply to the other version, so only Version 3's thread will be used.

To all, thank you for your inputs and suggestions. I think over the past year and a half, a very nice control has been produced.... On to Version 3 and no immediate release date is known.

----------


## Cube8

Can you explain which parts of the interface will change, that will cause binary compatibility to break?

----------


## LaVolpe

> Can you explain which parts of the interface will change, that will cause binary compatibility to break?


Primarily, it will be saved settings. Version 3 will be expecting saved values in twips vs. pixels. That means it won't be backward compatible any longer; though binary compatibility really isn't broken at that point. Nevertheless, knowing this, I have the freedom to modify the control any way I want, and that will break binary compatibility. Internally, much of the code will need to account for DPI. Many of the internal functions will now be using single precision vs. long when dealing with GDI+ functions. Converting version 2 to use DPI and keep compatibility (binary or backwards) will be just too much in my opinion. Those are probably the major points; there are more.

----------


## VbNetMatrix

Can you explain more about what is DPI awareness ?

----------


## VbNetMatrix

I think I missed 2.1.31, can you provide link ?  I learn a lot by looking how you fix thing.
thanks.

----------


## Cube8

> Can you explain more about what is DPI awareness ?


Wikipedia: http://en.wikipedia.org/wiki/Dots_pe..._DPI_standards

Actually, increasing the DPI setting, while keeping the same resolution, makes everything bigger and the object dimensions are calculated differently...

----------


## LaVolpe

> Can you explain more about what is DPI awareness ?





> Wikipedia: http://en.wikipedia.org/wiki/Dots_pe..._DPI_standards
> 
> Actually, increasing the DPI setting, while keeping the same resolution, makes everything bigger and the object dimensions are calculated differently...


Correct. To put into perspective for this control....

The logic behind DPI is simply scaling. The higher resolution monitors we have nowadays, applications built under normal DPI of 96 may look tiny on the big screens. So XP started user-optioned DPI settings. Vista continued this option but added DPI virtualization. Windows 7 went one step further and can automatically implement DPI scaling and virtualization. 

Standard DPI settings are: 
Normal is 96 or a 1:1 ratio, 1x scaling of the object's dimensions
1.25x scaling is 120 DPI
1.5x scaling is 144 DPI
1.75x scaling is 168 DPI
2x scaling is 192 DPI
Scaling factor = (DPI / 96)

A bit off topic: DPI virtualization is nasty in my opinion and your app looks worse under it. It can be disabled automatically by telling Vista/Win7+ that your app is DPI-aware via a manifest. It can also be disabled manually by the user. Under DPI virtualization, your app is lied to an told that the user DPI is 96. Your app works just fine, so you think. But before it is displayed to the user, Windows will stretch the entire app by the DPI scaling factor and display that. To get an idea of what your 96 DPI app would look like at a DPI of 144, virtualized. Simply screen capture your app and stretch that capture by 150%.

*Loading Images*. Most modern image formats can store resolution/DPI information the image was created in. When an image is loaded, the DPI of the image is not important. The source DPI, along with the screen DPI, is used when rendering.
FYI: GDI+ will report current screen DPI as the image's source DPI if the image does not contain that info.

*Rendering Images*. A standard formula that uses both source/image DPI and destination/screen DPI is: 
logicalSize = (physicalSize * screenDPI) / imageDPI
DPI forces one to consider dimensions in two coordinate spaces: logical and physical. The physical dimensions are the actual image dimensions at the DPI the image was created in. The logical dimensions are calculated based on the destination and/or source DPI values. Typically, you'll find images with non-normal DPI created from scanned pictures and also metafiles are known to be other than 96 DPI. 

Real world examples follow:

1) JPG. Physical size is 2100x2250 at 300 DPI
Rendered size in some DPI aware applications at 96 DPI: 672x720
You'll notice the size is about 1/3rd the physical size. Just plug in the values into the formula provided.

Same JPG displayed at various screen DPI settings:
@ 96 DPI: 672 x 720
@120 DPI: 840 x 900
@144 DPI: 1008 x 1080

2) WMF. Physical size is 1542x1877 at 1000 DPI
Rendered size in most applications at 96 DPI: 148x180
You'll notice the size is about 1/10th the physical size

Same WMF displayed at various screen DPI settings:
@ 96 DPI: 148 x 180
@120 DPI: 185 x 225
@144 DPI: 222 x 270

With the above two examples, if you notice, all rendered sizes are smaller than actual size. However, the quality will be very good because the image is being scaled down. The WMF is a vector format so it will scale well, regardless what direction scaling takes.

Notes about above examples: 

a) VB does not render images this way. The exceptions are metafiles. If you load, into a VB image control, a jpg or bitmap containing source DPI info, the loaded image will be the physical size, not the logical size. However, for metafiles, the opposite is true. Why treat one image format different from the others? Rhetorical question. Maybe it is a vector vs. raster thing?

b) Using the source/image DPI will probably be default in the updated control. Microsoft Word uses this option, but VB does not. Let's say you scanned a 3x5 inch photo at 300 DPI resulting in an image 900x1500 pixels. Do you display an image on a 96 DPI monitor at 900x1500 (result is about 9x15 inches viewed) or do you use our formula and display it at 288x480 (result is 3x5 inches viewed)? I am leaning in the favor of how Word would display the image vs how VB would. After all, the source image is 3x5 not 9x15.

I'd say a majority of images out there are created without any DPI information stored. This is a decision maker. What value do you use for the imageDPI parameter of our function if option chosen to honor the source DPI? Well, GDI+ returns the screen DPI as the image DPI. This option, in effect, keeps the image the same size regardless of the screen's DPI settings because the two DPI settings cancel each other out in the formula. The image will never be scaled due to DPI. Another option is to default to 96 DPI when the image DPI information is missing. This option ensures image is scaled with various screen DPI settings. The control will handle it this way. If image loaded on a 96 DPI screen setting and no source DPI exists, the image will be considered 96 DPI as long as it is in the control. If it were loaded on a 120 DPI screen, then it would be considered 120. This DPI setting will travel with the control and the image will not be modified.

For this example, we'll use a 256x256 image that was created with unknown image DPI, substituting the unknown with default 96 DPI (the screen setting at time it was loaded at). 

2) PNG. Physical size is 256x256 displayed at various screen DPI settings
@ 96 DPI: 256 x 256
@120 DPI: 320 x 320
@144 DPI: 384 x 384

With the above example, if you notice, all rendered sizes above the source DPI are larger than actual size. Image quality will not be as good since we are scaling upwards. Lower quality images obviously results in lower quality scaling.

*What's the big deal?*. You may ask why I feel this is important. Good question. VB is DPI aware for the most part. Any application you build at normal DPI will be scaled larger, including controls, under higher DPI. VB *automatically* scales many controls, *including VB-created usercontrols* and there are some exceptions. So, in 96 DPI, you have my Alpha Image Control on a form and it is displaying a nice 256x256 image at full size, no scaling/stretching. What happens when you turn your screen's DPI to 120? VB will resize the image control to 320x320 and also scale/position your other VB controls by 125%. The image rendered in my control is still at 256x256 because it is not DPI aware. If it were DPI aware, the image would be scaled to 320x320 also. It may not look ideal being scaled up, but every other thing in your application is scaled up 125% except the image. Which is worse? That being said, when I modify the control, the DPI awareness can be customized.

Note: DPI may not be a player when the alpha image control's Aspect property results in stretching/scaling the image. This is because VB resizes the controls and the Aspect property stretches/scales the image to the control's size.

*In summary*. Applications you build at 96 DPI, most likely will be displayed at higher DPI on systems today. This is partly due to much larger screens, users wanting tiny apps looking bigger, and newer operating systems changing DPI automatically.  Any custom built control should be DPI aware in my opinion.

----------


## VbNetMatrix

that was a very well done explanation on the subject.  Thanks Lavolpe, it made me understand the context on the necessity of DPI awareness and what it would change in the control behavior.

5 stars...

----------


## LaVolpe

For the users of this control -- good news. I will be able to maintain binary compatibility after all.

The next update which will be v3.0.0 will be DPI-aware by default. For backwards compatibility, any previously compiled version of the control will still work with the new version; however, that previous version will not be DPI aware. This simply means that for existing compiled applications using the old version of the control, will continue to work as they always have worked when the new version replaces the old version. 

Recap. Odds are significantly increasing that your app will be scaled due to user-defined or O/S-opted DPI settings. This control will be designed to automatically scale its contained image with the system DPI and will also have options to allow you to override default behavior.

*Image DPI scale*. The intent of using this DPI is to scale the image so that it is the same size as the source image. If a 3x5 inch image was scanned in 300,600,1200 DPI, it will appear as 3x5 inches on the screen at any DPI even though the physical size of the image may be 3,6,12 times that. 
*Screen DPI scale*. The intent is to keep your images the same size relative to the screen they are displayed on. If an image is approximately 1/10th of your screen size, it will remain 1/10th of your screen at any screen DPI setting

The new version will handle DPI this way. 4 DPI options will be available

lvicNoDPIAwareness: No scaling, same as v2.x.x
scaledImageSize = physicalSize
lvicAutoDPIAwareness: (Default) Both screen and embedded image DPI used for scaling. 
scaledImageSize = (physicalSize * screenDPI) / embeddedDPI
lvicIgnoreEmbeddedDPI: Only screen DPI used for scaling
scaledImageSize = (physicalSize * screenDPI) / 96
lvicUseOnlyEmbeddedDPI: Only embedded image DPI used for scaling
scaledImageSize = (physicalSize * 96) / embeddedDPI
The above options can result in the same image being displayed in 4 different sizes if the screen and the embedded image DPI are other than 96 DPI.
Example: JPG image at 600 pixels wide created in 300 DPI and displayed on a 120 DPI screen
lvicNoDPIAwareness: width = (600 * 1) / 1 = 600 [same physical size on all DPI screens]
lvicAutoDPIAwareness: width = (600 * 120) / 300 = 240
lvicIgnoreEmbeddedDPI: width = (600 * 120) / 96 = 750
lvicUseOnlyEmbeddedDPI: width = (600 * 96) / 300 = 192 [same physical size on all DPI screens]
*[same physical size on all DPI screens] = image size is not scaled with your other controls when DPI changes

*There is an issue if* you opt for lvicNoDPIAwareness or lvicUseOnlyEmbeddedDPI which ignores screen DPI. Let's say you develop your app in a 120 DPI screen. When app is displayed on a 96 DPI screen, VB scales the control smaller for the lower screen DPI. This means your images, ignoring screen DPI, will probably be clipped by the resized control. To prevent this, may need to add yet another option to always scale when screen DPI is smaller than development DPI. Maybe something like this....

lvicDPIscalingForbidden: When design-time screen DPI is higher than current screen DPI, the following overrides will be automatic unless lvicDPIscalingForbidden is selected
If lvicNoDPIAwareness is desired: scaledImageSize = (physicalSize * screenDPI) / 96If lvicUseOnlyEmbeddedDPI is desired: scaledImageSize = (physicalSize * screenDPI) / imageDPIIf lvicAutoDPIAwareness is desired: no change in logicIf lvicIgnoreEmbeddedDPI is desired: no change in logicAnother option that will be considered is to allow you to dictate your own screen and/or image DPI values which will override actual values. This option will allow you to scale images relative to some other device, say a 600 DPI printer for example. I can foresee this being used in some sort of print-preview type of display.

Note: When the Aspect property of the control is other than 'ActualSize', the image is being scaled/stretched to the control. VB will resize the control based on DPI and the image will then be scaled/stretched to that adjusted control size. Version 2.x.x of the control behaves the same way. The overall effect is that DPI awareness does not apply in this situation, other than VB scaling the control dimensions based on screen DPI.

How to make v2.x.x DPI-aware when Aspect is 'ActualSize'? This can be faked using the following logic
a) No optional XOffset or YOffset settings
b) Set Aspect to ActualSize
c) Set AutoSize to SingleAngle
-- previous 2 steps ensure control is sized to actual image size
d) Set AutoSize to NoAutoSize
e) Set Aspect to Scaled
f) Do not manually modify the size of control hereafter
Now when VB resizes the control based on screen DPI, your image will scale proportionally with your other controls

----------


## Cube8

I admire your passion, LaVolpe!
You have "heard" so many compliments, that anything I say will be needless.

----------


## VbNetMatrix

Hi Lavolpe, 

I've stumbled upon a strange bug involving resize (stretch) and interpolation: Nearest Neigbourg.

at some point, the control is resized but not the content of the control.  Meaning we got 1 pixel with a full Alpha channel.  It seem to occur only when the control is wider then HALF the screen size.

I thought you would be interested in seeing it into action.

I made a small image and loaded it in a Lavolpe control and also in an image control, 
then, by clicking the button,  it decrease both control.

The bug is not random but it appear only on specific size wich I failed to recognize any pattern.

this bug in action here:
http://vbnetmatrix.com/download/lavolpe/projet1.zip

----------


## LaVolpe

> I thought you would be interested in seeing it into action.


Always interested in bug reports. Good timing too. The DPI-version of the control is nearly completed. I'll be taking a look-see.

Follow up #1. I'll look at this a bit more, but am already thinking it may be out of my hands.

1) If you run your sample project again. Whenever the widths appear different, force a repaint. For example, move another window on top of yours & then move it off your form.

2) You will notice that the control painted as expected on the repaint

3) Internally, I looked at 4 routines to see if possibly there were any calculation errors that would result in 1 less pixel being painted. But there isn't any errors. When it gets to the last line of code that actually draws the image, the dimensions to be drawn are correct.

Follow up #2. I am going to play with another idea to see if results are more reliable.

Ideas: Not the answer you are looking for, but in these cases where you are trying to use the control as a border/line by stretching an image, you may choose to use a VB image control instead. Even though the AIC may not be ideal for all situations, it is flexible enough for anyone to draw anything they want into a standard bitmap & load that into the AIC. You can stretch the image to a normal bitmap/DIB via StretchBlt and load that into the Alpha Image Control.

----------


## VbNetMatrix

I know a Vb Image control could do it, but I would prefer using PNG !

I also though about a possible cause...

I noticed that when VB use screen resolution it use SINGLE type, even if the screen size is in fact a LONG value.  This might be because internally it's converting to twips.

if then SO, if your control use LONG instead of SINGLE for the size. it might lose resolutions when internally converted to twips ?

I know it's a long shot...

If you could tell me where to look inside the code, I could make some test.  I have no intention of modifying your control, I just want to check out if the bug could be there.  Knowing the 4 functions you mentionned in previous post, I might be enable to spot something you missed (no hard feeling intended)

I'm a decent programist, but your control is just too wide project to be looked at in an easy way and I currently don't have the time to process the whole package, I'm in the middle of university class.  So, if you could just point out the function you were looking, I might have some luck.

thanks

----------


## LaVolpe

> I know it's a long shot...


That's not it. I checked the render command. The size of the stretch is correct. I checked in 3 different places. It also would not explain why it would paint correctly simply by covering up the form with another window and uncovering it.

Rounding with single vs long may be a player if you were reducing the size by a fraction of a TwipsPerPixelX but not by a whole TwipsPerPixelX. A whole TwipsPerPixelX is a single pixel. The screen is pixels, regardless of scale mode.

I thought maybe it had to do with drawing directly to the screen. But using FastRedraw property (off screen buffer), same results. It is a GDI+ thing or another bug with VB and windowless controls, and I'm convinced of it now. If you want to double check things yourself, look at this line in the Usercontrol_Paint event. m_Size.Width is the stretch width


```
   m_Image.Render rDC, .nLeft, .nTop, m_Size.Width * X, m_Size.Height * Y _
        , , , , , m_Angle, m_Effects.AttributesHandle, hGraphics, m_Effects.EffectsHandle(m_Attributes And &HFF&), Me.Interpolation
```

Note: If you wish to use a VB image control instead, for this particular case, you can still do that and continue to use a PNG file. You would load the png into a GDIpImage class, then save it to an initialized stdPicture object which would then be set to your VB image control.

----------


## VbNetMatrix

I'll check it out promptly, in the mean while, if you have time I would apreciate some code for the img control  to load object with a png picture.  graphic programming is not my high point...   :Frown:

----------


## LaVolpe

> I'll check it out promptly, in the mean while, if you have time I would apreciate some code for the img control  to load object with a png picture.  graphic programming is not my high point...


Image control cannot contain PNG, but a PNG can be converted to bitmap which image control can do...


```
Dim tGDIpImg As GDIpImage, tStdPic As stdPicture
Set tGDIpImg = LoadPictureGDIplus(yourFileName)
Set tStdPic = New stdPicture
If SavePictureGDIplus(tGDIpImg, tStdPic, lvicSaveAsBitmap) Then Image1.Picture = tStdPic
```

----------


## VbNetMatrix

thanks a lot for the code...  very appreciated.

While debugging and searching for the problem, I realized that something (enhancement) would be verrrrry nice to have in your control.

So I'm making this very nasty little demand for enhancement request:
When using the LOAD from the control at design time, it "could" be nice if the name of the file were saved into the control for later reference.  not the full path, but just the "original" file name  it would be a property that would be mostly useless, unless you're debuggin  :Smilie:   (or developping) I got 2 images almost identical and at some point I was wondering wich one caused the problem and I couldn't remember wich one I loaded last...  I have to restart all the test from the begining... *grin*

well.. it is asked...  doesn't cost me to try!  I can however see many practical use of that information.

regards.

----------


## VbNetMatrix

a little off topic, but for thoses who had in past a similar problem as we previously discussed with the "TOp vs Top" property...  I found a verrrrry nice and easy way to fix this kind of problem.

at first I was wondering why changing the property name didn't work when saving... so I look inside VbExe code... (did I said that out loud?!...   :Wink:  and I found out that Vb does a lowercase comparaison when deciding if property should be saved or not...

so making a short story how to fix a problem like TOp vs Top, I'll give you an exemple and apply to your case.

Exemple:
property or any VbName:   "MyVbNamE"  you want to change it to "MyVbName"

VERY IMPORTANT: DO ALL THE STEP.  Otherwise you risk having a "CONFLIT NAME DETECTED on next projet opening.  If that happen, follow the step to fix it. (below)"

1. Change MyVbNamE to MyVbName and HIT SAVE
2. Change MyVbName to MyVbNameX and HIT SAVE
X being any letter you want to add... doesn't matter
3. Change it back from MyVbNameX to MyVbName and HIT SAVE

now, exit the project, open it again and Voila!

for thoses who WONDER why not only 2 step... that's because of the way Vb Save the project... if you don't do all 3 step, he will only save it at 2 place inside the file and you risk having a "conflit name detected"  wich is easy to fix by doing the process all over again, but it's pretty annoying.   :Wink: 

in the case though when re-opening the project, you receive a msg saying: 
--> Conflit name detected, "MyVbName" will be used. <--

it mean you didn'T properly follow the 3 step. That's a bummer...  now you'll have to start your project from scratch, it's ruined...  just kidding....  :Wink:   you can RETRY the method previously discuss, it should fix the problem... if not...  continue reading.

that bugged me at first...  but I found out why.  This happen only if you modify a CLASS name (not property) or a Form Name or other major class element without following the EXACT 3 step I described above.

This is because Vb store theses name in 2 places (duh) and to fix this, you'll need to manually change the second name wich is the SAME but with a different case...  funny, Vb does a Lowercase comparaison when saving but is case sensitive when loading...  another Microsoft funny joke   :Wink: 

so to fix it, easy: look inside the Vbp file if it's a class name or a form name, change the case of the name.  Something like:
Module=mod_MyVbNamE; MyFile.bas

look also in the frm file, there is 2 declaration there:
in the first few line you got something like:
Begin VB.Form MyVbNamE

and later one BEFORE the module coding, you'll get:
Attribute VB_Name = "MyVbName"

just make both name the same.

but really... the 3 easy step are more fun  :Wink:   unless you like playing with your file OUTSIDE Vb... wich is often not a good idea.

----------


## VbNetMatrix

oh and by the way I struggle with something on the last version...  I don't know if my code is faulty...  but when I do:

aImgSlider.Mirror = lvicMirrorHorizontal

I lose like 2 pixel width of the image on the left (wich was previously right before the mirror)

if you need sample code (but it's really straightfoward really)  just tell me.

my current application is as follow:

2 Lavolpe Component 1 big (behind) and 1 small in front.  

when mouse enter activate on big image, small image is:

aImgSlider.Mirror = lvicMirrorHorizontal

when mouse exit, I mirror none.

----------


## LaVolpe

Thanx for the bug report. Solution shown below & will include in next update

1. Bug: Mirroring losing 1 or 2 pixels. A calculation error & not sure why I did it the way I did. I'll have to see if this patch breaks when rendering with rotation and/or GDI+ v1.1 effects, or if it was a even/odd image size issue.

In the cGDIpImage class' Render & RenderSkewed functions, you will see 2 places in each routine where the width & height are being adjusted when mirroring. Change them to remove the subtraction of the 1&. Easy enough to locate, look for testing of srcWidth & srcHeight < 0


```
 ' example
If srcWidth < 0& Then srcX = imgCx - srcX - 1&           
If srcHeight < 0& Then srcY = imgCy - srcY - 1&
```

2. Regarding your filename suggestion. It's a bit more complicated than that. The control doesn't know the filename, ever. The property page extracts the file data and creates an image from that & passes the parsed image to the control. The control only receives a byte array, never a file name. Why? Simply put, the property page can accept files, drag/drop & pasted data too which can be URLs, clipboard items, Base64 text & other things that are not files. Additionally, the control would need to be modified even further to save it to a property bag, retrieve it, and display it via a property. The file name is only useful possibly for debugging. 

If your main concern is for debugging in IDE, I'd recommend this
Object: ppgCustom
Routine: cmdBrowse_Click
Modification: In the sections for Case 0,1,2 add a Debug.Print statement after the browser returns
However, the above won't apply once the control is compiled as Debug statements are not compiled

----------


## VbNetMatrix

thanks Lavolpe for the Bug fix, I'll apply immediately and await the next version for official Fix.
as for the FileName, I understand perfectly I didn't looked at the code before making the request.

a debug.print won't help though.  Sometime I'm playing with a version of a file and then only a few days later I change it to something else and I lose track of wich file I used after a few changes...  as they are almost identical, it cause me to doubt sometime...   I'll have to be more carefull about documenting each time I change the file  :Wink: 

thanks for having answered my request though.  I apreciate.

----------


## VbNetMatrix

refering to post #390

I did some testing and I couldn't reproduce your behavior when you said covering then uncovering
the form would "fix" the visual bug.

did you worked from my template ?

http://www.vbnetmatrix.com/download/...e/PixelBug.zip

----------


## VbNetMatrix

refering to post #392, 

I tried it... work... but it set the transparency to WHITE Color...  any way I can change that behavior to adopt "background" color of the control (I used a picture box instead of an image control)

Both control (image box and picture box) have the same behavior.

your help is very much apreciated.

----------


## LaVolpe

> refering to post #392, 
> 
> I tried it... work... but it set the transparency to WHITE Color...  any way I can change that behavior to adopt "background" color of the control


Yes, supply a SAVESTRUCT as the final parameter to SavePictureGDIplus


```
Dim tGDIpImg As GDIpImage, tStdPic As stdPicture, SS As SAVESTRUCT
Set tGDIpImg = LoadPictureGDIplus(yourFileName)
Set tStdPic = New stdPicture
SS.RSS.FillColorARGB = ConvertRGBtoARGB(Picture1.BackColor)
SS.RSS.FillColorUsed = True
If SavePictureGDIplus(tGDIpImg, tStdPic, lvicSaveAsBitmap, SS) Then Picture1.Picture = tStdPic
```

The SAVESTRUCT allows you to pretty much override any "normal" behavior while saving

----------


## VbNetMatrix

Again Lavolpe, you're the Master of GDI!

you should edit your code though to replace the image1 reference by picture1 in the last line, you're making reference to both.

thanks you 1000x times, I tested it, work like a charm.

----------


## LaVolpe

> you should edit your code though to replace the image1 reference by picture1 in the last line, you're making reference to both.
> 
> thanks you 1000x times, I tested it, work like a charm.


Done. I just whipped that sample up quickly. Original post was referring to image control & your issue related to picturebox. Oops; at least I didn't confuse you.

----------


## VbNetMatrix

yeah I know what you mean... cut and paste a sample, and forgeting to switch a var... it happen to me all the time  :Wink:

----------


## Foolish Tech

Awesome control!  

I wish I knew what I was doing with graphics, but alas I do not.  

I have an issue that is very strange.  I have a particular 8-bit BMP graphic I am trying to use on a form in my project, and I am using the latest version of your control with everything as default, I've changed nothing...

The image appears GREAT on *Windows XP*, however when loaded on a *Windows 7* PC, the image is distorted with a lot of extra black that shouldn't be there.  See the attached pic for a side-by-side comparison.  



As I said I've messed with absolutely none of the control's various settings in this picture.  I have experimented with a few settings to see if I could resolve the issue but I have no idea what I'm doing.  

The image does display fine on both operating systems if I use the VB6 picture control to display it.  

Advice?

----------


## Foolish Tech

Nevermind... I'm still curious, but it's not important now as I simply re-saved the image as PNG and it displays properly on both OSes.

----------


## LaVolpe

> As I said I've messed with absolutely none of the control's various settings in this picture.  I have experimented with a few settings to see if I could resolve the issue but I have no idea what I'm doing.  
> 
> The image does display fine on both operating systems if I use the VB6 picture control to display it.  
> 
> Advice?


Maybe you can post the image so I can take a look-see. You might have uncovered a bug with my control or possibly another workaround needed due to GDI+ inadequacies? It certainly appears as if some color has been made to be transparent

----------


## Foolish Tech

> Maybe you can post the image so I can take a look-see. You might have uncovered a bug with my control or possibly another workaround needed due to GDI+ inadequacies? It certainly appears as if some color has been made to be transparent


Sure thing, get it here:  https://sites.google.com/a/obxcompgu...o_original.bmp

----------


## LaVolpe

Thanx for the image. There is only 1 thing a bit unusual with it. I won't be able to get to a Win7 machine until the weekend, but it displays fine on XP & Vista. The unusual thing is that it has a DPI setting of 1081 which appears quite high.

The bottom line is that GDI+ loads the bitmap. My cFunctionsBMP class only handles 32bpp and allows GDI+ to load all other color depths.

I've uploaded the exact same image, but removed the DPI settings from it. If you have chance to test it before I get to a Win7 machine, does it display correctly or poorly? << attachment removed >>

----------


## Jonney

> Thanx for the image. There is only 1 thing a bit unusual with it. I won't be able to get to a Win7 machine until the weekend, but it displays fine on XP & Vista. The unusual thing is that it has a DPI setting of 1081 which appears quite high.
> 
> The bottom line is that GDI+ loads the bitmap. My cFunctionsBMP class only handles 32bpp and allows GDI+ to load all other color depths.
> 
> I've uploaded the exact same image, but removed the DPI settings from it. If you have chance to test it before I get to a Win7 machine, does it display correctly or poorly?
> Attachment 87776


On my Win7, both show black dots.

----------


## LaVolpe

> On my Win7, both show black dots.


Ok, thanx. That is not good. As I said, GDI+ loads the image. This could be a problem with GDI+ or my CreateSourcelessHandle routine that all bitmaps get sent to. Will try to resolve it this weekend

----------


## Foolish Tech

> Ok, thanx. That is not good. As I said, GDI+ loads the image. This could be a problem with GDI+ or my CreateSourcelessHandle routine that all bitmaps get sent to. Will try to resolve it this weekend


Yep, still shows black dots.  

A little background:  my app is designed for others to use and custom brand with their own logo/text.  So I didn't create the image, but I did I did find out something about the creation of the image from the person who sent it to me.  

He said that he tried to create the ever elusive, non-existent, "_transparent bmp_" with it (because before finding you awesome control, I had limited my app to BMP only using the built-in VB6 picturebox.)  As said, the image originally displayed fine in the picturebox on Win7, but the issue of course occurred when he updated the app to a newer version which uses your control.  

He didn't remember all the voodoo he underwent in his attempt to create this "transparent bmp", however.  But maybe he used some funky hex color code somehow packed into a BMP format, that could explain something *shrug* so I would consider his image a special exception in the graphics world and not something you'll probably run across very often  :Wink:  

Hope this helps,

----------


## LaVolpe

> I would consider his image a special exception in the graphics world and not something you'll probably run across very often


If only... I have scrutinized your file and found no liberties taken. It is simply an 8 bpp, 256 color image. The contained bitmap header is correctly filled out (except maybe for that high DPI). None of the palette colors use the alpha byte. In short, there is nothing wrong with the image. I do think, right now, it is a problem with my control. When moving from 1 O/S to another, sometimes it unveils logic errors previously unseen. My gut says that this problem can occur with other paletted bitmaps too.

----------


## LaVolpe

> Yep, still shows black dots.


Ok, took a bit to figure it out. The issue is order of code. When I create a sourceless GDI+ image, I copy the bits from one handle to the other, then copy the palette. On Vista & earlier, no problem, but on Win7, a problem. So, by copying the palette first, then the image bits, problem goes away. Though I know the fix for this specific problem, I need to re-look at other code too where I manipulate palette information (i.e., creating/displaying animated gifs). Fix will be in the next update which I expect to be out by end of month.

If you can't wait til March, here's an immediate patch
In the modCommon module, find the function CreateSourcelessHandle then...


```
' find this block of code

If GdipBitmapLockBits(Handle, dstBoundsI, ImageLockModeRead, tBMPsrc.PixelFormat, tBMPsrc) = 0& Then
    ' open the destination for writing using the pointer we just got from source
    tBMPdst = tBMPsrc
    If GdipBitmapLockBits(ReturnObject, dstBoundsI, ImageLockModeWrite Or ImageLockModeUserInputBuf, tBMPdst.PixelFormat, tBMPdst) = 0& Then
        GdipBitmapUnlockBits ReturnObject, tBMPdst                  ' done
        ' for paletted images, need to transfer palette also
        If tBMPsrc.PixelFormat <= lvicColor8bpp Then
            GdipGetImagePaletteSize Handle, cPal.Count
            If lType Then
                GdipGetImagePalette Handle, cPal, cPal.Count
                GdipSetImagePalette ReturnObject, cPal
            End If
        End If

' and replace with this block of code (just re-arranging things a bit) & fixing 1 minor logic bug too

' for paletted images, need to transfer palette also
If (tBMPsrc.PixelFormat And &HFF00&) \ &H100& <= 8& Then
    GdipGetImagePaletteSize Handle, cPal.Count
    If cPal.Count Then
        GdipGetImagePalette Handle, cPal, cPal.Count
        GdipSetImagePalette ReturnObject, cPal
    End If
End If
If GdipBitmapLockBits(Handle, dstBoundsI, ImageLockModeRead, tBMPsrc.PixelFormat, tBMPsrc) = 0& Then
    ' open the destination for writing using the pointer we just got from source
    tBMPdst = tBMPsrc
    If GdipBitmapLockBits(ReturnObject, dstBoundsI, ImageLockModeWrite Or ImageLockModeUserInputBuf, tBMPdst.PixelFormat, tBMPdst) = 0& Then
        GdipBitmapUnlockBits ReturnObject, tBMPdst                  ' done
```

----------


## VbNetMatrix

nice finding that one... it's kind of burried deep.
Win7 is the first OS to fully support PNG, (to others: no Vista doesn't)   I'm guessing it is using the palette information to show the png as soon as it arrive (in IE9), therefore, he doesn't recalculate (re-adjust) the palette after he has all the bit of the images because he think he already loaded it first...  
could be possible.

The palette is the first thing to be sended after the header on Web uploade isn't ?

----------


## LaVolpe

@VbNetMatrix

Not sure if that is the issue here since we are talking about a simple 8 bpp bitmap. However, GDI+ does the palette different in Win7 as proven by the bug & fix. I am surprised GDI+ would do anything with the palette since we are not drawing the image, but simply setting the palette colors. This could be troublesome for previous version apps that use GDI+ to toggle palette colors for sprites

Anyway, if I get really curious, I could use the earlier code and write out the palette & bitmap pixel data. Then use the fixed code & do it again. At that point, via comparison I would be able to figure what GDI+ is doing. But at this point in the game, I'm not that interested right now.

P.S. You mentioned changes with Win7 and Png. Can you post the source, I'd like to get caught up on any other changes GDI+ went thru with Win7

----------


## VbNetMatrix

I read that stuff long ago when IE9 got out because my custommer where having problem with their website when "their client" used IE9  It was an OS problem, Ms fixed it by adding a condition inside IE

if OS <=Vista
png blababa
else >= win7
png blabnaaabla

I'll try to find back that article.  it was rather technical, you'll like it.

----------


## VbNetMatrix

can't find it back  :Frown:   I found some article by google team about their javascript "fix" for png that wasn't needed under Ie9 anymore...   but not the technical thing I had in past...

I'll look further as soon as I have more time

----------


## VbNetMatrix

Hi Lavolpe, 

I got a png that seem to have been specially crafted...  I can load it inside your component but when I  do an Export I always get an all black image.

I know it is probably NOT an issue with your component, I suspect foul play with the image...
but I really wish I could have the image back  :Wink:   So since you're a specialist in image, I thought maybe looking at this strange phenomenon could interest you.

http://vbnetmatrix.com/download/lavolpe/crafted.zip

if you got any solution for exporting, I am ALL EARS OPEN!

 :Wink: 

You've been quiet lately, does the V3 coming up ?

----------


## LaVolpe

When you say "Export", I am assuming you mean right clicking within the property page and saving the image to file? If so, I cannot replicate your problem. Here is the image I extracted, is it the same as you expected?

----------


## VbNetMatrix

By export, I meant using the code I provided withing the project I created.

My program (not the project I gave in previous post) load image of user choice, apply some watermark and save it back.  but when I do that with THAT image, the result is a big black rectangle.

I found out how it was crafted though, but unless I read pixel by pixel and change each pixel back to another image, I don't know how I could fix it.  The guy used Black pixel ALL over the image and he play with opacity for making the image appearing... it's kind of cleaver because program like Adobe Photoshop doesn't allow you to change the color of the Opacity, but with your component, I succeeded.
I'm not sure if your component got a "filter" I could apply to image... ( About this, I read the documentation but I didn'T find where you mention how to apply filter or effect like the one you did in some previous post with the Fox and the Bubble to give 3d effect with Alpha channel.)

Also take not that I'm using WinXp and under this OS, the image you just sent appear as this:



The "viewer" see it correctly, but other WinXp BASE program see it as a big black rectangle.

thanks for all your help.

----------


## LaVolpe

Possible you have an outdated GDI+ dll? On XP and Vista, simply loading the image in reply #419 into the AIC, it displays properly. Saving it to file on both systems, the saved file displays properly when loaded into the AIC. I cannot reproduce your problem. Everything works just fine

For your info, the GDI+ version I have on my XP box is dated Oct 2010

Now if you are saying that some other program can't read the image correctly, but the AIC can, then the other program has a problem. If however, you are saying that after manipulating the image, it is saved as a black rectangle, then I think it would be helpful to see some of the code you use to change the image before saving it.

To prevent any confusion, please post an image that displays properly in a typical viewer but doesn't display correctly in the AIC.

Edited: Regarding v3 of the AIC. I think I'll have the save functions rewritten/debugged this week. Then I just need to test the control out against the sample projects to ensure I didn't foul something up during some of the rewrites. I probably did, just hope I can find most of them so you guys don't have to  :Wink: . 
If all goes well, it'll be released within 1-2 weeks from today

----------


## VbNetMatrix

> Possible you have an outdated GDI+ dll?


doubt that...Like I tried to explain, this is NOT a bug.  it is the way the image was crafted.




> On XP and Vista, simply loading the image in reply #419 into the AIC, it displays properly. Saving it to file on both systems, the saved file displays properly


try to save the file as BMP, you'll understand what I am experimenting.  As I have stated before though, this is not a bug with your component.  This image is crafted in a special way to give that result.  However, in order to deal with the way this image is crafted, I need to be able to change the color of the Transparency.  To explain myself more properly, I made 2 images imageA.png has a RED transparency and imageB.png has a BLACK transparency (more common)

file can be found here:
http://vbnetmatrix.com/Download/Lavolpe/imageb.zip

This is the same method GIF use in order to make transparency.  It take 1 color and set it as the transparent color.  All pixel of that color are then transparent.

in png it work a little bit different but when applied, it is like each pixel with this color has opacity set to 0.




> For your info, the GDI+ version I have on my XP box is dated Oct 2010


what file in particular should I look for ?




> If however, you are saying that after manipulating the image, it is saved as a black rectangle, then I think it would be helpful to see some of the code you use to change the image before saving it.


Use the code I sent in post #418 and change Dest format to BMP.  but again... this IS NOT A BUG.  The result is the consequence of the way the file was crafted.

----------


## LaVolpe

> Use the code I sent in post #418 and change Dest format to BMP.  but again... this IS NOT A BUG.  The result is the consequence of the way the file was crafted.


It's a matter of understanding GDI+ limitations. The AIC will display it correctly after it has been saved to a BMP. But on XP, anyway, window's picture/fax viewer, MS Paint, & others may display it as a black rectangle when saved to bitmap. This is because GDI+ doesn't support 32 bpp alpha channel bitmaps. Not sure if Vista & Win7 versions of GDI+ have been fixed to provide that capability. With my AIC, I've known this for years and have custom routines to determine if the alpha channel is used and if so, how it is used.
a) all alpha values are 255 - the alpha channel exists but has no effect on the image
b) all alpha values are zero - the entire image is either transparent or app should treat it as all are 255
c) alpha value applies & the RGB components may or may not be premultiplied against the alpha values
-- read comments at bottom of sample code provided below. 
-- regarding para b) above: In the rare case of a 100&#37; transparent 32bit bitmap (not one pixel is opaque nor semi-opaque), then image is treated as if all alpha values are 255 not zero. A decision needed to be made & that was my decision

When an app does not support the alpha channel of bitmaps, then the channel is assumed to be all opaque. Since the image forecolor is black and the color of the transparent pixels are black, the image appears 100% black on software that doesn't properly read the bitmap format. Changing the color of the transparent pixels to say white would make the bitmap appear as black text over white background. However, this is WRONG. Even though the pixels are white, their opacity level is 0% -- fully transparent. It doesn't matter what color those pixels are, they should never be visible in a decent viewer; unless the viewer has options to render with/without the alpha channel

Note: PNG & GIF viewers handled these situations a bit differently when their formats were new to the world. Both have a special field in their format that identifies a background color. This bkg color would be used if the software displaying the PNG/GIF could  not or would not render transparency.

Note: If some app is using the alpha channel to write their own information in it, then apps like mine are going to assume the alpha channel is used for the image, not for some custom values. In those cases, then the only apps that may display the image as intended is the one that created the custom values or apps that do not honor the alpha channel

Edited: Now to discuss changing colors of transparent pixels so they are not always black? This has no real advantage except for viewers that cannot properly recognize 32bpp bitmap formats using the alpha channel.

-- Not doable with GDI+ easily as far as I know. The problem is that when GDI+ sees 100% transparency, it always changes the pixel values to black when rendering. This means you can have an all-white image at 100% transparency. If you save it like that; no problem. But if you draw anything onto it then save it, GDI+ changes any remaining transparent white pixels, within the drawing area, to now be transparent black pixels

-- GDI+ won't let you create a blank image containing 100% transparent pixels other than black. If you try to create a GDI+ brush of any transparent color and fill the blank image, all transparency is changed to 0,0,0,0 regardless of the brush color

-- Here's a bit of proof


```
Option Explicit
Private Declare Function GdipGetImageGraphicsContext Lib "gdiplus.dll" (ByVal pImage As Long, ByRef graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus.dll" (ByVal mGraphics As Long) As Long
Private Declare Function GdipCreateSolidFill Lib "gdiplus.dll" (ByVal mColor As Long, ByRef mBrush As Long) As Long
Private Declare Function GdipDeleteBrush Lib "gdiplus.dll" (ByVal mBrush As Long) As Long
Private Declare Function GdipFillRectangleI Lib "gdiplus.dll" (ByVal graphics As Long, ByVal brush As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long

Private Sub Command1_Click()

    Dim SS As SAVESTRUCT, tImg As GDIpImage, bAlphas() As Byte
    SS.Width = 256: SS.Height = 256
    SS.ColorDepth = lvicConvert_TrueColor32bpp_ARGB
    SS.RSS.FillColorARGB = ConvertRGBtoARGB(vbGreen, 0) ' transparent green
    SS.RSS.FillColorUsed = True
    
    Set tImg = New GDIpImage
    ' call function to create new bitmap. That function calls a GDI+ API that erases the bitmap
    ' with the passed color (transparent green).  But you will see, all transparency ends up black
    SavePictureGDIplus Nothing, tImg, lvicSaveAsBitmap, SS
    SavePictureGDIplus tImg, App.Path & "\test1.bmp", lvicSaveAsBitmap
    
    ' now we'll use a solid green brush and change the alpha values to zero manually
    SS.RSS.FillColorARGB = ConvertRGBtoARGB(vbGreen, 255)   ' opaque green
    SavePictureGDIplus Nothing, tImg, lvicSaveAsBitmap, SS
    ReDim bAlphas(0 To CLng(SS.Width) * SS.Height - 1&)     ' all zero values
    tImg.AlphaMask bAlphas(), True                          ' change alpha values
    Erase bAlphas()
    SavePictureGDIplus tImg, App.Path & "\test2.bmp", lvicSaveAsBitmap
    
    ' sounds promising, no? Nope. Now if you draw anything onto this green transparent image using GDI+,
    ' any green transparency reverts to black transparency
    Dim tIcon As GDIpImage, hGraphics As Long, hBrush As Long
    
    Set tIcon = LoadPictureGDIplus(Me.Icon)
    GdipGetImageGraphicsContext tImg.Handle, hGraphics
    tIcon.Render 0&, , , , , , , , , , , hGraphics
    ' and for the fun of it, we'll create a transparent blue brush and fill part of the image with it
    ' but where it paints, it will be black not blue
    GdipCreateSolidFill ConvertRGBtoARGB(vbBlue, 0), hBrush
    GdipFillRectangleI hGraphics, hBrush, 128, 128, 96, 96
    GdipDeleteBrush hBrush
    GdipDeleteGraphics hGraphics
    Set tIcon = Nothing
    
    SavePictureGDIplus tImg, App.Path & "\test3.bmp", lvicSaveAsBitmap

    ' Loading the 3 test bitmaps into the AIC, you'll get these results:
    ' 1) all black transparent bmp: Image will appear 100% opaque black not transparent
    ' 2) all green transparent bmp: Image will appear 100% opaque green not transparent
    ' 3) green & black transparency with icon. Image will be 100% transparent except for the icon in top/left corner
    ' Why is 100% transparency in bitmaps 1 & 2 being shown as opaque? Simply because of the tie breaker rules
    ' my routines use when trying to determine alpha usage. The rules are simple enough:
    ' a) Any alpha values other than 0, then alpha is assumed in use & applied to the image
    ' b) If all alpha values are zero then either image is 100% transparent or alpha values are not used and image is 100% opaque
    ' -- since the AIC is designed to display images, the default tie breaker is: 100% opaque, not 100% transparent
    ' -- odds of seeing a 100% transparent 32bit bitmap are extremely rare, so assume it is not on purpose
End Sub
```

-- So, how does one change the transparent color in a bitmap? Pixel by pixel modifications. Prior to saving, one needs to loop thru the image bits and check for zero alpha values. Once found, change the RGB component of that pixel to the desired color

----------


## VbNetMatrix

very interesting indeed.

about your conclusion, it was exactly what I had in mind... in fact right before I read your post, I already had an export of the file that I did pixel by pixel by modifying the alpha channel of thoses who were crafted in that special way.

thanks, I really learned a lot.

you're still the pro!

----------


## VbNetMatrix

Hi Lavolpe, 

I found something you would be interested in.
a bug (that is easy to fix) that make your component completely crash inside the IDE.

here the process to REPRODUCE the bug from your side. 


1. make a project, put a Lavolpe Component on the form.
2. add a BUTTON on the form  (important)
3. add an image inside the component with the property page.
4. save and exit.

5. Open your project back, 
6. open the property page of the lavolpe image.
7. Click browse to select a new image (DO NOT CHOOSE THE IMAGE YET)
8. Click on the form button... (the one you added)

the Lavolpe component will crash.

regards.

----------


## VbNetMatrix

Hi again...

I got a little question about SaveControlAsDrawnToGDIpImage parameter...

I've tried to see the difference... but it seem in PNG there is no difference.
I can see difference if I export to BMP, there will be squared instead of stranparency while setting the parameter to True, will "emulate" the transparency color...

but in PNG, does it change anything ?

----------


## LaVolpe

Regarding the error generated within the property page. Thanx and here's the fix which will be applied to the updated control when I post it later this month. FYI. Error was not generated in Vista.

Object: Property Page (ppgCustom)
Routine: cmdBrowse_Click
1. At very bottom of the event, add this


```
ExitRoutine:
If Err Then Err.Clear
```

2. In same event, find this line: If cBrowser.ShowOpen(PropertyPage.hWnd) Then
Just before that line, add this: On Error GoTo ExitRoutine

3. In same event, find this line: With cFolderBrowser
Just before that line, add this: On Error GoTo ExitRoutine

Ok, regarding your question about PNG and SaveControlAsDrawnToGDIpImage... Sorry I don't understand what you are asking.

----------


## VbNetMatrix

I'm trying to load a lavolpe.picture into tImg (GDIpImage) and then modify SOME pixel and then save result back...

unfortunately, when I do that, I can SHOW on screen on another control the RESULT and it is Fine.  but when I try to save that result to DISK, I got the original file unchanged.

as for SaveControlAsDrawnToGDIpImage, it does work but some pixel are slightly changed no matter what parameter I provide.  And I wanted to know more about what that parameter was really doing.

but my main question is more "how I can save back to disk the picture I have modified" since it doesn't seem to work.

If instead of using a picture as source, I use a blank image and then copy pixel by pixel the "source" image and then add my modification, then SavePictureGDIplus work correctly...

in other word:

this work:
  Set tImg = New GDIpImage
  ss.Width = lavPicture.ScaleWidth
  ss.Height = lavPicture.ScaleHeight
  ss.ColorDepth = lvicConvert_TrueColor32bpp_ARGB

  SavePictureGDIplus Nothing, tImg, , ss
...  'here pixel modification
SavePictureGDIplus tImg, App.Path & "\00.png", lvicSaveAsPNG, ss

This doesn't work:
  Set tImg = lavPicture.picture
  ss.Width = lavPicture.ScaleWidth
  ss.Height = lavPicture.ScaleHeight
  ss.ColorDepth = lvicConvert_TrueColor32bpp_ARGB

  SavePictureGDIplus lavPicture.picture, tImg, , ss
...  'here pixel modification
SavePictureGDIplus tImg, App.Path & "\00.png", lvicSaveAsPNG, ss

----------


## LaVolpe

When tImg has no image and you pass a SS to SavePictureGDIplus, you are telling the routines to create a new blank image of the requested bit/color depth: lvicConvert_TrueColor32bpp_ARGB

When tImg is a loaded picture and you call SavePictureGDIplus with a passed SS that contains a bit/color depth, it is possible that a conversion occurs in the save routines. That conversion may be what you are experiencing. You have no control over the conversion process

Try 1 of these:

1) set SS.ColorDepth = lvicNoColorReduction

Else one of these:

If the image in tImg is 32bpp then...
a) After loading the image into tImg, make tImg.KeepOriginalFormat to false. This converts tImg to a 32bpp bitmap format
b) change your pixel values, save image to PNG

If the image in tImg is not 32bpp or you are not sure, then...
a) save tImg with SS.ColorDepth as lvicConvert_TrueColor32bpp_ARGB as a bitmap format, not PNG
b) do your pixel modifications
c) now save to PNG as needed

----------


## VbNetMatrix

I never work with something lower then aPNG  why settle for less when you can have no degradation, compression and alpha blending?!  So, it's eitheir ICO or PNG for me  :Wink: 

I started with a working project on a BLANK image... then I changed:

SavePictureGDIplus Nothing, tImg, , SS
to
SavePictureGDIplus aicLine.Picture, tImg, , SS

(now not working)

then I tried solution #1 (before and after SavePictureGDIplus in 2 different try)
not working...

then I tried:
tImg.KeepOriginalFormat = false  - as proposed
this work.

what are the implication ?  what will it do to the image ?  Should I expect weirdo reaction under some parameter ?

thanks


set SS.ColorDepth = lvicNoColorReduction

----------


## VbNetMatrix

(read previous msg)

should I understood that SS is not required if I pass an image ?

SavePictureGDIplus aicLine.Picture, tImg
instead of 
SavePictureGDIplus aicLine.Picture, tImg, , SS

will it take the SS struct from the image ?

I tried it, seem to work...

----------


## LaVolpe

Working with 32bpp bitmaps is ideal. All image formats (png, jpg, icon, etc) are reduced to bitmap when being displayed on screen. 32bpp bitmaps can have their bits accessed easily with GDI+. A 32bpp bitmap can be saved to any format that uses the alpha channel without any degradation. Regarding passing SS, it is not needed unless you want to change the image during saving. When not passed, all values are filled from the image, as necessary. PNG, TGA are formats that can compress most color depths without color loss. Other image formats may be limited to specific ranges of color depths before loss occurs

Exception: If saving to an image format that doesn't support the source image color depth, then loss of original data may apply. For example, GIF doesn't support 32bpp unless  alpha values are either 0 or 255. 

Note about saving. If passing a SS, then there is a chance that the image can be redrawn, depending on the SS structure values/settings. If the image is redrawn, then any transparent pixels will be reset to black transparency by GDI+.

----------


## VbNetMatrix

yeah I knew a lot about image format.  I did an essay at university on them (and it's online too) but it is in french...
I speculate that in the long run, GIF and JPEG will vanish (for good)

ok, so in my case, SS is optional...

but what are the implication of the added line:
tImg.KeepOriginalFormat = false

wich make me able to SAVE the change to the real image.
does it imply more then just changing the pixel I have changed ?

----------


## LaVolpe

> but what are the implication of the added line:
> tImg.KeepOriginalFormat = false
> 
> wich make me able to SAVE the change to the real image.
> does it imply more then just changing the pixel I have changed ?


When that property is set to false, any cached data is thrown away and the image is reduced to a bitmap of equal color depth of the source. That property is intended to reduce memory consumption for loaded images. By default, loaded images keep their original source data (with few exceptions) and this can be seen as wasted memory use.

Unless the source image was a bitmap to begin with, resetting that property will result in the image being reported as PNG, but internally, the image will always be bitmap. Reading the comments at the the top of the GDIpImage class may be helpful

----------


## VbNetMatrix

very interesting. 

the cache thing is an interesting feature though, even if it can be seen as a waste of memory.
I didn't saw that KeepOriginalFormat in the documentation, I must have missed it.

thanks again

----------


## VbNetMatrix

Hi Lavolpe, 

I remember once you told us that in order to preserve memory, we could use a technique if 2 button has the same image...

can't find the post  :Frown:  
I thing it was 
Set lavolpe1.picture = lavolpe2.picture

but was it all ?

sorry to make you repeat yourself.

edited: yes, right... sorry for that.  I looked everywhere, I thought I read that not long ago!

----------


## LaVolpe

> can't find the post


Post #3, 1st page  :Wink:

----------


## alanxp

LaVolpe you're a *Genius*. I wonder if i could ever learn as much as you!

I Have a question tho my friend, I've been using AlphaImageControl 1.1.0 since quite a while, and i recently found out about this Great NEW VERSION! 

However i'm trying to make a game like Pokemon with your control and it seems to lagg quite a bit with 1.1.0 ... 

Please check this Out:
11 AlphaImagePictures Animated and moving.
http://img20.imageshack.us/img20/9757/battle2010.png

I'd like to know with all the implementations in this Newest version would it be Faster or slower to this kind of project if i use it instead of the old version 1.1.0 of your Alpha Image Control.

I really would appreciate your comment back.  :wave:  Greetings!

----------


## VbNetMatrix

Hi alanXp, 

I see that your application rely on large image.  Lavolpe component is no doubt the best for handling different image format, but like you, I have notice some problem with large image.

The fix I propose and use in my program is to use regular image/picture box component for image that doesn'T need to have alpha blending (transparency) .

Lavolpe (a few post back) showed me how to load a PNG into memory and then transfer it to a regular image/picturebox control.

I think the same effect could be used in your program by replacing the background image (zorder1) by a picture box.

I have used this technique on a game myself with a background png of 1280x768 without any lag effect using a simple Pentium 4 - 3.0ghz

I never tried the v1.1 Component and I'm using the latest version.

hope this help.

----------


## alanxp

that would be nice, all i would need is the PNG loaded with TRANSPARENCY. does it support transparency correct?

I'm trying to look for that post but i've got no luck 

Thank you for Helping me man!

----------


## VbNetMatrix

Hi

reference to page 8, post #309
http://www.vbforums.com/showthread.php?t=630193&page=8

Not sure I explained myself properly.
What I was trying to say is:
1. use Normal image or picture box for the background as this doesn't require transparency, 
2. use Lavolpe component for all other image that require transparency.

You'll achieve better speed that way as Lavolpe component is running a lot of subroutine in the background and (correct me Lavolpe if I'm wrong) Background image doesn't require all of what Lavolpe component is doing.

also I don't know your level of expertise in programmation, so ensure your subrountine is all fine tuned in order to use maximum speed.  Use API as much as possible instead of low Vb6 class like PSET and such if you require them.  I never saw a pokemon game, therefore I don't know what you're trying to achieve, but I once did a replica of Starcraft (not all the game, just the running 191 frames of the intro where you decide wich game type to choose)) with Lavolpe component, so I know the component can handle a lot of stress and action when used correctly.

I'm rather pretty busy right now but I'll do my best to answer your answer if you have any.

----------


## alanxp

ah, helping others is always good and very well rewarded, so i have my Background which is Already a PictureBox. Then The rest of the objects are LaVolpe's Alpha Image Control *v1.0* 

So my Only Question is.... Moving to *Alpha Image Control v2.0*  will make things Smoothly or Slower?

What i use to move the images is a simple loop like this:


vb Code:
for i = 1 to max_frames     lavolpesaic.loadpicture = frame(i)     lavolpesaic.left =  lavolpesaic.left + (i *10)     sleep 1     doeventsnext i

Here is a Sample of the Controls from AIC i've used:



Except that i move like 5 Lavolpes Image Controls a the same time, Resizing and Loading the Images.. All during the same Loop. That happends every time when the person gets into Battle.

 I know this is pretty Basic, and everything seems to move slowly. What am i doing wrong? I apreciate your help here.  :Frown:

----------


## VbNetMatrix

Ok, now I understand it more.

first of all, I see in your code that you are using Doevents and Sleep.

this is a NO GO...  for many reason.  one of them is that you'll slow down your entire program.

you would be better to use a timer with a public variable to keep the frame number as reference instead of your for next loop.

Doevents is good when you have a LONG process and you want to be able to still click on button and do other thing.  it is not recommended otherwise.

Sleep is to be avoided AT ALL cost, especialy in game.

during sleep, your program is locked up.  and existing of sleep, it will have to take into account everything that happen while it was sleeping, including button clicking, mouse hover and all.
even if you sleep 1ms, you are still delaying a lot of thing you're not aware of.  That's probably the main cause for your lag.

you're looking for something more like this:


```
Option Explicit

Public lngframeNo As Long

Private Sub Form_Load()
  lngframeNo = 1
  Timer1.Interval = 15  '(that's the maximum accurency of 98&#37; of computer on the market)  Raise it if it's too fast for you
  Timer1.Enabled = True
End Sub

Private Sub Timer1_Timer()
    lavolpesaic.LoadPicture = Frame(lngframeNo)
    lavolpesaic.Left = lavolpesaic.Left + (lngframeNo * 10)
    lngframeNo = lngframeNo + 1
    
    If (lngframeNo > max_frames) Then
      lngframeNo = 1
      'Timer1.Enabled = False   'This line is optional.  use it if your sequence END here, don't use it if it's perpetual moving sequence
    End If
End Sub
```


hope that help.

oh... and if you need even more speed, 

I would recommend an ARRAY of Lavolpe component and getting rid of loadpicture, 
use visible or zorder instead.

----------


## mjohnlq

Hi. LaVolpe
Your UnicodeFileDialog Class is very good for me.
But it has a little bug.

//Below Code
' returns/sets the filename the dialog starts with or returns
Public Property Get filename() As String
...
        lLen = InStr(ofn.nFileOffset, ofn.lpstrFile, vbNullChar) - 1&
...
End Property

should be changed as below:

lLen = InStr(ofn.nFileOffset, ofn.lpstrFile, vbNullChar & vbNullChar) - 1&

otherwise, when select mult files, the filename will only return the path, not all the files's name.

Please see below link:
http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

lpstrFile
Type: LPTSTR
The file name used to initialize the File Name edit control. The first character of this buffer must be NULL if initialization is not necessary. When the GetOpenFileName or GetSaveFileName function returns successfully, this buffer contains the drive designator, path, file name, and extension of the selected file.
If the OFN_ALLOWMULTISELECT flag is set and the user selects multiple files, the buffer contains the current directory followed by the file names of the selected files. For Explorer-style dialog boxes, the directory and file name strings are NULL separated, with an extra NULL character after the last file name. For old-style dialog boxes, the strings are space separated and the function uses short file names for file names with spaces. You can use the FindFirstFile function to convert between long and short file names. If the user selects only one file, the lpstrFile string does not have a separator between the path and file name.
If the buffer is too small, the function returns FALSE and the CommDlgExtendedError function returns FNERR_BUFFERTOOSMALL. In this case, the first two bytes of the lpstrFile buffer contain the required size, in bytes or characters.

Thanks!

----------


## wham

Hi Lavolpe

Thanks a lot for awesome codes.
I'm a just beginner.
I want to set the animated pics to work just 1 cycle(No loop).
I have tryed using the EndLoopOnFirstFrame function, but it doesn't work.
I don't know....
Would you please let me know how to solve it?

And I have one more question about that when I use the AlphaImgCtl1.Animate2.Stop function.
How to display the first frame of pics. I mean, get back to the first frame of pics.

Thanks a lot.

Private Sub command1_Click()

 AlphaImgCtl1.Animate2.EndLoopOnFirstFrame = True
 AlphaImgCtl1.Animate2.StartAnimation

End Sub

----------


## VbNetMatrix

> Hi Lavolpe
> 
> I want to set the animated pics to work just 1 cycle(No loop).
> I have tryed using the EndLoopOnFirstFrame function, but it doesn't work.
> And I have one more question about that when I use the AlphaImgCtl1.Animate2.Stop function.
> How to display the first frame of pics. I mean, get back to the first frame of pics.
> End Sub


Hi Wham, 

I think the EndLoopOnFirstFrame tell the component to STOP on the first frame AFTER it completed the cycle.  Is that what you're trying to accomplish ?  I'm not sure I understand your problem properly.
One more thing, are you using Animated Gif or Animated Png ?

----------


## VbNetMatrix

ok I found something...

it is not in the documentation per say but Lavolpe code is pretty well documented.
so here what we read in the EndLoopOnFirstFrame Code:

    ' default behavior is to have last frame displayed when animation terminates due to loop count met
    ' If desired to display 1st frame instead of last frame, set this property to true

and here what you have to do:

  AlphaImgCtl1.Animate2.LoopCount = 1  'mean you only want one 1 LOOP of all frame of the image.
  AlphaImgCtl1.Animate2.EndLoopOnFirstFrame = True  'mean that when loop end (it is now on LAST frame), it will display FIRST frame instead
  AlphaImgCtl1.Animate2.StartAnimation    'do the magic..

hope that help.

----------


## wham

> ok I found something...
> 
> it is not in the documentation per say but Lavolpe code is pretty well documented.
> so here what we read in the EndLoopOnFirstFrame Code:
> 
>     ' default behavior is to have last frame displayed when animation terminates due to loop count met
>     ' If desired to display 1st frame instead of last frame, set this property to true
> 
> and here what you have to do:
> ...



Hi VbNetMatrix,

Thank you so much!!!!
It works great!!!! :Thumb:  :Thumb:  :Thumb: 
Your answer is just what I was looking for.
Thanks again.

Thanks to your help, I can save my time.
I used the below codes. But I don't need it anymore.
Thank you!!!

Private Sub AlphaImgCtl1_AnimationFrameChanged(Frame As Long)

	If AlphaImgCtl1.ImageCount = AlphaImgCtl1.Animate2.CurrentFrame Then
		AlphaImgCtl1.Animate2.StopAnimation
		AlphaImgCtl1.Animate2.MoveTo (1)
	End If

End Sub


Private Sub AlphaImgCtl1_Click()

	AlphaImgCtl1.Animate2.StartAnimation

End Sub

----------


## VbNetMatrix

I'm glad I could help.

Lavolpe is currently kind of very busy with the BIG NEW release he is preparing.
we will all enjoy the upcoming release of this excellent component.
take care.

----------


## Stidor

Is there any reason why UserControl_OLEStartDrag doesn't raise the StartDrag event when set to Automatic?

Ideally I'd like to set some drag data when the drag starts.



```
'//// standard OLE event
Private Sub UserControl_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
    
    Data.Clear
    If Me.OLEDragMode = vbOLEDragAutomatic Then
        If modCommon.SaveImage(m_Image, Data, lvicSaveAsCurrentFormat) Then
            AllowedEffects = vbDropEffectCopy
        Else
            AllowedEffects = vbDropEffectNone
        End If
    Else
        RaiseEvent OLEStartDrag(Data, AllowedEffects)
        ' if user doesn't set AllowedEffects, VB will cancel drag event
    End If
    
End Sub
```

----------


## VbNetMatrix

> Is there any reason why UserControl_OLEStartDrag doesn't raise the StartDrag event when set to Automatic?
> 
> Ideally I'd like to set some drag data when the drag starts.



In order to answer your question, it would need to be more specific.
are you trying to drag lavolpe control over something else, or trying to drag another control onto Lavolpe control?

----------


## Stidor

Onto another Lavolpe control.

I replaced standard pictureboxes - which used to fire the StartDrag event with the Lavolpe control which does not fire off the StartDrag event in OLEDrag automatic mode.

Just curious why?

----------


## VbNetMatrix

let me do some test...

----------


## VbNetMatrix

I think the OLE Drag Start is for another purpose (with an external component).

you're trying to get to know when the drag even start.

use a boolean flag with a global variable and use the 
DragOver event of the lavolpe component and you'll know when the Drag Start.

when the object is dropped, cancel your boolean flag.

tried here, work like a charm.

----------


## Stidor

I downloaded the latest version from this topic when I was browsing the source.

This is from the control;


vb Code:
'//// standard OLE eventPrivate Sub UserControl_OLEStartDrag(Data As DataObject, AllowedEffects As Long)        Data.Clear    If Me.OLEDragMode = vbOLEDragAutomatic Then        If modCommon.SaveImage(m_Image, Data, lvicSaveAsCurrentFormat) Then            AllowedEffects = vbDropEffectCopy        Else            AllowedEffects = vbDropEffectNone        End If    Else        RaiseEvent OLEStartDrag(Data, AllowedEffects)        ' if user doesn't set AllowedEffects, VB will cancel drag event    End If    End Sub

As you can see, in Automatic mode StartDrag event is not fired

----------


## VbNetMatrix

yeah I just check the code and that event is never fired in automatic mode...

it puzzle me a little but I'm not sure it is an issue.  I think only Lavolpe can answer that one.

however, take a look at that link.

http://www.datadynamics.com/Help/Sha...ragMode7A.html

it explain the proper expected behavior.

I'm hoping Lavolpe could step in and explain us.

but as I said, you can use the workaround I explained early.

----------


## Stidor

This is somewhat related, and thought I'd be best asking here.

What's the possibility of somehow getting alpha images into a the listview control?

----------


## Jonney

Wondering why Lavolpe not appearing on this thread for a long time. I wish him peace and health.

----------


## VbNetMatrix

same from my part...  I really have a lot of admiration for that guy.  He gave us a nice product.

----------


## yogiyang

I think he is busy developing new version of Alpha Image Control.

This new version will not be backward compatible!

----------


## azzler

hi, i have this LavolpeAlphaImage2 activeX control. what i want is to load a picture in it via common dialog during runtime. how can i possibly do this. kindly show me an example. thanks in advance  :Ehh:

----------


## Jonney

Did Anybody know how is Lavolpe doing? Has he changed a new job or was something happened?

----------


## shinyboy

hi I use THis Control In mY form But When I want Print mY form By form.print this error whas show -----------> error 482 : printer error ? Why this Happen?

----------


## yogiyang

Try to use following code to load image.




> AlphaImageLib1.Picture = LoadPictureGDIplus("C:\MyTest.jpg")

----------


## coolcurrent4u

can this control be used to replace the vb6 one

----------


## Frido

Hi at all,
i found this control a fiew days ago, and it is a great one.
I tested it a fiew times, and i understand the most features.
My question is, is it possible to shape a form with this control? I have nothin found about it, and no idea to do this.

Sorry about my bad english! :-)

----------


## Bonnie West

> My question is, is it possible to shape a form with this control? I have nothin found about it, and no idea to do this.


No, it can't do that. However, you may want to check out How to Make a Round (Circular) Form and Here's How to Make a Form With a HOLE in it for possible solutions.

----------


## sergelac

the image is always distorted when using "apply tolerance" with size reduction
with any output format

----------


## go2abdul

Hi to all,

While searching for a alternate image control for MS Access (2010) I found this control. Looks great but I have issues using this ActiveX in MS Access. Would anyone post a sample Access DB to show how to use this control? I need this control to save/retrieve image from the database.

Thanks in advance.

----------


## mleo1

How to make this control above other controls. send to back, and send to front does not work

----------


## Cube8

> How to make this control above other controls. send to back, and send to front does not work


You can't send it to front. It is a windowless control. It will always be behind other controls.

----------


## Bonnie West

> You can't send it to front. It is a windowless control. It will *always be behind* other controls.


Or more precisely, the AlphaImgCtl UserControl can't be positioned on top of any non-graphical control (those with an hWnd property). You can, however, put the AlphaImgCtl in front of any graphical control (such as an Image, Label, Shape or other windowless UserControls) either during design time or at run time via the control's ZOrder method.




> Three graphical layers are associated with forms and containers. The back layer is the drawing space where the results of the graphics methods are displayed. Next is the middle layer where graphical objects and *Label* controls are displayed. The front layer is where all nongraphical controls like *CommandButton*, *CheckBox*, or *ListBox* are displayed. Anything contained in a layer closer to the front covers anything contained in the layer(s) behind it. *ZOrder* arranges objects only within the layer where the object is displayed.

----------


## Cube8

Indeed. I just gave a simplified answer  :Smilie:

----------


## kembreg

The IDE will not let me add the "fox" control to a form.
I get that "prohibet" icon when I hover above a form when the "fox" control is selected.

Any idea what I am doing wrong?

----------


## VbNetMatrix

well...
1. have you registered the component using Administrator privilege ?
2. make sure IE10 IS NOT installed.  if you have installed it BEFORE upgrading to IE11, you need to uninstall IE11, then uninstall IE10, then install IE11 (if you really want IE11)
plz note that this only affect IDE and IE10 has no bad side effect on compiled program.  as for myself, I kept IE9 on my Dev computer because it's the safest course of action.
Once IE11 is installed, OCA file are no longuer created (ocx transit file) and most OCX will require the file before compilation.  Again, the problem only affect DEV machine, not the compiled result.

----------


## passel

> Or more precisely, the AlphaImgCtl UserControl can't be positioned on top of any non-graphical control (those with an hWnd property). You can, however, put the AlphaImgCtl in front of any graphical control (such as an Image, Label, Shape or other windowless UserControls) either during design time or at run time via the control's ZOrder method.


I haven't played with the control, but I would imagine you could put the control in a panel (or picturebox even), and then adjust the zorder of the container. But, that might defeat the purpose of the control, since the background of the container would be visible and that may be undesirable.  
I should probably read the whole thread, and try the control before commenting, but then I'll probably not get around to it.

----------


## kembreg

Thanks for your answer. Been using VB6 for a long time.  Never registered a component before.  Can you tell me how? I googled and did not find much.  Thanks!

----------


## kembreg

Wow!  I got it running.  Now comes the big question:

How to add a shadow to the image.
I have seen La Volpe's work before with PNGs and have seen a shadow effect on some examples.

Any advice would be welcome.

David

----------


## Arnoutdv

Why don't you start a new thread instead of posting in an old codebank thread?

----------


## evanzulli

Hi!
I don't know if anyone is still using this wonderful activex control. I've made a few enhacements but i stumbled on a little bug. When i resize the control in a secondary display (monitor) using windows extended desktop to full screen size it does not work properly. Since my debug pc has not a secondary display adapter so as to debug the ocx i was wondering if anyone noticed this too. And if so can help me out of this situation.
Any help would be apreciated.
Thanks!

----------


## LaVolpe

I won't be updating this project any longer. Have plans on rewriting it to add a few major enhancements.

But in the mean time, if you can describe exactly what isn't working, maybe I can help. If it is related to your 'enhancements' then you'll need to fix what your broke.

----------


## evanzulli

I simply added some text property to show as overlay, some textaligment properties, and same textdisplay offsets. I dont think this can mess up the things i'll describe you later.

The thing is i want to resize the control in full screen in the secondary display adapter and the control doesnt take the new width and height values. i think its related to the thing that it takes vb6 screen object max measures and the control i'm tryin to resize is bigger than this measures since the secondary display is an hd tv! 

Thanks a lot.

----------


## LaVolpe

> i think its related to the thing that it takes vb6 screen object max measures


Bingo. Within the usercontrol's sptGetScaledSizes routine, look for the following lines of code:


```
            If ucCx > Screen.Width \ Screen.TwipsPerPixelX Then ucCx = Screen.Width \ Screen.TwipsPerPixelX
            If ucCy > Screen.Height \ Screen.TwipsPerPixelY Then ucCy = Screen.Height \ Screen.TwipsPerPixelY
```

Exist in a couple places in that method. Rem those out and see what happens. May just be the trick.

Search the entire project for Screen.Width and/or Screen.Height. These are used in a couple of other classes, other code.

----------


## evanzulli

Thanks for your quick response! 
I've already done this... but with no efect!
I'll give it a second shot, and tell how it went...

Thanks again!

----------


## LaVolpe

Well, those are the only lines that are restricting size. Keep in mind that a control may be limited in size by VB itself.  

The max size vb will allow resizing appears to be 32767 x 32767 pixels. Don't know how large that HDtv screen is. Can you post the screen size reported for the tv & the maximum size reported by the Alpha Image Control (it's public ScaledWidth & ScaledHeight properties). Keep in mind that the control's size will be in pixels while the screen measurements are in twips; so divide screen measurements by TwipsPerPixelX/Y as appropriate for comparisons

----------


## evanzulli

Thanks a lot for your unvaluable support.
Commenting out those lines did the magic! 
The first time i tried it was not working because on the testing machine the ocx was not updated.
I updated the modified one manually and voila, as expected.

Thanks again for your support.

----------


## LaVolpe

Cool. Didn't think your tv would be near 33K pixels in size

----------


## evanzulli

It is not! But the problem i suppouse that raises is, that the main screen is only 1024 x 768 and the secondary screen bigger than that (1920x1080). 
I guess problem is, that the control is not aware on which display its beeing shown, and since the vb6 Screen object does not know anything about the extended desktop.

Thanks a lot again.
Bye.

----------


## Cube8

Now, LaVolpe, that's another issue to take into account for the new control  :Wink:

----------


## LaVolpe

> Now, LaVolpe, that's another issue to take into account for the new control


Referring to a re-write? It already is addressed... accidentally. Instead of restricting a control's size to the desktop size, hardcoded the restriction <= 32767 or user-defined value

----------


## Godaya

Hello Sir!
First I'm Saying very thank you for giving us this amazing activex control  :Smilie: 

I'm working with small personal project. I need to know how do i zoom image using this control. I tried your samples but i didn't get what i need actually. I need to zoom image without scaling control size and can i move zoomed image while moving mouse on the control? I'm a beginner to VB6. And sorry for my bad English. hope u help me. Thank you sir  :Smilie:

----------


## LaVolpe

I don't fully understand, zooming without scaling? In order to zoom in/out, you are changing the scale of what you are looking at? 

Maybe this is what you are talking about? A rectangle moves with the mouse. The area inside the rectangle is zoomed only, not the entire image?

----------


## Godaya

> I don't fully understand, zooming without scaling? In order to zoom in/out, you are changing the scale of what you are looking at? 
> 
> Maybe this is what you are talking about? A rectangle moves with the mouse. The area inside the rectangle is zoomed only, not the entire image?



Hello,
Thanks for replying. I meant that the entire image is being zoomed. Once it's zoomed the using the mouse pointer the image is to be scrolled (top to bottom,left or right) but without the scroll bars. If this idea is more advance the "the rectangle move with the mouse" is okay! Thank you!  :Smilie:

----------


## LaVolpe

Actually, sliding it within its frame is much simpler.

1) AlphaImageCtrl properties that should be set:
WantMouseEvents=True

2) Declare 2 new variables at top of your form: Private m_ImgX As Single, m_ImgY As Single

3) AlphaImageCtrl events


```
Private Sub AlphaImgCtl1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        m_ImgX = X - AlphaImgCtl1.XOffset
        m_ImgY = Y - AlphaImgCtl1.YOffset
    End If
End Sub
Private Sub AlphaImgCtl1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then AlphaImgCtl1.SetOffsets X - m_ImgX, Y - m_ImgY
End Sub
```

Now you can slide the image within its bounds.

If you wish to use that pan/zoom example and see how the above tweaks work, suggest adding this to that project after you've added the above tweaks:

1) In the AlphaImgCtl1_DblClick() event, add this: AlphaImgCtl1.SetOffsets 0, 0
2) In the AlphaImgCtl1_PrePaint() event, add the offsets:


```
        AlphaImgCtl1.Picture.Render hdc, (AlphaImgCtl1.Width - (AlphaImgCtl1.Width * zoomOffset)) \ 2 + HScrollPan.Value * zoomOffset + AlphaImgCtl1.XOffset, _
            (AlphaImgCtl1.Height - (AlphaImgCtl1.Height * zoomOffset)) \ 2 + VScrollPan.Value * zoomOffset + AlphaImgCtl1.YOffset, _
            AlphaImgCtl1.Width * zoomOffset, AlphaImgCtl1.Height * zoomOffset, , , , , , _
            AlphaImgCtl1.Effects.AttributesHandle, , AlphaImgCtl1.Effects.EffectsHandle(AlphaImgCtl1.Effect)
```

Edited: To see the changes, slide ^^ to the right & see the blue, bold additions

*Ensure the control's container ScaleMode is vbPixels*

----------


## schmurtz

Hi, Alpha Image Control is awesome, I've tried different examples and I'm really impressed !
I'm looking for a way to displays png files (with some transparent areas) on the top of a VLC (videolan) control.

To do that I think that a second transparent form above the one with the VLC control could be a good way.
If find a good example here and here based on GDI+ to make transparents forms and just displaying a PNG but when I try to animate it I don't have good results (a lot of CPU and a lack of fluidity on old computers). UpdateLayeredWindow from "user32.dll" seems to be a good way to make a transparent forms but I'm not a good enough developer to adapt it with Alpha Image Control.

*So my questions are :* 
Do you know a way to display and animate PNG with transparency above controls (like buttons, VLC...) ? My choice is a transparent form but may be it's not the right way...
If a second and transparent form is the good way, do you think possible to adapt UpdateLayeredWindow with Alpha Image Control or is there another way to make it ?


Thank you very much  :Smilie: .

----------


## LaVolpe

Interesting idea, especially for animation. Here's some tips/steps to get you going. But you kinda hurt my feelings when you offered those examples from PlanetSourceCode and didn't include mine which could be found here. Just kidding about hurt feelings

1) Add the alpha image control (AIC) to a test form and add an image to it, ensure it animates correctly when the form is in runtime. Once this is verified, we can play.
2) Gonna need quite a few APIs and I'll list them below & provide some code to get you started
3) Ensure the AIC is sized same as you want the form sized (remember just testing), doesn't matter where it is positioned. Make the form borderless
4) The AIC props: Enabled=False, AlignCenter=False, Aspect=Scaled
Note: if rotating image, then AlignCenter=True, but you have to offset where to paint in the PaintImageAsDrawnToHDC calls on the form
5) Paste this code in the form & change the AIC name to what you called your AIC
6) Load, run & play. Double click on the form to unload it. Click, hold & drag to move it.
7) Never make the form 100% transparent. You may need task manager to kill it.

Most of the code below is needed for applying ULW to the form. You are using the AIC for just 2 reasons: notify when new animated frame is rendered and to draw the frame to another hDC. If you are manually updating the AIC to a new image thereby animating it yourself, you would simply erase the memory bitmap (via FillMemory API) & then call the pvUpdateWindow after setting the AIC image

```
Option Explicit

Private Declare Function UpdateLayeredWindow Lib "user32.dll" (ByVal hWnd As Long, ByVal hdcDst As Long, ByRef pptDst As Any, ByRef psize As Any, ByVal hdcSrc As Long, ByRef pptSrc As Any, ByVal crKey As Long, ByRef pblend As Long, ByVal dwFlags As Long) As Long
Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetLayeredWindowAttributes Lib "user32.dll" (ByVal hWnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
Private Declare Function ReleaseCapture Lib "user32.dll" () As Long
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
Private Declare Function GetDC Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hWnd As Long, ByVal hdc As Long) As Long
Private Declare Sub FillMemory Lib "kernel32.dll" Alias "RtlFillMemory" (ByRef Destination As Any, ByVal Length As Long, ByVal Fill As Byte)
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function CreateDIBSection Lib "gdi32.dll" (ByVal hdc As Long, ByRef pBitmapInfo As Any, ByVal un As Long, ByRef lplpVoid As Long, ByVal Handle As Long, ByVal dw As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Const WS_EX_LAYERED As Long = &H80000
Private Const GWL_EXSTYLE As Long = -20
Private Const ULW_ALPHA As Long = &H2
Private Const ULW_COLORKEY As Long = &H1
Private Const WM_NCLBUTTONDOWN As Long = &HA1
Private Const HTCAPTION As Long = 2
Private Const AC_SRC_ALPHA As Long = &H1
Private Const AC_SRC_OVER As Long = &H0
Private Const GWL_STYLE As Long = -16
Private Const WS_BORDER As Long = &H800000
Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Type Size
    cX As Long
    cY As Long
End Type
Private Type BITMAPINFOHEADER        ' GDI structure
    biSize As Long
    biWidth As Long
    biHeight As Long
    biPlanes As Integer
    biBitCount As Integer
    biCompression As Long
    biSizeImage As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed As Long
    biClrImportant As Long
End Type

Private m_hDC As Long, m_hBmp As Long, m_DIBptr As Long
Private m_Opacity As Long
Private m_MousePoints As POINTAPI
Private m_Size As Size


Private Sub AlphaImgCtl1_AnimationFrameChanged(Frame As Long)
    FillMemory ByVal m_DIBptr, m_Size.cX * m_Size.cY * 4&, 0
    AlphaImgCtl1.PaintImageAsDrawnToHDC m_hDC, 0, 0
    Call pvUpdateWindow
End Sub

Private Sub Form_DblClick()
    Unload Me
End Sub

Private Sub Form_Load()
   
    m_MousePoints.X = -1&
    m_Opacity = 255
    m_Size.cX = ScaleX(AlphaImgCtl1.Width, Me.ScaleMode, vbPixels)
    m_Size.cY = ScaleY(AlphaImgCtl1.Height, Me.ScaleMode, vbPixels)
    If pvCreateLWdc = False Then
        Stop
        ' error couldn't create a basic DC & bitmap
    End If
    Me.Move Me.Left, Me.Top, ScaleX(AlphaImgCtl1.Width, Me.ScaleMode, vbTwips), ScaleY(AlphaImgCtl1.Height, Me.ScaleMode, vbTwips)
    AlphaImgCtl1.PaintImageAsDrawnToHDC m_hDC, 0, 0
    SetWindowLong Me.hWnd, GWL_EXSTYLE, GetWindowLong(Me.hWnd, GWL_EXSTYLE) Or WS_EX_LAYERED
    Call pvUpdateWindow
    Show
    DoEvents
    AlphaImgCtl1.Animate2.StartAnimation
    
End Sub

Private Sub pvUpdateWindow()
    Dim srcPt As POINTAPI
    Dim lBlendFunc As Long
    lBlendFunc = AC_SRC_OVER Or (m_Opacity * &H10000) Or (AC_SRC_ALPHA * &H1000000)
    UpdateLayeredWindow Me.hWnd, 0&, ByVal 0&, m_Size, m_hDC, srcPt, 0&, lBlendFunc, ULW_ALPHA
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton And m_MousePoints.X > -1& Then
        If m_MousePoints.X <> X And m_MousePoints.Y <> Y Then
            ReleaseCapture
            m_MousePoints.X = -1
            SendMessage Me.hWnd, WM_NCLBUTTONDOWN, HTCAPTION, ByVal 0&
        End If
    End If
End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        m_MousePoints.X = X
        m_MousePoints.Y = Y
    End If
End Sub

Private Function pvCreateLWdc() As Boolean
    Dim bhi As BITMAPINFOHEADER
    Dim tDC As Long
    With bhi
        .biBitCount = 32
        .biHeight = -m_Size.cY
        .biWidth = m_Size.cX
        .biPlanes = 1
        .biSize = Len(bhi)
    End With
    tDC = GetDC(0)
    m_hDC = CreateCompatibleDC(tDC)
    ReleaseDC 0, tDC
    m_hBmp = CreateDIBSection(m_hDC, bhi, 0&, m_DIBptr, 0&, 0&)
    If m_hBmp <> 0 Then
        m_hBmp = SelectObject(m_hDC, m_hBmp)
        pvCreateLWdc = True
    Else
        DeleteDC m_hDC: m_hDC = 0&
    End If
End Function

Private Sub Form_Unload(Cancel As Integer)
    If m_hBmp <> 0 Then
        DeleteObject SelectObject(m_hDC, m_hBmp)
        DeleteDC m_hDC
    End If
End Sub
```

Now the AIC wasn't designed for this. There is a waste of CPU cycles going on as the control is actually drawing on the form, but you can't see that. But the AIC does send us a message to let us know that animation frame changed & we can have the AIC paint to our memory DC. All is good, though double painting is going on. My CPU hardly noticed the animated form, larger the image, may be noticed a bit more? Have fun

Edited: If you have any question regarding the posted code, ask.

I think you may have given me a reason to add similar functionality in the new version of this control, if I ever get it done. A way to link the AIC to user-defined DC and do all the painting directly to that DC vs the AIC's DC (which is really its container's DC)

The screenshot shown below is a  single frame from a 20 frame animation. The form (goldfish) is 100% opaque and you can clearly see the alphablending through its fins. The source image is a PNG with various levels of translucency.

----------


## schmurtz

Hi,

Is there a way to use Drag & Drop on AIC without loading the file drooped ?
I would like to check if my drooped file have the right dimensions (and some other things) before loading it in AIC (and optionally not loading it if the dimensions is not correct)

Thank you !

----------


## VbNetMatrix

> Hi at all,
> i found this control a fiew days ago, and it is a great one.
> I tested it a fiew times, and i understand the most features.
> My question is, is it possible to shape a form with this control? I have nothin found about it, and no idea to do this.
> 
> Sorry about my bad english! :-)


Not sure why some have replied NO instantly, but it is indeed possible because I did it on one of my program but you need to use setwindowsLong also

just use a transparent PNG, the PNG must NOT be an ALPHA transparency but a color transparency (like gif)  You can achieve the result using the same color (let's say pure red, 255,0,0)  IrfanView (free) can convert the png to the proper transparency for you

the non transparent part would be the part you want to shape your form.  then you apply setwindowslong and set the "red" color to be transparent.
I used the same principle on one of my comercial program.

The lavolpe control is not per say required though, but using it allow you to shape your form as a "skin"
wich is way easier then using the exemple for  "oval shape form"

----------


## VbNetMatrix

Hi Lavolpe, not sure why I never received a post that someone replied here...  but I wanted to tell you again a big thanks for your control and wish you could continue developing thoses great product.  I live my life supporting old Vb6 app for big organisation and your control saved me many time.  I know I proposed it in past but what about a donation page for your control ?  I could design it for you if you want.  You deserve it.

----------


## LaVolpe

> Hi,
> 
> Is there a way to use Drag & Drop on AIC without loading the file drooped ?
> 
> Thank you !


Yes, of course  :Smilie: 
Read the comments in the UserControl_OLEDragDrop event. If you have more questions, just ask.

----------


## LaVolpe

> ... wish you could continue developing thoses great product.


I will put out one more version of this control which will likely lead to minor revisions down the road. Off and on this year, I've been researching and testing lots of ideas. The new version which I hope to put up in a month or two will NOT be compatible with this version now.  Some stuff will be removed and no longer supported, but the new version will add some new options and capabilities. Some major differences between this version & what will be coming...

1) DPI awareness, to include per-monitor DPI-awareness  and embedded DPI within the image format
:: an option to have icon selection dependent on DPI changes will also be included (assuming icon contains multiple sizes)

2) ICM (Image Color Management) for both source & destination

3) Removing most UDT/TYPE declarations in the Global class and replacing them with Classes instead. This allows me more flexibility

4) Internally, the class will render via a GDI+ matrix. User's won't notice anything new, but it helps simplify complex hit testing for shaped controls & also simplifies determining partial painting as needed

5) Users will have more options to be involved in the rendering process: background painting, before image renders, rendering the image, after image renders & borders

I wanted to address processing of animated frames by using background threads. Haven't found a stable solution that allows me to use GDI+ in multiple threads. This won't be included in the next version, but something I haven't given up on yet. Animation setup is a complete re-write for the control & will dramatically speed up initial load & display of 1st frame, but additional frames will be delay loaded. This will be an option: use the newer or older process.

One of the larger options (code-wise) that will disappear is ability to download images from the web directly to the control. I am removing the responsibility from the AIC. User's will need to download their own images & pass the downloaded file or binary data to the control for loading.

----------


## Bonnie West

> Not sure why some have replied NO instantly, but it is indeed possible ...


My interpretation of Frido's somewhat unclear question was that he was asking whether the AIC has _built-in_ methods that can give a Form an arbitrary shape or not. At that time, the AIC didn't yet have such an ability (I haven't checked yet if it does now). However, as you have pointed out, the solution is quite easy and it is independent of LaVolpe's AIC.

----------


## VbNetMatrix

That will be awesome...  Thanks Lavolpe.  I'm glad to know you're back on it  :Smilie:   but as a programist myself, I know time is not something we control  :Frown: 
but rest assure your new control will be waited for until it come!

thanks again!

----------


## VbNetMatrix

> My interpretation of Frido's somewhat unclear question was that he was asking whether the AIC has _built-in_ methods that can give a Form an arbitrary shape or not. At that time, the AIC didn't yet have such an ability (I haven't checked yet if it does now). However, as you have pointed out, the solution is quite easy and it is independent of LaVolpe's AIC.


yes independant to Lavolpe Control, but much more easier to use with Lavolpe.  Instead of using code like "oval form" like you pointed out, wich is very hard because you have to build the matrix of each point making the outside of your form, you just have to "draw" a png containing the form you want.  Then you make a bordeless form, apply Lavolpe AIC containing your PNG (same size as form you want) then the outside of form just disapear using SetWindowsLong...

wich is kind of pretty cool to make skin.  More to that you could even make a program with skin that could be changed/design by user of the program wich would not be possible without AIC control

----------


## Bonnie West

> yes independant to Lavolpe Control, but much more easier to use with Lavolpe.  Instead of using code like "oval form" like you pointed out, wich is very hard because you have to build the matrix of each point making the outside of your form, you just have to "draw" a png containing the form you want.  Then you make a bordeless form, apply Lavolpe AIC containing your PNG (same size as form you want) then the outside of form just disapear using SetWindowsLong...
> 
> wich is kind of pretty cool to make skin.  More to that you could even make a program with skin that could be changed/design by user of the program wich would not be possible without AIC control


Or, for a more lightweight option, you could just render the PNG image directly on the Form using either GDI+, WIA v2.0 or other methods.  :Wink:

----------


## LaVolpe

> Or, for a more lightweight option, you could just render the PNG image directly on the Form using either GDI+, WIA v2.0 or other methods.


Fully concur. Using a ton of code wrapped in some AcitveX control or ActiveX DLL just because it is easy, is not a substitute for understanding what the specific task needs and supplying your own couple dozen lines of code instead.  Using GDI+, loading and rendering a PNG on a VB hDC is just a handful of declarations & a few lines of code

----------


## VbNetMatrix

> Fully concur. Using a ton of code wrapped in some AcitveX control or ActiveX DLL just because it is easy, is not a substitute for understanding what the specific task needs and supplying your own couple dozen lines of code instead.  Using GDI+, loading and rendering a PNG on a VB hDC is just a handful of declarations & a few lines of code


No offense intended, but my speciality is database, your speciality (in this case) is Graphics.  for you, playing with GDI+ is easy.  for me, it's simpler using your component to apply the graphics.  for other users like me who doesn't play much with GDI, your component will remain a source to save time (and money) instead of having to debug our own code in a speciality we don't have (GDI)  Your component is the best  :Smilie:

----------


## LaVolpe

No offense taken and no offense meant by my posting. For example, one can install this image control or Olaf's vbRichClient to render a PNG to a form. But it is overkill if that is the *only* purpose for using those ActiveX objects. How simple is it to draw a PNG onto a form? Very little research would be needed. GDI+ has been out and about for a long time now and exists on every O/S since XP. Here's 8 API calls needed for such a minor task:

GdiplusStartup: starts GDI+ 
GdipLoadImageFromFile: loads the PNG 
GdipCreateFromHDC: use your form's hDC
GdipGetImageBounds: get size of PNG
GdipDrawImageRectRectI: draw/scale PNG to your form size
GdipDeleteGraphics: clean up
GdipDisposeImage: clean up
GdiplusShutdown: stop GDI+




> ... Your component is the best


Thank you. I have been a bit disappointed that other VBers out there have not created more replacements for the VB image and picturebox controls to support alpha-blended image formats. Rendering these are simple enough, but rendering is not the same as a userccontrol that can be used in design-time and used by those with little graphics experience

----------


## VbNetMatrix

> No offense taken


Glad to hear, I know in past my choose of wording might not be the most appropriated and could lead to confusion and I'm sorry for that




> Thank you. I have been a bit disappointed that other VBers out there have not created more replacements for the VB image and picturebox controls to support alpha-blended image formats. Rendering these are simple enough, but rendering is not the same as a userccontrol that can be used in design-time and used by those with little graphics experience


If I had time, I would follow your step and put my own work online in Database ADO replacement for Vb6.  My component is so much simpler to use then the one provided by Vb6 .  You really inspired me in many way.

I wanted to ask you a question...  Would it be possible to make the new component "wise" compiling to avoid including format 
that we don'T use ?  for myself, I'm using JPG and PNG, I would prefer to have a component with only thoses capability...
GIF and most other component (RLE) and compagny are subject to die in a few years. (in my opinion)

it would probably be too much trouble to strip the component like that...  but it would remove some overload on the rendering (? checking format all the time) part and could probably be much more efficient in term of speed.  Could be used in "small" animation game.

what you think ?

----------


## VbNetMatrix

> GdiplusStartup: starts GDI+ 
> GdipLoadImageFromFile: loads the PNG 
> GdipCreateFromHDC: use your form's hDC
> GdipGetImageBounds: get size of PNG
> GdipDrawImageRectRectI: draw/scale PNG to your form size
> GdipDeleteGraphics: clean up
> GdipDisposeImage: clean up
> GdiplusShutdown: stop GDI+


I'll check that out as soon I got time
thanks alot for your help

----------


## LaVolpe

> I wanted to ask you a question...  Would it be possible to make the new component "wise" compiling to avoid including format 
> that we don'T use ?  for myself, I'm using JPG and PNG, I would prefer to have a component with only thoses capability...
> 
> what you think ?


I actually considered that because I felt same as you that some may want to use the control just for image formats not supported by VB.  I may offer the ability and explain to users how to activate it, but undecided which method to use. As is, the control supports images contained in these file formats: bmp, jpg, gif, wmf, emf, ico, cur, animated ico/cur, tif, png, apng, tga, pcx, pnm, pam, avi, mp3/wma and contained in binaries like DLLs, exes, ocxs. Any other format is indirectly supported by supplying the control a byte array of the image in RGB format. 

1) Format-specific properties, constants, enumerations, functions & even classes would be surrounded by conditional IF statements, i.e., #IF IncludeWMF  Then ... #End If. A list of  those _Include###_ variables would exist in the project's properties window and would be required to be updated by the user before the control was compiled. Once compiled, any unsupported code would be excluded during compiling. Internally bmp format would always be supported

2) Use outside DLLs, i.e., EncoderPNGsupport.DLL, EncoderTGAsupport.DLL, etc. This would be like using add-ins for the control. During design-time and runtime, if the DLLs existed, then the control would include those formats else it would not. Maybe the DLLs would be attached to the image control during design/runtime via a property. I would create the DLLs and they would be included with the image control source code.

3) I also considered a LITE version of the control that only handled VB image formats + PNG + TIFF.

This topic is still under consideration and if offered, I'd likely go with option #1 or #3. Haven't made up my mind.




> it would probably be too much trouble to strip the component like that... but it would remove some overload on the rendering (? checking format all the time) part and could probably be much more efficient in term of speed. Could be used in "small" animation game.


Supporting formats does not produce any real additional overhead. Once an image is loaded, it exists in bmp format internally, either directly by my logic or indirectly via GDI+. The image load logic I'm using in the new version checks just 8 bytes of the image data to determine the format. Even if the format cannot be 100% decided based on just those 8 bytes, at most the logic requires just two load attempts to positively confirm the format. Rendering speed is not dependent on format, with exception of animation. The current animation routines in the control can be sped up by pre-building the frames vs. building each on demand & that is new to the future control

The only true advantage of excluding sections of code relevant to formats that you do not need to be supported would be making the control file size smaller. Each format is a separate class within the control. If the format is not loaded into the control, then the class is not loaded.

----------


## VbNetMatrix

> 3) I also considered a LITE version of the control that only handled VB image formats + PNG + TIFF.
> This topic is still under consideration and if offered, I'd likely go with option #1 or #3. Haven't made up my mind.


 :Big Grin: 
a lite version !!!!  ohhhhh!  :Smilie: 
would be nice...  but would require to double the work... each time you fix a bug, you'll have to fix it in twice component... sadly.

btw, can you enlight me on something...  what the TIFF format has over png ?  I know TIFF is more "raw" and doesn't compress much. but since PNG doesn't degrade...  can't see the advantage of TIFF over png.

----------


## LaVolpe

Double the work? Nah, enough forethought & then the same control can be converted to a LITE version with conditional compilation arguments.

TIFF allows multiple pages (maybe biggest advantage). TIFF also allows other color spaces like CMYK and far more metadata  tags. TIFF can compress using more than 1 technique: LZW, JPEG, CCIT among others.  TIFF doesn't degrade either unless compressing using JPEG-style compression.

----------


## georgekar

Lavolpe have you ever check if gdiplus run without hangs in windows 64 bit; Because I had to through the jpg export after found that when more than one exe use gdi plus one of them hang on exit, some times more than one.

----------


## LaVolpe

> Lavolpe have you ever check if gdiplus run without hangs in windows 64 bit; Because I had to through the jpg export after found that when more than one exe use gdi plus one of them hang on exit, some times more than one.


Nope, never seen an issue. VB runs in a 32 bit process. Any issues are likely the result of improper start/stopping of GDI+? I personally never load GDI+ more than once in a process.

*Note*: GDI+ uses hooking. When you start up GDI+, it creates a top-level window in another thread attached to your process. If you do not close down GDI+ while in the IDE, i.e., END statement encountered, hitting the STOP button, etc, then whatever event you stop GDI+ in will not be called. This can produce a crash, not immediately, but likely to happen. So, the tip here, is just like subclassing/hooking for anything else, only close your project normally when using GDI+ in the IDE.

Other crash-related issues could be due to improper usage: creating a graphics object and using GDI operations on the DC that the graphics object is attached to. Not deleting GDI+ objects you created, create an image from file/array and somehow delete that source before the image is destroyed, and other possible reasons.

----------


## georgekar

I don't have problem in IDE.  I had prepared a revision with per exe startup and shutdown, no per command in M2000, nothing change. Same problem. When I remove gdiplus and replace the routine to save jpg with a vb class...no problem.,All test run perfect.Check it with this scenario...One exe call 10 other exe end each one first run a delay and then save a picture in a jpg file with the help of gdiplus. So check if all programs ends properly. You can check task manager and temporary folder for that.

----------


## LaVolpe

Don't know what to tell you, other  than I think you are doing something incorrectly. If you are starting 10 different applications, each application is running in its own process and each GDI+ startup is attached to that unique process. Good luck troubleshooting it.

----------


## georgekar

So you say that in windows 8 and up, at 64 bit you never see a problem in a vb exe when exit...Do you ever check temporary folder to see if your application remove temporary files?

----------


## LaVolpe

> So you say that in windows 8 and up, at 64 bit you never see a problem in a vb exe when exit...Do you ever check temporary folder to see if your application remove temporary files?


I don't have Win8 or higher. I have never had anyone report an issue like yours for anything I've created that uses GDI+. I do know that no matter what, if VB is terminated incorrectly (crashes for example), temp files are not removed. If they are not removed under normal use and closure, I haven't a clue.

----------


## georgekar

The point is that vb not crash, but not closed either. This in not happen every time, that is the mystery. So with my example with 10 exe that runs all together we get some of them "not responsed". I put msgboxes to check where are problem and i found that problem was after all objects closed. I believe that is a problem in GDI+. 
You said that you never use Win8. So I never else I use windows 8 but after a look at Windows 10 64bit I found relative problem, so in my home computer I do an installation of a Win 8 os in Virtual box (I can't install Windows 10..) and start to check the temp file and task manager. If I didn't do that then a I said all is ok...because vb program indeed close the UI, but not the connetion with GDI+ . And I try with one token only. Not always happen and that is very bad...Because we have to replicate the problem to solve.

----------


## LaVolpe

I still doubt GDI+ has anything to do with it. As far as I know GDI+ does not hold a reference to anything in a VB project. VB will shut down when all running code has terminated and all objects are unloaded (circular references are almost always a culprit).  GDI+ is not an object. This may be appropriate to post in the VB discussion forums if you'd like others to help troubleshoot and brainstorm.

----------


## VbNetMatrix

georgekar, can you be more specific with the temp file not erased ?

because VB6 IDE always had that habit of not erasing temp file, it is a bug per say but MS never fixed it, it doesn't crash anything... they just forget to make a delete temp file on exist IDE.

btw, on my side, never had any GDI+ problem on Win8, I made a commercial product wich is run on hundred of computer, nobody reported any problem or suspicious crash. can you be more specific about the problem ?  maybe I can help you  troubleshoot.  Is it a EXE problem or a IDE problem, can you make a "small" sample that reproduce the problem even intermitently ?  If it's  a IDE problem, are you sure you installed Vb6 properly, on Win8 there is some precaution to do to install Vb6, it is more easier on Win7...  just realize this might not be the right thread for this but I'm open to more detail if you need help

----------


## LaVolpe

> ...  just realize this might not be the right thread for this but I'm open to more detail if you need help


Good call. If posting a project for troubleshooting, do it in the VB forums, not on this thread. Thank you

----------


## ricardovpm

Lavolpe am a great admirer of his work now use your LaVolpeAlphaImg2 control.
How do I select a region on the control to cut and save.
Thank you and sorry for my English "google"

----------


## LaVolpe

Ricardo, please post an image of what you are trying to do. Please show me what the result would look like before and after the image would be saved.

----------


## ricardovpm



----------


## ricardovpm

From an image I can rotate and give the zoom and then select a region and only saved the region using the same resolution

Thank you

----------


## LaVolpe

Here's a quick and easy way to do what I think you are asking for.

1) Add a picturebox to your form. Set these properties: Visible=False, BorderStyle=0, ScaleMode=Pixels
You can place the picturebox anywhere you want, out of the way. You may want to make it visible until you are satisfied that what is being captured is correct, then make it invisible forever.

2) Draw the image to the picturebox USING THE SAME scale, zoom, angle, etc that you were using in your screenshot... I'll call that picturebox PicCanvas


```
Dim X as Long, Y as long, Cx as Long, Cy As Long
Dim tPic As stdPicture
X = ? ' << set this to your selection rectangle's left edge (in pixels)
Y = ? ' << set this to your selection rectangle's top edge (in pixels)
Cx = ? ' << set this to your selection rectangle's width (in pixels)
Cy = ? ' << set this to your selection rectangle's height (in pixels)

With PicCanvas
    .AutoRedraw = False
    .Move .Left, .Top, [alphaimage control width], [alphaimage control height]
       ' ^^ The picbox must be exactly the same size as the alphaimage control
    .AutoRedraw = True
    ' draw the image exactly the same way you drew it to the alpha image control...
    AlphaImage1.Picture.Render .hDc, [fill in the parameters]
    Set tPic = .Image
    .Cls
    .PaintPicture tPic, 0, 0, Cx, Cy, X, Y, Cx, Cy
    Set tPic = Nothing
    .Move .Left, .Top, ScaleX(Cx, vbPixels, Me.ScaleMode), ScaleY(Cy, vbPixels, Me.ScaleMode)
End With
```

Now you can see the result. May have to add this line for testing: PicCanvas.Refresh

If you are satisfied with the result, you can use VB's SavePicture command to save the .Image property of PicCanvas

*Edited*: I had some problems with VB PaintPicture if the selection rectangle overlapped the target area on the same picturebox. I've updated the code above to fix that problem (blue text)

----------


## ricardovpm



----------


## ricardovpm

Where am I going wrong?
Lavolpe Thank you for now

----------


## LaVolpe

Screenshot of your source code is not readable. Please paste it in a reply. Then add [code] [/code] around the code so it is easily read here.

----------


## ricardovpm

sorry



```
Dim X As Long, Y As Long, Cx As Long, Cy As Long
Dim tPic As StdPicture
Me.ScaleMode = vbPixels
AlphaImgCtl1.SetRedraw = False
AlphaImgCtl1.WantPrePostEvents = True
AlphaImgCtl1.SetRedraw = True

X = Shape1.Left
Y = Shape1.Top
Cx = Shape1.Width
Cy = Shape1.Height

zoomOffset = pnZoom.Tag / 100
With PicCanvas
   .AutoRedraw = False
   .Move .Left, .Top, AlphaImgCtl1.Width, AlphaImgCtl1.Height
   .AutoRedraw = True
   AlphaImgCtl1.Picture.Render hDC, (AlphaImgCtl1.Width - (AlphaImgCtl1.Width * zoomOffset)) \ 2 + AlphaImgCtl1.XOffset * zoomOffset, _
      (AlphaImgCtl1.Height - (AlphaImgCtl1.Height * zoomOffset)) \ 2 + AlphaImgCtl1.YOffset * zoomOffset, _
      AlphaImgCtl1.Width * zoomOffset, AlphaImgCtl1.Height * zoomOffset, , , , , AlphaImgCtl1.Rotation, _
      AlphaImgCtl1.Effects.AttributesHandle, , AlphaImgCtl1.Effects.EffectsHandle(AlphaImgCtl1.Effect)
   
   Set tPic = .Image
   .Cls
   .PaintPicture tPic, 0, 0, Cx, Cy, X, Y, Cx, Cy
   Set tPic = Nothing
   .Move .Left, .Top, ScaleX(Cx, vbPixels, Me.ScaleMode), ScaleY(Cy, vbPixels, Me.ScaleMode)
End With
```

----------


## LaVolpe

Part of the problem is the Render call.  You are using the control's dimensions when you should be using the control's Picture.Width,Height. Below I've changed the code a bit to use With, End With so you can see where you should be using the properties of the image and the properties of the control.


```
With AlphaImgCtl1.Picture
    .Render hDC, (.Width - (.Width * zoomOffset)) \ 2 + AlphaImgCtl1.XOffset * zoomOffset, _
      (.Height - (.Height * zoomOffset)) \ 2 + AlphaImgCtl1.YOffset * zoomOffset, _
      .Width * zoomOffset, .Height * zoomOffset, , , , , AlphaImgCtl1.Rotation, _
      AlphaImgCtl1.Effects.AttributesHandle, , AlphaImgCtl1.Effects.EffectsHandle(AlphaImgCtl1.Effect)
End With
```

See if that is better.  If not, please post back with a snapshot so we can start fresh.

----------


## Jonney

> Part of the problem is the Render call.  You are using the control's dimensions when you should be using the control's Picture.Width,Height. Below I've changed the code a bit to use With, End With so you can see where you should be using the properties of the image and the properties of the control.
> 
> 
> ```
> With AlphaImgCtl1.Picture
>     .Render hDC, (.Width - (.Width * zoomOffset)) \ 2 + AlphaImgCtl1.XOffset * zoomOffset, _
>       (.Height - (.Height * zoomOffset)) \ 2 + AlphaImgCtl1.YOffset * zoomOffset, _
>       .Width * zoomOffset, .Height * zoomOffset, , , , , AlphaImgCtl1.Rotation, _
>       AlphaImgCtl1.Effects.AttributesHandle, , AlphaImgCtl1.Effects.EffectsHandle(AlphaImgCtl1.Effect)
> ...


As I said previously, users need not only picture presentation but also picture Editor. you have to work harder to write a editor so that you won't leave your Graphic knowledge in dust.  :big yellow:  :big yellow:  :big yellow:

----------


## LaVolpe

Jonney, suggesting I write an editor? Sorry buddy, not interested. Plenty of them about but not enough alpha-supported image controls exist for VB which is why I developed this one and why I'll put out one more rewrite this year & that will likely be the last major revision. I'll support it for awhile, and may even enhance it from time to time. But an image editor won't be coming from me.

----------


## ricardovpm

Lavolpe, thank you for the help you have given me, I hope anxious for the new version of its control.

With the new code you posted improved a lot so I want to do, now just need return only the region that I selected, see the new print.

----------


## LaVolpe

The following is your previous code, just modified slightly to ensure scalmodes match


```
Dim x As Long, y As Long, Cx As Long, Cy As Long
Dim zoomOffset As Double, tPic As StdPicture

x = Shape1.Left + Me.DrawWidth - AlphaImgCtl1.Left ' get area inside the shape
y = Shape1.Top + Me.DrawWidth - AlphaImgCtl1.Top
Cx = Shape1.Width - Me.DrawWidth * 2
Cy = Shape1.Height - Me.DrawWidth * 2

zoomOffset = pnZoom.Tag / 100
With picCanvas
    .ScaleMode = Shape1.Container.ScaleMode
   .AutoRedraw = False
   .Move .Left, .Top, AlphaImgCtl1.Width, AlphaImgCtl1.Height
   .AutoRedraw = True
    With AlphaImgCtl1.Picture
        .Render picCanvas.hdc, (.Width - (.Width * zoomOffset)) \ 2 + AlphaImgCtl1.XOffset * zoomOffset, _
          (.Height - (.Height * zoomOffset)) \ 2 + AlphaImgCtl1.YOffset * zoomOffset, _
          .Width * zoomOffset, .Height * zoomOffset, , , , , AlphaImgCtl1.Rotation, _
          AlphaImgCtl1.Effects.AttributesHandle, , AlphaImgCtl1.Effects.EffectsHandle(AlphaImgCtl1.Effect)
    End With
   Set tPic = .Image
   .Cls
   .PaintPicture tPic, 0, 0, Cx, Cy, x, y, Cx, Cy
   Set tPic = Nothing
   .Move .Left, .Top, ScaleX(Cx, .ScaleMode, .Container.ScaleMode), ScaleY(Cy, .ScaleMode, .Container.ScaleMode)
End With
```

It is important that the same Render parameters for the alpha image control is used above that you used in the control's PrePaint event. So if you are also adjusting the X,Y coordinates when rendering to the control, you need to adjust them in the code above too.

Edited: Ensure the scalemode that picCanvas is using is the same scalemode that Shape1's container is using. I added code for that, but any tweaks you need to make are likely due to mismatching scale modes.

----------


## ricardovpm

We're almost there, note that the first image using the properties
(Aspect = 0 and AutoSize = 1) works great.


But in the second image (which I will use) with the properties
(Aspect = 4 and AutoSize = 1) the area is wrong, you can cut using these properties?



thank you

----------


## LaVolpe

Appears the image with Aspect=4 is not being rendered as zoomed. If it was, your clipped selection would probably be right.

----------


## ricardovpm

Lavolpe, excuse my insistence, but it's because I have to deliver a job and all that's missing it in my project.
I am enclosing part of the project for you to analyze and see if you can'm WHAT wanting.
Thanks again for the help
LaVolpe.zip

----------


## LaVolpe

Sorry. I have a thing, call it quirky, helping others make money off of my code.  I've given you lots of help. I trust you can spend the time to troubleshoot that last issue.

----------


## ricardovpm

Sorry, but I have expressed myself wrong when he said "work" was referencing "school work", do not know what the term used in your language, and if you can help me I will be very grateful, including its control along with the link of this forumIt is attached as a reference in my "school work".
But still I am very grateful with all your help so far and I take once again to congratulate his wisdom.
Ricardo Vieira Pulo (17 years - eighth computer technology class)
(São Paulo Brazil)
translation - google

----------


## LaVolpe

I tried to explain this at least two times. If you want the correct result, your Render parameters must be the same in both the PrePaint and CmdCut events.  They are not the same. If you fix that, maybe your problem can be resolved.

P.S. I could not load your project, could only look at the code. I do not have your version of the alpha image control, nor do I have the threed ocx. No biggie. I think your problem is related to the different rendering calls; thereby producing different results.

----------


## VbNetMatrix

> Sorry. I have a thing, call it quirky, helping others make money off of my code.  I've given you lots of help. I trust you can spend the time to troubleshoot that last issue.


about that...  I always wondered why you don't have a "donation" button.  I know I offered it to you in past but I would be very honored to offer you a web page host.  All you have to do buy the domain (about 10$ per year) and I would web host your domain and you would have full control over the web page.  I really apreciate your control, it's the least I could do.  I would be glad to "donate" myself to you.

----------


## ricardovpm

After selecting the region and show the PicCanvas, saving the piccanvas?

----------


## LaVolpe

VB's SavePicture function will save the picCanvas.Image to a bitmap

----------


## zeilo

Hi, firstly thank you for your amazing code.

I am facing a issue when printing an image.
The code uses the same routines to draw either in the screen or in printer.
It uses the vb scale methods of own each object (picturebox or printer) to define de position given in millimeters.
However the render method of AIC just prints near the right position when I use the same coordinates used in the picturebox and add a magical offset (27 pixels horizontal and 43 pixels vertical)
More over the image was trimmed in the rendering.
The image was loaded from a byte array read from a data base field.



```
        Set myImg = New GDIpImage
        myImg.KeepOriginalFormat = False
        Set myImg = LoadPictureGDIplus(myField.GetChunk(0, myField.FieldSize), False)
        Set myEffects = New GDIpEffects
        myEffects.TransparentColorUsed = True
        myEffects.TransparentColor = GetPixelGDIplus(myImg, 0, 0)

        'Expected to work
        'With IIf(mbPrinting, Printer, myPicBox)
        'myImg.Render .hDC, _
                             .ScaleX(mnLinAssPosX + mnMargemEsq, vbMillimeters, vbPixels) + .ScaleX(mnRTAssImgOffSetX, vbTwips, vbPixels) - myImg.Width / 2, _                                                                 
                             .ScaleY(mnLinAssPosY + mnMargemSup, vbMillimeters, vbPixels) + .ScaleY(mnRTAssImgOffSetY, vbTwips, vbPixels) - myImg.Height / 2, _
                             , , , , , , , myEffects.AttributesHandle, , myEffects.EffectsHandle(lvicNoEffects), lvicHighQualityBicubic
        'End with

        'Atcual work
        myImg.Render IIf(mbPrinting, Printer.hDC, myPicBox.hDC), _
                             myPicBox.ScaleX(mnLinAssPosX + mnMargemEsq, vbMillimeters, vbPixels) + myPicBox.ScaleX(mnRTAssImgOffSetX, vbTwips, vbPixels) + IIf(mbPrinting, 27, 0) - myImg.Width / 2, _                                                                 
                             myPicBox.ScaleY(mnLinAssPosY + mnMargemSup, vbMillimeters, vbPixels) + myPicBox.ScaleY(mnRTAssImgOffSetY, vbTwips, vbPixels) + IIf(mbPrinting, 43, 0) - myImg.Height / 2, _
                             , , , , , , , myEffects.AttributesHandle, , myEffects.EffectsHandle(lvicNoEffects), lvicHighQualityBicubic
```

Original image:  
Results
Picture box:
Printer: 

Have you ever dealt with such issue?

Thanks in advance.

Best regards.

----------


## LaVolpe

Looking at your screenshot. The picturebox rendering is correct? Obviously  the Printer version is not. It appears the printer may be slightly scaling the rendering. I say that because 1-pixel edges when scaled can be lost or thinned out when scaling. Though you are not scaling the rendering, just assigning the X,Y printer coordinates.

I assume the printer's scalemode is pixels. You may want to check the results of your X,Y calculations and see if rounding may be an issue. Don't know if it will help or fix the problem, but try passing whole number vs fractions, i.e.,

CLng(myPicBox.ScaleX(mnLinAssPosX + mnMargemEsq, ... )
CLng(myPicBox.ScaleY(mnLinAssPosY + mnMargemSup, ... )

----------


## zeilo

I created a simple project to find out the causes and I found one of them.

The effects to make the color transparent is responsible for trimming the image.



```
    Dim oGDIImg As LaVolpeAlphaImg.GDIpImage
    Dim oGDIEffects As LaVolpeAlphaImg.GDIpEffects
    
    Set oGDIImg = LaVolpeAlphaImg.LoadPictureGDIplus("C:\myImg.png")
    Set oGDIEffects = New LaVolpeAlphaImg.GDIpEffects
    oGDIEffects.TransparentColor = LaVolpeAlphaImg.AICGlobals.GetPixelGDIplus(oGDIImg, 0, 0)
    oGDIEffects.TransparentColorUsed = True
    
    Printer.CurrentX = 0
    Printer.CurrentY = 0
    Printer.Font.Name = "Times New Roman"
    Printer.Font.Size = 28
    Printer.Print "Just a small block of"
    Printer.Print "text to show that the"
    Printer.Print "image is printed with"
    Printer.Print "true transparency and"
    Printer.Print "not simply with a white"
    Printer.Print "background."
    'LaVolpeAlphaImg.PaintPictureGDIplus oGDIImg, Printer.hDC
    With Printer
        .ScaleMode = vbPixels
        'oGDIImg.Render .hDC, (.ScaleWidth - oGDIImg.Width) \ 2, (.ScaleHeight - oGDIImg.Height) \ 2, , , , , , , , oGDIEffects.AttributesHandle, , oGDIEffects.EffectsHandle(lvicNoEffects), lvicHighQualityBicubic
        oGDIImg.Render .hDC, , , , , , , , , , , , , lvicHighQualityBicubic
        oGDIImg.Render .hDC, oGDIImg.Width, oGDIImg.Height, , , , , , , , oGDIEffects.AttributesHandle, , oGDIEffects.EffectsHandle(lvicNoEffects), lvicHighQualityBicubic
        .EndDoc
    End With
```

Printer (PDFCreator) Result: 

Do you have any suggestion to workaround with image loss with the transparent effect?

I am still working to find out the reason about position issue using the same scale of the picture instead of printer dimensions.

Thank you very much for your fast response.

Best regards

----------


## zeilo

Finally I found a workaround for the printing issue.
To avoid that trimming of image happens, I created a picturebox 2 pixels wider (in both dimensions horizontal e vertical) than the image, then rendered the transparent GDIpImage with an offset of 1px and after i rendered in the printer DC.
On regards to position problem, I figured out that there is a difference between screen and printer. Coordinates in pixels used for the printer have to be increased in 4% to be correctly positioned. I still do not know the reason, but now is printing very fine.

----------


## aliman

Hello LaVolpe.
I didn't really understand the reason behind the size limitation to screen size when the selection of the *Aspect* is something other than _lvicActualSize_. Can you give some details?

----------


## LaVolpe

Don't have a great reason, but I'll give it to you.  You cannot physically view more than the screen size. Very large images require large amounts of  memory. 

The control was not written with the idea that it could be used as a view port. There are limitations on the size of any image backed by a DIB or bitmap. Those limitations are not public from Microsoft as far as I know, but to avoid potential errors I simply took the easy way out, expecting this to a be a problem for a very small percentage of typical users.

In my rewrite of this control (still not close to publishing it yet), this is one topic I still haven't found a great solution for. I personally don't like the limitation. I am close to finalizing a solution that won't be perfect but would remove the limitation. The solution is basically to use GDI+ (which has its own methods of handling large images) and rendering on demand the viewable portion of the image. This solution could negate AutoRedraw for very large images because of the DIB size limitation imposed by Windows. I would expect rendering to be significantly slower in these cases, especially if AutoRedraw is not applicable and/or image appearance is changed during rendering: scaling, rotation, mirroring, gray scaling, etc. Very large images may not be able to be saved, without scaling, to other image formats where the format itself restricts max dimensions. All being said, if GDI+ balks at loading very large images, all bets are off.

In any case, I do always foresee a max data size of 2 GB as a permanent limitation.

----------


## zeilo

Hello LaVolpe.

I am facing the following problem: in IDE (debug-time) I can load a picture to an Alpha Image Control from the picture property of a Standard Image Control, however when is in run-time (compiled) the error 481 - Invalid Picture is raised.



```
Set AlphaImgCtl1.Picture = LaVolpeAlphaImg.AICGlobals.LoadPictureGDIplus(Image1.Picture)
```

_---------------------------
Project1
---------------------------
Run-time error '481':

Invalid picture
---------------------------
OK   
---------------------------_

Could you help me to solve this?
Thank you very much.

----------


## LaVolpe

I'll take a look, but not likely in the next day or two. I am always interested in errors and bug reports.

In the mean-time, try passing the handle: Image1.Picture.Handle

Edited. A quick look, I was able to replicate the problem twice in a row. Then problem went away without doing a thing. I think I have it narrowed down, but will have to perform more tests. If I do figure it out (and I will), you will have to make the change to your copy of the control & recompile it. If this is the only issue and if passing only picture objects that contain bitmaps or jpegs, would recommend passing by handle vs the picture object. That way you won't have to modify the code, recompile, & redistribute the ocx.

Follow-up. To patch the bug:
Method:  modCommon.pvProcessStdPicSource
Add this: bSaveMemCopy = True
Where:


```
... 
If IPic.KeepOriginalData Then
    ....
Else
    bSaveMemCopy = True ' << insert here
    IPic.SaveAsFile ByVal ObjPtr(IStream), bSaveMemCopy, lResult
End If
...
```

----------


## yogiyang

Hello LaVolpe,

Can you check into the code of PhotoDemon - The open source photo editor. It supports very large image size. It is open source so you could study its source cod and implement interesting features in the new version.

http://photodemon.org/

Just my 2 cents.

----------


## LaVolpe

> Can you check into the code of PhotoDemon - The open source photo editor. It supports very large image size. It is open source so you could study its source cod and implement interesting features in the new version.


Very familiar with that project and the author. Not interested. My control is not designed as a photo editor, never will be. It is designed as a viewer. The goal was to expose the control to the user via properties and events so that the user can draw onto the control to customize the image all they want. That was always a shortcoming to VB's controls. The picturebox was the closest we came to custom drawing images.

----------


## aliman

Thank you for your -always- quick reply and for the answer.
I look forward for the new version of your control.  :Thumb:   :Thumb: 




> Very large images may not be able to be saved, without scaling, to other image formats where the format itself restricts max dimensions. All being said, if GDI+ balks at loading very large images, all bets are off.


What you describe couldn't happen even with this version of the control with a very large image size if Aspect is lvicActualSize ?
(I didn't test this since I don't know exactly how large has to be the very large image in order to cause problems).

----------


## LaVolpe

> What you describe couldn't happen even with this version of the control with a very large image size if Aspect is lvicActualSize ?


Yes it is possible. TIF for example is not uncommon to contain very high res images at 600 DPI or higher. VB will not allow a control to be sized greater than 16383 pixels. Translated down from 600 to 96 DPI (normal), that's rounded up to 2625 pixels, though the image dimensions would be 16406. Without DPI awareness, the control will attempt to load the image treating it as 16406, at current screen DPI, regardless of its actual setting. The lvicActualSize setting requests the same size as its dimensions & failure will occur. If AutoRedraw is requested, not sure if the O/S would allow, say a 16406x16406 bitmap, to be created. Memory-wise at 32 bpp image, over 1 GB of memory needed.

Granted that 2625 pixels scaled from 96 to 600 DPI is 16406, but is 2625 realistic? How about half that at 1200 DPI? Same result.

Again, it is possible. Likely? No. But to be a more bullet-proof control; this is an issue I'm attempting to find a good, usable, solution for. The best I've come up with so I don't have to create my own 'view port' is to rely on GDI+. If it can load it, then it can likely display it. The size of the image control is limited by VB, but that limit is larger  than the screen so no real issue there.

----------


## zeilo

Thank you, again.

Now everything is fine, great work.

You are awesome.

----------


## zeilo

Hi LaVolpe.

In a step forward, I dealed with the following issue, again it only occurs in run-time, in the debug-time within the IDE is just fine.

There is a quality loss in run-time when we load a picture from a IPictureDisp or StdPicture directly from its pointer.
If we load passing the handle porperty, instead, it works and the image is recovered perfectly.

However it does not apply for metafiles (.emf or .wmf), an error is raised when we try to load from the handle, either in run-time or debug-time.

Here goes the project sample.

----------


## LaVolpe

What I suspect you are experiencing is a little known behavior of VB.

1) Loading WMF,EMF by handle isn't supported in this version of the control. Just send the picture object. 

2) When you load a bmp/jpg by the object, you should not experience any quality issues.

3) When you load GIF by handle, compiled or not, or by object, when compiled, you will lose transparency

4) When you load icon by object, when compiled, you would lose quality if I didn't foresee that problem.

For #3 & #4 above, here is why. During design-time, uncompiled project, VB caches the original image data when it creates a stdPicture object. I believe this is simply so that VB can save the original data with the project in the .frx, ctx, and other project files. But when your project is compiled, VB does not save this data any longer when it creates the stdPicture object, it doesn't need to, for its purposes, because it knows that data is not needed for saving to project files.

Ok? When you pass the picture object to be loaded, my control's logic works like this:

1) Icon? Always load by the object's Handle to avoid VB's color reduction

2) Anything else: If VB kept the original data, use that data to load the image (as mentioned VB doesn't save this data when compiled)

3) If no original data exists, code asks VB to create the data. This is where VB is really bad with icons and GIFs. GIFs/JPGs are saved in bitmap format. GIFs lose transparency because internally by VB/COM, they are bitmaps not GIFs. Icons are color reduced down to 16 colors resulting in poor quality. You should see these quality issues if you viewed the result of the image file created by VB with: SavePicture "c:\test images\filename.ext", Image1

Note: Even if the original metafile data is not provided in the picture object, VB can recreate metafiles flawlessly 

This behavior of VB needs to be understood if passing picture objects to anything, to be used as image source data.

Suggestions if these formats will be used by the alpha image control (AIC) after your project is compiled:
1) GIFs. Load these into a resource file. Pass them via LoadResData()
:: doing so, ensures all frames are available &  transparency is preserved
2) Icons. Same as GIFs. You could also use VB's image control since the AIC uses the icon handle
:: using res file ensures all sub-icons are available if more than 1 icon exists
3) Bitmaps. Any method you want
:: stdPicture objects processed by ignoring alpha channel. If channel is used, pass by handle
4) JPGs. Load these via resource file if the original image data is needed by you. Otherwise, any method will work
:: saving a JPG loaded by VB to JPG format causes recompression of original data
5) WMF/EMF. Any method you want, but don't try to load metafiles by handle
:: see notes below
6) Any format not supported by VB: use the resource file method or disk file

Edited: I see you use this quite a bit: LaVolpeAlphaImg.AICGlobals....
Just FYI, shouldn't be necessary if you don't want to: Set AlphaImgCtl1.Picture = LoadPictureGDIplus(Image1.Picture)

Edited Again. A bit more about metafiles if trying to pass by handle
EMFs can be processed a couple different ways from its handle. This is not a major issue to support passing EMF by handle. However, WMFs are a different story...

When you have a WMF handle, you have a handle to its bits, its drawing commands. Without analyzing each command to determine where & what dimensions each command is attempting to draw to, there is no way I can think of to get the dimensions, nor aspect ratio of a WMF strictly from its handle. With the handle only, what we have is basically a non-placeable WMF -- no dimensions, no aspect ratio. In my own version of this control, WMFs passed by handle are treated as non-placeable and user has option to set dimensions. GetObjectType API helps identify type of image handle.

----------


## tbote

> I'll take a look, but not likely in the next day or two. I am always interested in errors and bug reports.
> 
> In the mean-time, try passing the handle: Image1.Picture.Handle
> 
> Edited. A quick look, I was able to replicate the problem twice in a row. Then problem went away without doing a thing. I think I have it narrowed down, but will have to perform more tests. If I do figure it out (and I will), you will have to make the change to your copy of the control & recompile it. If this is the only issue and if passing only picture objects that contain bitmaps or jpegs, would recommend passing by handle vs the picture object. That way you won't have to modify the code, recompile, & redistribute the ocx.
> 
> Follow-up. To patch the bug:
> Method:  modCommon.pvProcessStdPicSource
> Add this: bSaveMemCopy = True
> ...


Hi

Same problem here, seems strange, I have two developer machines, the first one with Windows 10+VB6 runs ok, the oher with Windows XP+VB6 shows error 481 loading the same JPG.

I've tried to apply your patch but that piece of code does not apperas in pvProcessStdPicSource:


```
... 
If IPic.KeepOriginalData Then
    ....
Else
    bSaveMemCopy = True ' << insert here
    IPic.SaveAsFile ByVal ObjPtr(IStream), bSaveMemCopy, lResult
End If
...
```

I've found this:



```
If ipic.KeepOriginalFormat Then
        ipic.SaveAsFile ByVal ObjPtr(IStream), False, lResult
        If lResult = 0& Then ipic.SaveAsFile ByVal ObjPtr(IStream), bSaveMemCopy, lResult
    Else
        ipic.SaveAsFile ByVal ObjPtr(IStream), bSaveMemCopy, lResult
    End If
```

Anyway I've added the line there and still error 481  :Frown:

----------


## LaVolpe

@tbote. Instead of True,False, try using 1&,0& respectively. That appears to work well in a recent project I uploaded to the codebank


```
If IPic.KeepOriginalFormat Then  ' from COM-cached data
    IPic.SaveAsFile ByVal ObjPtr(IStream), 0&, lResult
Else                             ' from COM-created data
    IPic.SaveAsFile ByVal ObjPtr(IStream), 1&, lResult
End If
```

Edited: If the error is still occurring, please let me know. In this version of the control, I have no low level code to manipulate the IStream (COM interface). Continued failure would likely result in a need to reset the stream's Read/Write pointer to the 1st byte before attempting to call IPic.SaveAsFile. Hoping that passing 1& vs True (-1) will nip this annoying inconsistency.

P.S. That error is self-generated in the code. If the LoadPictureGDIplus fails to return an image, it raises the error.

----------


## craggus2000

Hi LaVolpe,
I have been looking at using the excellent alphaimage in some of my vb6 apps, and wondered what the situation is with using it in a commercial application, i.e. if I choose to sell an app.
Is it allowed? And how am I best to credit you as the author in my code/application?
Many thanks

Craggus2000

----------


## Jonney

:wave:  :wave:  :wave: Does who know the status of Lavolpe? He was offline since 5 march 2016.

----------


## VbNetMatrix

Hi Lavolpe.

I can't thanks you enough for your contribution for Vb6.
if you could allow myself to benefit once more from your knowledge, I would greatly apreciate it.

How do you manage to "draw" on a transparent OCX ?
I'm using the "bonus code" (of another of your project) to draw a transparent png on a form.
it work perfectly.

but when I try to make an OCX out of it, (I'm forced to use Transparent background of the OCX properties)
the image doesn't show.

So I was wondering how you do it in AlphaImage control.  This control is so huge, it is hard for me to trace how you do it.  if you could just spare some of your time to made me benefit from your knowledge.  plz.

----------


## VbNetMatrix

> P.S. If you find a bug, especially one that annoys you, don't wait a month. I'm very receptive to bug reports


Hi Lavolpe, 
I follow you on other forum and continu to appreciate your knowledge and wisdom.
I know this project is not updated anymore.  But I though... maybe a bug report would revive your flame about it  :Smilie: 

(but if not, thanks anyway for all you gave us in the past)

I'm really trying to fix this for a project of mine...

if I take an image (png) of let's say 1(width) per 20(height)  composed of 1 color (mine is more complicated, but this does same thing)

and apply the following:

Aspect: 1- lvicStretch
Interpolation: 3- lvicNearestNeighbor

Then on the form, I stretch the picture to let's say 200pixel using

then here the problem...
I try to apply an effect:
  Call aicLine.Effects.CreateColorBalanceEffect(16, 0, 100)
  aicLine.Effect = lvicColorBalanceFX

The first (about) 16 pixel (width) are totally white (all height)

any idea for a quick fix ?

if you're interested in the challenge, I can post my code and the image on an ftp.
thanks again.

----------


## VbNetMatrix

> Aspect: 1- lvicStretch



I forget to add that if you don't stretch the image and use an already proper size picture, it work as intended.

----------


## Black_Storm

hi again.
can u help me about this ? https://stackoverflow.com/questions/...nt-form-in-vb6

i posted here too http://www.vbforums.com/showthread.p...75#post5127975

i want read psd file and layers in it and then show on dekstop (on a transparented form). i found source for read psd and show layers in form but cant show on desketop like transparented form.alpha image control can not support psd format and layers?

----------


## VbNetMatrix

Hi

I want to try to help you.
can you explain more because I'm not sure what you're trying to achieve.  First, you need to understand PSD ARE NOT IMAGE.  It's a DOCUMENT.  it's not like a BMP (image) wich can be opened in paint and wich property DIDN'T change since the creation of this image format in the 1980.  PSD is a propriatary form of document that  has no fixed property.  That mean, a PSD file from let's say Adobe Photoshop 4 is completely different then a PSD file from Adobe Photoshop 10.  

What I need is to know what you're trying to achieve....  Show "each" layer of the PSD document on the desktop?  or show the "resulted" end layer ?  (visible image) ?

if you're tying to show the end result, it would be better to export the PSD as a PNG file and then you'll have an alpha transparency image you can show on the desktop. (It can be achieve with some API)

----------


## Black_Storm

i want use PSD file format only because matter for me and a simple version of adobe so for example adobe photoshop 8.
my steps are :
1- designed a psd file in photoshop with more than 1 layers for example 2 or 3 or 4 or more.... and saved like sample.psd.
2- in vb6 can read sample.psd and can read layers and then show each layers in one form or can read all layers and show all layers on one form and then i want transparent form becase i like show just layers without form like show on dekstop effect.
3- i want cam hv been event for example when a layer shown then can click on layer on when moure overed show another layer.

and can u explain this in other forums about alpha control and psd format:
"Maybe you missed that the control is provide with full source code, so you should add your code to read PSD files among the other formats. Take as example the cFunctionsTGA.cls and do the same with the PSD. " what that means do u hv any example to i can understand this means?!!!
my language is not english.

----------


## Cube8

Again, as VbNetMatrix said, *you can't use a psd file* in any way *in VB*. It is a proprietary file format, created by Adobe for use specifically by Photoshop.

http://www.makeuseof.com/tag/the-bes...out-photoshop/



> The problem is that PSD is not an open format. While PNGs, JPGs, and BMPs can be opened in nearly every image editor out there, PSD is special — and it needs special support.


If you want to make a psd reader in VB, you are free to analyze the File Format Specification provided by Adobe.

----------


## VbNetMatrix

As Cube8 mentionned, PSD is propriatary... meaning, Adobe can stop supporting a specific format.  For example, you can't open PSD version 1 anymore because they were in conflict with the new design model they later develop.  if for example, you currently build an application supporting PSD v8 and in 3-4 years Adobe decide to stop supporting this version, no program will be able to "save" in that version, meaning what you're currently developping will be broken.  this will never happen with an open Image format (look at BMP, obsolete but still usable)

better export that PSD in PNG (many if you need separate layer) and use thoses.  It will be faster and you won't need to support a format or programming a read method.

----------


## Black_Storm

> and as Cube8 mentionned, PSD is propriatary... meaning, Adobe can stop supporting a specific format.  For example, you can't open PSD version 1 anymore because they were in conflict with the new design model they later develop.  if for example, you currently build an application supporting PSD v8 and in 3-4 years Adobe decide to stop supporting this version, no program will be able to "save" in that version, meaning what you're currently developping will be broken.  this will never happen with an open Image format (look at BMP, obsolete but still usable)
> better export that PSD in PNG (many if you need separate layer) and use thoses.  It will be faster and you won't need to support a format or programming a read method.



BUT i can tell you we can open and read psd format in vb6--> check attachment sample,but my problem asked,i need open and read and show on transpraneted form,i can read and show on form but i cant show on transparented form, i am waiting to can find a way.

----------


## Black_Storm

this picture can show what i want :

----------


## VbNetMatrix

now you confuse me...  you showed on right image you CAN DO IT.
if you can show the image on Vb6 form, where is the problem ??
just use SetLayeredWindowAttributes API
https://bytes.com/topic/visual-basic...6-transparency

I thought the problem was to show the PSD layer ?

----------


## Black_Storm

i used SetLayeredWindowAttributes API but result was been this image (not good).
i checked source code and can find this code :


```
SetPixelA theHdc, x + FLeft, y + FTop, r, g, b, a
```

this is main command for read from layer data and theHdc is same form.hdc .
i added SetLayeredWindowAttributes API after form load and checked and added after end of show layers and checked but result was been like attached my image,how can make good quality with shadows or ... ?





can i send source code and maybe u can fix it for me?

----------


## VbNetMatrix

post this to the other thread, I don't want to pollute Lavolpe AIC place.  I'll help you solve this with AIC

----------


## Black_Storm

i sent source code in this thread [http://www.vbforums.com/showthread.p...7#post5129607]

----------


## Black_Storm

i hv 2 question about this thread too (alpha image control).
1-how can make *smooth animation* (other way not use for next commands) and want show that animation on desktop with mouse event too?(can click on animation or drag and drop)?!!! possible?

i want show animation (smooth) on desktop like attached image but png format and transparented :


if possible can attach source code or sample code ? thanks


2-this control can support *apng* format?if not how can simulate this format with png ?

----------


## VbNetMatrix

Lavolpe AIC support APNG, and mouse driven event.  if you use your program with the previously discussed API, you can make your form transparent while supporting event on the image.

----------


## Black_Storm

can u send a sample source code *animation*  merged with *form controls* and show on desktop use by AIC? 
i have source for show animation on desktop with AIC but i can not merge controls like textbox or button or shape or ...
i dont want use trick like show animation on one form and show controls like as top form on animation.i want just use one form with aic control and form's controls.

----------


## VbNetMatrix

> can u send a sample source code *animation*  merged with *form controls* and show on desktop use by AIC?


Use eitheir an animated GIF or an aPNG (animated PNG) when you need the animation, you use:
aicPng.Animate lvicAniCmdStart

as simple as that. (1 line of code)

did you installed the AIC ?  if so, you can get nice APNG here: http://voormedia.com/blog/2016/09/an...ng-compression

----------


## Black_Storm

my means was been about *sample source code animation merged with form controls* and *show on desktop use by AIC*?
i have source for show animation on desktop with AIC but i can not merge controls like textbox or button or shape or ...
my problem is about merge controls like text boxes or command buttons or shape or ... when i use aic  and then maked transparent.
did u see picture attached in #582?


*see this result (how can fix it?): http://s.pictub.club/2017/01/27/sr2WTY.gif* or 

and i have another question
1- i have a animation with 20 frames and dont need loop animation just need 1 loop time.
2-how can start animation from frame 3 when form loaded or show.
3-then  play  from frame 3 to frame 12 with my custom speed?
4-when frame was been 12 then stop 2 second.
5-then start animation resume from frame 12 to frame 15
6-then animation jump to frame 18
7-play animation resume from frame 18 to end frame(frame 20)

----------


## Black_Storm

simple apng images needed for vbnetmatrix request :sampleframes.zip

----------


## labmany

I have a project which uses Alpha Image Control (AIC), it works fine on my development machine and clients who have Windows 7 but AIC does not show the image (blank control) on "some" Windows 10 machines, any clue?!

----------


## LaVolpe

Any clue? Gonna need a lot more info than that. I have Windows 10 and no problems. It might help to know whether this problem is for every instance of the control? Whether you are talking about the control displaying or using one of its functions to draw to a picturebox or other DC? Whether this seems related to a specific image format? etc, etc. Without far more details, I am not gonna be able to venture any guesses or suggestions.

Also, for the control(s) that don't display correctly, post the LoadPictureGDIplus statement you are using. See if post 553 & 554 on previous page apply, along with post 561, 562 & 563 on this page.

----------


## labmany

Thanks Lavolpe!

Actually I am loading an AVI file not a picture, though I am using LoadPictureGDIplus() to load it into the Picture property of the AIC.
I have like a custom made thumbnail viewer and using the following code to populate it :


```
Private Sub ThumbnailViewer()

    On Error Resume Next
    Dim tmpFL As String
    Dim n     As Integer

    For n = 0 To 4
        With imgThum(n)
            tmpFL = CURRPATH & "\" & flAviFiles.List(n + SlideIndex)
            If Right$(tmpFL, 1) <> "\" Then
                .Picture = LoadPictureGDIplus(tmpFL)
                .ToolTipText = "   " & Lang(20) + " :" + Str$(n + SlideIndex + 1) & "   "
                If Dir$(Replace$(tmpFL, ".avi", ".ini")) <> "" Then .BorderColor = vbRed Else .BorderColor = vbBlack
                .Visible = True
            Else
                .Visible = False
            End If        
        End With
    Next

End Sub
```

Normally it should look like this when all is OK :



On some versions of Windows it looks like this :



P.S. : 
  * The DivX codec is installed on all clients machines.
  * flAviFiles is a 'FileListBox' control with a pattern of *.AVI
  * Lang() is an array which loaded with different languages text
I know you will figure out the the above two lines but I had to write them anyway  :Smilie:

----------


## LaVolpe

When you have the the time, open this class module within the AIC project: cFunctionsAVI. Read the comments at top of the class and see if they apply. 

Also regarding this line: .Picture = LoadPictureGDIplus(tmpFL)
After that statement returns, test to see if .Picture.Handle = 0. If it does, the AVI failed to load using the AVIStreamOpenFromFile API or the AVIFileInit API failed (not likely).

Also ensure this line is true: If Right$(tmpFL, 1) <> "\" Then

I can play with this further if you can't get it working based on the comments in that class. But I'll need the AVI and a link where to get the codec. I can't guarantee I'll get to play real soon; have other things on my plate right now. My 1969 Mach I Mustang just died on the way to work and dealing with that today, off and on.

----------


## VbNetMatrix

> My 1969 Mach I Mustang just died on the way to work and dealing with that today


I feel you man.  :Frown: 

wich part broken ?  did u succeed to get replacment ?


in the meanwhile, I wanted to ask you a question about the AIC.  In a project of mine, I add the reference to the component but I didn't used it (yet).  Inside the IDE, I was debugging the app wich also use the MsFlexGrid and WinHttp component.  All 3 component I used in different application (but never all together) and I never had any problem.  In this particular project, the AIC was referenced but not put on any form.  the IDE experienced "Out of Memory" error from time to time when the program "end" normally or "stop" from the IDE.

removing the AIC reference, fixed the problem, but I fail to see how a reference to AIC without initializing it or using it on form could lead to that.
Did you ever experienced similar problem ?  Seem a rather unexplained problem.  I didn't tried too "reproduce" it since I had to deliver the application in a hurry.

any idea ?

thanks for any feedback

----------


## LaVolpe

Out of Memory isn't related to the AIC as far as I can see. I've taken great efforts to ensure no memory leaks. The control, when first used or any of its global methods are used, will create a GDI+ token. 

If a control is used, then other items may be created like a GDI+  image and/or bitmap, depending on options/settings of the control. However, even if there is a memory leak, I'd think one would need 100s of controls to cause that problem. Again, as far as I know, there are no leaks and with 1000's of downloads, this was never brought up previously. A quick test, using Task Manager, shows that the GDI count before a project run with the AIC, increases while the project is running (expected), and returns to that value after the project is closed. Pretty confident no leaks.

Out of memory can occur in a recursive routine also. If you have any recursive routines look at those. In the AIC control there are 3 places where recursion can occur. Those routines include async downloads via URL, creating adaptive palette option when saving image in low color depth, and when autosize of the control is set to true and a potential of resizing entering an infinite loop. In all of those, I've included code to prevent unexpected recursion. 

Are you by chance running any code that tries to resize controls based on form_resize? Maybe that could be an odd case that could cause an infinite loop if your code is forcing one size while the control's AutoSize feature is forcing another, maybe just a pixel off? But if you don't even have any controls sited on the form, that won't be in play.




> but I fail to see how a reference to AIC without initializing it or using it on form could lead to that.


That is odd indeed and may be coincidence. Maybe you can try it in reverse order. Add the AIC first, then the other references, one by one. Do you get the same results? If the control is not even sited on a form, no code is running so this is unusual. If you can reproduce the problem on demand, that could be helpful. Maybe there is some sort of race-condition being created between the AIC and the other references? 

Edited: When you get that message box, is it possible to break into the code to see what line is being executed? That would help.

The only issue I know that can happen is addressed at this posting. However, this problem is not specific to this AIC, it is applicable to any VB-created usercontrol when environment is manifested.

BTW: Mustang will need a new dizzy. Been waiting for the makeshift one I am using to fail so I can spend the money to buy a high performance custom-made replacement. Last one lasted about 5 years and finally crapped out -- good for me, now bad for my budget: $370  :Wink:

----------


## VbNetMatrix

Thanks a lot Lavolpe, I apreciate the cue.  I'm reading the link you provide, I'm not sure I understand why the IDE would crash with that configuration.
I'll try to reproduce it to see if it apply, I'm not using the shell but if I can understand the reason why it does, it might give me a cue on my own problem.

I'll also investigate more by reproducing the problem with the AIC, for now I have simply removed the AIC reference from the project as it was not mandatory. (I had hoped to skin my project in a later version)

again your work is excellent and I always apreciate your input.

I'm glad you came back on the forum, I had posted some other bug in your absence but it is not really important.  some were strange though (putting 2 AIC control over each other with transparency caused a race condition and the image became weird - zoomed in)

Do you still intend to produce a new version with DPI awareness ?  I'm asking with sincere interest but I understand how busy our regular life keep us from doing everything we wish  :Smilie: 

wish you the best for your car...  didn't know you were fan of antique  :Smilie:   I failed to translate the name of the part you are talking about, is it part of the carburator ?  It is a wonderfull car...  Wish I had one like that.  I wouldn't mind if you post some picture of her online  :Big Grin: 

thanks for all.

<<<When you get that message box, is it possible to break into the code to see what line is being executed? That would help.
Edit:  When it happen, I can't even save the project (it raise the out of memory error), I got to exit the IDE and load back.  fortunately, my setting are set to save project before every run.  But the problem don't raise while running.  It raise AFTER I hit STOP (while the program is on waiting) or when I EXIT the program and return to IDE

----------


## LaVolpe

> ...I had posted some other bug in your absence but it is not really important.  some were strange though (putting 2 AIC control over each other with transparency caused a race condition and the image became weird - zoomed in)


The control only draws itself under a few conditions: VB tells it to, user calls refresh, animation frame changed, user changes some drawing options or changes the assigned picture. For windowless controls, if 3 controls were overlapped with each other for example, a redrawing of one would trigger redrawing of all 3, where they intersect. VB clips the dirty area of the DC, sends control lowest in ZOrder a paint event, passes the repainted DC to the next in ZOrder, and so on. Once all have painted, VB updates the screen. As far as the effect you experienced, that would need to be troubleshot. Could be a logic error within the AIC. But in post #3 (1st page), twice I recommended not to overlap controls.




> Do you still intend to produce a new version with DPI awareness ?  I'm asking with sincere interest but I understand how busy our regular life keep us from doing everything we wish


Yes, I thought I was nearly done with it, but after learning more about DPI awareness, I wasn't happy with the logic and will need to start fresh.




> wish you the best for your car...  didn't know you were fan of antique   I failed to translate the name of the part you are talking about, is it part of the carburator ?


Dizzy = nickname for Distributor

----------


## VbNetMatrix

> in post #3 (1st page), twice I recommended not to overlap controls.


Yes, that's what I opted in to fix the problem  :Smilie:   although, the problem (in my case) was not the primary redraw when the control overlap, but when I move the mouse over the control.  Then, the image under the second control became zommed in...  anyway, like you said...  fixed by not overlapping  :Smilie: 

The other bugs was a scale bug where not all pixel get the proper color. (having a region completely white for some reason)




> --AIC v3 -- Yes, I thought I was nearly done with it, but after learning more about DPI awareness, I wasn't happy with the logic and will need to start fresh.


I wanted to ask you to take something into consideration...  It is YOUR control, so the decision is yours...  why not make the control in a way we can "remove" easyly part of it ?  For example, let's say someone intend to use it only for PNG and JPG, if we could remove module we could compile a control easier to "debug/diagnose" under some condition.

While attempting to fix a bug by my own in past, I have attempted to unload the class related to other image format... the task reveal itself to be almost impossible because of the intresec interraction with one another...  So I had this thought...  but I understand it would require some work.
anyway... like I said... just a thought.




> Dizzy = nickname for Distributor


that's the cap with electrode spinning to give fire to candle in proper order right ?
I had this piece broken down on me on a Dodge 72

----------


## LaVolpe

> I wanted to ask you to take something into consideration...  It is YOUR control, so the decision is yours...  why not make the control in a way we can "remove" easyly part of it ?  For example, let's say someone intend to use it only for PNG and JPG, if we could remove module we could compile a control easier to "debug/diagnose" under some condition.


I will consider options where the user can customize the ocx before they compile it.




> that's the cap with electrode spinning to give fire to candle in proper order right ?


Yes. Though the order is always one way: clockwise or counter-clockwise. The cables from the cap to the engine result in the proper firing order if the cables applied properly.

----------


## VbNetMatrix

> I will consider options where the user can customize the ocx before they compile it.


thanks  :Smilie: 




> Yes. Though the order is always one way: clockwise or counter-clockwise. The cables from the cap to the engine result in the proper firing order if the cables applied properly.


What I meant was : while rotating, it hit candle specific order like 1, 4, 3, 8, 2, 5, 7, 6 depending of motor configuration, eitheir in V or in line (like jaguar).
but yeah, we're speaking about the same part.

----------


## VbNetMatrix

Hi Lavolpe, 

I'm in a dead end with something, I hope you can help.

basiquely what I'm trying to do is:
Set pngLavolpe1.Picture = LoadPictureGDIplus(picVb6PictureBox.picture)

I received error 481, incorrect format.
I look at documentation from your component, didn't find anything unusual.

However, I found something that let me skeptical about eitheir or not your AIC can do this in that particular case.

When my program start, I got a white rectangle in the picturebox frim a file (BMP).  Nothing fancy

on some subroutine,  I do a 

1. picturebox.cls
2. ... some modification with DrawText Api
3. picturebox.refresh
4. set picturebox.picture = picturebox.image

then I try:
Set pngLavolpe1.Picture = LoadPictureGDIplus(picturebox.picture)

tha'ts where it'S crashing with error 481.

Is there a way I can manipulate my image with DrawText and then put it back in AIC control ?
I'm using picturebox because AIC doesn'T expose hDc


picturebox.ScaleMode is 3 'Pixel
picturebox.AutoRedraw = True

Thanks for any input...

ps.  glad you found your car part.  :Smilie:   hope you'll travel the road long before winter  :Smilie:

----------


## LaVolpe

Crashing should not be happening and I suspect it is due to not handling errors. If LoadPictureGDIplus fails, it generates an error. Use On Error statement before calling that function. Ok, that fixes any crashing.

Now regarding incorrect format error. That error only occurs if LoadPictureGDIplus. Long story short... When passing the Picture object, AIC tries to get VB to give it the image data via a stream. This obviously is a problem on some systems, based on previous posts. I've offered some possible tweaks in those previous posts, but not all may apply. One workaround that should work is to pass the handle, ie., Set pngLavolpe1.Picture = LoadPictureGDIplus(picturebox.picture.*handle*). Hopefully that gets past that error.

Regarding the AIC not exposing it's hDC. But it does through the WantPrePostEvents property and responding to the PostPaint (in your case). However, and this could be a problem,  GDI+ should always be used to draw text. This is because the hDC passed in that event may be holding a 32bit image and DrawText/TextOut does not render correctly on 32bit bitmaps. The alpha channel can become invalid.

----------


## VbNetMatrix

> Crashing should not be happening and I suspect it is due to not handling errors.


I'm still in developping phase... by crashing I meant not doing what we expect... throw error 481 instead of loading image...
sorry to have mislead you...  I'm not handling error at this point.




> Now regarding incorrect format error. That error only occurs if LoadPictureGDIplus. Long story short... When passing the Picture object, AIC tries to get VB to give it the image data via a stream. This obviously is a problem on some systems, based on previous posts.


I would be interested to read thoses post...  although I don't think it's the issue here (some systems...)  Never had ANY problem with your component except "some" minor glitch in rendering...




> I've offered some possible tweaks in those previous posts


I'll try to find them.  Do you remember some content to facilitate the search ?




> One workaround that should work is to pass the handle, 
> ie., Set pngLavolpe1.Picture = LoadPictureGDIplus(picturebox.picture.*handle*)


instant fixe!  thanks.





> GDI+ should always be used to draw text. This is because the hDC passed in that event may be holding a 32bit image and DrawText/TextOut does not render correctly on 32bit bitmaps. The alpha channel can become invalid.


Thanks for the information.  I'm writing directly onto a picturebox then passing the picture to the AIC control.  It doesn'T need transparency, it's simply a BMP, then I save it to PNG or JPG, depending of the image.

The program I do simply put and order image in an Access Database for VR on sales, with the program, you can add, remove and manage the VR that are or not on sales...  Then the program create Thumbnail and the resulting Access Database.

The result is displayed as a web page I have created in the form of a "book" where you can turn page, click thumbnail...

an image is worth 1000 words:
http://www.campingbaiedudiable.ca/roulottes_vendre.html

----------


## LaVolpe

> I would be interested to read thoses post...  although I don't think it's the issue here (some systems...)  Never had ANY problem with your component except "some" minor glitch in rendering...
> 
> I'll try to find them.  Do you remember some content to facilitate the search ?


Start with the last few posts on previous page and post #562 on this page.




> instant fixe!  thanks.


If passing the handle worked but passing the picture object did not work, then what I described in my previous reply is the reason. Just FYI.

----------


## VbNetMatrix

> Start with the last few posts on previous page and post #562 on this page.


Got it, passed an hour reading your material and reference on MSDN.  it raised some question...  (see below)




> If passing the handle worked but passing the picture object did not work, then what I described in my previous reply is the reason. Just FYI.


Forgive me, can you be more specific ?  What cause the problem ?

Ok, here from component 2.1.32


```
    If ipic.KeepOriginalFormat Then
        ipic.SaveAsFile ByVal ObjPtr(IStream), False, lResult
        If lResult = 0& Then ipic.SaveAsFile ByVal ObjPtr(IStream), bSaveMemCopy, lResult
    Else
        ipic.SaveAsFile ByVal ObjPtr(IStream), bSaveMemCopy, lResult
    End If
```

Of, I'm not sure I understand something...
bSaveMemCopy is Declared as Boolean but never Initialized...  (so it was false all the time) So Let replace all code but removing the unused bSaveMemCopy

We got this:


```
    If ipic.KeepOriginalFormat Then
        ipic.SaveAsFile ByVal ObjPtr(IStream), False, lResult
        'old: If lResult = 0& Then ipic.SaveAsFile ByVal ObjPtr(IStream), bSaveMemCopy, lResult
        'If lResult = 0& Then ipic.SaveAsFile ByVal ObjPtr(IStream), False, lResult
    Else
        'old: ipic.SaveAsFile ByVal ObjPtr(IStream), bSaveMemCopy, lResult   'Wich MEAN FALSE
        'bug Fix 2.1.33 (not released yet)
        ipic.SaveAsFile ByVal ObjPtr(IStream), True, lResult
    End If
```

That work as Intended, bug fixed.. now my question is about the other part



```
    If ipic.KeepOriginalFormat Then
        ipic.SaveAsFile ByVal ObjPtr(IStream), False, lResult
        'If lResult = 0& Then ipic.SaveAsFile ByVal ObjPtr(IStream), False, lResult
    Else
```

    IPicture.SaveAsFile:
IPicture.SaveAsFile Link

       Return Value:
IPicture.SaveAsFile Return Value Link
           E_FAIL        = 0x80004005    'Unspecified failure
           E_INVALIDARG  = 0x80070057    'One or more arguments are not valid
           S_OK          = 0x00000000    'Operation successful

so, if lResult = 0 mean S_OK, why are we doing the same operation a second time ?
is there any benefit ?

just wondering... I'm confused.

----------


## LaVolpe

> so, if lResult = 0 mean S_OK, why are we doing the same operation a second time ?
> is there any benefit ?
> 
> just wondering... I'm confused.


You're confused? So was I as to why it failed on occasion. 

lResult is not the return value of ipic.SaveAsFile. It is the number of bytes copied to the stream (3rd parameter of the function). If zero bytes, then failure.

Reason why doing it twice was mentioned in the routine's comment I believe. Inconsistencies. However, I think part of the problem I was having, discovered couple years later, could be the parameter being passed. Is it boolean? Is it long? Is it something else? Per object explorer in VB (F2 key), it is "Boolean". But that may not be trustworthy. For example, ipic.Render states parameters as long, but if you pass long you get type mismatch unless you pass single. 

As to why passing FALSE can work when passing a boolean variable doesn't work is likely due to imperfect documentation and/or my misunderstanding of the function.

----------


## DEXWERX

It's a typo in the original stdole2.tlb. How it doesn't crash every time boggles the mind.

OCIdl.idl uses BOOL (32bit) while stdole2.tlb uses VARIANT_BOOL (16bit)

Have you tried invoking SaveAsFile using DispCallFunc() instead?

----------


## VbNetMatrix

> lResult is not the return value of ipic.SaveAsFile. It is the number of bytes copied to the stream (3rd parameter of the function). If zero bytes, then failure.


Oups!!  How could have I been so distracted! lool...




> ...could be the parameter being passed. Is it boolean? Is it long? Is it something else?


as per "non official" version 2.1.33 of mine, I have changed the parameter for LONG and I also have put something like:

if (lresult=0) then
  msgbox "nope, wasn't that..."
end if

so if it glitch in any of my program in like next 6 month, I'll know, otherwise, I'll consider the matter fixed for good.


Thanks for fixing this.  I love this component.

----------


## VbNetMatrix

> It's a typo in the original stdole2.tlb. How it doesn't crash every time boggles the mind.
> OCIdl.idl uses BOOL (32bit) while stdole2.tlb uses VARIANT_BOOL (16bit)
> Have you tried invoking SaveAsFile using DispCallFunc() instead?


DispCallFunc()??  didn't know...  but the fix work now, so...

Got a couple of question though...

1.  where can we get documentation about OCIdl.idl and stdole2.tlb for the matter at hand ??
2. I saw you did a vb6.tlb, what does it does and would it be possible to create a vb6.tlb to fix and replace stdole2.tlb ?

thanks

----------


## DEXWERX

> DispCallFunc()??  didn't know...  but the fix work now, so...
> 
> Got a couple of question though...
> 
> 1.  where can we get documentation about OCIdl.idl and stdole2.tlb for the matter at hand ??


I always read the source, as MSDN documentation can be lacking and is often wrong.
stdole2.tlb can be decompiled to IDL using the OLE-Com Object viewer (which comes with Visual Studio)
OCIdl.idl comes with any of the Windows or Driver Development kits (or visual studio / visual c++)





> 2. I saw you did a vb6.tlb, what does it does and would it be possible to create a vb6.tlb to fix and replace stdole2.tlb ?
> thanks


VB6.tlb's main use is to allow easier use of pointers, by aliasing some of the built in runtime functions.
like getting the safearray reference of an array, and read/write access to memory via pointer, 
as well as r/w access to the pointers of VB's reference types (string/array/object).
It's also declares often used functions like CopyMemory.

It's possible to correctly VB-Ize the IPicture definition from OCIdl.idl and include it in a typelib like my VB6.lib
That's actually a great idea. I need to finish adding in Control Array interfaces anyway, might as well add a fixed IPicture.

----------


## Black_Storm

hi i completed my game project but have2 problem with AIC


movie of result : here
1-i have a one sprite sheet png file and one alpha image control,my images is like this :




i want when mouse entered on normal state then "fade in" to over state  and show over state image and stop and then when mouse down pressed on over state  then fade in to down state and then start animation frame 1 to 100 play with custom duration speed for example (500 miliseconds)

matter is for me to make fade in  simulation
i dont want make frames for simulate fade in 

how can do that ?



and my question 2 :  how can mirror face from left to right or from top to down without reverse frame? i hv a sprite sheet for walking but when i used mirror method AIC mirrored and frames reversed but i want just face mirror and dont want frame reveres too.
in my project i  designer each left view animation of characher like as sperate because i cant use mirror or AIC(alpha image control).

----------


## Black_Storm

any body here can answer to my 2 questions in #607

----------


## Black_Storm

hi i wantt use AIC user control in another user control
i set backstyle of myusercontrol to transparent and then i used aic user control in my user control.
when i puted my user control on a test form background of  my user control was been transparent but AIC was been white backcolor !!!
i have this problem with *ImgEx* or *stdPicEx*.
how can fix it? (i want use my user control with transaparent AIC  or ImgEx  or stdPicEx  in same time on a form)

----------


## LaVolpe

I'll try to get back with you this weekend. My system just updated with latest Win10 update & things are not working right. Took me quite awhile to get VB up and running again (reinstalled it), but it's still not quite right. Only decision I have now is to try to figure out to fix what still needs fixing or rollback the Win10 update.  Until then...

----------


## Black_Storm

i am waiting so. and i am waiting for imgex or stdex class updgare to apng support too.

----------


## LaVolpe

From your screenshot, I'd expect the bkg color to be gray not white. In any case, if you make your UC transaprent, then also set its Windowless property to true. Then transparency should be shown throughout. If that is not an acceptable solution, you can try compiling the AIC to a separate OCX and see if the issue continues. Or try different combinations of  your usercontrol. Changing any combination in the AIC will fail to produce the desired effect.

Bottom line, the AIC gets its hDC, that it draw on, from VB. If VB gives it a solid fill background, that's what is drawn on.

----------


## Black_Storm

i tested with windowless but now how can move my custorm usercontrol on form with mouse?

and can u answer to my old question?
how can mirror face from left to right or from top to down without reverse frame? i hv a sprite sheet for walking but when i used mirror method AIC mirrored and frames reversed but i want just face mirror and dont want frame reveres too.
in my project i designer each left view animation of characher like as sperate because i cant use mirror or AIC(alpha image control).

----------


## LaVolpe

Don't understand what you are describing, regarding mirroring and sprites?

Here are two related links that discusses placing windowless transparent UCs in another transparent UC. It is not going to make you happy.  
http://www.vbforums.com/showthread.p...Transparent-UC
http://www.vbforums.com/showthread.p...ntrol-Question

The behavior you are seeing can be replicated with VB's Image Control too.
1. Create a new UC, set these properties: BackStyle=transparent, ClipBehavior=none, Windowless=true
2.  Add a VB image control and place a transparent GIF on the UC. This is kinda like my AIC
3. Now, create another UC and place the first UC in it. Without setting this UC's BackStyle=transparent & Windowless=true, the GIF background is no longer transparent.

----------


## Black_Storm

i write my problem on picture.
my porblem is with mirror animation.
i want mirror animation to horizontal or vertical and when mirrored,animation play from first frame to last frame(when i used aic mirror animation play from last to first frame).

i want just turn back my animation face to left or right or top to bottom without reverse frames too.


and if u can help me in this *thread*
any way to use nine patch picures(png) in vb6? can i use aic for nine patch too?how?

----------


## LaVolpe

How are you animating? Are you using the GDIpImage.SegmentImage method to tile the image? More details would be helpful

----------


## Black_Storm

i am use segment images, i sent picture used in #615 but i attachment here too.make a  animation with this attachment for test and then check with horizontal mirror too.

----------


## LaVolpe

Now I can better understand and found a logic flaw too

1. Open the class GDIpImage and find this routine SegmentImage
2. Change this line: newSEQ(0, lCount) = Val(sSeq(lCount)) - 1&
to this: newSEQ(0, lCount) = Val(sSeq(lCount *- 1*)) - 1&
3. Provide the new sequence manually... example:


```
    With AlphaImgCtl1
        .Animate2.PauseAnimation
        .Mirror = lvicMirrorHorizontal
        .Picture.SegmentImage 5, 2, , , "5,4,3,2,1,10,9,8,7,6"
        .Animate2.ResumeAnimation
    End With
```

----------


## Black_Storm

i changed  class GDIpImage and  routine SegmentImage to :


```
newSEQ(0, lCount) = Val(sSeq(lCount - 1)) - 1&
```

and then i writed manual code  :


```
 With AlphaImgCtl1
        .Animate2.PauseAnimation
        .Mirror = lvicMirrorHorizontal
        .Picture.SegmentImage 5, 2, , , "5,4,3,2,1,10,9,8,7,6"
        .Animate2.ResumeAnimation
    End With
```

and worked but if i hv been more than 10 sprites images and each image have been random frames for example more than 100 frames so i should be write code manual for each animation .

how can fix this problem to work always without  this part :


```
  With AlphaImgCtl1
        .Animate2.PauseAnimation
        .Mirror = lvicMirrorHorizontal
        .Picture.SegmentImage 5, 2, , , "5,4,3,2,1,10,9,8,7,6"
        .Animate2.ResumeAnimation
    End With
```

my means is i want just set mirror to horizontal mirror in property page.

----------


## Arnoutdv

You have to mirror the cells in the image, so don't mirror the complete image.

----------


## LaVolpe

> You have to mirror the cells in the image, so don't mirror the complete image.


Another option. The SegmentImage function also can accept a byte arrray (if the class comments are read). Now, it's only a  matter of sizing an array for 100 items and creating a short loop to populate the array. This, in my opinion, is minimal effort.

@BlackStorm. Suggest the method just described. I won't be modifying the class for this purpose. One of the beauties of this project is that is open source and nearly anything that one may want to add or alter can be done outside of the control. I really concentrated on trying to expose every possible thing to the coder via control/class properties and methods. The goal was not to have to make custom tweaks to the UC, simply call its methods/properties to change the control's behavior.

----------


## Black_Storm

i simulated this model :


```
'example :
'when columns is 5 and rows is 2
'5 4 3 2 1 10 9 8 7 6 

'example :
'when columns is 4 and rows is 3
'4 3 2 1 8 7 6 5 12 11 10 9

'example :
'when columns is 4 and rows is 2
'4 3 2 1 8 7 6 5

'example :
'when columns is 3 and rows is 4
' 3 2 1 6 5 4 9 8 7 12 11 10
```

and then i changed this part from SegmentImage rutin :
orginal code :



```
else
For lCount = 1& To TileCount
newSEQ(0, lCount) = lCount - 1&
newSEQ(1, lCount) = FrameDuration
Next
```

to :



```
        Dim MySeq() As String, MyTempSeq() As String: ReDim MyTempSeq(TileCount)
        Dim MyMasterSeq As String
        Dim s As Long, cnt As Long, cnt2 As Long
        Dim Lngi As Long, Lngi2 As Long
        cnt = 0: cnt2 = 0: s = Columns
        For Lngi = 1 To Rows
            s = Lngi * Columns
            cnt = s
            For Lngi2 = s To (s - (Columns - 1)) Step -1
                cnt2 = cnt2 + 1
                MyTempSeq(cnt2) = cnt
                cnt = cnt - 1
            Next
        Next
        
        MyMasterSeq = Join(MyTempSeq, ",")
        MyMasterSeq = Replace(MyMasterSeq, ",", "", 1, 1, vbBinaryCompare)
        MySeq() = Split(CStr(MyMasterSeq), ",")
        
        
        For lCount = 1& To TileCount
            newSEQ(0, lCount) = Val(MySeq(lCount - 1)) - 1&
'            newSEQ(0, lCount) = Val(sSeq(lCount)) - 1&  ' ensure values in range of 1-TileCount
            If Err Then                                 ' internally, range is 0 to TileCount-1
                Err.Clear
                newSEQ(0, lCount) = 0&
            ElseIf newSEQ(0, lCount) > TileCount - 1& Then
                newSEQ(0, lCount) = TileCount - 1&
            ElseIf newSEQ(0, lCount) < 0& Then
                newSEQ(0, lCount) = 0&
            End If
            newSEQ(1, lCount) = FrameDuration
        Next
```

and now i can set mirror with property page without any codes needed.is that correct?

----------


## LaVolpe

If it works for you, then it's correct. But one of my long-standing principles apply... you break it, you fix it; no more help from me. In other words, once someone modifies my code for their purposes, I don't offer advice on how to fix it if it fails.

----------


## Black_Storm

> If it works for you, then it's correct. But one of my long-standing principles apply... you break it, you fix it; no more help from me. In other words, once someone modifies my code for their purposes, I don't offer advice on how to fix it if it fails.


work for me but i want ask from you because i dont know other method means used in that class or any classes maybe used  inthis class too.i want know any  idea for any problem to maybe happen in feature.what problem maybe happen?

and apng not added to imgex or stdex yet?when time will be start?(i am waiting to apng support too)

----------


## LaVolpe

> work for me but i want ask from you because i dont know other method means used in that class or any classes


Yes, already mentioned it. Build your array outside the AIC, i.e., in your form, and pass the array. Don't customize a generic routine to no longer be generic.

----------


## VbNetMatrix

> My system just updated with latest Win10 update & things are not working right. Took me quite awhile to get VB up and running again (reinstalled it), but it's still not quite right.


Hi Lavolpe, hope you fixed your problem with last version of Win10.  As for myself, I gave up on "Win10 & Vb6"
I installed Oracle VM and on my Win10 machine, I ran a VirtualBox of Win7 in full screen.  work like a charm  :Smilie: 

if that can help:
https://www.virtualbox.org/wiki/Downloads

----------


## Schmidt

> ... If anyone downloads that zip and doesn't have your DLL, then this thread will get posts with questions about that project.


Ok, good enough point for me, to remove the stuff I've posted from this thread - moving suggestion (and example) over into the Main-VB6-Forum:
http://www.vbforums.com/showthread.p...ing-direction)

Olaf

----------


## Black_Storm

hi,i have this png sprite picture and used in aic :


i changed AIC to segment type and then i want extract one of splited picture in to a image box with keep transparent? can i do that?
or can extract and then use imgex for show in image box? (image box is matter for me).
i dont want save as png on hard drive i need just use my image index selected from aic control (segmented images) and show direct to imagebox with transparency.

----------


## LaVolpe

VB's image control won't do transparency except for GIF, WMF, icons less than 32 bit. 

You can extract the tile to another AIC using the SavePictureGDIp function with the optional SaveStruct parameter.
1. Set the image index to the tile you want
2. In the SaveStruct, set the ExtractCurrentFrameOnly member to true
3. Save the tile as a stand-alone image, probably as PNG if sending to ImageEx

Also, the AIC can display any tile in a segmented image simply by changing the .Picture.ImageIndex property

----------


## Steve Grant

Hi Keith, I have just started to use your control.

I am showing Album Art to the user in a 200 x 200 AIC. If the file does not contain a picture in the metadata, I am downloading just 10 images and placing them in 10 36 x 36 AIC's for the user to choose.
I have already discovered by playing that the AIC's picture property always contains the original picture size and quality, no matter how small I have scaled it. This, I think, is great.

My question is do I really need 10 mini AIC's or is there some way I can display the 10 images in 1 AIC and the user select which one they want?

----------


## LaVolpe

You can do that a couple of ways, here is maybe the easiest?

Use a picturebox sized 360x36, borderless if desired
As you load each image, you can paint it to the appropriate tile in the picture box. Simple math will tell you which tile the user clicked on. Use the Render method of the Picture property.

If that isn't good enough, you can actually create one 360x36 AIC but requires more effort. That process is basically the same principle and that can be done at least two ways. But I won't go into the details if the easier option suits your needs.

Edited: Since one of the options requires drawing into an AIC, I whipped up an example because I don't think I've provided one of those yet...

This is probably the next easiest method that allows you to keep the "combined" image in an AIC. Note in this example, I'm creating a horizontal strip of images. Obviously just a sample, and you'd need to adjust for any scaling you may want and/or creating a grid vs strip.


```
Private Declare Function GdipGetImageGraphicsContext Lib "GdiPlus.dll" (ByVal pImage As Long, ByRef graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long

' don't need to initialize GDI+ for your form since the AIC already using it

Private Sub Command1_Click()
    
    Dim tImg As GDIpImage, SS As SAVESTRUCT
    Dim x As Long, y As Long, cx As Long, cy As Long
    Dim hGraphics As Long
    
    cx = AlphaImgCtl1.Picture.Width
    cy = AlphaImgCtl1.Picture.Height
    
    Set tImg = New GDIpImage    ' create a new image 10x original width & same height
    SS.Height = cy
    SS.Width = cx * 10
    SS.ColorDepth = lvicConvert_TrueColor32bpp_ARGB
    ' special purpose call to create a new image from nothing (documented)
    SavePictureGDIplus Nothing, tImg, lvicSaveAsPNG, SS
    
    ' get GDI+ hDC-like pointer from the newly created image
    GdipGetImageGraphicsContext tImg.Handle, hGraphics
    ' render each 'tile' to the strip
    For x = 0 To tImg.Width - 1 Step cx
        AlphaImgCtl1.Picture.Render 0&, x, y, cx, cy, , , , , , , hGraphics
    Next
    GdipDeleteGraphics hGraphics  ' release that pointer
    
    Set AlphaImgCtl2.Picture = tImg  ' assign to a new/existing control & size the control
    With AlphaImgCtl2
        .Move .Left, .Top, Me.ScaleX(cx * 10, vbPixels, Me.ScaleMode), Me.ScaleY(cy, vbPixels, Me.ScaleMode)
    End With
    
End Sub
```

----------


## Steve Grant

Many thanks.

Steve.

----------


## VbNetMatrix

> Edited: Since one of the options requires drawing into an AIC, I whipped up an example because I don't think I've provided one of those yet...


Thanks for this code...  was waiting for it long time  :Wink:

----------


## LaVolpe

> Thanks for this code...  was waiting for it long time


Sorry if I didn't reply to a request -- may have just missed it. Hope the example helps.

Note: there are restrictions (bit depths & image format types) regarding usage of GdipGetImageGraphicsContext. Bottom line: suggest bitmap, png and 16bpp or better.

----------


## VbNetMatrix

> Sorry if I didn't reply to a request -- may have just missed it. Hope the example helps.
> 
> Note: there are restrictions (bit depths & image format types) regarding usage of GdipGetImageGraphicsContext. Bottom line: suggest bitmap, png and 16bpp or better.


Thanks Keith, very much appreciated...  
as a side note, I work ONLY with BMP and PNG
(for image quality purpose)

----------


## Black_Storm

hi,i hv two problem now.
1- i created new user control and then i used aic control in it too.i want create new property or new method for use some of functions or others to use it.
for exampe i created this sub :


```
private sub loadimage()
' i want use LoadPictureGDIplus from aic control
LoadPictureGDIplus (...)
end sub
```

my porblem is about functions called from aic control in my user control.
when i want write function name.vb can know it but when i type ( for example "LoadPictureGDIplus(" vb dont know this function with parameters.
and when i use LoadPictureGDIplus with parameters and when i want use my user control vb show error to me about LoadPictureGDIplus unknow function or ... .

how can fix it?

----------


## Black_Storm

hi,my problem in *#636* not fixed yet and i am waiting to answers.

and i hv 2 problem now,can help me for fix it?
1- i writed my problem in my picture :

my problem is about when i want use aic control compiled(ocx of it) on vb.net form.
when i add and set image i can not see image in box on form.how can fix it?



2-i designed my user control and used aic control in it too.i set properties like picture and i compiled and worked in vb6 good but when i wanted test my ocx(my user control compiled) in vb.net i can see just background of aic control without any image(my user control is transparent but aic control is just opaque and dont show images too),how can fix it?

----------


## LaVolpe

I can't answer your questions regarding vb.net

There is a lot of documentation on requiring VB user controls to be modified for .net. I think Microsoft event created some conversion/migration functions, but not sure. You may want to browse the .NET portion of the forums for answers regarding VB6 user controls. Key search terms: VB6 usercontrol migration

----------


## Black_Storm

> I can't answer your questions regarding vb.net
> 
> There is a lot of documentation on requiring VB user controls to be modified for .net. I think Microsoft event created some conversion/migration functions, but not sure. You may want to browse the .NET portion of the forums for answers regarding VB6 user controls. Key search terms: VB6 usercontrol migration


1-#636 not answered yet ( its about vb6) ( i can not call  loadgdipplus or other functions when i used aic user control in my user control)

2-i created a user control in vb6 and properties seted to transparent backstyle and tested in vb.net and worked good so my problem is not about user control my question is about aic user control because when i want use aic user control in vb.net backcolor is opaque so problem is about aic.

3-i hv a question about how use  UserDocument class , i want get percent ( 0 to 100 progress) of download and show percent in form too,i readed about UserDocument class and events in it like AsyncReadProgress(AsyncProp As AsyncProperty) and AsyncProp.BytesMax,AsyncProp.BytesRead.can u send a sample code for download more than 1 pictures as async and with percent downloading(0 to 100)?

----------


## Arnoutdv

You should really start a new thread for your problems.
The problems you have are not bugs in the control, but have to do with how you want to use the control.

And if you are not satisfied with the control you should ask for a refund.

----------


## LaVolpe

> 1-#636 not answered yet ( its about vb6) ( i can not call  loadgdipplus or other functions when i used aic user control in my user control)


Can you show me how you are using the control in your project? Specifically, the project tree view. Group project? Is the AIC compiled to an ocx? More details needed.




> 2-i created a user control in vb6 and properties seted to transparent backstyle and tested in vb.net and worked good so my problem is not about user control my question is about aic user control because when i want use aic user control in vb.net backcolor is opaque so problem is about aic.


Already mentioned, I can't answer your .Net questions. The control was designed for VB6 not .Net and .Net can have issues with VB6 developed controls.




> 3-i hv a question about how use  UserDocument class , i want get percent ( 0 to 100 progress) of download and show percent in form too,i readed about UserDocument class and events in it like AsyncReadProgress(AsyncProp As AsyncProperty) and AsyncProp.BytesMax,AsyncProp.BytesRead.can u send a sample code for download more than 1 pictures as async and with percent downloading(0 to 100)?


This should be posted in the VB forums as it appears to have nothing to do with this control.





> And if you are not satisfied with the control you should ask for a refund.


And being the Xmas holiday week - refunds are extended for another year  :Wink:

----------


## Steve Grant

Hopefully just a quickie. I realised this morning that the sizes for my Coverart were always returned correctly by Alpha, but the colour depth isn't.

I am attaching a Cover which I believe is 24BPP but alpha reports 32. Mp3Tag and Irfanview show the same sizes but only 24BPP.

----------


## LaVolpe

How is the cover art being extracted? Your attachment is JPG (forums probably converted it).

Is the cover art being resized before being added to the AIC? Reason I ask is that resizing can introduce 32bpp alphadepending on the interpolation method. GDI+ can blur the edges when higher interpolation modes are used. This alphablending may not be noticeable by the human eye (typically 1 pixel edges), but exists nonetheless. In addition, using the clipboard to set an image can report the image as 32bpp because the DIB placed on the clipboard may be 32bpp when the O/S screen depth is 32bpp. 
Edited: Clipboard scenario was incorrect/misleading. The 32bpp scenario applies to screen captures and DIB placed on clipboard.

Otherwise, probably going to need the source file zipped up so I can take a look see, if it's important enough. If the source is MP3 or WMA, the parsing routines will attempt to use the cover art, as-is, if only 1 image exists. If multiple images exist, a conversion from the original format to TIFF is performed, per image, and all images in the source become a multi-page TIFF. But IIRC, there is no conversion to other bit depths during the process of adding the image to a TIFF page (exception may be color-lossless depth reduction to 24/8/4/1 from higher depth, if possible)

Edited: Why multi-page tiff? The AIC has no way of returning multiple images in any format other than ICO/CUR/GIF/APNG/TIFF. GIF is restricted by depth (8bpp or less), APNG not a widely accepted format, and ICO/CUR not really appropriate in this case. Since the parsing routines weren't designed to return an array of images, TIFF seemed an acceptable solution since each tiff page can be a different color depth and size from any other page. In addition, the AIC has methods to navigate/select individual pages

----------


## Steve Grant

Thanks for looking at this Keith. I don't use the AIC for extraction as my programme can load and play any format.

The AIC is on Form2 'the Edit form' and I have set the AIC to scale the images to its size. I use the TagsLibrary dll from 3delite over at Un4seen.com. It sends the data out as a stream so I do the following;



```
If CoverArt.Data <> 0 Then 'See is there is any data in memory
            Form2.A1.Picture = LoadPictureGDIplus(PFM.MemToHBitmap(ByVal CoverArt.Data, ByVal CoverArt.DataSize.LowPart - 1)) 'Get an hBitmap handle from the memory and pass it to AIC. jpg's only.
        End If
```

I can use the same handle (converted to stdpicture) to load an image control. Both the Image and the AIC report the same sizes. But the image handle sent to GetObject returns 24bit AIC returns 32. Also mp3Tag, dbPoweramp and Irfanview report 24.

----------


## LaVolpe

First. That image is JPG. When loaded into VB image/picturebox, the JPG is converted to bitmap. Therefore, what is being passed from the .Picture.Handle property is a 24bpp bitmap handle. If you were to load that JPG file into the AIC or pass the VB image/picturebox .Picture.Handle value, you should get 24bpp also.

This JPG you posted must have been converted from bitmap at some point?

Your MemToHBitmap() returns a bitmap handle not a JPG. When a handle is passed to AIC, it is processed by modCommon.pvProcessGDIhandleSource. That routine uses API GetObject to return info about the handle. Included in that info is the bit depth. If the depth is being reported as 32bpp, then that explains it. Now, if bit depth returned in that info < 32, then the routine calls GdipCreateBitmapFromHBITMAP API to create a GDI+ image from that handle. I doubt that API creates a 32bpp image from the handle if the handle was to a 24bpp image.

As a more definitive test, suggest this and let me know what it returns.


```
hBmp = PFM.MemToHBitmap(ByVal CoverArt.Data, ByVal CoverArt.DataSize.LowPart - 1)
GetObject hBmp, Len(udtBmp), udtBmp: Debug.Print udtBmp.bmBitsPixel
DeleteObject hBmp
```

Edited: If GetObject info indicates 32bpp, here is what I'm thinking... MemToHBitmap creates a DIB based on the O/S screen depth, then converts the cover art image to bitmap and passes that DIB handle. Since your screen depth is likely 32bpp, a 32bpp handle.

----------


## Steve Grant

Ok the returned value is 32. Here is the code for the converter, it is part of a Class from Emil Weiss. It doesn't look like it uses the clipboard but I am sure you will pinpoint the problem.

Just so I understand, if I load the same jpg into an image control using LoadPicture it still says 24. is that for the reasons stated above? I can post the entire class if you want.



```
Public Function MemToHBitmap(ByVal DataPtr As Long, ByVal Size As Long) As Long
    Dim bArray() As Byte
    Dim stream As IUnknown
    Dim Img As Long
    Dim hBitmap As Long

    ' Array Redimensionieren

    ReDim bArray(Size - 1)
    CopyMemory bArray(0), ByVal DataPtr, ByVal Size

    ' Stream erstellen
    CreateStreamOnHGlobal bArray(0), False, stream

    ' ist ein Stream vorhanden
    If Not (stream Is Nothing) Then

        ' GDI+ Bitmapobjekt vom Stream erstellen
        If Execute(GdipLoadImageFromStream(stream, Img)) = OK Then

            ' Handle des Bitmapobjektes ermitteln
            If Execute(GdipCreateHBITMAPFromBitmap(Img, hBitmap, 0)) = OK Then

                ' hBitmap zurück geben
                MemToHBitmap = hBitmap
            End If

            ' Bitmapobjekt löschen
            Execute GdipDisposeImage(Img)

        End If
    End If

End Function
```

----------


## LaVolpe

Took a little bit to troubleshoot. The answer: GdipCreateHBITMAPFromBitmap creates a 32bpp bitmap from at least 24bpp images. Not tested whether this also applies to 16 bits or less.

Bottom line: AIC is reporting correctly. The bitmap depth associated with the handle from your routine is 32bpp. If you were to pass the MP3/WMA file name to the AIC, you'd likely return the 24bpp bitmap/jpg you are expecting.

Note to self: Should I ever rebuild this project, that's another thing I'll have to keep in mind. I also use that API in some cases and wasn't aware it appears to use the screen color depth when creating a bitmap. Never fully tested that API to understand various what-if scenarios.

Oops, didn't answer your other question



> Just so I understand, if I load the same jpg into an image control using LoadPicture it still says 24. is that for the reasons stated above?


Kinda apples and oranges. JPG and BMP are different animals. That function you posted does not produce JPGs, it produces a bitmap. _Your JPG is coming from some other routine_. Regarding JPGs, VB converts JPG internally to BMP in order to display it in the image/picturebox controls. All JPGs should report 24bpp or less; therefore, VB's .Picture.Handle will be a 24bpp (or less) bitmap. The problem, if you want to call it that, is your routine's GdipCreateHBITMAPFromBitmap defaulting to screen depth in this case.

In fact, if you use a function like "HandleToStdPicture" and pass the hBmp returned from your function to create a stdPicture object for VB's use, then GetObject will return 32bpp when passed .Picture.Handle.  BTW: HandleToPicture or HandleToStdPicture can be found on this site for converting a hBmp handle to a VB stdPicture object. It is also available in the AIC: modCommon.HandleToStdPicture


```
' copy HandleToStdPicture and related APIs to your form, then...
hBmp = PFM.MemToHBitmap(ByVal CoverArt.Data, ByVal CoverArt.DataSize.LowPart - 1)
Set Me.Picture = HandleToStdPicture(hBmp, vbPicTypeBitmap)
GetObject Me.Picture.Handle, Len(udtBmp), udtBmp: Debug.Print udtBmp.bmBitsPixel
```

----------


## Steve Grant

Thank you very much. There was me thinking it might be a 'quickie'!

Happy New Year to you & yours.

----------


## Black_Storm

> Can you show me how you are using the control in your project? Specifically, the project tree view. Group project? Is the AIC compiled to an ocx? More details needed.
> 
> Already mentioned, I can't answer your .Net questions. The control was designed for VB6 not .Net and .Net can have issues with VB6 developed controls.
> 
> This should be posted in the VB forums as it appears to have nothing to do with this control.
> 
> 
> And being the Xmas holiday week - refunds are extended for another year




1-i maked a copy of aic orginal source and then opened.then added another user control under aic user control and then used aic control in my user control.then i create a new property for example loadpic name by vb6 activex interface wizard and then when i called loadgdiplus or other functions so vb know that function but dont know parameter so show error to me about unknow function called.

about question 3 : my means about use aic control because i seen UserDocument class  in aic control and events definiition of it and i seen AsyncReadProgress(AsyncProp As AsyncProperty) and AsyncProp.BytesMax,AsyncProp.BytesRead. too in aic control. i want use aic control and get percent of download image between 0 to 100 %and show on form too.i think if i can use AsyncProp.BytesMax and AsyncProp.BytesRead used in UserDocument class of aic control so i can make percent but my problem about how use of this class?can  you send a simple sample to how use aic control and use UserDocument class to can get percent of download?

----------


## LaVolpe

Ah, now I understand the problem for #1. Those functions are part of a class. The class is "Global" for projects that include the AIC, not for the AIC itself. If you'll look at code in the AIC, you will notice no code calls those functions, rather they call the functions in the bas module. Since the bas module cannot be made public to projects that include the AIC but a class can, the class wraps some of the bas module functions. If you want the intellisense, you'll need to create an instance of the class and then call the functions in that class, then release the class.

Regarding #3. There are many examples on this site and one exists in this codebank for using a usercontrol to download from the internet with a percent-like status. Here is one: http://www.vbforums.com/showthread.p...tra-dependency

----------


## Black_Storm

i want use aic for download images but i want can see percent download too and show on form percent.how can do that?how can use of "UserDocument class" dinnifition in aic in my project too? can i use of their events ? can u send a simple sample ?

----------


## LaVolpe

You can use another usercontrol (or other methods) to download whatever you want. With those other methods, create your percentage display as needed, and when the complete file has been downloaded, then send the data to the AIC to display the image. You are asking questions that are not relative to this control and I am not not going to help you modify/rewrite my control for your purposes. If you have questions about UserDocuments, post those in the questions portion of the forum. Good luck.

----------


## Black_Storm

any body here can help me about show png image on form or desktop with blur effect under it ?
my thread : how can show my png image on form with display blur effect under it-need user control

----------


## Black_Storm

> any body here can help me about show png image on form or desktop with blur effect under it ?
> my thread : how can show my png image on form with display blur effect under it-need user control


can i use aic control for display image with blur effect under it ? if possible so how?
i want test on form and use for dekstop (layred windows ) too

----------


## Arnoutdv

@Black_Storm, please start your own threads for questions
You are polluting this CodeBank submission with questions about your own project.

----------


## Black_Storm

hi i hv new question when i want use aic control,
1-i want just a png image and when resize to horizontal or vertical then repeat image like repeater(i want use png or apng image and use resize action too.(like attached picture)
how can do that?
i want like number 2 after resize 


2-i am using aic control, now i want make mask clipping how can do that like this picture?
or any other idea?


3- i am doing use aic control but now i want put my pnd or apng image on other controls like text box frame or .... ? (see this picture)
if not possible so any idea?

----------


## LaVolpe

1. Repeating, tiling. In the previous page (post 631), I gave an example of creating a blank GDIpImage and drawing into it. You can use something like that to create an image on the fly. You could also look at the TilePictureGDIplus global function, but that draws to a DC, does not create a new image.

2. Mask clipping. Never looked into it. Your animation looks neat. I'd imagine this would not be something really simple. One may need to define pixels in 3D space and apply 3D rendering algorithms? That's just a guess and good luck -- should be challenging.

3. You have asked this question several times in the other part of the forums. I'm not going to use this thread to discuss topics not related to this control. I've said that before and from this point forward, will simply ignore such questions in the future. Sounds like you are using my control inside another one you created and/or extracting my controls code for your own purposes. That's not a problem, but I'm not going to spend time making that work for you, or anyone else. No insult intended.

----------


## Black_Storm

> 1. Repeating, tiling. In the previous page (post 631), I gave an example of creating a blank GDIpImage and drawing into it. You can use something like that to create an image on the fly. You could also look at the TilePictureGDIplus global function, but that draws to a DC, does not create a new image.
> 
> 2. Mask clipping. Never looked into it. Your animation looks neat. I'd imagine this would not be something really simple. One may need to define pixels in 3D space and apply 3D rendering algorithms? That's just a guess and good luck -- should be challenging.
> 
> 3. You have asked this question several times in the other part of the forums. I'm not going to use this thread to discuss topics not related to this control. I've said that before and from this point forward, will simply ignore such questions in the future. Sounds like you are using my control inside another one you created and/or extracting my controls code for your own purposes. That's not a problem, but I'm not going to spend time making that work for you, or anyone else. No insult intended.


i writed tag in question about png or *apng*,how work with animated png too ? i seen post 636 but was been about single image static. can u send a sample code to can repeat apng too(my means i want duplicate one animation to example 10 count in result was been in a single image box) 

2- i dont work with 3d space but i want just can use mask clipping for can show something under my image or front on my image by hidding some curves,no way ? or simple mask cliping sample code ?

3-because i am waiting for find solution for this problem yet.

----------


## Black_Storm

> i writed tag in question about png or *apng*,how work with animated png too ? i seen post 636 but was been about single image static. can u send a sample code to can repeat apng too(my means i want duplicate one animation to example 10 count in result was been in a single image box) 
> 
> 2- i dont work with 3d space but i want just can use mask clipping for can show something under my image or front on my image by hidding some curves,no way ? or simple mask cliping sample code ?
> 
> 3-because i am waiting for find solution for this problem yet.


can u send a sample code for repeat apng too ?

----------


## Cube8

Can some moderator/admin please move those posts to a new thread?
This thread is not for supporting the usage of the control.

----------


## Black_Storm

> Can some moderator/admin please move those posts to a new thread?
> This thread is not for supporting the usage of the control.


my apng image is like this (left image) :



i want when i resize my aic control horizontal so can see right image result.how can do that ?

----------


## Cube8

> when i am useing aic so why i shoulld be create new thread and when i am use apng supported format in aic control so why i shoulld be create new thread about work with aic control? maybe possible with aic control and other code


The purpose of this thread is to provide code for download and maybe some clarification about its usage.
For more help/support, you should create a thread under Visual Basic 6 and Earlier forum, in order to avoid clutter in this one.

----------


## LaVolpe

@Black_Storm. Remember that this tool is primarily for displaying images, not an image editor/composer. It isn't a mini-paint program. In addition, I already warned you that once you decided to modify my code for your purposes, my support would be limited, if at all.

Above being said, you have to understand APNG to even attempt to build it frame by frame, which would be needed in this case. It might be doable by filling in a MULTIIMAGESAVESTRUCT and passing that to SavePictureGDIplus. No guarantees.

----------


## Black_Storm

hi, i want create a simple app like paint but i want use aic control and then i want these parameters :

1-can open a image size more than 7000 px in 7000px.
2-can zoom in or zoom out in it. (mouse wheel support)
3-can move in zoomed image like hand cursor
4-can draw rectange or star or another png image on my master image
5-can draw text on my master image with custom size or font or color 
6-can undo or redo
7-and finally can save image edtied in another place.

can u have a simple source code aic used to can use in my project 
and my question is about each numbers.

for example :
about 1:  can use these sizes(more than 7000 px width or height in aic?) (can u send a sample code or source code to can use?)
about 2: how can zoom in or zoom out with aic?(can u send a sample code or source code to can use?)
about 3: how can move like hand cursor in aic zoomed?(can u send a sample code or source code to can use?)
about 4 : how can draw another aic image on my master aic image  control?(can u send a sample code or source code to can use?)
about 5: how can draw text with customize color or font  on my aic control?(can u send a sample code or source code to can use?)
about 7-how can merge all layers or images mereged in aic control?(can u send a sample code or source code to can use?)

----------


## Black_Storm

hi, i tested this code on windows 7 and work good :
for run i should be use  2 aic control names ( aicFace and aicHour ) on form.
i used this code for blend 2 images and then save as png .



```
Dim tmpc As Integer
 tmpc = 0
 tmpc = Val(ucPic.Tag)
 tmpc = tmpc - 1

 Dim imgClockFace As GDIpImage
 '
 Set aicFace.Picture = LoadPictureGDIplus(App.Path & "\actions\temp" & tmpc & ".jpg", True)
 aicFace.Left = 0
 aicFace.Top = 0
 aicFace.Width = aicFace.Picture.Width
 aicFace.Height = aicFace.Picture.Height
 '
 '
 Dim idx As Byte
 idx = 0
 If op(0).Value = True Then idx = 0
 If op(1).Value = True Then idx = 1
 If op(2).Value = True Then idx = 2
 If op(3).Value = True Then idx = 3
 '
 Set aicHour.Picture = LoadPictureGDIplus(App.Path & "\tmpalamat\idx" & idx & ".png", True)
 aicHour.Left = 0
 aicHour.Top = 0
 aicHour.Width = aicHour.Picture.Width
 aicHour.Height = aicHour.Picture.Height
 Dim pms As PICTUREMERGESTRUCT
 If imgClockFace Is Nothing Then Set imgClockFace = aicFace.Picture

 With pms
 .CanvasHeight = aicFace.Height
 .CanvasWidth = aicFace.Width
 .Pictures = 2
 ReDim .MIS(0 To 1)
 Set .MIS(0).Picture = imgClockFace
 .MIS(0).Width = pms.CanvasWidth
 .MIS(0).Height = pms.CanvasHeight
 Set .MIS(1).Picture = aicHour.Picture
 .MIS(1).Left = X - (a(idx).Picture.Width \ 2)
 .MIS(1).Top = Y - (a(idx).Picture.Height \ 2)
 .MIS(1).Width = aicHour.Width
 .MIS(1).Height = aicHour.Height

 End With
 
 

 Set aicFace.Picture = MergePictureGDIplus(pms)
 SavePictureGDIplus aicFace.Picture, (App.Path & "\actions\temp" & Val(ucPic.Tag) & ".png"), lvicSaveAsPNG
```

but same code not worked in windows 10 because of this part :



```

 With pms
 .CanvasHeight = aicFace.Height
 .CanvasWidth = aicFace.Width
 .Pictures = 2
 ReDim .MIS(0 To 1)
 Set .MIS(0).Picture = imgClockFace
 .MIS(0).Width = pms.CanvasWidth
 .MIS(0).Height = pms.CanvasHeight
 Set .MIS(1).Picture = aicHour.Picture
 .MIS(1).Left = X - (a(idx).Picture.Width \ 2)
 .MIS(1).Top = Y - (a(idx).Picture.Height \ 2)
 .MIS(1).Width = aicHour.Width
 .MIS(1).Height = aicHour.Height

 End With
```

when i changed lines to comment so program runed but without my result.
i want know why this source code work on win7 but not work on win10? and how can fix this code to can use in windows 10 too?

----------


## LaVolpe

Can you be more specific as to what did not work? In the code you posted, are any of the values 0 or image references set to Nothing? You really didn't give me enough information to go on.  Could be helpful to post the saved image from Win7 and the saved image in Win10.

Also, ensure your app has write permissions to: (App.Path & "\actions\temp" & Val(ucPic.Tag) & ".png")

----------


## VbNetMatrix

Hi Lavolpe, 

recently I started to have random crash with AIC as if Microsoft made a patch where the garbage collector make something where the parent container initialize after the init event...  anyway, 

m_HitTestPts is empty sometime when sptGetHitTest() is called and that result in subscript out of range on line:

If m_HitTestPts(pNew).X > m_HitTestPts(pOld).X Then

any idea how I could fix this ?

it happen only in IDE, but I have to reboot the IDE like hundred of time a day... very annoying.  when it happen, any compiled OCX made with AIC crash with the error "there is no licence for this component"

plz help!

----------


## LaVolpe

Can you reproduce the error on demand?

In the sptGetHitTest() routine, m_HitTestPts array should already be filled and is tested when the HitTest property is either lvicEntirelImage or lvicTrimmedImage, control is enabled (default), has a picture assigned, and mouse events are wanted (default). The sptGetHitTest() routine is called when mouse is over the control or releasing the mouse button during a click/drag event.

Each time the hit test should be recalculated, the m_RenderFlags is updated to include the bit: render_DoHitTest. This is triggered in a couple of events: Paint, changing the HitTest property, and WantMouseEvents property. 

You can try adding this: 


```
        If (m_RenderFlags And render_DoHitTest) Then
            If m_HitRegion = 0& Then Call sptCreateHitTestPoints(m_HitRegion)
        End If
```

to the sptGetHitTest() routine, immediately after the statement: _If UserControl.Enabled Then_

Theoretically, that could be a valid sanity check that may solve the problem. Just can't think of any combination you are using that could be causing the problem. Only thing that comes to mind is DoEvents possibly, maybe the UserControl_Hide() event not triggering (that releases the timer used to check for mouse over/leave events)

----------


## VbNetMatrix

> Can you reproduce the error on demand?
> 
> In the sptGetHitTest() routine, m_HitTestPts array should already be filled and is tested when the HitTest property is either lvicEntirelImage or lvicTrimmedImage, control is enabled (default), has a picture assigned, and mouse events are wanted (default). The sptGetHitTest() routine is called when mouse is over the control or releasing the mouse button during a click/drag event.
> 
> Each time the hit test should be recalculated, the m_RenderFlags is updated to include the bit: render_DoHitTest. This is triggered in a couple of events: Paint, changing the HitTest property, and WantMouseEvents property. 
> 
> You can try adding this: 
> 
> 
> ...


Hi Lavolpe, thanks for your answer.
I'm not using DoEvents (EVER) I consider it a "last" resort that has the potential to crash a program... for many reason you just mentionned.

I can reproduce the bug.  it appeared on my  dev machine recently (4 month ago) after a Microsoft Patch wich I can't retrace now.  Oh... btw, stay FAR away from feb 13 2018  kb 4011686   (126mb)  it's a Office 2016 Patch.  if you install it, Vb IDE crash when you "open" an Access Database using ADO.  Compiled EXE are sane though.

anyway, like I said about AIC, if I make "any" project with it, even an empty one and start the program (F5) in IDE, sometime it work, sometime it crash... normally, less then 5 attempt, make it crash.  the time you spend between retry has no incidence, it's not a timing issue.

I'm about to reformat my machine soon to see if that fix the problem.  only Vb6 IDE is affected. (safe for Office 2016 patch)  ... strange... seem almost intentional  :Wink:

----------


## georgekar

Use a virtualbox with a fresh os.

----------


## lethalthret

just wanted to say thanks the control is awesome and helped me to understand alot

----------


## bardar

Hello, first of all I must say that the control is fantastic. I am very ignorant about programming and I am "very basic user". So I hope you will forgive me for my question: is it possible to copy the image loaded in a standard picturebox and modified with drawing commands (line, circle, ...)  in an AIC ? If yes, which is the syntax I would use ? (I tried: Set AIC.picture = Picturebox1.picture but, of course, it does not work). I would like to avoid the need to save to disk the content of Picurebox1 and load again into AIC. Many thanks in advance for your reply

----------


## DaveDavis

It's a very valuable material to study GDI+ and do photographic programming.
Have anyone converted to .NET?

----------


## jeakins01

Awesome control.  We use it throughout our programs.  Any update on the release of v3 of this control?

----------


## LaVolpe

> Awesome control.  We use it throughout our programs.  Any update on the release of v3 of this control?


I'm not sure - lost a bit of interest. I have torn this thing down at least a dozen times and was never happy with the end result. With the ability to use thunks along with GDI+ to render directly into VB image controls. I'm not even sure something like this control is even worth the effort of maintaining, other than it's a convenience for those not fluent with GDI+.

I wouldn't hold my breath for an update since I have gone in different directions... but never say never.

----------


## jeakins01

Are there any examples of copying a part of the current form screen to this AIC control.  I have tried several methods and they are not working.  Using BitBlt to copy to a picture object and using LoadPictureGDIPlus to load it into the control.  I get invalid picture object.  The goal is that I then want to use the control to rotate the captured screen image section.

----------


## LaVolpe

If you open the class: AICGlobals, and look at the samples in the method: LoadPictureGDIplus, you will see a really simple potential solution. You'll also want to set the Rotation, Aspect and other applicable properties of the control.


```
AlphaImgCtl1.Picture = LoadPictureGDIplus(Screen)
```

If you are interested in the code behind that call, then open the module and look at the bottom of the method pvProcessObjectSource for the line: ElseIf TypeOf Source Is Screen Then

Note: The above will do the entire screen. Since you only need part of the screen, reviewing the code behind the call would be useful.

----------


## tmighty2

I love this control very much! I use it to drag pictures from Chrome to VB6.
It works great.

However, there is a situation where VB6 can hang.

Do you think you could have a look, please?

Could you please start Chrome and then search for an image?

In my case, I have searched for "schleudern".
Then I have dragged the image of the girl onto the LaVolpeAphaImg.

The first time you do this, nothing will happen. The image won't show up in the control, but it won't hang.
Now when you try it again, VB6 will hang.
I have taken a quick look what happens in the control, but I soon got into the complex parts of the code.

Do you think you could take a look?

Thank you so much!!

ps: I have a recorded a 

 to show what I'm doing.

----------


## tmighty2

I just noticed that the control has got its final update.
Also, it works perfectly fine with Firefox, so I guess it's a problem with how Chrome handles this image dragging... it shows this "collection bar" where the user can drop the image.
So I do have a solution for this problem.

----------


## tmighty2

Unfortunately the same problem occurs with Firefox. So it's browser independent, but it seems to happen if the google collection bar appears.

----------


## shagratt

Can Alpha Image Control be used to draw a 8bit transparency image in a transparent form? I'm failing to do it.  
I can make the form transparent, but alpha image controls mix the backcolor of the form instead of transparency.

----------


## hennyere

> *NOTICE :: NOTICE :: NOTICE*
> Version 2 of the control came to an end. No new enhancements will be added to version 2. Bug fixes _may_ be applied as they are discovered. Support for version 2 will eventually cease.
> 
> Version 3 of the control will replace version 2 and will be DPI-aware. This will result in how images are loaded and displayed on a PC based on DPI settings (XP and above). In the case of icons/cursors, it may also result in which sized icon is displayed, based on current DPI settings. Externally, how you use this control will not change very much. Internally, a logical coordinate space will be used for all measurements and storage of properties, unlike the physical coordinate space now used. Like VB, this control will use twips internally. Externally to control users, pixels will still be used. DPI awareness will also be a customizable property. To properly support DPI-awareness,* binary compatibility will be broken*; hence a new version.
> __________________________________________________________
> 15 Jan 2012. Minor patch applied. See change history below
> ----------------------------------------------------------
> 
> *Purpose*: A control that allows viewing & creating many image formats, particularly alpha-blended ones. 
> ...


Hi, Lavolpi!

Where can I find the latest version of Alpha Image Control v2?

Regards!

----------


## LaVolpe

Version 3 is on my list of things to do. Not done yet and don't know when it will get done.

----------


## doss

[QUOTE=LaVolpe;4073183]Regarding cropping: Well, you can already do that with existing methods:



```
Option Explicit
' in this example, the control's parent scalemode is pixels

Private Sub AlphaImgCtl1_Click()
    CropImage AlphaImgCtl1, 30, 30, 100, 100
End Sub

Private Sub CropImage(theImage As AlphaImgCtl, X As Long, Y As Long, _
                        Width As Long, Height As Long)
    
    ' the AlignCenter property should already be set to False for better runtime visual change
    With theImage
        .SetRedraw = False
        .AlignCenter = False
        .AutoSize = lvicNoAutoSize
        ' ensure X, Y are pixel scalemode 
        .SetOffsets -X, -Y
        ' ensure X, Y, Width, Height are appropriate container scalemode
        .Move .Left + X, .Top + Y, Width, Height
        .SetRedraw = True
    End With
        
End Sub
```

Edited yet again. The above code works extremely well if Aspect is actual size; otherwise, it doesn't because resizing the control changes the dimensions of rendered image which means it isn't really designed to crop while stretched or scaled without a lot of extra calculations from you, including drawing in the PrePaint event (or saving the image to a new GDIpImage object with scaled dimensions ahead of time)

*********************************************************
Hi Lavolpe I just now try this code for cropping function. It's work very well.

but I have an issue.
:CropImage AlphaImgCtl1, 30, 30, 100, 100:

Now I altered the values to this

CropImage AlphaImgCtl1, 0, 0, AlphaImgCtl1.Picture.Width , AlphaImgCtl1.Picture.Height

After result Image Crop height size is Ok but Image width size is crop to my desktop screen resolution width only.

Selected Image width size is 1800 pixels. After result it crop to my desktop screen resolution (1366) width only

Please help me how to crop an image actual width.

Thanks Advance. :wave:

----------


## LaVolpe

Replied to your PM. Basically, there are some restrictions made within the code to prevent the AIC from being sized larger than a full screen. The restrictions can be found, and commented out, in sptGetScaledSizes

----------


## zeilo

Dear LaVolpe.

A photo when opened in image editing programs is displayed correctly, however when loaded in Alpha Image Control it is automatically rotated counterclockwise.



The image is 3456x4608 72 dpi jpg photo from a smartphone.

Any guess about what is happening?

Thank you in advance!

----------


## shagratt

> Any guess about what is happening?


Yes, that's because your photo got information about orientation in the EXIF information saved from the camera/phone wich take it. Some programas read it and change orientation based on that. Other software ignore it and just display the image as it was saved.

----------


## zeilo

Thank you very much shagratt!!!

I think there is a bug in the *SetClipRect* method:

'/// sets optional clipping on the rendered image. Border usage is exempt from clipping
Public Sub SetClipRect(ByVal X As Long, ByVal Y As Long, ByVal Width As Long, ByVal Height As Long, Optional ByVal Refresh As Boolean = True)
Attribute SetClipRect.VB_Description = "Method clips the control's graphic output"
    ' pass width and/or height as zero to remove clipping rectangle
    If (Width Or Height) = 0 Then
        SetRect m_ClipRect, 0&, 0&, 0&, 0&
        If Refresh Then UserControl.Refresh
    ElseIf (Width > 0& And Height > 0&) Then
        SetRect m_ClipRect, X, Y, Width + X, Height + *X*
        If Refresh Then UserControl.Refresh
    End If

End Sub

It should be *Height + Y* instead of *Height + X*

----------


## LaVolpe

@Zeilo. Yes, should be Hieght + Y

Regarding JPG. To address the camera orientation, the information should exist in the JPG's metadata and if it does exist, auto-orientation can be applied to correct it. Here's how to adapt the AIC for those types of JPGs.

1. In modCommon LoadImage function, find this line: Case lvicPicTypeJPEG
Immediately after that line, insert this: Call pvAutoOrientateJPG(cImageData)

2. At the bottom of modCommon, add the new pvAutoOrientateJPG method


```
Private Sub pvAutoOrientateJPG(cImageData As cGDIpMultiImage)

    Dim lSize As Long, lValue As Long
    Dim arrData() As Byte, lOrient As Long
    Dim tImageData As cGDIpMultiImage, hBmp As Long
    Const PropertyTagOrientation  As Long = &H112&

    GdipGetPropertyItemSize cImageData.Handle, PropertyTagOrientation, lSize
    If lSize = 18& Then
        ReDim arrData(0 To lSize - 1&)
        If GdipGetPropertyItem(cImageData.Handle, PropertyTagOrientation, lSize, arrData(0)) = 0& Then
            CopyMemory lSize, arrData(4), 4&
            If lSize = 2& Then
                CopyMemory lValue, arrData(8), 4&
                If lValue = 3& Then
                    lOrient = arrData(16) Or arrData(17) * &H100&
                    Select Case lOrient
                    Case 2, 4: lOrient = lOrient + 2    ' RotateNoneFlipX, Rotate180FlipX
                    Case 6, 8: lOrient = lOrient - 5    ' Rotate90FlipNone, Rotate270FlipNone
                    Case 1, 3: lOrient = lOrient - 1    ' Rotate180FlipNone
                    Case 5, 7                           ' Rotate90FlipX, Rotate270FlipX
                    Case Else: lOrient = 0&             ' invalid value
                    End Select
                End If
            End If
        End If
    End If
    If lOrient > 0& Then
        GdipImageRotateFlip cImageData.Handle, lOrient
        GdipCreateHBITMAPFromBitmap cImageData.Handle, hBmp, -1&
        If hBmp <> 0 Then
            Set tImageData = New cGDIpMultiImage
            pvProcessGDIhandleSource tImageData, hBmp, False
            Set cImageData = tImageData
        End If
    End If

End Sub
```

3. Add this new API towards top of modCommon


```
Private Declare Function GdipImageRotateFlip Lib "GdiPlus.dll" (ByVal pImage As Long, ByVal rfType As Long) As Long
```

With the above changes, all JPGs will be tested for non-standard orientation and auto-corrected. If auto-correction is needed, then the JPG will be converted to a Bitmap and no longer be a JPG. If no auto-correction is needed, no action taken.

----------


## zeilo

Thank you very much LaVolpe!!!

Great job! Now is working perfectly!

----------


## zeilo

Thank you very much LaVolpe!!!

Great job! Now is working perfectly!

----------


## Black_Storm

i have new problem for open orginal source.when i want open source just see this error : expersion too complex how can fix that?

----------


## LaVolpe

> i have new problem for open orginal source.when i want open source just see this error : expersion too complex how can fix that?


Search the code for "Not Not". I don't think I use that code in that project, but am not looking at the code right now. You may have that code in another part of your project somewhere. If so, post the question in the general questions portion of the forum. If you find it in the alpha image control, let me know. I can take a look tomorrow when I get home from work.

Ugh, I see you posted the question several times elsewhere. At least figure out which control is generating the error vs. sending this question to each person that wrote a control you are using, hoping one of them will do your debugging for you.

----------


## Black_Storm

> Search the code for "Not Not". I don't think I use that code in that project, but am not looking at the code right now. You may have that code in another part of your project somewhere. If so, post the question in the general questions portion of the forum. If you find it in the alpha image control, let me know. I can take a look tomorrow when I get home from work.
> 
> Ugh, I see you posted the question several times elsewhere. At least figure out which control is generating the error vs. sending this question to each person that wrote a control you are using, hoping one of them will do your debugging for you.



i find a way for fix this porblem but i think this is not good idea,i unchecked ax-tools code smart 2013 from add in manager and then restart vb and no problem now,i think this porblem is about IDE editor.

but i have a simple question now 

i loaded a image from https like as this :


```
Private myloader As AICGlobals
Set myloader = New AICGlobals
'img is alpha image control
Set img.Picture = myloader.LoadPictureGDIplus("https://.... url",,false)
```

for example this image is 300*300 pixel,now i want save this picture to png format croped to 230*230.
this code workd for me for save just 



```
myloader.SavePictureGDIplus img.Picture, SavePath, lvicSaveAsPNG
```

but how can crop and save?

----------


## LaVolpe

Cropping? Start on page 7, post 245. Read that one and the next few. There are a couple options & sample code

----------


## Black_Storm

> Cropping? Start on page 7, post 245. Read that one and the next few. There are a couple options & sample code


i used your code :


```

     With tmpimg
        .SetRedraw = False
        .AlignCenter = False
        .AutoSize = lvicNoAutoSize
        ' ensure X, Y are pixel scalemode
        .SetOffsets -0, -0
        ' ensure X, Y, Width, Height are appropriate container scalemode
        .Move .Left + 0, .Top + 0, .Width - (70 * Screen.TwipsPerPixelX), .Height - (70 * Screen.TwipsPerPixelY)
        .SetRedraw = True
    End With

    myloader.SavePictureGDIplus tmpimg.Picture, SavePath, lvicSaveAsPNG
```


i changed that line to :


```
        .Move .Left + 0, .Top + 0, Width - 70, Height - 70)
        'or 
       .Move .Left + 0, .Top + 0, 3000, 3000)
```

but saved as orginal size alltimes,why?
i want saved croped image for example from 300*300 orginal pixel to 230*230pixel as png

----------


## LaVolpe

Try to better understand the control you are using. That code crops the image within the display, it is not editing the image, is it? If you would have did as I asked and read the next few after post #245, you would have seen an example of creating a cropped image that you can save.

----------


## Black_Storm

> Try to better understand the control you are using. That code crops the image within the display, it is not editing the image, is it? If you would have did as I asked and read the next few after post #245, you would have seen an example of creating a cropped image that you can save.


i used wia like as this for crop png file (my problem fixed now) :



```

    Dim img  As New WIA.ImageFile
    Dim IP   As New WIA.ImageProcess
    img.LoadFile orginalfilename
    IP.Filters.Add IP.FilterInfos!Crop.FilterID
    IP.Filters(1).Properties("Left") = 0
    IP.Filters(1).Properties("Top") = 0
    IP.Filters(1).Properties("Right") = 0
    IP.Filters(1).Properties("Bottom") = 70
    IP.Filters(1).Properties("FrameIndex") = 0
    IP.Apply(img).FileData.ImageFile.SaveFile "path and png file name"
```

----------


## xiaoyao

This is a real 32-bit transparent PNG control. It   uses dozens of modules and class files. Is there a way to minimize the code?
but it's can zorder on button1,button2
it's only like StdPictureEx.cls
image1.picture=*.png
image2.picture=*.png

----------


## Nyc301

Great, amazing and wonderful control. Congratulation!!!  :Smilie: 
Just wondering to know if there is the possibility to change the rotation point.

Currently the rotation of the image pivots exactly in the center; I would be grateful to anybody who could give me an hint or maybe the solution.

Thanks  :wave:

----------


## Black_Storm

how can change this user control to standard exe,i want just use in my exe not like as ocx,i did try for change type to standard exe and so some user definition and public varibales is not worked and i did try for create standard exe and add this user control like as custom user control but same errors about changing classess and variables.

any body can attach standard exe version with this user control

----------


## xiaoyao

You can try to load the OCX control without registration

----------


## Black_Storm

> You can try to load the OCX control without registration


my question is about none use ocx.
i want have standard exe project and then use my other forms and use this user control in my forms and then make exe without  use external ocx or load ocx with or without rgistration.just a simple exe.

----------


## Hosam AL Dein

Hi Lavolpe ,
How can I get a pixel color for a GIF animated image while it is playing frames ?

----------


## wqweto

> Hi Lavolpe ,
> How can I get a pixel color for a GIF animated image while it is playing frames ?


FYI, LaVolpe has officially left these forums some time ago and he's not actively answering questions in any of the threads he started.

cheers,
</wqw>

----------


## Hosam AL Dein

> FYI, LaVolpe has officially left these forums some time ago and he's not actively answering questions in any of the threads he started.
> 
> cheers,
> </wqw>


I am sorry to hear that . Hope he is fine .

----------


## wqweto

https://www.vbforums.com/showthread....0300-FYI-Adios

----------


## Hosam AL Dein

> https://www.vbforums.com/showthread....0300-FYI-Adios


He was one of the most knowledgeable . He helped me a lot and I respected him . Although I am sorry he will not be here on the forum any more , but I am happy for him choosing a new goal to seek . All respect and appreciation .

----------


## Hosam AL Dein

Lavolpe shipped a global helper class with the control . It is  AICGlobals

It has many methods . One of them is : GetPixelGDIplus . 



```
Form1.BackColor=  GetPixelGDIplus (AlphaImgCtl1.Picture , 5 ,5)
```

For animated pictures , use this code in the _AnimationFrameChanged_ event

----------


## Politano

I don't know if I'm a layman or not, but I couldn't run the uncompiled project, could anyone help me?

----------

