Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Showing Image in Frame ActiveX Control

5.00/5 (1 vote)
27 Mar 2010CPOL3 min read 2  
This article describes how the image can be shown in Frame ActiveX control with proper size.

Introduction

This article is related to Office development for Microsoft Excel. Normally for showing an image in Excel file, we can use Forms.Image control, but this control causes some distortion to the image and the image is shown blurred when the control loses focus. For resolving this issue, another control can be used to show the images and that is Forms.Frame control.

But the Frame control has some drawbacks like it does not resize itself according to the size of the actual image, in essence, it does not have auto size feature as is available with Image control. So we need to set the size of frame object through code as per the size of image. But the problem does not end here. Image size measurement unit is different than the measurement unit of Excel.

So here in this article, I present the solution to set the Frame size appropriately. This includes some magic numbers also. Let's have fun with these numbers.

Background

It is easy doing things manually but when it comes to doing things programmatically, things become little bit tricky. I needed to develop an Excel Addin in which I needed to show images on Excel. Initially I added Forms.Image controls to show the images but that was not working as per expectations so I decided to use Forms.Frame control that shows a very sharp image and does not blur when it loses focus.

Using the Code

I am not detailing out here how to create addin but I will discuss only how to add Frame control programmatically and how to size it as per the actual image size.

So here goes the code for adding Forms.Frame control to Excel:

C#
int top = 100, left = 100, width = 100, height = 100;
Excel.OLEObject oleObj = null;		
Excel.OLEObjects oleObjCollection = ((Excel._Worksheet)
	applicationObject.ActiveWorkbook.ActiveSheet).OLEObjects(Type.Missing) 
	as Excel.OLEObjects;
// This code adds Frame object, with some initial dimensions, 
// to OLE Object collection of Excel.
objObj = oleObjCollection.Add("Forms.Frame.1", Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
left, top, width, height);
Forms.Frame objFrame = oleObj.Object as Forms.Frame;

Here the applicationObject is the Excel Application object from which we first retrieve the OLE Object collection of the workbook and then add the Frame object to that collection to get that frame on Excel.

Once the Frame control is added to Excel, we set the image for that frame and then set the size of that frame. And that is the tricky part, when we calculate the size of image it comes in pixels but to set the size of frame, we need to convert that pixel value into points that is the size measurement unit of Excel.

C#
System.Drawing.Image img = System.Drawing.Image.FromFile("C://image.jpg");
objFrame.Picture = ImageConverter.Convert(img) as stdole.StdPicture;
oleObj.Width = GetPixelToPointWidth(img.Width);
oleObj.Height = GetPixelToPointHeight(img.Height);		

Before setting the picture to Frame object, we need to convert that picture in compatible format and for that, we need to write ImageConverter class, as GetIPictureDispFromPicture method is not available directly because of its protection level.

C#
using System.Windows.Forms;
public class ImageConverter : AxHost 
{
	private ImageConverter(): base(null) 
	{
	}
	public static IPictureDisp Convert(System.Drawing.Image image) 
	{
		return AxHost.GetIPictureDispFromPicture(image) as IPictureDisp;
	}
}

And here is the tricky part. These methods convert the pixel value to point value according to the DpiX and DpiY values of Excel. And here comes the magic number, that is 72.

C#
private float GetPixelToPointWidth(int w)
{
	System.Drawing.Graphics g = System.Drawing.Graphics.FromHwnd
				((IntPtr)applicationObject.Hwnd);
	return (w / g.DpiX)* 72;
}
private float GetPixelToPointHeight(int h)
{
	System.Drawing.Graphics g = System.Drawing.Graphics.FromHwnd
				((IntPtr)applicationObject.Hwnd);
	return (h / g.DpiY)*72;
}

Points of Interest

This conversion factor can be applied in some other situations also where we need to calculate the height, width for Excel and Ole objects.

You can reach me at manojdwivedi07@gmail.com for any queries or suggestions regarding this article.

History

  • 27th March, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)