VFP
Exontrol.COM Software - Frequently Asked Questions
VFP.0:
In VFP, VFP Advanced 32-bit you can use any of the following versions:
  • /COM indicates the 32-bit edition of the ActiveX version

The application built using /COM version runs on any Windows 32 or 64-bit machine.

In VFP Advanced (x64) you can use any of the following versions:

  • /COM/64 indicates the 64-bit edition of the ActiveX version

The application built using /COM/64 version runs on Windows 64-bit machine only. The application built using /COM/64 version cannot run on Windows 32-bit machine.

If you want to use your application on 32 and 64-bit machines, you can go for:

  • /COM/ANY indicates the 32 and 64-bit editions of the ActiveX versions

Should I use a 32-bit or 64-bit version of the control?

VFP.1:
There can be a problem with VFP responding to events.

Make sure you call

	AutoYield = .F.
within your code.

The AutoYield property specifies whether an instance of Visual FoxPro processes pending Windows events between execution of each line of user program code.
VFP.2:
A> The following method uses the Items.DefaultItem / Template methods 

The following code works for eXG2antt control, but the idea is the same for all controls that support Items.DefaultItem / Template property like: eXGantt, eXGrid, eXTree, eXList, eXComboBox, eXPlorerTree, and so on.

Let's say that your code looks like follows:

LOCAL h
SCAN
	_key="K_"+ALLTRIM(STR(projekte.ID))
	WITH THISFORM.myplan.Items
		h = .AddItem(ALLTRIM(projekte.project_name))
		.AddBar( h,"Project Summary" , DTOT(projekte.sdate),DTOT(projekte.edate), _key, "" )
		.ItemBar( h ,_key,3 ) = "my text"
	ENDWITH
ENDSCAN

The h variable indicates the handle of the newly created item. This value is always greater than 65000, so the VFP environment fires an error when compiling the AddBar and ItemBar properties because it considers accessing an array, and its limit is 65000. Of course this problem is related to VFP ignoring the fact that it is calling a property of a COM object! not an array, so our products provide a DefaultItem property that help VFP users to pass this error. So, in VFP the above code should look like follows:

SCAN
	_key="K_"+ALLTRIM(STR(projekte.ID))
	WITH THISFORM.myplan.Items
		.DefaultItem = .AddItem(ALLTRIM(projekte.project_name))
		.AddBar( 0,"Project Summary" , DTOT(projekte.sdate),DTOT(projekte.edate),_key, "" )
		THISFORM.myplan.Template = "Items.ItemBar( 0,`" + _key + "`,3 ) = `my text`"
	ENDWITH
ENDSCAN 

The difference ( marked in red ) is that the first parameter for properties like AddBar and ItemBar is 0, and before calling them the Items.DefaultItem property indicates the handle of the item being accessed. How it works? The control uses the value of the Items.DefaultItem property, when the first parameter of the ItemBar, AddBar and so on is 0. The AddItem property saves before the handle of the newly created item to the DefaultItem property, and so the VFP error is gone, and the code works like you expect.

B> The following method uses the TemplateDef / Template methods 

The following code works for eXG2antt control, but the idea is the same for all controls that support TemplateDef / Template and so on.

Let's say that your code looks like follows:

LOCAL h
with thisform.G2antt1
	.BeginUpdate
	.Columns.Add("Tasks")
	with .Chart
		.FirstVisibleDate = {^2000-12-25}
		.PaneWidth(0) = 48
	endwith
	with .Items
		h = .AddItem("Task")
		.AddBar(h,"Task",{^2001-1-2},{^2001-1-6},"K","exBarHAlignCaption = 1")
		.ItemBar(h,"K",4) = 18
	endwith
	.EndUpdate
endwith

The h variable indicates the handle of the newly created item. This value is always greater than 65000, so the VFP environment fires an error when compiling the AddBar and ItemBar properties because it considers accessing an array, and its limit is 65000. Of course this problem is related to VFP ignoring the fact that it is calling a property of a COM object! not an array, so our products provide a DefaultItem property that help VFP users to pass this error. So, in VFP the above code should look like follows:

LOCAL h
with thisform.G2antt1
	.BeginUpdate
	.Columns.Add("Tasks")
	with .Chart
		.FirstVisibleDate = {^2000-12-25}
		.PaneWidth(0) = 48
	endwith
	with .Items
		h = .AddItem("Task")
		.AddBar(h,"Task",{^2001-1-2},{^2001-1-6},"K","exBarHAlignCaption = 1")
		WITH thisform.G2antt1
			.TemplateDef = "Dim h"
			.TemplateDef = h
			.Template = "Items.ItemBar(h,`K`,4) = 18"
		ENDWITH
	endwith
	.EndUpdate
