ошибка C1010: неожиданный конец файла при поиске предварительно скомпилированного заголовка. Вы забыли добавить '#include stdafx.h' в исходный код?

У меня есть проект, изначально разработанный на Microsoft Visual C++. NET версии 7.0.9466 и работает очень хорошо. Я пытался использовать MS 2013 для запуска своего проекта, и когда я пытаюсь создать проект, у меня появляется сообщение об ошибке:

ошибка C1010: неожиданный конец файла при поиске предварительно скомпилированного заголовка. Вы забыли добавить '#include "stdafx.h"' в исходный код?

Некоторые действия, которые я уже сделал:

  • Я выбрал параметр «Использовать (/Yu)» для предварительно скомпилированного заголовка в PropertyPages-> C/C++ -> Precompiled Header.
  • Я устанавливаю предварительно скомпилированный файл заголовка в stdafx.h
  • Я поставил #include "stdafx.h" в начале файла .cpp
  • Мне пришлось изменить #include "stdafx.h" на #include "../stdafx.h", потому что у меня было это сообщение об ошибке:

IntelliSense: не удается открыть исходный файл "stdafx.h"

Вот файл .cpp, в котором у меня есть эта ошибка сообщения

#include "../stdafx.h"
#include "timedmsgbox.h"

/////////////////////////////////////////////////////////////////////////
//
// CDlgTimedMessageBox
//
/////////////////////////////////////////////////////////////////////////

CMapPtrToPtr		CDlgTimedMessageBox::m_mapTimerIdToClassMe;
CCriticalSection	CDlgTimedMessageBox::m_sectMap;
extern BOOL AFXAPI AfxIsDescendant(HWND hWndParent, HWND hWndChild);

// the static one to call the messagebox with one line
UINT CDlgTimedMessageBox::TimedMessageBox(UINT flags, LPCTSTR ptszMessage, LPCTSTR ptszTitle, 
						DWORD dwTimeout, UINT dDefaultReturn,
						LPCTSTR ptszMessageTimer, HWND hwndParent, BOOL *pbStoppedByUser)
{
	CDlgTimedMessageBox		msgBox(flags, ptszMessage, ptszTitle, 
									dwTimeout, dDefaultReturn, 
									ptszMessageTimer, hwndParent);

	return msgBox.ShowMessageBox(pbStoppedByUser);
}

CDlgTimedMessageBox::CDlgTimedMessageBox(UINT flags, 
								LPCTSTR ptszMessage, LPCTSTR ptszTitle, 
								DWORD dwTimeout, UINT dDefaultReturn,
								LPCTSTR ptszMessageTimer, 
								HWND hwndParent)
{
	m_hParent			= hwndParent;
	m_Message			= ptszMessage;
	m_Title				= ptszTitle;
	m_flags				= flags;
	m_dwTimeout			= dwTimeout-1;
	m_MessageTimer		= ptszMessageTimer;
	m_DefaultReturn		= dDefaultReturn;
	
	m_hMsgBox			= NULL;
	m_hStaticText		= NULL;
	m_hDefaultButton	= NULL;
	m_bRunning			= FALSE;
	m_bStoppedByTimer	= FALSE;

	if( !m_hParent )
	{
		CWnd *m_pParent = AfxGetApp()->GetMainWnd();
		m_hParent = m_pParent->m_hWnd;
	}
}

CDlgTimedMessageBox::~CDlgTimedMessageBox()
{
}

