I have created new emty project. Then have added cpp and header hello world files taken from Jeff Prosise 'Programming Windows with MFC' book. Have set Use of MFC to Use MFC in a Shared DLL
Got error entry point must be defined
How to fix this problem?
CPP:
#include <afxwin.h>
#include "Hello.h"
CMyApp myApp;
/////////////////////////////////////////////////////////////////////////
// CMyApp member functions
BOOL CMyApp::InitInstance ()
{
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow (m_nCmdShow);
m_pMainWnd->UpdateWindow ();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
ON_WM_PAINT ()
END_MESSAGE_MAP ()
CMainWindow::CMainWindow ()
{
Create (NULL, _T ("The Hello Application"));
}
void CMainWindow::OnPaint ()
{
CPaintDC dc (this);
CRect rect;
GetClientRect (&rect);
dc.DrawText (_T ("Hello, MFC"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
H:
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance ();
};
class CMainWindow : public CFrameWnd
{
public:
CMainWindow ();
protected:
afx_msg void OnPaint ();
DECLARE_MESSAGE_MAP ()
};
You need to tell compiler to use WinMain (which is provided by MFC: http://msdn.microsoft.com/en-us/library/akdx0603.aspx) instead of main as an entry point.
Right click project, select Properties, and navigate to Linker -> System -> SubSystem. Change SubSystem to Windows.
Related
I try to create custom child window that derive from CWnd inside CFrameWnd parent. The child window just rectangle with border style. Child create after parent create. it handle on OnCreate event. But the child window not appears. What's wrong here?
#include <afxwin.h>
class Index: public CWnd
{
public:
Index()
{
CWnd* parentWnd = AfxGetApp()->m_pMainWnd;
Create(
NULL,
NULL,
WS_CHILD | WS_BORDER,
CRect(CPoint(0, 0), CSize(100, 100)),
parentWnd, NULL, NULL);
};
};
class MainFrame: public CFrameWnd
{
public:
MainFrame()
{
Create(
NULL,
"Parent and Child",
WS_OVERLAPPEDWINDOW,
CRect(CPoint(0, 0), CSize(640, 360))
);
};
protected:
afx_msg int OnCreate(LPCREATESTRUCT);
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
int MainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
Index* index = new Index;
index->ShowWindow(SW_NORMAL);
return 0;
};
class Application: public CWinApp
{
BOOL InitInstance()
{
m_pMainWnd = new MainFrame;
m_pMainWnd->ShowWindow(SW_NORMAL);
m_pMainWnd->UpdateWindow();
return true;
};
};
Application app;
When overriding methods such as CWnd::OnCreate or CWinApp::InitInstance, be sure to call the base class.
Avoid creating new windows in the constructor, it makes it very difficult to debug. Create the child windows in parent window's OnCreate method, pass the this to indicate parent:
class Index : public CWnd
{
public:
Index() {}
};
class MainFrame : public CFrameWnd
{
public:
MainFrame(){};
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct)
{
CFrameWnd::OnCreate(lpCreateStruct);
Index* index = new Index;
index->Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
CRect(0, 0, 400, 300), this, NULL, NULL);
index->ShowWindow(SW_NORMAL);
return 0;
};
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
class Application : public CWinApp
{
BOOL InitInstance()
{
CWinApp::InitInstance();
m_pMainWnd = new MainFrame;
m_pMainWnd->CreateEx(0, AfxRegisterWndClass(0), NULL,
WS_VISIBLE | WS_OVERLAPPEDWINDOW, 20, 20, 600, 400, NULL, 0);
return true;
};
}; Application app;
Well your post shows only WS_CHILD | WS_BORDER for Index class.
I am back.
I was extremely busy, but now I have some time to dive deeper into your code.
I have seen similar code in many places and to be honest this should never see the day.
Several things:
I never do any allocation in the class’ constructor. Neither memory nor handled. If allocation fails there is no way to gracefully exit the app but crash. There are more appropriate places to call for windows creation.
Your posted code is going to crash since you call Create member of the CWnd class, not CFrameWnd class. It implements Create differently, calling CreateEx. CWnd would ASSERT. That is why I have changed it.
The code posted is not the code you are building with and that makes any attempt to help you much harder.
Continuing:
you are allocating MainFrame and Index objects on the heap. This will create a memory leak since you do not clean allocations on exit.
This does not apply to MainFrame. This class calls delete on PostNcDestroy. This is by design. All Document, View, and Frame classes are designed to be allocated dynamically and release object allocation. You can declare the Index class object as a member variable of the MainFrame. This way it will be allocated on the frame (stack) and deallocated automatically when MainFrame object goes out of scope.
When you call Create to attach Index class to the windows handle, pass AFX_IDW_PANE_FIRST value as the ID. Frame Window will resize the window with this ID automatically.
Another piece of advice: keep the definitions and declaration in separate files – .cpp and .h. Also, keep classes in different files. It makes code maintenance much easier. in your case, you need a .cpp file to build exe.
I know this is an exercise, but if you are going to learn it is better to do it correctly from the beginning. I did not separate this snippet into different units to make it easier for you to compare code and see changes.
#include <afxwin.h>
class Index : public CWnd
{
public:
Index()
{
};
void OnPaint()
{
CPaintDC dc(this); // device context for painting added to indicate that this exists
CRect recWnd;
GetClientRect(recWnd);
dc.DrawText(CString(_T("This is a child window")), CRect(0, 10, recWnd.Width(), 50), DT_CENTER);
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(Index, CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
class MainFrame : public CFrameWnd
{
public:
MainFrame()
{
};
int OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// below, keep only one line uncommented
// if this line is uncommented Index windows will automatically resize.
//m_Index.Create(NULL, NULL, WS_CHILD, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL);
//This version will not
m_Index.Create(NULL, NULL, WS_CHILD | WS_BORDER, CRect(0, 0, 300, 100), this, NULL, NULL);
m_Index.ModifyStyleEx(0, WS_EX_CLIENTEDGE); //to better see the client
m_Index.ShowWindow(SW_NORMAL);
return 0;
};
protected:
Index m_Index;
protected:
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
class Application : public CWinApp
{
virtual BOOL InitInstance()
{
MainFrame* pMainFrame = new MainFrame;
pMainFrame->Create(NULL, _T("Parent and Child"), WS_OVERLAPPEDWINDOW, CRect(0, 0, 640, 360));
m_pMainWnd = pMainFrame;
m_pMainWnd->ShowWindow(SW_NORMAL);
m_pMainWnd->UpdateWindow();
return true;
};
};
Application app;
I am updating some old software that does not work on Win7 or later. so, I am rebuilding some MFC libraries that are using latest win32 updates.
Now I have two issues:
MessageBox appears behind the CFrameWnd so it can't be accessed sending the application to halt.
Open dialog box (whether is based on CFileDialog or IFileDilog) does not get refreshed when changing the file type.
However, both problems are solved if the CFrameWnd is hidden. or, in case of MessageBox, you will not need to hide the window if you write: PostMessage(0x118); which in fact I don't know why.
There must be something I am missing Here.
I also Have another problem when using the OpenFileDialog class that inherits from the IFileDialog. is when closing this dialog without picking up a file, the application Crashes.
//--targetver.h
#pragma once
#include <sdkddkver.h>
//--stdafx.h:
#ifndef CS_EXTRALEAN
#define CS_EXTRALEAN
#endif
#pragma once
#include "targetver.h"
#include<afxwin.h>
#include<afxext.h>
#include<afxcmn.h>
//--stdafx.cpp
#include "stdafx.h"
//--CMainWnd.h
#pragma once
class CMainWnd : public CFrameWnd
{
public:
CMainWnd();
~CMainWnd();
afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT, CPoint);
DECLARE_MESSAGE_MAP()
};
//--CMainWnd.cpp
#include "stdafx.h"
#include"CMainWnd.h"
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
CMainWnd::CMainWnd()
: CFrameWnd()
{
CString class_name = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
AfxGetApp()->LoadStandardCursor(IDC_ARROW),
(HBRUSH)::GetStockObject(BLACK_BRUSH),
AfxGetApp()->LoadStandardIcon(IDI_ASTERISK));
HRESULT hResult = this->Create(
class_name,
L"This is CMainWnd",
WS_OVERLAPPEDWINDOW,
this->rectDefault,
NULL,
NULL,
0,
NULL);
}
CMainWnd::~CMainWnd() { }
void CMainWnd::OnPaint()
{ }
void CMainWnd::OnLButtonDown(UINT, CPoint)
{
MessageBox(L"HELLO MFC", L"MFC", MB_OK);
}
//--CAppWnd.h
#pragma once
class CAppWnd : public CWinApp
{
public:
CAppWnd();
~CAppWnd();
BOOL InitInstance();
DECLARE_MESSAGE_MAP()
};
//--CAppWnd.cpp
#include "stdafx.h"
#include "CAppWnd.h"
#include "CMainWnd.h"
BEGIN_MESSAGE_MAP(CAppWnd, CWinApp)
END_MESSAGE_MAP()
CAppWnd::CAppWnd()
:CWinApp()
{ }
CAppWnd::~CAppWnd()
{ }
BOOL CAppWnd::InitInstance()
{
this->m_pMainWnd = new CMainWnd;
this->m_pMainWnd->ShowWindow(m_nCmdShow);
return CWinApp::InitInstance();
}
CAppWnd The_App;
There was a simple problem. You override OnPaint but didn't call the default procedure. OnPaint handles to WM_PAINT message, it doesn't forgive this error.
void CMainWnd::OnPaint()
{
CFrameWnd::OnPaint(); //<= this was missing
//custom paint...
//CClientDC dc(this);
//dc.TextOut(0, 0, L"test");
//dc is automatically released...
}
Or you can use CPaintDC which is a wrapper for BeginPaint/EndPaint API
void CMainWnd::OnPaint()
{
CPaintDC dc(this);
//custom paint...
//dc.TextOut(0, 0, L"test");
//dc is automatically released...
}
If you don't do any painting in this frame window then remove the whole CMainWnd::OnPaint() function and the correspoonding ON_WM_PAINT message.
Above change should fix your error. I would rewrite the rest of the code so it calls the default override first. Example:
#include "stdafx.h"
#include "resource.h"
class CMainWnd : public CFrameWnd
{
public:
CMainWnd();
~CMainWnd();
afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT, CPoint);
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
CMainWnd::CMainWnd() : CFrameWnd() {}
CMainWnd::~CMainWnd() {}
void CMainWnd::OnPaint()
{
CFrameWnd::OnPaint();
}
void CMainWnd::OnLButtonDown(UINT f, CPoint pt)
{
CFrameWnd::OnLButtonDown(f, pt);
CFileDialog dlg(TRUE, 0, 0, 0,
L"All files|*.*|"
L"Text files|*.txt;*.txt||" , this);
if (dlg.DoModal() == IDOK)
MessageBox(dlg.GetPathName(), L"MFC", MB_OK);
}
class CAppWnd : public CWinApp
{
public:
BOOL InitInstance();
};
BOOL CAppWnd::InitInstance()
{
CWinApp::InitInstance();
CMainWnd *frame = new CMainWnd;
CString class_name = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
AfxGetApp()->LoadStandardCursor(IDC_ARROW),
(HBRUSH)::GetStockObject(BLACK_BRUSH),
AfxGetApp()->LoadStandardIcon(IDI_ASTERISK));
frame->Create(class_name, L"This is CMainWnd",
WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault, NULL, NULL, 0, NULL);
frame->ShowWindow(m_nCmdShow);
m_pMainWnd = frame;
return TRUE;
}
CAppWnd The_App;
Note that you can call up static members directly, for example CFrameWnd::rectDefault, it doesn't cause an error either way but it makes the code more clear.
I am new to MFC and in below code OnPaint() is not invoked.
//TestWnd.H
#ifndef TESTWND
#define TESTWND
#include<afxwin.h>
//window
class TestWnd:public CFrameWnd
{
public:
TestWnd();
protected:
afx_msg void onPaint();
DECLARE_MESSAGE_MAP()
};
#endif
//TestWnd.cpp
#include"TestWnd.h"
TestWnd::TestWnd()
{
Create (NULL, _T ("The Hello Application"),
WS_OVERLAPPEDWINDOW,
CRect(120, 100, 700, 480), NULL);
}
void TestWnd ::onPaint()
{
MessageBox(_T("The window has been PAINTED!!!"));
//CPaintDC dc(this);
//CRect crec;
//GetClientRect(&crec);
//dc.DrawText(_T("Hello"),-1, &crec, DT_SINGLELINE/* | DT_CENTER | DT_VCENTER*/);
}
BEGIN_MESSAGE_MAP(TestWnd,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
//TestApp.h
#ifndef TESTAPP
#define TESTAPP
#include<afxwin.h>
class TestApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
#endif
//TestApp.cpp
#include "TestApp.h"
#include "TestWnd.h"
TestApp g_obj;
BOOL TestApp::InitInstance()
{
m_pMainWnd = new TestWnd;
m_pMainWnd->ShowWindow(m_nCmdShow);
//m_pMainWnd->UpdateWindow();
return TRUE;
}
The reason is very simple.
ON_WM_PAINT requires a handler named OnPaint. You implemented a handler named onPaint. Because there is a default implementation the default CFrameWnd::OnPaint is called.
Rename your handler to OnPaint.
I have a simple MFC dialog.
class CMessageBoxWithCustomTextDlg : public CDialogEx
{
// Construction
public:
CMessageBoxWithCustomTextDlg(CWnd* pParent = NULL); // standard constructor
__declspec(dllexport) void SetData(std::string& data);
// Dialog Data
enum { IDD = IDD_MESSAGEBOXWITHCUSTOMTEXT_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedShowMessagebox();
};
I would like to export it as dll and call it from a simple console application. Is it possible?
It is possible; here is how I did it:
For your console application have it be simply this:
#include <Windows.h>
typedef void (*EntryFunc)();
int main()
{
HMODULE hMod = LoadLibrary(L"MFCDll.dll");
EntryFunc func = (EntryFunc)GetProcAddress(hMod, "entrypoint");
func();
}
The name of the DLL is MFCDll.dll and there is an exported function called entrypoint in that DLL.
For the DLL I created a New MFC DLL project. And other than the dialog code and the dialog in the resources add this code:
extern "C" __declspec(dllexport) void entrypoint()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CMessageBoxWithCustomTextDlg dlg;
dlg.DoModal();
}
And the console program will load the DLL, call into the DLL and the dialog shows.
I am try to create very simple c++ MFC project. Since it is very simple one I need to create it form scratch.
my code so far is shown below. But now I need to add picture control and thus my Intent use CImage class. But to use CImage class I need to add altimage.h header to my project. But When I do so it gives a error that cannot open source file altimage.h. So
How can I overcome this problem.
How to add the file I needed when I creating the MFC projects form the scratch.
please help me solvethis.
thanks
#include <afxwin.h> //MFC core and standard components
//#include <altimage>
#include "resource.h" //main symbols
//-----------------------------------------------------------------------------------------
//Globals
//CEdit * TEST;
CEdit * RECOG_CHARS;
CButton * BTN_CONVERT;
CButton * BTN_QUIT;
CStatic * IMG_IMAGE;
class HWCR_FORM : public CDialog
{
public:
HWCR_FORM(CWnd* pParent = NULL) : CDialog(HWCR_FORM::IDD, pParent)
{ }
// Dialog Data, name of dialog form
enum{ IDD = ID_MAIN_INTERFACE };
protected:
virtual void DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); }
//Called right after constructor. Initialize things here.
virtual BOOL OnInitDialog()
{
CDialog::OnInitDialog();
RECOG_CHARS = (CEdit *)GetDlgItem(CE_ID_TEXT);
BTN_CONVERT = (CButton *)GetDlgItem(CB_ID_START);
BTN_QUIT = (CButton *)GetDlgItem(CB_ID_QUIT);
IMG_IMAGE = (CStatic *)GetDlgItem(CS_ID_IMAGE);
HBITMAP image = (HBITMAP)LoadImage(NULL,L"C:\\Users\\Kasun\\Desktop\\image.bmp",IMAGE_BITMAP,150,120,LR_LOADFROMFILE);
IMG_IMAGE->SetBitmap(image);
RECOG_CHARS->SetWindowTextW(L"Hi there");
return true;
}
public:
DECLARE_MESSAGE_MAP()
};
//-----------------------------------------------------------------------------------------
class HWCR : public CWinApp
{
public:
HWCR() { }
public:
virtual BOOL InitInstance()
{
CWinApp::InitInstance();
SetRegistryKey(_T("Hills Of Darkness"));
HWCR_FORM dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
return FALSE;
} //close function
};
//-----------------------------------------------------------------------------------------
//Need a Message Map Macro for both CDialog and CWinApp
BEGIN_MESSAGE_MAP(HWCR_FORM, CDialog)
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------------------
HWCR theApp;
First at all, in order to use CImage, you need to include header file
#include <atlimage.h>
instead of
#include <altimage>
Secondly, be sure that this file's directory is included into MSVC paths...
Normally it should be included as this header file is part of MFC / Win32 SDK....check the directories in VS properties.
Z.