endwith
The following sample changes the Items.ItemBar(exBarCaption) and Items.ItemBar(exBarHAlignCaption) properties:
LOCAL h
with thisform.G2antt1
	.BeginUpdate
	.Columns.Add("Tasks")
	with .Chart
		.FirstVisibleDate = {^2000-12-25}
		.PaneWidth(0) = 48
	endwith
	with .Items
		h = .AddItem("Task")
		.AddBar(h,"Task",{^2001-1-2},{^2001-1-6},"K")
		WITH thisform.G2antt1
			.TemplateDef = "Dim h"
			.TemplateDef = h
			.Template = "Items.ItemBar(h,`K`,3) = `new caption and different alignment`"
			.Template = "Items.ItemBar(h,`K`,4) = 18"
		ENDWITH
	endwith
	.EndUpdate
endwith 

or:

with thisform.G2antt1
	.BeginUpdate
	.Columns.Add("Tasks")
	with .Chart
		.FirstVisibleDate = {^2000-12-25}
		.PaneWidth(0) = 48
	endwith
	with .Items
		.DefaultItem = .AddItem("Task")
		.AddBar(0,"Task",{^2001-1-2},{^2001-1-6},"K")
		WITH thisform.G2antt1
			.Template = "Items.ItemBar(0,`K`,3) = `new caption and different alignment`"
			.Template = "Items.ItemBar(0,`K`,4) = 18"
		ENDWITH
	endwith
	.EndUpdate
endwith 
The Template / TemplateDef methods can run any x-script code described here.
VFP.3:
The following VFP code assigns your logo, on the eXPrint's paper, but it gives "Function argument, value, type, or count is invalid" while compiling:
with thisform.Print1
	.HTMLPicture("i1") = "E:\Temp\Icons\arrow.gif"
	.ExtraCaption("A","Extra <img>i1</img>", 0, 0 )
	.PrintExt = thisform.G2antt1.Object
	.Preview
endwith

replace with:

with thisform.Print1
	.Object.HTMLPicture("i1") = "E:\Temp\Icons\arrow.gif"
	.ExtraCaption("A","Extra <img>i1</img>", 0, 0 )
	.PrintExt = thisform.G2antt1.Object
	.Preview
endwith

Calling the HTMLPicture property from Object, makes the compiler to call the property of the inside control instead confusing calling or setting an array.

Another approach, is using the Template property like in the following samples:

with thisform.ExplorerBar1
	.Template = "HTMLPicture(`pic`)= `E:/Temp/watch.gif`"
	.Groups.Add("<img>pic</img> Group 1").CaptionFormat = 1
endwith

or

with thisform.ExplorerBar1
.Object.HTMLPicture("pic") = "E:/Temp/watch.gif"
	.Groups.Add("<img>pic</img> Group 1").CaptionFormat = 1
endwith

instead

with thisform.ExplorerBar1
	.HTMLPicture("pic") = "E:/Temp/watch.gif"
	.Groups.Add("<img>pic</img> Group 1").CaptionFormat = 1
endwith
VFP.4:
The exTree component (any ATL based component) causes a change from the normal form method firing order when placed on a form. For example, VFP normally fires the following methods in the following order when instantiating a form: Load, Init, Show, Activate, GotFocus. When the exTree object is placed on the form, the VFP method firing order changes as follows: Load, Activate, GotFocus, GotFocus, Init, Show. This is obviously a big problem. Many methods were attempted to get around this including creating the object programmatically (which did successfully correct the firing order problem, but I could not get all things to work correctly, like showing the plus sign for root items among other things). I also attempted to set the object to invisible and set to visible in gotfocus and many other things...
Eventually, I came to the solution explained below. This solution just forces the VFP method firing order to be correct by calling methods explicitly.

  1. Create a custom form property (CFP) and set it equal to 0 in form.load.
  2. Set the CFP equal to 1 in form.init. It should be done at the BOTTOM of the method.
  3. Surround all code in form.show with IF CFP>0 ? ENDIF. At the end of all code within the IF stmt (as in, right before endif), explicitly call the form.activate method.
  4. Surround all code in form.activate with IF CFP>0 ? ENDIF. At the end of all code within the IF stmt (as in, right before endif), explicitly call the form.gotfocus method.
  5. Surround all code in form.gotfocus with IF CFP>0 ? ENDIF.
  6. Additionally, if any code is in the form.resize event, it should be surrounded by the IF CFP>0 ? ENDIF statement. This may also hold true for other methods that I have not yet encountered.
  7. Another issue concerns the visibility of the form. Even with the above code, I was getting a flash of the form at position 0,0 on the desktop before it then repositioned itself where I directed it. So, set form.visible to .F. in form.load and then set it to .T. in form.gotfocus.
  8. ** ANOTHER NOTE. Have to set APPLICATION.AUTOYIELD=.F. I am doing this in my startup program (unless I have problems and if so, I will set it equal to .F. in form.load and to .T. in form.unload). The VFP help system says that this should be set to .F. (as opposed to .T. which is the default) on any form on which an activex object is placed. It will prevent the activex from executing code in the middle of foxpro execution of code. As an example, if it was set to .T., sometimes when I clicked on another choice in the treeview, it would appear as highlighted, but the remaining objects on the form did not reflect that I just changed my selection. If I click it again, the remaining objects do change correctly. Setting it to .F. corrected the problem. 