#pragma warning( push)
#pragma warning (disable : 4312) // conversion to type of greater size
UINT CDlgTimedMessageBox::ShowMessageBox(BOOL *pbStoppedByUser)
{
	// start timer 
	CDlgTimedMessageBox::m_sectMap.Lock();
	{
		m_idTimer = (UINT)::SetTimer(NULL, 0, 1000, (TIMERPROC) CDlgTimedMessageBox::GlobalTimerProc);
		CDlgTimedMessageBox::m_mapTimerIdToClassMe.SetAt((void*)m_idTimer, this);
	}
	CDlgTimedMessageBox::m_sectMap.Unlock();
	
	// show MessageBox
	m_bRunning = TRUE;
	m_dwStarted = ::GetTickCount();
	
	m_CurrentMessage = m_Message;
	if( !m_MessageTimer.IsEmpty() )
	{
		CString	second;
		second.Format(m_MessageTimer, (m_dwTimeout+1)/1000);
		m_CurrentMessage.Format("%s%s", m_Message, second);
	}
	UINT erg = ::MessageBox(m_hParent, m_CurrentMessage, m_Title, m_flags);
	m_bRunning = FALSE;

	CDlgTimedMessageBox::m_sectMap.Lock();
	{
		::KillTimer(NULL, m_idTimer);
		m_idTimer = 0;
		CDlgTimedMessageBox::m_mapTimerIdToClassMe.RemoveKey((void*)m_idTimer);
	}
	CDlgTimedMessageBox::m_sectMap.Unlock();

	if( pbStoppedByUser )
		*pbStoppedByUser = !m_bStoppedByTimer;
	
	return erg;
}
#pragma warning( pop )

void CALLBACK CDlgTimedMessageBox::GlobalTimerProc(HWND hwnd, UINT uiMsg, UINT_PTR idEvent, DWORD dwTime)
{
	//TRACE("Global timer with id=%u\n", idEvent);
	
	CDlgTimedMessageBox	*pMe = NULL;
	
	// Find the corresponding class by the timer-id
	CDlgTimedMessageBox::m_sectMap.Lock();
	{
		CDlgTimedMessageBox::m_mapTimerIdToClassMe.Lookup((void*)idEvent, (void *&) pMe);
	}	
	CDlgTimedMessageBox::m_sectMap.Unlock();
	
	if( pMe!=NULL )
		pMe->LocalTimerProc();
}

void CDlgTimedMessageBox::LocalTimerProc(void)
{
	//TRACE("Local timer with id=%u (%s)\n", m_idTimer, m_Title);

	if( !m_bRunning )
		return;

	// lookup the handles 
	GetWindowHandles();


	if( !m_hStaticText || !m_hMsgBox )
		return;

	DWORD now = GetTickCount()-m_dwStarted;
	
	if( now >= (m_dwTimeout) )
	{
		// done with the box
		m_bStoppedByTimer = TRUE;
		::PostMessage(m_hMsgBox, WM_COMMAND, (WPARAM) m_DefaultReturn, (LPARAM) m_hDefaultButton);
	}
	else
	{
		m_CurrentMessage = m_Message;
	
		// not done: set text again
		if( !m_MessageTimer.IsEmpty() )
		{
			CString	second;
			second.Format(m_MessageTimer, (100+m_dwTimeout-now)/1000);
			m_CurrentMessage.Format("%s%s", m_Message, second);
		}
		::SetWindowText(m_hStaticText, m_CurrentMessage);
	}	
}

