ورود

View Full Version : سوال: مشکل در تبدیل انواع در ویژوال ++c ی 2008



feri88
پنج شنبه 08 اسفند 1387, 09:42 صبح
سلام
من کتاب "برنامه نویسی با ویژوال ++C " تالیف جعفر نژاد قمی و رمضان عباس نژاد رو خوندم(جلدش سبزه!)
قبلا که مثالهاش رو توی ویژوال ++C ورژن 6 اجرا می کردم، همه رو درست جواب می داد!
ولی الآن توی ویژوال ++C ی 2008 مشکل دارم؛
من مثال 4-6 این کتاب که مربوط به فصل ششه و در مورد استفاده از کنترل ListBox هست رو اجرا کردم، برنامه اش اینه:

// ListBoxDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ListBox.h"
#include "ListBoxDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
CAboutDlg();

// Dialog Data
enum { IDD = IDD_ABOUTBOX };

protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

// Implementation
protected:
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CListBoxDlg dialog




CListBoxDlg::CListBoxDlg(CWnd* pParent /*=NULL*/)
: CDialog(CListBoxDlg::IDD, pParent)
, Sum2(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CListBoxDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, List1);
DDX_Control(pDX, IDC_LIST2, List2);
DDX_Text(pDX, IDC_EDIT1, Sum2);
}

BEGIN_MESSAGE_MAP(CListBoxDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDDisplay, &CListBoxDlg::OnBnClickedDisplay)
ON_BN_CLICKED(IDC_BUTTON1, &CListBoxDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CListBoxDlg::OnBnClickedButton2)
END_MESSAGE_MAP()


// CListBoxDlg message handlers

BOOL CListBoxDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here

return TRUE; // return TRUE unless you set the focus to a control
}

void CListBoxDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.

void CListBoxDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}

// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CListBoxDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}


void CListBoxDlg::OnBnClickedDisplay()
{
// TODO: Add your control notification handler code here
int i;
int sum=0;
char s[10];
UpdateData(TRUE);
List1.ResetContent();
for(i=0;i<=20;i++)
{
sum=i*i;
_itoa_s(i,s,10);
List1.AddString(s);
}
Sum2=sum;
UpdateData(FALSE);
}

void CListBoxDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
int i;
CString s;
List2.ResetContent();
for(i=List1.GetCount()-1;i>=0;i--)
{
List1.GetText(i,s);
List2.AddString(s);
}
}

void CListBoxDlg::OnBnClickedButton2()
{
// TODO: Add your control notification handler code here
List1.ResetContent();
List2.ResetContent();
Sum2=0;
UpdateData(FALSE);
}
اولاش که مربوط به کلاس ها ییه که خود به خود تولید میشه، فقط سه تا تابع آخری، تو این برنامه اضافه شده،

بعد از اجرا این ارور رو میده:
کد:
------ Build started: Project: ListBox, Configuration: Debug Win32 ------
Compiling...
ListBoxDlg.cpp

d:\listboxdlg.cpp(171) : error C2664: 'CListBox::AddString' : cannot convert parameter 1 from 'char [10]' to 'LPCTSTR'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

ListBox - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
و میگه نمی تونه char (به طول 10 ) رو به 'LPCTSTR تبدیل کنه.

چی کار کنم که این ارور رفع بشه؟
باید تنظیماتی رو توی ویژوال ++C ی 2008 انجام بدم که این جور ارورها رفع بشه؟


بی زحمت کمکم کنید
مرسی:بوس:

Nima_NF
جمعه 09 اسفند 1387, 01:22 صبح
در نسخه های بعد از VC++6 به طور پیش فرض کامپایلر در حالت unicode برنامه را کامپایل می کند.

پس هر جا که از char استفاده شده است باید با TCHAR جایگزین شود، و هر جایی که مستقیم خود رشته را در برنامه با " " استفاده می کنید با پسوند L یا TEXT همراه شوند:



TCHAR str[20] = L"This is a test";

// or use this for both unicode and ascii
TCHAR str[20] = TEXT("This is a test");

feri88
جمعه 09 اسفند 1387, 18:36 عصر
سلام
مرسی
من تو حالت unicode ، از L و TEXT توی تابع Addstring استفاده کردم ولی تو هر دو تا حالت ارور می داد که Ls رو نمی شناسه.(فکر کنم منظورش این جور تبدیلا بود)
بعد اومدم از تبدیل نوع (CString ) استفاده کردم درست شد و پروژه اجرا شد، به این صورت:

List1.AddString((CString)s);


بعدش اومدم از حالت unicode به ASCII تغییر ش دادم(با project/properties/character set )
Addstring هم تو همون حالت عادی گذاشتم (با همون s از نوع char ) به این صورت:

List1.AddString(s);

بعد یه اروری داد که اصلا مربوط به تبدیل نوع نیست و نمی دونم ناشی از کجاست ؟
بی زحمت بگین این ارور چیه و چرا تو حالت ASCII این ارور رو می بینم؟

------ Build started: Project: ListBox, Configuration: Debug Win32 ------

Linking...
Embedding manifest...
mt.exe : general error c101008a: Failed to save the updated manifest to the file ".\Debug\ListBox.exe.embed.manifest". The

parameter is incorrect.

ListBox - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Nima_NF
جمعه 09 اسفند 1387, 22:54 عصر
سعی کنید تا جای ممکن از CString برای پارامتر های توابع و کلاس های MFC استفاده کنید تا به طور اتومات معادل TCHAR رشته ها را در نظر بگیرد.

شما هرگز نباید بنویسید Ls ، همانطور که گفتم فقط وقتی از کوتیشن " "L استفاده می کنید نه اسم رشته را.
به CString هم تبدیل نکنید، به جای این کار کلا از همان CString استفاده کنید.

به جای S کد زیر را در حالت unicode تست کنید (برای هر دو حالت debug و release باید آن را در properties یونیکد تنظیم کنید):



List1.AddString(L"test");

این خط نباید هیچ خطایی بدهد، اگر داد یعنی در جای دیگر اشتباهی کرده اید یا اصلا پروژه یونیکد تنظیم نشده است.

ضمنا، فقط این موارد نیست، تمامی توابع استاندارد C یا ++C که استفاده کرده اید نیز باید معادل یونیکد آن ها استفاده شود، مثلا همین itoa_s برای اسکی هست، معدل یونیکد/اسکی آن (هر دو حالت) itot_s_ است در هدر فایل Tchar.h:



TCHAR s[10];
_itot_s (i, s,10);



بی زحمت بگین این ارور چیه و چرا تو حالت ASCII این ارور رو می بینم؟وقتی تغییرات کلی در تنظیمات پروژه می دهید، باید از طریق منوی build گزینه clean solution را انتخاب کنید تا کلیه فایل های کامپایل شده را پاک کنید و سپس مجددا کامپایل کنید.