This will cause the firing order to be correct. If you don't have any code in activate, show or gotfocus you don't have to do any of this. However, if you later add code to any of these events, you would have to go back and modify to adhere to these standards. So, it may be a good idea to just put the IF STMT code in each of the events with a note that all code must be within the stmt, since 6 months later, one could easily forget what needed to be done.

Thanks to Tim Stickley, Decision Modeling, Inc who submitted the note. This note is related to VFP 7.0, and it seems to be corrected in VFP 8.0
VFP.5:
I just wanted to say, that using the Exontrol exSuite has been really great! Thank you for making such a nice product.I mainly program in VFP (Visual FoxPro) and I am currently working with VFP 9.0 (beta).  During my experience with exGrid (which has just started), I decided to share the information I collected with other Visual Foxpro programmers.  I would also like to share it with you in case you find it useful for assisting VFP developers. The information and code I am providing is "public domain" and "free of charge" to any VFP developer, so long as the comments are left "as-is" and they are distributed free of charge.

Check out the VFP exGrid information page: http://fox.wikis.com/wc.dll?Wiki~exGrid~VFP

Check out the VFP wrapper class (exVGrid.zip): ftp://66.132.144.112/VFP/

The zip file contains:
  VFP project
  Sample VFP Screen
  exVGrid Class code (including event handler, event logging, printing)
  exGrid #DEFINE (constants)
  VFP exGrid "events" Interface Class

I have also created an information page specific to VFP and OLE Objects that might be helpful to any VFP programmers using your controls.  You can find it at: http://fox.wikis.com/wc.dll?Wiki~OLEObjects

Thanks to Paul James, QORE, Inc, Inc who submitted the note. This note is related to VFP 9.0 ( beta ).
VFP.6:
The controls like ExComboBox, ExTree, ExGrid, ExplorerTree includes plenty of methods to load data using one or more of the followings :
  • AddItem, InsertItem, InsertControlItem
  • DataSource property
  • PutItems

In VFP, the controls provide the DefaultItem property of the Items collection that helps users to access the properties that are using HITEM type for the Item parameter. The VFP fires "Invalid Subscript Range" error, while it tries to process a number grater than 65000. Since, the HITEM is a long value that most of the time exceeds 65000, the VFP users have to use this property, instead passing directly the handles to properties.

The following sample shows to change the cell's image:

.Items.DefaultItem = .Items.AddItem("Item 1")
.Items.CellImage(0,1) = 2

In VFP the following sample fires: "Invalid Subscript Range":

i = .Items.AddItem("Item 1")
.Items.CellImage(i,1) = 2

because the i variable  is grater than 65000.

The following VFP sample loads data to an ExplorerTree control in Form.Init event using all of the mentioned methods ( The sample can be modified to run for any of the other components )

				* Initializes a BASE64 encoded string that holds 3 icons. 