void CDlgTimedMessageBox::GetWindowHandles(void)
{
	HWND		hWnd;
	CWnd		*pWnd;
	CString		title;
	CPtrList	allButtons;

	//
	// Handle of the messageBox
	//
	if( !m_hMsgBox )
	{
		hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
		while( (hWnd!=NULL) && (m_hMsgBox==NULL) )
		{
			pWnd = CWnd::FromHandle(hWnd);
			pWnd->GetWindowText(title);

			if( AfxIsDescendant(m_hParent, hWnd) && ::IsWindowVisible(hWnd) && (m_Title.CompareNoCase(title)==0) )
			{
				m_hMsgBox = hWnd;
				break;
			}
			
			hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
		}
	}

	//
	// Handle of the static text
	// TODO only if text-replace is needed
	//
	if( m_hMsgBox && !m_hStaticText )
	{
		// not sure if this will work always
		// under Win2000 it did
		//m_hStaticText = ::GetDlgItem(m_hMsgBox, 0xFFFF);

		// not sure, so lets find it dynamically!

		char		className[_MAX_PATH];
		CString		classNameOk("STATIC");
		LONG		id;

		hWnd = ::GetWindow(m_hMsgBox, GW_CHILD);
		while( (hWnd!=NULL) && (m_hStaticText==NULL) )
		{
			id = ::GetWindowLong(hWnd, GWL_ID);
			
			// small ids only for buttons
			if( id > IDHELP )
			{
				if( ::GetClassName(hWnd, className, _MAX_PATH) )
				{

					// looking only for a static 
					if( classNameOk.CompareNoCase(className) == 0 )
					{
						// not check the text
						pWnd = CWnd::FromHandle(hWnd);
						pWnd->GetWindowText(title);
						
						if( m_CurrentMessage.CompareNoCase(title) == 0 )
						{
							m_hStaticText = hWnd;
							break;
						}

					}
				}
			}
			else
			{
				allButtons.AddTail(hWnd);
			}

			hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
		}

	}

	//
	// Handle of the default button
	//
	if( m_hMsgBox && !m_hDefaultButton )
	{
		m_hDefaultButton = ::GetDlgItem(m_hMsgBox, m_DefaultReturn);
		
		// Problem: 
		// if generated with MB_OK the button has NOT IDOK, but IDCANCEL !!
		// then lets take the first button we find !
		// (with and IDCANCEL this works, because it is the only button
		// if this problem encounters also with 2 buttons, I have no chance 
		// to find out which one is the better one!)
		while( allButtons.GetCount()>0 && !m_hDefaultButton )
		{
			m_hDefaultButton = (HWND) allButtons.GetHead();
			allButtons.RemoveHead();
			
			if( m_hDefaultButton )
				m_DefaultReturn = ::GetWindowLong(m_hDefaultButton, GWL_ID);
		}
	}
}

а вот файл stdafx.h

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently

#pragma once

#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
#endif

// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER				// Allow use of features specific to Windows 95 and Windows NT 4 or later.
//#define WINVER 0x0400		// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#define WINVER 0x0602       // SMS2014XXXX alteração para funcionar windows 8
#endif

#ifndef _WIN32_WINNT		// Allow use of features specific to Windows NT 4 or later.
//#define _WIN32_WINNT 0x0400		// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#define _WIN32_WINNT 0x0602       // SMS2014XXXX alteração para funcionar windows 8
#endif						

#ifndef _WIN32_WINDOWS		// Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif

#ifndef _WIN32_IE			// Allow use of features specific to IE 4.0 or later.
#define _WIN32_IE 0x0400	// Change this to the appropriate value to target IE 5.0 or later.
#endif

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit

// turns off MFC's hiding of some common and often safely ignored warning messages
#define _AFX_ALL_WARNINGS

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions
#include <afxdisp.h>        // MFC Automation classes
#include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls

#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>			// MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT

#include <afxdhtml.h>

Я новичок в визуальной студии, и я понятия не имею, что со всем этим не так. Кто-нибудь может помочь мне с этим?


person Darós    schedule 11.02.2015    source источник
comment
Вам придется изменить параметры компиляции /Yc и /Yu для каждого файла. Это непрактично, просто используйте простой stdafx.h, чтобы параметры компиляции были хорошими. И либо переместите файл .h, либо используйте настройку дополнительных каталогов включения компилятора.   -  person Hans Passant    schedule 11.02.2015


Ответы (1)


Это путаница между intellisense и компилятором.

Вы сможете обойти это, добавив $(ProjectDir) к параметру Additional Include Directories для приложения и заменив "..\StdAfx.h" на "StdAfx.h", так как IntelliSense теперь должен начать выбирать путь.

person Petesh    schedule 11.02.2015
comment
Это не помогло в VS 2015. Я добавил $(ProjectDir) в каталоги Include в каталогах VC++ в свойствах проекта, но все равно получаю ту же ошибку для #include ..\..\stdafx.h. Я предполагаю, что единственным обходным путем является использование фильтров вместо подпапок для файлов кода C++. - person Scott Hutchinson; 23.05.2018