|
HeHe! I saw the original posts!
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
Is it possible to call into a .NET class library from a VC60 C++ app? If yes, how?
I wanted to create a middle layer between C++ app and .NET class library - sort of a wrapper for .NET class library. Towards that end, in VS2005, I created a C++ Win32 Dll. I have turned on CLR option from Project->Properties>Configuration. But in this project, I couldn't figure out how do I instantiate ClassLibrary and make calls into it. Can someone please enlighten?
Thanks.
None
|
|
|
|
|
concoran wrote: Can someone please enlighten?
It sounds like this is your initial use of C++/CLI? If so I recommend learning about it first before you approach your project. There are almost endless articles, tutorials and sample/example projects available here and on MSDN to educate you about the power of C++/CLI.
|
|
|
|
|
Hi Led,
Yes, I am new to CLI, but not to C++. I am also new to Codeproject. Can you pls point to where I can find articles on this website?
Thanks in advance.
None
|
|
|
|
|
concoran wrote: Can you pls point to where I can find articles on this website?
On the "Articles" menu (it's between "Hellp" and "Message Boards") click the "Site Directory" link
|
|
|
|
|
Hi, I'm using Visual Studio 2005 C++/CLI. I have been surfing for information on zooming using CLI. The SetWindowsExt() and SetViewportExt() functions do not seem to be available any more. If anyone has a link to an article or can at least point me in the right direction it would really help.
Thanks,
Buck
|
|
|
|
|
Hi Buck,
if you want to modify things you paint yourself (say inside OnPaint),
then you can use the transform methods of the Graphics class; they let
you set translation, rotation, scaling (or an enire matrix), then do
the paint stuff as before.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
Hi Luc,
Here is the code that allows me to use the mouse to draw a rectangle around an area of the display that I want to fill the display with, hence zooming. The aspect ratio is kept constant so if the rectangle is too high or too wide then it adjust the heighth or width accordingly. The Translate function positions the origin. The Scale function sets the scaling in the x and y directions. This TransformPointsExample function is called from OnPaint(PaintEventArgs^ e).
private: void TransformPointsExample(PaintEventArgs^ e)
{
float aspect_ratio = (float)nDisplayHeight / nDisplayWidth;
float zoombox_height = (float)zoomRectEndPos.Y - zoomRectStartPos.Y;
float zoombox_width = (float)zoomRectEndPos.X - zoomRectStartPos.X;
if(zoombox_height / zoombox_width > aspect_ratio)
zoombox_width = zoombox_height / aspect_ratio;
else
zoombox_height = zoombox_width * aspect_ratio;
float y_scale = (float)nDisplayHeight / zoombox_height;
float x_scale = (float)nDisplayWidth / zoombox_width;
Matrix^ myMatrix = gcnew Matrix();
myMatrix->Translate(-(float)zoomRectStartPos.X, -(float)zoomRectStartPos.Y);
myMatrix->Scale(x_scale, y_scale, MatrixOrder::Append);
e->Graphics->Transform = myMatrix;
}
Buck
|
|
|
|
|
Hi Buck,
thanks for the update. Any questions?
You did not have to create a Matrix, Graphics.TranslateTransform() plus
Graphics.ScaleTransform() would have given same result and avoid an object.
As it is now you should do myMatrix.Dispose() when OnPaint is done!
[CORRECTION] See the next two replies by Mark: in C++/CLI Dispose() can not be
called directly, but a delete is in order [/CORRECTION]
-- modified at 5:28 Thursday 30th August, 2007
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
Luc Pattyn wrote: you should do myMatrix.Dispose() when OnPaint is done!
Or for C++ consistency, use
delete myMatrix;
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: delete myMatrix;
I'm not fluent in C++, but the way I understood it is:
- delete undoes a new
- managed objects are created with gcnew, are garbage collected, and
should have their Dispose() method called if the class offers it.
The original code had: Matrix^ myMatrix = gcnew Matrix();
and Matrix class offers Dispose()...
greetings
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
Starting in VC++ 2005, you can't call Dispose directly. You can deterministically clean up a
managed object with delete though. You can also use stack semantics - like a local variable
with the same scoping but it's created on the managed heap behind the scenes. It's automatically
disposed when it goes out of scope.
Matrix^ myMatrix = gcnew Matrix();
delete myMatrix; <font><font color="Red">
or
Matrix myMatrix; <font color="Red">
You also can't make ref classes disposable (derived explicitly from IDisposable) in C++.
Now, if you add a destructor, the class automagically inherits from IDisposable, the
destructor becomes Dispose(), and an explicit finalizer can be added ( syntax is
"!classname()") which should be called from the destructor. The compiler makes sure
the finalizer is only called once (SuppressFinalize)...
public ref class TestRef
{
int *pInts;
public:
TestRef()
{
pInts = new int[100];
}
~TestRef()
{
this->!TestRef();
}
!TestRef()
{
delete[] pInts;
}
}; Destructors and Finalizers in Visual C++[^]
Cheers
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Wow, this looks quite different from C# (and VB.NET I guess),
thanks for the info Mark.
I did add a correction to my previous message to Buck.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
It was the biggest surprise to me when I migrated from the managed
extensions in VS2003. I knew of the syntax changes but when the first
Dispose() errors came up I had to look into it and found it changed significantly.
I like it though - it's more C++-like
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Maybe these will help:
Graphics.PageScale (property)
Graphics.Transform (property)
Graphics.RotateTransform()
Graphics.TranslateTransform()
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hi, I am using Visual Studio 2005 C++/CLI. I am delving into some event driven programming and I can use the mouse to draw a rectangle. The rectangle is drawn as the user moves the mouse with the left button down. I am using the Graphics->DrawRectangle() method. The idea here is to DrawRectangle() over the previous rectangle with a white pen the draw the new rectangle with a black pen. What I am seeing (and it makes complete sense) is that as I move the mouse the drawing of the white rectangle "covers" some of the screen display that was already there. This doesn't seem very elegant. Is there a method that will remove the previous rectangle without disturbing the existing screen display. I don't want to paint the entire screen because my application takes about 1 second to paint the entire screen.
private: System::Void Form_MouseMove(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e)
{
if(e->Button == System::Windows::Forms::MouseButtons::Left)
{
int height = zoomRectEndPos->Y - zoomRectStartPos->Y;
int width = zoomRectEndPos->X - zoomRectStartPos->X;
zoomRectEndPos = this->MousePosition;
Graphics^ g = this->CreateGraphics();
Pen^ whitePen = gcnew Pen(Color::White, 0.5);
g->DrawRectangle(whitePen, zoomRectStartPos->X, zoomRectStartPos->Y, nPreviousWidth, nPreviousHeight);
Pen^ blackPen = gcnew Pen(Color::Black, 0.5);
g->DrawRectangle(blackPen, zoomRectStartPos->X, zoomRectStartPos->Y, width, height);
nPreviousWidth = width;
nPreviousHeight = height;
}
}
Thanks,
Buck
|
|
|
|
|
Hi Buck,
I understand the normal way (adding the rubber banding to your normal OnPaint,
and Invalidate everything) causes a lot of unnecessary repaint work.
I have not used this myself, but I did read some discussions on this topic.
I do not fully like it, but here it is:
The concept is based the ControlPaint class, which has very nice DrawReversible
methods; they allow to draw a line or frame, and to undo that by drawing it again.
So there would be no need to Invalidate the underlying stuff.
Unfortunately it paints on the entire screen, using screen coordinates, and
disregarding any windowing. Hence if your form is partly obscured by the corner
of something else, it will paint over that something else (unless you
create the logic to discover what parts of your intended window are really
visible...).
If you don't mind the lack of clipping, it should work for you; it clipping
is important (and possibly complex) I am afraid there is no easy solution.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
|
Here's what I hope is an easy group of questions:
I know the VS2005 IDE plugs method definitions into the .H file of C++/CLI forms because it's build on the same generator used by C#. The question is should I expend the effort to move method bodies over to the .CPP file every time I wire up a new control event handler? Is there a drawback (other than bad C++ practice) to have all of the code in the .H file? Are methods defined in the .H file without the use of they keyword "inline" treated as "inline" anyway, or are they compiled as if they were defined in the .CPP file?
Thanks.
|
|
|
|
|
Xpnctoc wrote: without the use of they keyword "inline" treated as "inline" anyway,
For information of that type I would recommend you check out Stan Lippman's blog
Xpnctoc wrote: Is there a drawback (other than bad C++ practice)
Technically it's not C++. Since you are creating a .NET assembly the native C++ use of headers files does not apply. So the the two situations are not comparable.
|
|
|
|
|
In addition to led mike's reply, I would like to mention the following. I wouldn't mess with anything produced by the wizard because your changes can affect how the wizard updates your code. In non-wizard produced code, you may have to separate declaration from definition if you have circular dependencies. Unlike the C# and VB compilers, AFAIK, you need to create forward declarations to resolve circular dependencies.
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
I appreciate the response. I do have a fairly strong background in native C++, and I'm used to setting up my data structures so as to avoid circular references. I was just wondering if there could be any impact on performance. But, as Led Mike pointed out, it is really apples to oranges since I'm dealing with managed assemblies instead of native DLLs. So I'll just continue practicing good coding conventions in my managed and unmanaged classes, and let the forms generator do its own sloppy thing
|
|
|
|
|
However, you have to be very careful with C++/CLI. Sometimes it behaves just like C++, sometimes like C# and VB, and sometimes like none of above! For instance, derived class ctors execute before base class ctors! I guess this is normal for .NET languages but it just seems so unnatural too me.
The "For instance, derived class ctors execute before base class ctors!" comment is incorrect see my post below!
-- modified at 18:55 Wednesday 29th August, 2007
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
George L. Jackson wrote: For instance, derived class ctors execute before base class ctors!
HUH?? In what case?
I know (well, I've "heard") virtual calls in constructors (never a good idea anyway)
are handled different, but AFAIK C++ ref classes are still built from the inside out.
ref class refbase
{
public:
refbase()
{
Console::WriteLine("refbase");
}
};
ref class refsuper : public refbase
{
public:
refsuper()
{
Console::WriteLine("refsuper");
}
};
int _tmain()
{
refsuper ^super = gcnew refsuper();
Console::WriteLine("\r\n");
Console::WriteLine("Press Enter to end...");
Console::ReadLine();
return 0;
}
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Oops! You are right! I meant the derived class initialization list is executed before the base class ctor. I think I had too much filet fish today.
-- modified at 19:04 Wednesday 29th August, 2007
ref class Foo
{
public:
Foo()
{
Console::WriteLine("foo.ctor");
}
};
ref class Base
{
public:
Base()
{
Console::WriteLine("base.ctor");
}
};
ref class Derived : Base
{
Foo^ f;
public:
Derived() : f(gcnew Foo)
{
Console::WriteLine("derived.ctor");
}
};
int main(array<System::String ^> ^args)
{
Derived^ d = gcnew Derived;
return 0;
}
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|