local s, i
s = "gBJJgBAIDAAGAAEAAQhYAf8Pf4hh0QihCJo2AEZjQAjEZFEaIEaEEaAIAkcbk0olUrlktl0vmExmUzmk1m03nE5nU7nk9n0/oFBoVDolFo1HpFJpVLplNp1PqFRqVTqlVq1XrFZrVb"
s = s + "rldr1fsFhsVjslls1ntFptVrtltt1vuFxuVzul1u13vF5vV7vl9v1/wGBwWDwkbiAAQGJqrAxgAxjAruJQETf+FnmHx+Ux2NzOSpuZ0GcxtUw+YxuHy0yzOlh+byGh1+Nz1A2G"
s = s + "u22r1uoo+e1mV3G+0+t1Mo02Q4sZyfIjO12mjjW13+a3tB6fR4/X4WD62tzOI5ej5Pdnfi7+Qje1w+83Pryu6mXq9vc4PA43s23Yyt46P72WK7rwucnTZufAL7vs9LFPgzSaOq+bNOi5TlPwvMJuO/6NQAyEBtU/rkwJDT/QdBUGvMmbPQU/j6vy70I"
s = s + "O890KQPGL4vo27RRLDjYxBDzyuk+0TsU6cGI1FcfsnCcJPtJEVr06MisRBMgPs5jxxtAzKw86bjqBFciShIz5RLD0vyWvrOyjGceyvL0HwLLcZO9CM0qTJ0nSOwcRx9M7NQUpkszAqs6TW4bDSTIcpSqrEgq3J1B0bR1H0guqLB8ldKI8kCRJIACSpRTicRfSKbIo4R+H+edTPyeAfnAf9WIycAHnBVYf1eA5gAfW9amAAdd1qQ"
s = s + "AA1+5YD1/YLHINY7l2Qg1jEBYYD2ScAD2jV4BnwB9rIyeABn8B9uIyfIHn+T9xIzUb"
s = s + "8oCA"
with this.explorerTree1
	.BeginUpdate
		.Images(s)
		with .Groups
			with .Add("Group <b>1</b>")
				* Using the AddItem, InsertItem methods
				.ToolTip = "Using the <b>AddItem</b>, <b>InsertItem</b> methods to create your own hierarchy"
				.Image = 1
				.FullRowSelect = .F.
				.CaptionFormat = 1
				.LinesAtRoot = -1
				.Indent = 17
				with .Items
					.DefaultItem = .AddItem("Root 1")
					.CellImage(0,0) = 1
					i = .DefaultItem()
					.DefaultItem = .InsertItem(i, ,"Child 1")
					.CellImage(0,0) = 2
					.DefaultItem = .InsertItem(i, ,"Child 2")
					.CellImage(0,0) = 3
					i = .DefaultItem()
					.DefaultItem = .InsertItem(i, ,"Child 1")
					.CellImage(0,0) = 2
					.DefaultItem = .InsertItem(i, ,"Child 2")
					.CellImage(0,0) = 1
				endwith
				.Expanded = .t.
			endwith
			
			with .Add("Group <b>2</b>")
			* Using the DataSource method	
				.ToolTip = "Using the <b>DataSource</b> method to to bind a recordset to the group."
				.Image = 2
				.CaptionFormat = 1
				
				rs=CREATEOBJECT('ADODB.RECORDSET')
			    rs.Open('Select * From workouts', 'Driver=Microsoft Visual FoxPro Driver;SourceType=DBC;Exclusive=NO;SourceDB= ' + Home(1) + 'Wizards\Template\Workout\Data\WORKOUT.DBC', 3)
				.DataSource = rs
				
				.Expanded = .t.
			endwith
			
			with .Add("Group <b>3</b>")
			* Using the PutItems method
				.ToolTip = "Using the <b>PutItems</b> method to load data from an array."
				.Image = 2
				.CaptionFormat = 1
				.Expanded = .T.
				
				set udfpa to reference
				DIMENSION MYARRAY[4]
			    MYARRAY(1) = "1"
			    MYARRAY(2) = "2"
			    MYARRAY(3) = "3"
			    MYARRAY(4) = "4"
			   .PutItems(MYARRAY)
			   set udfpa to value
			   
			endwith
			
			with .Add("Group <b>4</b>")
			* Enumerating records using the AddItem method
				.ToolTip = "Loading data using the <b>AddItem</b> method by enumerating the fields."
				.Image = 3
				.CaptionFormat = 1
				.ColumnAutoResize = .F.
				.BeginUpdate
				.HeaderVisible = .t.
				Close Databases
				clear
				USE Home(1) + "foxuser.dbf" IN 0 AGAIN ALIAS Foxuser EXCLUSIVE		
				go Top
				with .Columns
					.Clear
					for i = 1 to FCount()
						.Add(field(i))
					next i
				endwith
				with .Items
					DO WHILE NOT EOF()
						.DefaultItem = .AddItem(eval(field(1)))
						for i = 2 to FCOUNT()
							.CellCaption(0,i-1) = eval(field(i))
						next
						Skip 1	
					ENDDO
				endwith
				.EndUpdate
				.Expanded = .T.			
			endwith
			
		endwith
	.EndUpdate
endwith
VFP.7:
Call the Object method so the HTMLPicture property is called for native object as in the following sample:

extree.OBJECT.HTMLpicture("pic1") = "c:\test.bmp"

Calling the HTMLPicture property of the extree directly does not fire any error, nor display the picture in the <img> fields.

VFP.8:
When you show a modal window, Visual FoxPro disables all OLE host windows on the form. The ActiveX can not receive any user input related messages anymore, because the window is disabled (the WS_DISABLED windows style is added to the window that hosts the ActiveX control so actually it is disabled) . As a result, the control does not respond to mouse or keyboard events, nor does it receive the focus. 

In order to fix this, you can call the following code on form's GotFocus event:

thisform.OleControl1.OBJECT.Enabled = .T.
where the OleControl is any of our UI components. Also, you can easily use API functions to remove the WS_DISABLED window style.
VFP.9:
The "Object class is invalid for this container" error may occurs, in case the parameters for the AddObject are not what it expects. For instance, the ActiveX must uses its program identifier for cOLEClass parameter, while for other elements, this parameter is not used. 

>>>> When using ActiveX, the correct syntax for object.AddObject is like follows:

LOCAL aka

aka = THISFORM
aka.AddObject("myctrl","olecontrol","Exontrol.ExMenu")
WITH aka.myctrl
  .Visible = .T.
  .Items.ToString = "A[id=10](B[id=20],C[id=30](D[id=40],E[id=50]),F[id=60])"
ENDWITH

where the "Exontrol.ExMenu", is the program identifier, which can be found on the control's help main page. For instance, On the page G2antt_default.htm, you can find the "The object's program identifier is:  ... " The program identifier specifies the string to be passed for the cOLEClass ( 3rd parameter ) of the AddObject method.  

