|
Hmm... well about the SimpleForm example, it's just the simplest example I have ever seen on creating a form and then also be able to use all kinds of functions and also create controls in an easy way. I don't like having resource files or stdafx and such, that's why I use this way.
I might not understand you right but your point is that there are many unessesary things I include by importing the dlls? And that I can solve that by only importing the functions I need by using some dllimport runtimeservies called InteropServices?
Btw, yeah I'm kind of new to .NET or at least I don't really know the exclusive things for just .NET... I kind of only know some standard c++, I started going from console -> GUI not too long ago in c++, so that's why I want to get a hold of simple things like drawing and so on, also I need to be good at it for a school project later on. Other than that I have worked abit with Visual Basic before...so all program/memory optimizing and advanced functions is not familiar to me yet. But after all I haven't needed them yet?
Know any good task/program that I can try to create for learning the essentials and everything?
Regards,
Hmmkk
|
|
|
|
|
I've never used MFC that much, so I'm not really familar with it.
However, when you use MFC header files as includes to your managed WinForm project, you're just creating potential problems for yourself. MFC, as useful as it is (especially for the Document/View architecture) is an unmanaged class system. And, as such, it is incompatible with the managed .NET classes (unless you use Interop, or other code techniques to facilitate the integration). The .NET design teams realized that MFC and COM and all the pre-.NET legacy code out there that performs so well, should be able to be used in the CLR Runtime environment (or, hell, no one would want to acquire the coding expertise in the new .NET Framework class system). So, they developed Platform Invoke (or Interop) to make these two worlds accessible to each other.
Interop confuses most programmers unfamilar with it (it confuses me, and I've read a fair amount of documentation on it).
Many of the classes in both MFC and .NET are wrappers for the objects and functions from the underlying Win32 system DLLs. But, that's an oversimplification.
I would suggest that you buy yourself a good book on the subject and look through the example code provided, and also, read the documentation included with your Visual Studio .NET install (and the .NET Framework SDK).
The Framework classes in System.Windows.Forms and System.Runtime.Drawing are the managed .NET equivalent of Windows and Windowing techniques, generally, and MFC has similar classes (with completely different syntax and methods). You can use the two together, but, you should have an understanding of the underlying system calls that the wrappers are making, or you'll be colliding with your own code half the time.
And, so, the simple way is to just use one system or the other until you are familar enough with each to integrate them.
There is a good Microsoft book on this subject:
Programming with Microsoft Visual C++ .NET, Sixth Edition (Core Reference)
by George/Kruglinski Shepherd
|
|
|
|
|
Hello again,
I am recreating an example app - a hexadecimal editor - I am getting three errors when I compile.
These are all C2039's. They are "MeasureFontHeight" is not a member of "CHexViewerView","Top" is not a member of "CRect", and "ReadLine" is not a member of "HexViewerDoc". The code using these follows:
// HexViewerView.cpp : implementation of the CHexViewerView class
//
#include "stdafx.h"
#include "HexViewer.h"
#include "HexViewerDoc.h"
#include "HexViewerView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CHexViewerView
IMPLEMENT_DYNCREATE(CHexViewerView, CScrollView)
BEGIN_MESSAGE_MAP(CHexViewerView, CScrollView)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, &CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CScrollView::OnFilePrintPreview)
END_MESSAGE_MAP()
// CHexViewerView construction/destruction
CHexViewerView::CHexViewerView()
{
// TODO: add construction code here
memset(&m_logfont, 0, sizeof(m_logfont));
m_nPointSize = 120;
_tcscpy(m_logfont.lfFaceName, _T("Fixedsys"));
CWindowDC dc(NULL);
m_logfont.lfHeight = ::MulDiv(m_nPointSize,
dc.GetDeviceCaps(LOGPIXELSY),720);
m_logfont.lfPitchAndFamily = FIXED_PITCH;
m_pFont = new CFont;
m_pFont->CreateFontIndirect(&m_logfont);
}
CHexViewerView::~CHexViewerView()
{
if (m_pFont != NULL)
{
delete m_pFont;
}
}
BOOL CHexViewerView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CScrollView::PreCreateWindow(cs);
}
int CHexViewerView::MeasureFontHeight(CFont* pFont, CDC* pDC)
{
//how tall is the identified font in the identified device class(DC)
CFont* pOldFont;
pOldFont = pDC->SelectObject(pFont);
CRect rectDummy;
CString strRender = _T("1234567890ABCDEF- ");
int nHeight = pDC->DrawText(strRender, -1, rectDummy,
DT_TOP | DT_SINGLELINE | DT_CALCRECT);
pDC->SelectObject(pOldFont);
return nHeight;
}
// CHexViewerView drawing
void CHexViewerView::OnDraw(CDC* pDC)
{
CHexViewerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CString strRender;
CFont* pOldFont;
CSize ScrolledSize;
//int MeasureFontHeight;
int nStartLine;
int nHeight;
CRect ScrollRect;
CPoint ScrolledPos = GetScrollPosition();
CRect rectClient;
GetClientRect(&rectClient);
//Determine how tall each line is
pOldFont = pDC->SelectObject(m_pFont);
nHeight = MeasureFontHeight(m_pFont, pDC);
//Find a starting line based on scrolling
//and current line size
ScrolledSize = CSize(rectClient.Width(),
rectClient.Height());
ScrollRect = CRect(rectClient.left, ScrolledPos.y,
rectClient.right,
ScrolledSize.cy + ScrolledPos.y);
nStartLine = ScrolledPos.y/16;
//Verify we are where we should be
ScrollRect.Top= nStartLine*nHeight;
if (pDoc->m_pFile != NULL)
{
int nLine;
for (nLine = nStartLine;
ScrollRect.top < ScrollRect.bottom;
nLine++)
{
if (!pDoc->ReadLine(strRender, 16, nLine*16))
break;
nHeight = pDC->DrawText(strRender, -1,
&ScrollRect,
DT_TOP | DT_NOPREFIX | DT_SINGLELINE);
ScrollRect.top += nHeight;
}
}
pDC->SelectObject(pOldFont);
// TODO: add draw code for native data here
}
void CHexViewerView::OnInitialUpdate()
{
CHexViewerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CSize sizeTotal(0,pDoc->m_lFileSize);
SetScrollSizes(MM_TEXT, sizeTotal);
CScrollView::OnInitialUpdate();
}
// CHexViewerView printing
BOOL CHexViewerView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CHexViewerView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CHexViewerView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
// CHexViewerView diagnostics
#ifdef _DEBUG
void CHexViewerView::AssertValid() const
{
CScrollView::AssertValid();
}
void CHexViewerView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}
CHexViewerDoc* CHexViewerView::GetDocument() const // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CHexViewerDoc)));
return (CHexViewerDoc*)m_pDocument;
}
#endif //_DEBUG
// CHexViewerView message handlers
******************************************************
the associated header file code follows:
******************************************************
// HexViewerView.h : interface of the CHexViewerView class
//
#pragma once
class CHexViewerView : public CScrollView
{
protected: // create from serialization only
CHexViewerView();
DECLARE_DYNCREATE(CHexViewerView)
// Attributes
public:
CHexViewerDoc* GetDocument() const;
protected:
CFont* m_pFont;
LOGFONT m_logfont;
int m_nPointSize;
int m_nPageHeight;
int m_nPageWidth;
// Operations
public:
// Overrides
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void OnInitialUpdate(); // called first time after construct
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// Implementation
public:
virtual ~CHexViewerView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in HexViewerView.cpp
inline CHexViewerDoc* CHexViewerView::GetDocument() const
{ return reinterpret_cast<CHexViewerDoc*>(m_pDocument); }
#endif
**********************************************************************************
The ReadLine is iterated in the code segment from HexViewerDoc.cpp which follows:
**********************************************************************************
public:
BOOL ReadLine(CString& strLine,
int nLength,
LONG lOffset = -IL);
// TODO: Add your specialized creation code here
return TRUE;
I am unable to see what I am doing wrong. Can anyone help please ?
Thank you in advance. Joe
|
|
|
|
|
as you don't describe the error that occur, and where it does appear, i doubt anyone could help you...
TOXCCT >>> GEII power [toxcct][VisualCalc]
|
|
|
|
|
Thank you for looking at this, I thought I was being specific as to the error and included the segments of code these things came from.
|
|
|
|
|
you provide nowhere it crashes (show the lines instead of the whole code)....
thus, you don't even tell what is the desciption of the error C2039...
TOXCCT >>> GEII power [toxcct][VisualCalc]
|
|
|
|
|
I agree - my question is not well defined. I withdraw it.
I found the example and I was missing an entire code segment.
Thank you for your effort.
Joe
|
|
|
|
|
Hello,
I have added a variable to a class using add variable wizard. I wish to undo
or delete this addition - how do I do that? Thank you in advance.
Joe
|
|
|
|
|
you can do this manually by removing the member from the class.
there's nothing more to do.
if you wished to remove a function member added with class wizard, it would be a bit more difficult, especially when it is a message handler ; but as i understand, it is not your case, is it ?
TOXCCT >>> GEII power [toxcct][VisualCalc]
|
|
|
|
|
Thank you, I have removed it manually.
|
|
|
|
|
Now I get the error;
Just-In-Time Debugging
System.NullReferenceException
This is how I want it:
lblQ->Text = myQuestions[CurrentQuestion]->getQuestion()
myQuestions is a pointer class (declared: Question myQuestions __nogc[CurrentQuestion]; ) and getQuestion returns the string theQuestion. lblQ is btw just an Label (Label *lblQ)
and also I just tried two ways:
1:
lblQ->Text = new System::String(myQuestions[CurrentQuestion]->getQuestion();.c_str());
2:
myQuestions[CurrentQuestion]->setQuestion("hi");
string temp = myQuestions[CurrentQuestion]->getQuestion();
lblQ->Text = new System::String(temp.c_str());
Both gave the Just-In-Time debugger error.
Best Regards,
Hmmkk
|
|
|
|
|
myQuestions[CurrentQuestion] obviously == NULL ??? Is it a pointer and it needs to be allocated with new ?
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Yes, I guess your quite right there.
I bet there is some major error in the code that could be much better done=s But after all this is just a test program that I'm making.
To give you some insider/background info about the program:
I'm trying to create a Quiz program. I create by a class MainForm that inherits Form (the system one). The MainForm consists pretty much only by a previous and next button for CurrentQuestion++ or -- then call UpdateScreen, where it's suppose to update the Label lblQs text to the "theQuestion" string in a Question class, which shall store questions and answers.
Is there anyway you could watch through my short code or do you have any idea of a sollution?
Best Regards,
Hmmkk
|
|
|
|
|
Hmmkk wrote:
But after all this is just a test program that I'm making.
Then it's a good chance to learn how to do things well There's never a reason to write sloppy code.
Having said that, this code doesn't look that sloppy to me, it's just a simple mistake, you're trying to access something and you need to check that it exists first, and create it if it doesn't and it needs to.
Hmmkk wrote:
Is there anyway you could watch through my short code or do you have any idea of a sollution?
At this stage, I don't even know what your list contains. HOwever, the solution is that you need to create an object to sit at the position you're trying to access, before you try to access it, as I said initially.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
//Object creation
static const int MAX_QUESTIONS = 10;
int CurrentQuestion;
Question *myQuestions[MAX_QUESTIONS];
//Some of the Question class
class Question
{
public:
Question();
~Question();
void setQuestion(string Question) {theQuestion = Question;}
string getQuestion() { theQuestion = "hi"; return theQuestion.c_str();}
string getClue() { return theClue;}
private:
string theQuestion;
};
//The update method
void MainForm::UpdateScreen()
{
lblStatus->Text = S"Updating";
lblQ->Text = new System::String(myQuestions[CurrentQuestion]->getQuestion().c_str());
}
I bet there's something wrong about the declaration of object or?
Best Regards,
Hmmkk
|
|
|
|
|
<small><b>Hmmkk wrote:</b></small>
<i>I bet there's something wrong about the declaration of object or? </i>
No, it's exactly what I said it was
<small><b>Hmmkk wrote:</b></small>
<i>Question *myQuestions[MAX_QUESTIONS];</i>
You have an array of pointers. That means you have MAX_QUESTIONS ( currently 10 ) memory addresses in a row, and the compiler knows that you expect these memory addresses to point to instances of the Question class. However, they will point to random areas of memory until you reassign them. Given that your array is fixed, I'd be inclined to drop the *, and make it an array of Questions, not pointers. If you must use pointers, then you need an initialisation loop that does either of these:
for(int i =0;i<MAX_QUESTIONS;++i)
{
myQuestions[i] = new Question();
}
which will fix your problem, but gives you no advantage over not using pointers, or
for(int i =0;i<MAX_QUESTIONS;++i)
{
myQuestions[i]= NULL;
}
Now you can create questions as you need them, by checking first if the value is NULL ( but if you want to create a dynamically sized list, you should use a vector instead ).
Either way ( even if you use a vector ) your program will leak memory unless at the end you step through the list and call delete on each object.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Yay!=) I actually made it work now, at least I think so. Instead of initiating a pointer to the class, I use normal creation.
Question myQuestions[MAX_QUESTIONS];
and also static is gone.
So I guess I was right about being "gone with the wind" with the Object part, but how would it look like if I used it as a pointer? How to make it work?
Thanks alot btw!
Best Regards,
Hmmkk
|
|
|
|
|
Oki, you answered the question even before I could post=)
Thanks alot, now I know how to initialize pointer objects too=)
You are a really kind man, sir. Thanks!
Best Regards,
Hmmkk
|
|
|
|
|
No worries - glad to help.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
I have two forms (Form1 and Form2). Form1 will create an instance of Form2. After some processing certain elements from Form2 will be passed back to Form1. I think I know what I need todo (roughly) but I have a problem including each Form header in the other. I don't think this is possible (is it?) so how do I go about creating instances of each form if I can't include their headers?
I know there was a similar post on this but it didn't answer my specific question.
Thanks in advance.
|
|
|
|
|
If you are including the same header to the forms, instead using #pragma once
use Old Defenition style Example:
#ifndef _CORE_H_
#define _CORE_H_
public __gc class Core
{
//To Do:
};
#endif //_CORE_H_
With this you can use it from anywhere and you can include header into any file. Or multiple file. you will not get redefenition error
|
|
|
|
|
I had a similar problem. I just created a class that I pointed both forms to and used it to pass information between the forms.
So creat a new __gc class. From form1 create an object of that class. then point it to form2's object.
Pass is the class i'm using to pass information.
<br />
Pass *pass = new Pass();<br />
Form2 *input = new Form2(); <br />
input->pass1 = pass;<br />
input->ShowDialog();<br />
<br />
label_InputSomthing->Text = pass->somthing;<br />
Invalidate();<br />
<br />
Pass *pass1;<br />
pass1->something = textBox_something->Text;<br />
<br />
Close();<br />
|
|
|
|
|
Thaks guys I'll give it a go.
Saksida - will the old style definitions go inside the namespace tag or outside. e.g
#ifndef _CORE_H_
#define _CORE_H_
namespace test
{ ... }
#endif
or
namespace test
{
#ifndef _CORE_H_
#define _CORE_H_
...
#endif
}
|
|
|
|
|
Do I need to use the #indef definition in both forms or jsut the main one?? If I use it in both I get errors.
error C2143: syntax error : missing ';' before '*'
error C2501: 'test::Form1::form2' : missing storage-class or type specifiers
error C2501: 'test::Form1::f2' : missing storage-class or type specifiers
When I try to declare an instance of form2.
If I use it in the main form only I get only one error.
error C2011: 'test::form2' : 'class' type redefinition
I could do with some help here. I'm not very experienced with c++ let alone managed c++. Been on this for a couple of days and nothing I try wants to work.
|
|
|
|
|
Make sure to #include both your passing class and form2 in your form1.
|
|
|
|
|