ورود

View Full Version : مبتدی: مشکل با نوع رشته ای در VC و تابع DrawText



Farzandekurosh
پنج شنبه 27 مرداد 1390, 02:16 صبح
با سلام خدمت همه دوستان .

یه برنامه ساده نوشتم که یه پنجره win32 ایجاد میکنه و وسط صفحه یه متن مینویسه و Frame Per Second رو بالای پتجره مینویسه:خجالت:


MessageBox(0,"Register Class Failed !","ERROR",MB_OK);

error::ناراحت:

error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [24]' to 'LPCWSTR'

برا پارامتر سوم هم خطا میده البته اگه از ماکروی TEXT به صورت زیر استفاده کنم خطا نمیده :

MessageBox(0,TEXT("Register Class Failed !"),TEXT("ERROR"),MB_OK]);

و مشکل اصلی :


void render( void )
{
//declares
RECT rectFormat;
GetClientRect(hwnd,&rectFormat);
D3DXFONT_DESC fontDesc;
static char buffer[256];

//----------------------------
fontDesc.Height = 30;
fontDesc.Width = 20;
fontDesc.Weight = FW_BOLD;
fontDesc.MipLevels = 0;
fontDesc.Italic = false;
fontDesc.CharSet = DEFAULT_CHARSET;
fontDesc.OutputPrecision = OUT_DEFAULT_PRECIS;
fontDesc.Quality = DEFAULT_QUALITY;
fontDesc.PitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
wcscpy_s(fontDesc.FaceName,_T("Times New Roman"));
D3DXCreateFontIndirect(MyDevice,&fontDesc,&mFont);

sprintf(buffer, "Frames Per Second = %.2f",dt);

MyDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

MyDevice->BeginScene();
// Render geometry here...
mFont->DrawText(0,buffer,-1,&rectFormat,DT_NOCLIP,D3DCOLOR_XRGB(100,100,100));

mFont->DrawText(0,TEXT("Hello d3d World."),-1,&rectFormat,DT_CENTER | DT_VCENTER,D3DCOLOR_XRGB(100,100,100));

MyDevice->EndScene();

MyDevice->Present( NULL, NULL, NULL, NULL );
}


error ::ناراحت:

error C2664: 'ID3DXFont::DrawTextW' : cannot convert parameter 2 from 'char [256]' to 'LPCWSTR'


در ضمن :

float dt;

به صورت سراسری تعریف شده که قبل از اجرا شدن تابع render در حلقه اصلی برنامه مقدار FPS محاسبه و تو این متغیر ریخته میشه. روش محاسبه FPS رو تو کتاب Introduction to 3d game programming wint directx 9 :shader گفته که سورس های مثال هاش رو دارم ولی تو سورس ها همچین خطایی نمیده من تو vs2010 کد مینویسم تو vs2008 هم همین مشکل رو داشتم

اگه خط :

mFont->DrawText(0,buffer,-1,&rectFormat,DT_NOCLIP,D3DCOLOR_XRGB(100,100,100));


رو به صورت :

mFont->DrawText(0,(LPCWSTR)buffer,-1,&rectFormat,DT_NOCLIP,D3DCOLOR_XRGB(100,100,100));

بنویسیم خطا نمیده ولی buffer رو به صورت کاراکتر های نا مفهوم جاپ می کنه .:ناراحت:

Hr.Ziggurat
پنج شنبه 27 مرداد 1390, 12:29 عصر
تویه VC++ 6 به بعد ، توابع ویندوزی ای که با رشته ها کار میکنند ، در کل دو نوع شدند ، توابع ای که با W تموم میشند ، و توابع ای که با A تموم میشند. نوع اول رشته هایی که باشون کار میشه باید از نوع LPCWSTR باشند و نوع دوم از نوع LPCSTR ( همون char* ).تو رشته نوع LPCWSTR هر کارکتر 2 بایته و رشته از نوع UNICODE هستش (این کار واسه ی پوشش کارکترهای مختلفه).
البته مقدار کد اسکی حروف انگلیسی تو این نوع رشته تغییری نکرده:
char *t="S\0A\0L\0A\0M";
MessageBox(0,LPCWSTR(t),LPCWSTR(t),0);
واسه تبدیل رشته های ثابت LPCWSTR میشه از دستور TEXT یا L استفاده کرد. واسه ی رشته های متغییری هم میتونی یه تیکه کد بنویسی که بعد هر حرف یه "\0" بذاره.


