How to import data from MySQL to SQL Server 2014 ?

Importing data from one database engine to another is often a pain. Getting the data out of MySQL is easy, but pushing it to SQL Server may be harder. The easiest way to achieve this is to use « SQL Server Import and Export Wizard » to directly query your MySQL Database, and push the data in your SQL Server.

Trying other techniques often leads to a waste of time. For example, Continuer la lecture

Form layout manager for C++ Builder 6

You have a C++ builder application, with some complex forms, and you’d like them to properly react to window resizing.
You heavily used anchors and alignment, but reached the limits of these features. For example, as soon as you have 3 controls in a row and that your form is resized, you can’t get them to grow proportionaly. If some controls must sometimes be hidden, you can’t get their neighbours to automatically shift to fill the holes.
Dealing with these situations manually is painful and costly, you miss Java layouts.

There’s no builtin features solving these problems in older versions of C+ Builder (<= 6), but you might find helpful my GitHub CppBuilderFormLayoutDemo project, which contains a couple of classes inspired from Java Layout Managers, along with a C++ Builder 6 demo project.

demo-layout
Continuer la lecture

Using WM_SETREDRAW to prevent window flickering

Flickering is a common issue with Windows applications. Different techniques exist to solve it, but they are more or less intrusive, and more or less efficient. Double-buffering for example is probably the best solution, but hard to put in place in a legacy code (even impossible sometimes). Using the WM_SETREDRAWmessage can be a light and efficient solution. Continuer la lecture

When C++ Builder 6 fails to properly import COM Objects

In Borland C++ Builder 6, the code generated to import COM objects slightly differs from the one generated by previous versions of C++ Builder.
Specifically, the VARIANT date type is used instead of TVariant. Giving up its TVariant « smart wrapper » was a good move from Borland, but it broke backward compatibility with output parameters of some COM methods, which don’t receive a value anymore.

For example, below is the code generated by C++ Builer 4 for the FarPoint TfpSpread COM object (from file FPSpreadADO_TLB.h) :
[code lang=cpp]
VARIANT_BOOL __fastcall GetText(long Col, long Row, TVariant* Var)
{
_TDispID _dispid(/* GetText */ DISPID(252));
TAutoArgs<3> _args;
_args[1] = Col /*[VT_I4:0]*/;
_args[2] = Row /*[VT_I4:0]*/;
_args[3] = Var /*[VT_VARIANT:1]*/;
OleFunction(_dispid, _args);
return _args.GetRetVariant();
}
[/code]

When generated using C++ Builder 6, the code becomes :
[code lang=cpp]
VARIANT_BOOL __fastcall GetText(long Col, long Row, VARIANT* Var)
{
_TDispID _dispid(/* GetText */ DISPID(252));
TAutoArgs<3> _args;
_args[1] = Col /*[VT_I4:0]*/;
_args[2] = Row /*[VT_I4:0]*/;
_args[3] = Var /*[VT_VARIANT:1]*/;
OleFunction(_dispid, _args);
return _args.GetRetVariant();
}
[/code]

Notice the Var parameter, whose type was changed from TVariant* to VARIANT* : that’s the source of the problem.

The issue comes from the TAutoArgs class, more specifically from its array of Variant.
The Variant assignment operator (=) behaves differently depending if its RHS is a TVariant* or a VARIANT* :

  1. Variant = TVariant* : The Variant is initialized with a reference to the TVariant* object (vt = VT_BYREF|VT_VARIANT, and pvarVal receives a pointer to the TVariant*
  2. Variant = VARIANT* : the Variant ‘=’ operator assumes the VARIANT* is a VT_BOOL. Changes to the Variant are not reflected on the VARIANT*

To fix the problem, one must explicitly set the Variant as a reference to the VARIANT*. For example, the previous example must be changed to :
[code lang=cpp]
VARIANT_BOOL __fastcall GetText(long Col, long Row, VARIANT* Var)
{
_TDispID _dispid(/* GetText */ DISPID(252));
TAutoArgs<3> _args;
_args[1] = Col /*[VT_I4:0]*/;
_args[2] = Row /*[VT_I4:0]*/;
_args[3].vt = VT_BYREF|VT_VARIANT /*[VT_VARIANT:1]*/;
_args[3].pvarVal = Var;
OleFunction(_dispid, _args);
return _args.GetRetVariant();
}
[/code]