Hello...
For a while now, I've been using a Microsoft MFC ActiveX in diffrent tehnologies like .NET, web - JavaScript and MFC.
For the first two is kind of easy to import an activex inside yout project...
For .NET you either add a reference to a COM.. that is the ActiveX that is using a .NET Framework tool - aximp - to create two wrappers.
Inside Javascript, you will use the <object> tag and after that you can call diffrent methods exposed by that activeX...
For catching an event in JS you have to write this code...
<script for="ActiveX_ID" event="EventName()">...code here...</script>
What about MFC? How can we call a method inside a MFC Application.
The answer is very simple if you used MFC and COM before.
A CWnd or a COleControlSite object has a InvokeHelper method.
virtual void AFX_CDECL InvokeHelper(
DISPID dwDispID,
WORD wFlags,
VARTYPE vtRet,
void* pvRet,
const BYTE* pbParamInfo,
...
);
You should look inside MSDN for details... Here I'm going to show you how can you invoke a property or a method.
For getting a field inside a property:
VARIANT vtResult;
this->GetDlgItem(IDC_ACTIVEXCTRL)->InvokeHelper(propertyId, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&vtResult, NULL);
where propertyId is the ID of the property(the same is for setting a value of a property).
For invoking a method, with one or more than one parameter, you can use:
static BYTE params[] = VTS_BSTR VTS_BSTR;
unsigned long result = 0;
this->GetDlgItem(IDC_ACTIVEXCTRL)->InvokeHelper(methodId, DISPATCH_METHOD, VT_I4, (void*)&result, params,
(LPCSTR)parameter1, (LPCSTR)parameter2);
where parameter1 and parameter2 are two BSTRs.
Well.. that's about it...
Happy coding!!!
Monday, October 27, 2008
Thursday, October 23, 2008
Complementary Knapsack problem
Hello..
Every programmer (or almost every programmer) heard of the faimos problem called, The knapsack problem. This problem can be formulated in math way: Having a set of numbers, find a subset of numbers this set and their sum are under or equal than a given value?
The solution of this is very simple and there are many web-sites where you can find the implementaion or the pseudo-code.
We name "Complementary Knapsack problem" the problem where we must find a subset that sum is greater than a given value and the difference of the sum and the given number is minimum.
I've done some research using Google and I found nothing(maybe I haven't searched enough).
The solution of this problem is solving the Knapsack problem for the a value equal with: sum of all numbers in set minus the given value. Because this problem offers an optimal solution, if we remove from out set of numbers the result of this problem, we find our subset and if we sum them we get a number grater that the given value and the difference is minimum.
Every programmer (or almost every programmer) heard of the faimos problem called, The knapsack problem. This problem can be formulated in math way: Having a set of numbers, find a subset of numbers this set and their sum are under or equal than a given value?
The solution of this is very simple and there are many web-sites where you can find the implementaion or the pseudo-code.
We name "Complementary Knapsack problem" the problem where we must find a subset that sum is greater than a given value and the difference of the sum and the given number is minimum.
I've done some research using Google and I found nothing(maybe I haven't searched enough).
The solution of this problem is solving the Knapsack problem for the a value equal with: sum of all numbers in set minus the given value. Because this problem offers an optimal solution, if we remove from out set of numbers the result of this problem, we find our subset and if we sum them we get a number grater that the given value and the difference is minimum.
Monday, September 22, 2008
Invoke .NET from MFC(COM object - ActiveX)
Hi there...
A couple of days ago I wanted to use a .NET assembly from a MFC application. You can see other post where I explain how to make an interface in .NET and expose it to COM.
In this post I want to show you how to call a method from that assembly that has a byte[] parameter. and how to get a parameter from a COM object. As you can see(if you've made that .tbl file and imported in C++), the byte[] parameter from .NET is exposed as a SAFEARRAY*.
The trick is to create a SAFEARRAY* like this:
BYTE* myBuffer = ... ; // the length of the buffer is len
SAFEARRAYBOUND sabdBounds[1] = { {len, 0} };
LPSAFEARRAY psa = SafeArrayCreate(VT_UI1, 1, sabdBounds);
memcpy(psa->pvData, myBuffer, len);
//call the method from .NET assembly
To call a method or get a property from a COM object, you can use the InvokeHelper method:
//get signature BSTR string
VARIANT vtResult;
this->GetDlgItem(IDC_MyActiveXID)->InvokeHelper(propertyId, DISPATCH_PROPERTYGET
DISPATCH_METHOD, VT_VARIANT, (void*)&vtResult, NULL);
After this call, you should check on vtResult.vt to see the return type.
Have fun!
A couple of days ago I wanted to use a .NET assembly from a MFC application. You can see other post where I explain how to make an interface in .NET and expose it to COM.
In this post I want to show you how to call a method from that assembly that has a byte[] parameter. and how to get a parameter from a COM object. As you can see(if you've made that .tbl file and imported in C++), the byte[] parameter from .NET is exposed as a SAFEARRAY*.
The trick is to create a SAFEARRAY* like this:
BYTE* myBuffer = ... ; // the length of the buffer is len
SAFEARRAYBOUND sabdBounds[1] = { {len, 0} };
LPSAFEARRAY psa = SafeArrayCreate(VT_UI1, 1, sabdBounds);
memcpy(psa->pvData, myBuffer, len);
//call the method from .NET assembly
To call a method or get a property from a COM object, you can use the InvokeHelper method:
//get signature BSTR string
VARIANT vtResult;
this->GetDlgItem(IDC_MyActiveXID)->InvokeHelper(propertyId, DISPATCH_PROPERTYGET
DISPATCH_METHOD, VT_VARIANT, (void*)&vtResult, NULL);
After this call, you should check on vtResult.vt to see the return type.
Have fun!
Friday, September 19, 2008
Exposing .NET Components to COM
Looking on MSDN website you'll find this:
http://msdn.microsoft.com/en-us/library/zsfww439.aspx
So as you can see, you can't expose static components to COM.
C# code:
namespace ClassLibrary1{
[Guid("4322F88E95-DD27-4ae6-B6DE-054440FC70AA")]
[InterfaceType (ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface _Class1
{
[DispId(1)]
int Add(int i);
}
[Guid("13FE123D-4D34-495F-AB4D-909BBB463EEA")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ClassLibrary1.Class1")]
[ComVisible(true)]
[ComDefaultInterfaceAttribute(typeof(_Class1))]
public class Class1 : _Class1
{
public int Add(int i)
{
return i + 10;
}
}
}
C++ code:
#include "stdafx.h"
//the location must point to the tlb file
#import "D:\\ClassLibrary1\\bin\\Debug\\ClassLibrary1.tlb"
int _tmain(int argc, _TCHAR* argv[])
{
ClassLibrary1::_Class1 *com_ptr;
CoInitialize(NULL);
ClassLibrary1::_Class1Ptr p(__uuidof(ClassLibrary1::Class1));
com_ptr = p;
long a = com_ptr->Add(1);
CoUninitialize();
return 0;
}
To make this work, you have to Register the .NET library to COM from Properties-Build tab and run the command : regasm ClassLibrary1 /tbl:ClassLibrary1.tlb
To deploy this, you'll have to gacutil the assembly.
gacutil /i ClassLibrary1.dll but first you'll have to strong-name sign it.
http://msdn.microsoft.com/en-us/library/zsfww439.aspx
So as you can see, you can't expose static components to COM.
C# code:
namespace ClassLibrary1{
[Guid("4322F88E95-DD27-4ae6-B6DE-054440FC70AA")]
[InterfaceType (ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface _Class1
{
[DispId(1)]
int Add(int i);
}
[Guid("13FE123D-4D34-495F-AB4D-909BBB463EEA")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ClassLibrary1.Class1")]
[ComVisible(true)]
[ComDefaultInterfaceAttribute(typeof(_Class1))]
public class Class1 : _Class1
{
public int Add(int i)
{
return i + 10;
}
}
}
C++ code:
#include "stdafx.h"
//the location must point to the tlb file
#import "D:\\ClassLibrary1\\bin\\Debug\\ClassLibrary1.tlb"
int _tmain(int argc, _TCHAR* argv[])
{
ClassLibrary1::_Class1 *com_ptr;
CoInitialize(NULL);
ClassLibrary1::_Class1Ptr p(__uuidof(ClassLibrary1::Class1));
com_ptr = p;
long a = com_ptr->Add(1);
CoUninitialize();
return 0;
}
To make this work, you have to Register the .NET library to COM from Properties-Build tab and run the command : regasm ClassLibrary1 /tbl:ClassLibrary1.tlb
To deploy this, you'll have to gacutil the assembly.
gacutil /i ClassLibrary1.dll but first you'll have to strong-name sign it.
Wednesday, September 3, 2008
WPF 3D View

Hello...
A little while ago, I tried Xceed datagrid view... and I saw there a 3D view... You can check it out on their website. A simillar application is on Apple iPhone.
So, I started to make a WPF control simillar to that list.
The control can be found at : www.codeplex.com/3dView
Have fun!
Tuesday, August 19, 2008
Visual Studio 2008 Unit test GUI
Hi there...
Fot thouse who are using unit tests build with Visual Studio 2008, I've created a Windows Forms application for running unit tests inside multiple .NET assemblys.
The project is on Codeplex.
Tuesday, August 12, 2008
Alternate log shrink in MS SQL 2005 - empty the database log
Hello...
Today I wanted to install VSTS 2008 and the installer "told" that I have no space on my HDD. After a quick look inside ProgramFiles folder, I saw that the SQL Databases have very large log files... So I've decided to empty them... After some Google solutions - without any succes - I've combined to results from thouse search results...
New log file 'C:\Databases\databasefile_log.LDF' was created.
Today I wanted to install VSTS 2008 and the installer "told" that I have no space on my HDD. After a quick look inside ProgramFiles folder, I saw that the SQL Databases have very large log files... So I've decided to empty them... After some Google solutions - without any succes - I've combined to results from thouse search results...
- detach a database
- attach a data base without the log file...
The first one is simple... Right click on the DB and choos Detach...
The second one is more tricky... You'll have to use the SP:
sp_attach_single_file_db @dbname= 'databasename', @physname= 'C:\Databases\databasefile.mdf'
The results of this SP is the following...
File activation failure. The physical file name "C:\Databases\databasefile_log.ldf" may be incorrect.New log file 'C:\Databases\databasefile_log.LDF' was created.
So... we now have a new log with a size of 504KB...
Enjoy!
Subscribe to:
Posts (Atom)