>>>> In case the aka is _SCREEN, the code fails as it gives "Object class is invalid for this container", which indicates that you can not place any ActiveX on the main Visual FoxPro window, instead you can follow the trick to do the job, inserting some UI elements to your man window.  IN this case the container is still the form, while the visual container is the _SCREEN which specifies the main Visual FoxPro window. In other words the form receives all events, so you can write there your handlers. The form does not need to be visible, so you can set its Visible property on .F..

DECLARE INTEGER SetParent IN user32;
INTEGER hWndChild,;
INTEGER hWndNewParent

SetParent( thisform.olecontrol1.hWnd, _SCREEN.HWnd )
where the olecontrol1 is the name of the object in the form.
VFP.10:
The extended control in VFP that hosts the control, provides a few properties like Enabled, Edit, Visible, Width, Height, Edit, .... In order to call the original control's Edit, Enabled method rather than Edit, Enabled method of the wrapper control in VFP, you must call the Edit method of the Object property of the control like in the following sample:
with thisform.Grid1
	.Object.Edit()
endwith

instead of:

with thisform.Grid1
	.Edit()
endwith

or

with thisform.Grid1
	.Object.Enabled = .F.
endwith

instead of:

with thisform.Grid1
	.Enabled = .F.
endwith 
VFP.11:
The VFP fires the "Missing or invalid" or "File access is denied" error, when it is trying to open a sct file from a folder with no Full Control permission set

The error may looks as follows:

In order to prevent that, you can:

  • Copy the C:\Program Files\Exontrol\Control\Sample folder to some other folder, where you have Full Control.
  • Change the Security Permission of the folder where you run the sample, to include the Full Control permission.

    By default, the Security of the Sample folder my looks as:

    and it should look such as
  • Run the Microsoft VFP as administrator ( Admin )
VFP.12:
An application is considered an isolated application if all of its components are side-by-side assemblies. A side-by-side assembly is a collection of resources?a group of DLLs, windows classes, COM servers, type libraries, or interfaces?available for an application to use at runtime. Typically, a side-by-side assembly is one to several DLLs. 

Isolated COM allows your application to use ActiveX components without having to register them. The original vision of this was to allow copy deployment of the application, but Isolated COM has many benefits. You can have a private copy of the DLL without worrying that another application will install an older or newer copy that breaks your application. Isolated COM also allows you to successfully install and run on non-Administrator accounts.

The solution is to include the control's manifest file to the application's resource under 24 ( Manifest Resource Type ) with the identifier 1. !The solution for VFP it's a bit tricky, so please download and check the VFP sample bellow for more details!

  • Build the EXE file from your VFP project
  • Open the EXE using the Visual Studio
  • Locate the 24\1 resource in the EXE. By default, the VFP generates a manifest like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity 
	version="1.0.0.0" 
	type="win32" 
	name="Microsoft.VisualFoxPro" 
	processorArchitecture="x86"
/>
<description>Visual FoxPro</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            language="*"
            processorArchitecture="x86"
            publicKeyToken="6595b64144ccf1df"
        />
    </dependentAssembly>
</dependency>
</assembly>
  • Generates the control's manifest file, using the eXHelper tool
    • Open the eXHelper tool, and select the component whose manifest file you need to generate
    • Right-click the Middle/Template panel, and choose the Generate Assembly Manifest (exg2antt.manifest )
    • Copy the <file> section of the manifest file and you should get something like:
<file name="exg2antt.dll" hashalg="SHA1">
	<comClass clsid="{CD481F4D-2D25-4759-803F-752C568F53B7}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="Exontrol.G2antt.1" description="G2antt Class" miscStatusContent="recomposeonresize,cantlinkinside,insideout,activatewhenvisible,setclientsitefirst"></comClass>
	<comClass clsid="{2DD65709-C0BA-4764-AADF-820919FF181B}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Column.1" description="Column Class" ></comClass>
	<comClass clsid="{28AC7755-06AC-4439-9ADD-EA012B4B2F10}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Columns.1" description="Columns Class" ></comClass>
	<comClass clsid="{1801677D-52FE-4759-B10A-C4FE70EAE035}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Items.1" description="Items Class" ></comClass>
	<comClass clsid="{E2B55693-3D70-426B-9E08-ECF9DC93D98D}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.OleEvent.1" description="OleEvent Class" ></comClass>
	<comClass clsid="{919D16E8-2002-4C11-BC81-1CA0FF8FDDEF}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.OleEventParam.1" description="OleEventParam Class" ></comClass>
	<comClass clsid="{C39F7717-C8C1-44A0-A495-DB5E92FDC79D}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Appearance.1" description="Appearance Class" ></comClass>
	<comClass clsid="{9E3FB380-6CB7-4CCA-B726-FE191133A8A0}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.ExDataObjectFiles.1" description="ExDataObjectFiles Class" ></comClass>
	<comClass clsid="{A30C0D8D-98A5-476B-860A-3397645BA8F8}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.ExDataObject.1" description="ExDataObject Class" ></comClass>
	<comClass clsid="{4B82A833-421F-496F-BE2F-F5C41DBED707}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}"  description="Template Class" ></comClass>
	<comClass clsid="{D4D088E8-0FA5-4414-A322-D105149D6313}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}"  description="TemplatePage Class" ></comClass>
	<comClass clsid="{1AA7ABFA-8C27-4579-9F06-7CCFAF301B72}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Editor.1" description="Editor Class" ></comClass>
	<comClass clsid="{23AA3A91-C107-44B2-BD23-3978B343DB8A}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Chart.1" description="Chart Class" ></comClass>
	<comClass clsid="{7862FEFF-7FE6-401A-A692-CE4758CDD0FC}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Level.1" description="Level Class" ></comClass>
	<comClass clsid="{D6C57467-EC60-429F-87B7-3751DFB1EEAE}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Bar.1" description="Bar Class" ></comClass>
	<comClass clsid="{75A35E6C-2144-435F-96FF-0BE4A9643176}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Bars.1" description="Bars Class" ></comClass>
	<comClass clsid="{FC5F6509-4354-4D92-A9A9-24EEB081670E}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.ConditionalFormat.1" description="ConditionalFormat Class" ></comClass>
	<comClass clsid="{DEDF38EB-BEEA-48D1-8D9E-AF0C81FA8E71}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.ConditionalFormats.1" description="ConditionalFormats Class" ></comClass>
	<comClass clsid="{91E561B9-B514-4F1F-BAE1-3E5903C85DA3}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.InsideZoomFormat.1" description="InsideZoomFormat Class" ></comClass>
	<comClass clsid="{513CF640-A498-4800-ACEF-4473491CF282}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.InsideZoom.1" description="InsideZoom Class" ></comClass>
	<comClass clsid="{B6528DA9-8C75-4389-9B72-EE8A8C2BABA3}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.InsideZooms.1" description="InsideZooms Class" ></comClass>
	<comClass clsid="{15F8B91F-49AD-4663-B878-8A3DE05E4A30}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Notes.1" description="Notes Class" ></comClass>
	<comClass clsid="{926F669D-85C4-4D6D-BC9D-BA3759D8B237}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Note.1" description="Note Class" ></comClass>
	<typelib tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib>
</file> 
  • Go Back to Visual Studio's Resource Template, and paste the <file> before /assembly ends and you should get something like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity 
	version="1.0.0.0" 
	type="win32" 
	name="Microsoft.VisualFoxPro" 
	processorArchitecture="x86"
/>
<description>Visual FoxPro</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            language="*"
            processorArchitecture="x86"
            publicKeyToken="6595b64144ccf1df"
        />
    </dependentAssembly>
</dependency>
<file name="exg2antt.dll" hashalg="SHA1">
	<comClass clsid="{CD481F4D-2D25-4759-803F-752C568F53B7}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="Exontrol.G2antt.1" description="G2antt Class" miscStatusContent="recomposeonresize,cantlinkinside,insideout,activatewhenvisible,setclientsitefirst"></comClass>
	<comClass clsid="{2DD65709-C0BA-4764-AADF-820919FF181B}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Column.1" description="Column Class" ></comClass>
	<comClass clsid="{28AC7755-06AC-4439-9ADD-EA012B4B2F10}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Columns.1" description="Columns Class" ></comClass>
	<comClass clsid="{1801677D-52FE-4759-B10A-C4FE70EAE035}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Items.1" description="Items Class" ></comClass>
	<comClass clsid="{E2B55693-3D70-426B-9E08-ECF9DC93D98D}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.OleEvent.1" description="OleEvent Class" ></comClass>
	<comClass clsid="{919D16E8-2002-4C11-BC81-1CA0FF8FDDEF}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.OleEventParam.1" description="OleEventParam Class" ></comClass>
	<comClass clsid="{C39F7717-C8C1-44A0-A495-DB5E92FDC79D}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Appearance.1" description="Appearance Class" ></comClass>
	<comClass clsid="{9E3FB380-6CB7-4CCA-B726-FE191133A8A0}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.ExDataObjectFiles.1" description="ExDataObjectFiles Class" ></comClass>
	<comClass clsid="{A30C0D8D-98A5-476B-860A-3397645BA8F8}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.ExDataObject.1" description="ExDataObject Class" ></comClass>
	<comClass clsid="{4B82A833-421F-496F-BE2F-F5C41DBED707}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}"  description="Template Class" ></comClass>
	<comClass clsid="{D4D088E8-0FA5-4414-A322-D105149D6313}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}"  description="TemplatePage Class" ></comClass>
	<comClass clsid="{1AA7ABFA-8C27-4579-9F06-7CCFAF301B72}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Editor.1" description="Editor Class" ></comClass>
	<comClass clsid="{23AA3A91-C107-44B2-BD23-3978B343DB8A}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Chart.1" description="Chart Class" ></comClass>
	<comClass clsid="{7862FEFF-7FE6-401A-A692-CE4758CDD0FC}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Level.1" description="Level Class" ></comClass>
	<comClass clsid="{D6C57467-EC60-429F-87B7-3751DFB1EEAE}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Bar.1" description="Bar Class" ></comClass>
	<comClass clsid="{75A35E6C-2144-435F-96FF-0BE4A9643176}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Bars.1" description="Bars Class" ></comClass>
	<comClass clsid="{FC5F6509-4354-4D92-A9A9-24EEB081670E}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.ConditionalFormat.1" description="ConditionalFormat Class" ></comClass>
	<comClass clsid="{DEDF38EB-BEEA-48D1-8D9E-AF0C81FA8E71}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.ConditionalFormats.1" description="ConditionalFormats Class" ></comClass>
	<comClass clsid="{91E561B9-B514-4F1F-BAE1-3E5903C85DA3}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.InsideZoomFormat.1" description="InsideZoomFormat Class" ></comClass>
	<comClass clsid="{513CF640-A498-4800-ACEF-4473491CF282}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.InsideZoom.1" description="InsideZoom Class" ></comClass>
	<comClass clsid="{B6528DA9-8C75-4389-9B72-EE8A8C2BABA3}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.InsideZooms.1" description="InsideZooms Class" ></comClass>
	<comClass clsid="{15F8B91F-49AD-4663-B878-8A3DE05E4A30}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Notes.1" description="Notes Class" ></comClass>
	<comClass clsid="{926F669D-85C4-4D6D-BC9D-BA3759D8B237}" tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" progid="ExG2antt.Note.1" description="Note Class" ></comClass>
	<typelib tlbid="{70337FFD-810F-4CDC-B09A-44CDCEE7DF1B}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib>