ولی راه ساده ترش اینه که توابع ای که استفاده میکنی آخرش یه حرف A بذاری ، تا بتونی از رشته هاییه نوع ساده (multibyte)، توشون استفاده کنی! هر تابع تویه کتابخونش به صورت W دار تعریف شده مثل :
#define MessageBox MessageBoxW
پس طبیعیه که توابع نیازمند رشته های نوع LPCWSTR باشند.
فقط کافیه به جای MessageBox از MessageBoxA و به جای DrawText از DrawTextA استفاده کنی! به همین راحتی.

Farzandekurosh
پنج شنبه 27 مرداد 1390, 17:10 عصر
پس اینطور که من برداشت کردم دو نوع داریم یکی LPCSTR که همون char* خودمونه و LPCWSTR که کاراکتر wide هستش و دو بایته
حالا دو تا سوال پیش میاد :

1- واسه رشته هایی که انگلیسی هستن که نیازی به استفاده از LPCWSTR نداریم؟

2- پروژه های نمونه ای که من دارم (از کتاب intro to 3d with dx 9... by frank leona و ...) از حرف A آخر توابع استفاده نکرده و وقتی که تو ویژوال جدید (2008 و 2010) بازشون میکنم بعد از convert بدون خطا اجرا می شن البته بعد از convert ویژوال هیچ تغییری تو کد نمیده این جریانش چی میشه ؟!

Hr.Ziggurat
پنج شنبه 27 مرداد 1390, 19:25 عصر
پس اینطور که من برداشت کردم دو نوع داریم یکی LPCSTR که همون char* خودمونه و LPCWSTR که کاراکتر wide هستش و دو بایتهLPCSTR و LPCWSTR هر دو اشاره گر واسه ی رشته ها هستند.
typedef char *LPCSTR;
typedef wchar_t *LPCWSTR ; //String of Wide Char's
البته به غیر از این دوتا چند نوع دیگه مثل LPSTR و LPCTSTR و... هم وجود دارند. که مشابه دو نوع قبلی اند.


- واسه رشته هایی که انگلیسی هستن که نیازی به استفاده از LPCWSTR نداریم؟نه ، نیازی نیست.


- پروژه های نمونه ای که من دارم (از کتاب intro to 3d with dx 9... by frank leona و ...) از حرف A آخر توابع استفاده نکرده و وقتی که تو ویژوال جدید (2008 و 2010) بازشون میکنم بعد از convert بدون خطا اجرا می شن البته بعد از convert ویژوال هیچ تغییری تو کد نمیده این جریانش چی میشه ؟!
استفاده یا عدم استفاده از UNICODE تویه توابع ، در ابتدای فایل های هدر ویندوز با استفاده از کد ماکرو تعیین میشه.مثلا:

#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif // !UNICODE

حالا واسه ی اینکه توابع ویندوزی از ANSI به جایه UNICODE استفاده کنند و نیازی به A آخر توابع نباشه ، دوتا راه داری. یا باید قبل include کردن فایلهایه هدر ویندوز بنویسی :
#undef UNICODE
که البته اینجوری باید اسم تابع اصلی رو از _tWinMain به WinMain تغییر بدی.

یا اینکه بری تو تنظیمات پروژه و از قسمت جنرال ، مقدار Character Set رو به Use Multi-Byte Character Set تغییر بدی. تویه convert کردن همین اتفاق میفته.

AbdolHabib8
یک شنبه 30 مرداد 1390, 08:14 صبح
سلام.اگه جای :
"Salam"
هم ینویسی :
L"Salam"
هم درست کار می کنه.