</file>
</assembly>
  • Save the 24\1 resource, and close the Visual Studio.

Now, copy the generated EXE and the exg2antt.dll to a client machine, and run the EXE.

You can download it here the VFP project.

While running the executable, you might be asked for "main.FXP". In order to prevent this you can follow any of the following options.

The first one is to create a shortcut to executable file, and change the Target of the shortcut to run the executable with "main.FXP" as arguments.

For instance if the shortcut's Target shows as:

"C:\...\Downloads\Isolated-VIEW (VFP)\ExG2antt\Iso.exe"

changes it to:

"C:\...\Downloads\Isolated-VIEW (VFP)\ExG2antt\Iso.exe" main.FXP

The second option is to create a BAT file that shows as:

@echo off
start /B Iso.exe main.FXP

While running the shortcut or BAT file, you won't be asked for the FXP file.

See also: How to Generate Assembly Manifest File (Registration-Free)?
VFP.13:
The Anchor property defines which borders of the parent container that a visual control is anchored to when resizing the container. In other words, the Anchor defines the position /size of the control based on its parent. The Anchor property works for all components that you can resize in design-mode. The eXComboBox, eXCalendar, or any other library that provides drop down components, works in the same way, excepts that control's height is not the same as the control's label height ( by design ). In case, you need to use the Anchor property with any of these components, you need to change the control's LabelHeight when the form's Resize event occurs. As a separate issue, you can use the Anchor and the eXComboBox, with no change, if you are using the control's Style property on Simple. In this case, you are allowed to change the size of the control on the form, and so Anchor property will change all borders of the control when user resizes the form.

In order to change the control's label height and Anchor property on 240, you should do the following:

  • Place the control to a form in design mode
  • Define the control's Name property ( for instance ComboBox1 )
  • Specify the control's Style property to what you need to have. If using the control's Simple mode nothing than change the Anchor property to 240 is required, else
  • Resize and move the control in design mode to desired position
  • Change the control's Anchor property to 240
  • Save and run the form

If using the control's Simple mode, you will notice that all margins of the control are adjusted based on the Anchor property. If using the control's DropDown or DropDownList mode, you will notice that the control's top and bottom margins of the control ( label ), are not changed if resizing the control, and this is happen because the Anchor property changes the control's height not the control's label height. In order to change the control's label height too, you need to add a handler for Resize event, as shown bellow:

  • Go to design mode, select the component, and change the LabelHeight and Height properties to have the same values
  • Select the Form, and add the Resize event for the form, with the following code
WITH thisform.ComboBox1
  .LabelHeight = .Height
ENDWITH 
  • Save and run the form

Now, everything works smoothly. This behavior is not a problem of VFP or of the control's itself. 

In case, you are wondering why the eXComboBox, eXCalendar ( drop down components ) are the single one that work this way, please insert any of the following:

  • "Microsoft DBCombo Control, version 6.0"
  • "Microsoft DataCombo Control, version 6.0"
  • "Microsoft ImageComboBox Control, version 6.0" 
and you will notice exactly the same behavior.
VFP.14:
An array is an ordered series of data values, called elements, which are referenced by number. Because arrays exist in memory, they provide fast data access and easy manipulation. You can easily specify, locate, or manipulate elements in an array. Unfortunately, the VFP is not able to pass any array to a property of a COM object, so we need to use the TemplatePut method as shown bellow:

For instance, the following code:

LOCAL laMyArray(3)

laMyArray(1)=1
laMyArray(2)=3
laMyArray(3)=5

WITH thisform.exGrid as EXGRIDLib.Grid
	.SingleSel = .F.
	.Items.Selection = @laMyArray
ENDWITH 

 generates the "Syntax Error" at compiling time, so instead you have to use the following code:

LOCAL laMyArray(3)

laMyArray(1)=1
laMyArray(2)=3
laMyArray(3)=5

WITH thisform.exGrid as EXGRIDLib.Grid
	.SingleSel = .F.
	.TemplateDef = "Dim selArray"
	.TemplatePut(@laMyArray)
	.Template = "Items.Selection = selArray"
ENDWITH
The green section is a replica of exactly what red section should do. Shortly, the sample passes the VFP reference of the laMyArray to an internal variable selArray, which using the Template method is passed to the Items.Selection property using the x-script language.
VFP.15:
You may encounter a syntax error when calling a set property with multiple properties. Because VFP can not handle properly properties with multiple properties, you can use the Template feature as explained bellow.

For instance, let's say we are trying to change the Link property of the Items object as follows:

with thisform.G2antt1
	.BeginUpdate
	.AntiAliasing = .T.
	.Columns.Add("Task")
	with .Chart
		.FirstVisibleDate = {^2001-1-1}
		.PaneWidth(0) = 128
		.NonworkingDays = 0
		.LinksWidth = 2
	endwith
	with .Items
		.AddItem("")
		h3 = .AddItem("Task 3")
		.AddItem("")
		.AddBar(h3,"Task",{^2001-1-13},{^2001-1-15},"K3")
		h1 = .AddItem("Task 1")
		.AddItem("")
		.AddBar(h1,"Task",{^2001-1-2},{^2001-1-4},"K1")
		h2 = .AddItem("Task 2")
		.AddBar(h2,"Task",{^2001-1-7},{^2001-1-9},"K2")
		.AddItem("")
		.AddLink("L1",h1,"K1",h2,"K2")
		.AddLink("L2",h2,"K2",h3,"K3")
		.Link("<*>",15) = 4
	endwith
	.EndUpdate
endwith

generates a syntax error as Link(...) = 4 line, as VFP can handle properties (set) with multiple parameters, so instead you can use the following code:

with thisform.G2antt1
	.BeginUpdate
	.AntiAliasing = .T.
	.Columns.Add("Task")
	with .Chart
		.FirstVisibleDate = {^2001-1-1}
		.PaneWidth(0) = 128
		.NonworkingDays = 0
		.LinksWidth = 2
	endwith
	with .Items
		.AddItem("")
		h3 = .AddItem("Task 3")
		.AddItem("")
		.AddBar(h3,"Task",{^2001-1-13},{^2001-1-15},"K3")
		h1 = .AddItem("Task 1")
		.AddItem("")
		.AddBar(h1,"Task",{^2001-1-2},{^2001-1-4},"K1")
		h2 = .AddItem("Task 2")
		.AddBar(h2,"Task",{^2001-1-7},{^2001-1-9},"K2")
		.AddItem("")
		.AddLink("L1",h1,"K1",h2,"K2")
		.AddLink("L2",h2,"K2",h3,"K3")
		thisform.G2antt1.Template = "Items.Link(`<*>`,15) = 4"
	endwith
	.EndUpdate
endwith
VFP.16:
In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in such a way that memory which is no longer needed is not released. We have been asked to check for a memory leak when using one of ours controls (exgrid) in VFP. Shortly, memory leaks may occur once the user resizes the form that contains one of our controls. We have tested it and the conclusion is that just resizing an empty form generates "possible" memory leaks as explained bellow:
  • run VFP
  • type "create screen" into command window
  • save the form/screen
  • run the form/screen (empty form)
  • open the Task Manager
  • locate the "Microsoft Visual FoxPro 9.0"

you should get something like:

  • monitor the memory column while resizing the form

and later you get something like:

In conclusion, resizing an empty form in VFP generates "possible" memory leaks. You can observe that after a while the memory won't increase anymore, so we won't consider it memory leak (for instance, the VFP may cache the screen behind the form, or something similar). Investigating memory leaks are not easy tasks. When we receive a request for memory "leaks", we try to replicate the sample and scenario within several programming languages, development environments, not only VFP, as if there is a "true" memory leak that belongs to one of our components it occurs in all development environments.

We have created a basic VB application that hosts the ExGrid component (as isolated, so no installation is required or regsvr32 is required), which resizes randomly the form (and so the control). The following picture shows the graph(middle) of memory consumption while running the rmemleak.exe application:

You can download the sample project here.

See also: Memory Leak (Stress Application)