PDA

View Full Version : مشکل آیتمهای Combobox در تنظیمات انگلیسی زبان ویندوز



nasr
شنبه 12 آبان 1386, 16:53 عصر
سلام
من واقعا با این ساپورت نکردن UniCode در دلفی مشکل دارم
طبق این عکسی که می بینید وقتی آیتمهای یک ComboBox فارسی باشند و تنظیمات زبان روی انگلیسی باشه
حروف اجق وجق میشه
این در حالیه که وقتی برنامه را با سی شارپ می نویسم هیچ مشکلی نداره و این واقعا شده دردسر برای من
لطفا نگید از مجموعه TNT استفاده کنم

ممنون

Hamid_PaK
شنبه 12 آبان 1386, 18:46 عصر
ناصر جان کی به این مشکل بر می خورید ؟؟؟
آیتم ها را در inspector وارد می کنید و در dfm ریسورس ذخیره می شود ؟ درست است ؟

nasr
یک شنبه 13 آبان 1386, 08:36 صبح
ناصر جان کی به این مشکل بر می خورید ؟؟؟
آیتم ها را در inspector وارد می کنید و در dfm ریسورس ذخیره می شود ؟ درست است ؟
بله درسته.
من یه پروژه بزرگ می خوام بگیرم که با توجه به تجربه ای که دارم با تنظیمات انگلیسی زبان دستم برای کار بسته میشه و خیلی جاها مشکل پیدا می کنم
از جمله همین ComboBox . و پیامهایی که برنامه باید بدهد مثلا ShowMessage('سلام')

ممنون میشم اگه راه حلی پیشنهاد کنید

Hamid_PaK
یک شنبه 13 آبان 1386, 08:52 صبح
روشی که من برای رفع این مشکل استفاده می کنم (البته روش رو خودم ابداع کردم) به شرح زیر است :
دلفی در ریسورسهای خودش از یونیکد استفاده نمی کند ، پس با ذخیره متون در آن در هنگام بازخوانی با مشکل مواجه خواهد شد !
شما باید موارد فوق را یا به صورت const و یا با ذخیره در یک ini و روش های دیگر در هنگام بارگذاری برنامه فرا خوانی و تعریف کنید .
کار کمی مشکل به نظر می رسد ولی شدنی است مثلا شما اگر گزینه های یک ComboBox را از طریق کد نویسی تعریف کنید در تمامی نسخه ویندوز هایی که فونتهای فارسی را داشته باشند (98Arb 2000 XP) به یک شکل دیده خواهند شد ، بدون بهم ریختگی.
اگر خواستی روش کار تعریف متون آیتمهای یک فرم را نیز شرح خواهم داد.

یا حق ...

SYNDROME
یک شنبه 13 آبان 1386, 08:59 صبح
اگر خواستی روش کار تعریف متون آیتمهای یک فرم را نیز شرح خواهم داد.

حمید جان گل اگه که بگید ما را شرمنده کرده اید.
موفق باشید

nasr
یک شنبه 13 آبان 1386, 09:03 صبح
روشی که من برای رفع این مشکل استفاده می کنم (البته روش رو خودم ابداع کردم) به شرح زیر است :
دلفی در ریسورسهای خودش از یونیکد استفاده نمی کند ، پس با ذخیره متون در آن در هنگام بازخوانی با مشکل مواجه خواهد شد !
شما باید موارد فوق را یا به صورت const و یا با ذخیره در یک ini و روش های دیگر در هنگام بارگذاری برنامه فرا خوانی و تعریف کنید .
کار کمی مشکل به نظر می رسد ولی شدنی است مثلا شما اگر گزینه های یک ComboBox را از طریق کد نویسی تعریف کنید در تمامی نسخه ویندوز هایی که فونتهای فارسی را داشته باشند (98Arb 2000 XP) به یک شکل دیده خواهند شد ، بدون بهم ریختگی.
اگر خواستی روش کار تعریف متون آیتمهای یک فرم را نیز شرح خواهم داد.

یا حق ...
سلام
ضمن تشکر

اگه لطف کنید واقعا ممنون میشم

Hamid_PaK
یک شنبه 13 آبان 1386, 09:29 صبح
من این روش رو قبلا هم توضیح داده بودم !!!
روش سادست ولی برای تنظیم یک روال بی نقص باید وقت نسبتا زیادی صرف شود.
1. شما ابتدا باید برای شناسایی هر کنترل یا از نام آن و یا از یک شماره که مثلا در tag آن ذخیره شود آنرا از دیگران تمیز دهید.
2. کنترلهای فرم را با استفاده از خصوصیت Components که یک TList است جستجو کرده و اگر نام آن (یا شماره آن) با شماره های تعریف شده شما همخوانی داشت ، متن آن را تعریف خواهید کرد.
3. در هنگام یافتن کنترل باید از یک روش برای تعریف متون خاص آن کنترل استفاده کنید ( ComboBox تنها به یک رشته ندارد ، باید آنها را از هم جدا کنید).

یه مثال ساده برای caption ها (استفاده غیر تجاری آزاد می باشد):


type
TCaptionList = array[0..1] of String;
TCaptionListItems = array of TCaptionList;

const
ctrl_names: array[0..3] of TCaptionList = (
( 'lbl_user', 'نام کاربری :' )
, ( 'lbl_pass', 'کلمه عبور :' )
, ( 'bt_login', 'ورود' )
, ( 'bt_exit', 'خروج' )
);

procedure SetChildCaptions(AComponent: TComponent; cap_list: array of TCaptionList);
var
i,
idx: Integer;

function GetItemIndex( cmpnt_name: String; cap_list: array of TCaptionList ): Integer;
begin
for Result := 0 to Length( cap_list ) -1 do
if CompareStr( LowerCase( cmpnt_name ), LowerCase( cap_list[ Result, 0 ] )) = 0 then Exit;
Result := -1;
end;

begin
//;
if AComponent.ComponentCount > 0 then
with AComponent do begin
for i := 0 to ComponentCount -1 do begin
if Components[ i ].ComponentCount > 0 then
SetChildCaptions( Components[ i ], cap_list );
if Length( Components[ i ].Name ) <= 0 then Continue;
idx := GetItemIndex( Components[ i ].Name, cap_list );
if idx >= 0 then
if Components[ i ].ClassType = TAction then
ShowMessage( Components[ i ].Name ) else
if Components[ i ].ClassType = TLabel then begin
TLabel( Components[ i ] ).Caption := cap_list[ idx, 1 ];
end else begin
SetWindowText( TWinControl( Components[ i ] ).Handle,
pChar( cap_list[ idx, 1 ] ));
end;
end;
end;
end;

procedure Tfrm_login.FormCreate(Sender: TObject);
begin
BiDiMode := bdRightToLeft;
FlipChildren(True); // باعث می شود که دیگر نیازی به راست به چپ چیدن کنترلها نباشد
SetChildCaptions(Self, ctrl_names);
end;

می توانید کد را کامل کنید که تمامی کنترلها را پشتیبانی کند ، حتی یک ComboBox.
همانطور که دیدید این کد را برای نوشتن برنامه های چند زبان (راست به چپ و بالعکس) نیز می توان مورد استفاده قرار داد.

یا حق ...

nasr
یک شنبه 13 آبان 1386, 09:44 صبح
اگه میشه لطف کنید در مورد ComboBox هم یه توضیحی بدید که چطور این کار را بکنیم

ممنون

Hamid_PaK
یک شنبه 13 آبان 1386, 10:05 صبح
ببین ناصر جان نوشتن یک روال برای ComboBox کار ساده ای است ، سعی کنی نوشتی !!!
راهنمایی می کنم ...
می تونی از رشته استفاده کنید و با یک حرف (,) آیتمها رو از یکدیگه جدا کنی :


begin
ComboBox1.Items.Clear;
ComboBox1.Items.CommaText := '"نام کاربر","تریخ تولد"';
end;

حالا از کد بالا برای کلاس کمبوباکس استفاده کنید.

یا حق ...

nasr
یک شنبه 13 آبان 1386, 11:57 صبح
من این قسمت را به این صورت تغییر دادم ولی باز هم آیتمهای ComboBox را اشتباه نشون میده




const
ctrl_names: array[0..3] of TCaptionList = (
( 'ComboBox1', 'محمد ,علی,رضا' )
, ( 'lbl_pass', 'کلمه عبور :' )
, ( 'bt_login', 'ورود' )
, ( 'bt_exit', 'خروج' )
);

..........

if AComponent.ComponentCount > 0 then
with AComponent do begin
for i := 0 to ComponentCount -1 do
begin
if Components[ i ].ComponentCount > 0 then
SetChildCaptions( Components[ i ], cap_list );
if Length( Components[ i ].Name ) <= 0 then Continue;
idx := GetItemIndex( Components[ i ].Name, cap_list );
if idx >= 0 then
if Components[ i ].ClassType = TAction then
ShowMessage( Components[ i ].Name ) else
if Components[ i ].ClassType = TComboBox then begin
TComboBox( Components[ i ] ).Items.CommaText := cap_list[ idx, 1 ];
end else
begin
SetWindowText( TWinControl( Components[ i ] ).Handle,
pChar( cap_list[ idx, 1 ] ));
end;
end;
end;

Hamid_PaK
یک شنبه 13 آبان 1386, 12:38 عصر
این رو امتحان کنید :


const
ctrl_names: array[0..4] of TCaptionList = (
( 'lbl_user', 'نام کاربری :' )
, ( 'lbl_pass', 'کلمه عبور :' )
, ( 'bt_login', 'ورود' )
, ( 'bt_exit', 'خروج' )
, ( 'ComboBox1', '"آیتم 1", "آیتم 2"' )
);
...
...
...
if AComponent.ComponentCount > 0 then
with AComponent do begin
for i := 0 to ComponentCount -1 do
begin
if Components[ i ].ComponentCount > 0 then
SetChildCaptions( Components[ i ], cap_list );
if Length( Components[ i ].Name ) <= 0 then Continue;
idx := GetItemIndex( Components[ i ].Name, cap_list );
if idx >= 0 then begin
if Components[ i ].ClassType = TComboBox then
TComboBox( Components[ i ] ).Items.CommaText := cap_list[ idx, 1 ] else
if Components[ i ].ClassType = TLabel then
TLabel( Components[ i ] ).Caption := cap_list[ idx, 1 ] else
begin
SetWindowText( TWinControl( Components[ i ] ).Handle,
pChar( cap_list[ idx, 1 ] ));
end;
end;
end;
end;

و باید توی تعریف رشته گزینه ها نیز دقت کنید ، مشکل کجاست !؟؟

یا حق ...

nasr
یک شنبه 13 آبان 1386, 12:55 عصر
باز هم آیتمهای ComboBox را اجق وجق می نویسه

این هم کل کد:


type
TCaptionList = array[0..1] of String;
TCaptionListItems = array of TCaptionList;

const
ctrl_names: array[0..4] of TCaptionList = (
( 'lbl_user', 'نام کاربر? :' )
, ( 'lbl_pass', 'کلمه عبور :' )
, ( 'bt_login', 'ورود' )
, ( 'bt_exit', 'خروج' )
, ( 'ComboBox1', '"آیتم شماره 2", "آیتم شماره 1"' )
);

procedure SetChildCaptions(AComponent: TComponent; cap_list: array of TCaptionList);
var
i,
idx: Integer;

function GetItemIndex( cmpnt_name: String; cap_list: array of TCaptionList ): Integer;
begin
for Result := 0 to Length( cap_list ) -1 do
if CompareStr( LowerCase( cmpnt_name ), LowerCase( cap_list[ Result, 0 ] )) = 0 then
Exit;
Result := -1;
end;

begin
//;
if AComponent.ComponentCount > 0 then
with AComponent do begin
for i := 0 to ComponentCount -1 do
begin
if Components[ i ].ComponentCount > 0 then
SetChildCaptions( Components[ i ], cap_list );
if Length( Components[ i ].Name ) <= 0 then Continue;
idx := GetItemIndex( Components[ i ].Name, cap_list );
if idx >= 0 then begin
if Components[ i ].ClassType = TComboBox then
TComboBox( Components[ i ] ).Items.CommaText := cap_list[ idx, 1 ] else
if Components[ i ].ClassType = TLabel then
TLabel( Components[ i ] ).Caption := cap_list[ idx, 1 ] else
begin
SetWindowText( TWinControl( Components[ i ] ).Handle,
pChar( cap_list[ idx, 1 ] ));
end;
end;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
BiDiMode := bdRightToLeft;
FlipChildren(True);
SetChildCaptions(Self, ctrl_names);
end;

Hamid_PaK
یک شنبه 13 آبان 1386, 13:03 عصر
من فکر می کنم مشکل جای دیگه باید باشه !!!
اصلا شما اطمینان دارید که ویندوز شما قادر به نمایش یونیکد در کنترلها می باشد ؟؟؟

nasr
یک شنبه 13 آبان 1386, 13:38 عصر
من فکر می کنم مشکل جای دیگه باید باشه !!!
اصلا شما اطمینان دارید که ویندوز شما قادر به نمایش یونیکد در کنترلها می باشد ؟؟؟

این یکی را چطور باید بفهمم؟؟

اصلا به نظر شما شروع کردن یک پروژه بزرگ دیتابیسی با دلفی و در حالیکه تنظیمات زبان باید روی انگلیسی باشه درسته یا نه؟

Hamid_PaK
یک شنبه 13 آبان 1386, 14:03 عصر
منظورتون از باید انگلیسی باشد یعنی اینکه
1. تنها زبان نصب شده بر روی ویندوز زبان انگلیسی است ؟؟؟
2. آیا برنامه بر روی ویندوز بالاتر از 2000 نصب و بکار گرفته خواهد شد ؟؟؟

اگر ویندوز شما راهی برای نوشتار با زبان فارسی نداشته باشد (یعنی اینکه تنها زبان نصب شده آن انگلیسی است) تنها گزینه استفاده از ساختن روشی برای تبدیل کیبورد انگلیسی به فارسی و استفاده از فونت های استاندارد (ایران سیستم) است که شخصا توسیعه نمی کنم !!!
چرا که ویندوز با نصب زبان فارسی و تنظیم استفاده از یونیکد و فونتهای آن زبان در کنترلها بخش عظیم کار را برای برنامه نویس انجام داده است و کار شما تنها کار با این سیستم است...

یا حق ...

nasr
یک شنبه 13 آبان 1386, 14:20 عصر
نه جناب Hamid_PaK (http://barnamenevis.org/forum/member.php?u=10875) من مشکلی با نصب زبان ندارم و فارسی روی ویندوز نصب هست. و فقط هم این برنامه روی ویندوز xp قراره کار کنه

ما از یک برنامه حسابداری استفاده می کنیم که تنظیمات زبان ویندوز باید انگلیسی باشه(در regional and language option) و در Language for non - unicode programs هم باید انگلیسی باشه

حالا هر برنامه ای که می خوام بنویسم با این مشکل روبرو هستم .
واقعا من دیگه دارم دیوونه میشم از دست این دلفی با این جریان Unicode ساپورت نکردنش

Hamid_PaK
یک شنبه 13 آبان 1386, 14:31 عصر
با این حساب تنها راه استفاده از کامپوننت های یونیکد است (tnt) و این مورد نیز هیچ ربطی به استفاده از روشی که گفتم نیز نداره !!!

امید وارم که دوستان دیگه بتونند مشکل رو حل کنند (هر چند که فکر نکنم راهی باشه).

یا حق ...

nasr
یک شنبه 13 آبان 1386, 14:46 عصر
با این حساب تنها راه استفاده از کامپوننت های یونیکد است (tnt) و این مورد نیز هیچ ربطی به استفاده از روشی که گفتم نیز نداره !!!

امید وارم که دوستان دیگه بتونند مشکل رو حل کنند (هر چند که فکر نکنم راهی باشه).

یا حق ...

با استفاده از tnt ها هم اصلا راه مناسبی نیست
اگه شما یه ComboBox بگذارید و بعد عبارت داخل اون را وارد یک Table کنید عبارت را تبدیل به علامت سوال (?????) میکنه و وارد جدول میکنه.

Hamid_PaK
یک شنبه 13 آبان 1386, 15:21 عصر
این بدلیل این است که شما در هنگام ذخیره داده در جدول آنها را همانطور که یونیکد هستند (WideString یا WideChar) وارد می کنید !!!

یا حق ...

nasr
یک شنبه 13 آبان 1386, 16:03 عصر
این بدلیل این است که شما در هنگام ذخیره داده در جدول آنها را همانطور که یونیکد هستند (WideString یا WideChar) وارد می کنید !!!

یا حق ...
میشه بگید چطور باید این کار را کرد؟
من از این کد استفاده می کنم


Adotable1.edit;
Adotable1.fieldbyname('a1').asstring := tntcombobox1.text;
adotable1.post;

Hamid_PaK
یک شنبه 13 آبان 1386, 17:47 عصر
اینو امتحان کنید :


ADOTable1.FieldByName('a1').AsVariant := TntComboBox1.Text;


یا حق ...

nasr
دوشنبه 14 آبان 1386, 10:06 صبح
سلام
2 تا سوال
یکی اینکه AsVariant چه فرقی با AsString میکنه؟
و بعدی اینکه من یه نرم افزار از شرکت ماکروسافت پیدا کردم
نرم افزار AppLocale Utility واسه مشاهده ی بهتر نرم افزارهای غیر یونیکد ( non-Unicode )

ساخته شده و حجمش هم 1.2 مگابایته

این برنامه خیلی خوبه و تمام کپشن ها را به خوبی و کاملا درست نشون میده فقط مشکلش اینه که متنی که خود کاربر وارد می کنه درست نوشته نمیشه
شما چیزی شبیه به این سراغ دارید؟

ممنون

Mohammad_Mnt
دوشنبه 14 آبان 1386, 12:15 عصر
AsVariant چه فرقی با AsString میکنه؟
اولی یک متغیر ورینت برمی‌گردونه و دومی یک متغیر استرینگ. متغیرهای ورینت می‌تونند تقریباً هر مقداری را داشته باشند:

MyVariant := 5;
MyVariant := 'Hello!';
MyVariant := 'c';

nasr
دوشنبه 14 آبان 1386, 16:49 عصر
اینو امتحان کنید :


ADOTable1.FieldByName('a1').AsVariant := TntComboBox1.Text;
یا حق ...
مشکل وارد کردن اطلاعات با این روش حل شد

ولی حالا برای Locate کردن یک جدول مشکل را چطور حل کنم. چون عبارت داخل TntComboBox را نمیشناسه.


ADOTable1.Locate('a1' , TntComboBox1.Text , []))
و مثلا وقتی مینویسیم


showmessage(tntedit1.text);
علامت سوال میشه
??????

ویا حتی برای Query هم مشکل داره


with ADOQuery1 do
begin
SQL.Clear;
SQL.Add('select * from Alum where a1 = ''' + TntComboBox1.Text + '''');
ExecSQL;
Active := True;
end;

Hamid_PaK
دوشنبه 14 آبان 1386, 18:27 عصر
اینو امتحان کنید :

with ADOQuery1 do begin
Close;
Parameters.ParamByName('text1').Value := TntComboBox1.Text;
SQL.Text := 'select * from Alum where a1 = :text1';
Open;
end;

یا حق ...

nasr
شنبه 19 آبان 1386, 11:43 صبح
اینو امتحان کنید :

with ADOQuery1 do begin
Close;
Parameters.ParamByName('text1').Value := TntComboBox1.Text;
SQL.Text := 'select * from Alum where a1 = :text1';
Open;
end;یا حق ...
سلام
ضمن تشکر فراوان از اینکه مشکلم حل شد فقط یه چیز دیگه مونده
من در برنامه به جای اینکه برای هر نمایش اطلاعاتی نخوام یه TAdoQuery بگذارم روی فرم فقط یه دونه میگذارم و از اون در کل برنامه استفاده می کنم

حالا با اینکار باید برای هر جستجویی یه Query بگذارم که این هم مشکله
آیا میشه به جای استفاده از Parameters کاری کرد که از همون روشی که خودم نوشتم استفاده کنم
ممنون

پرواز
شنبه 19 آبان 1386, 15:38 عصر
سلام
ضمن تشکر فراوان از اینکه مشکلم حل شد فقط یه چیز دیگه مونده
من در برنامه به جای اینکه برای هر نمایش اطلاعاتی نخوام یه TAdoQuery بگذارم روی فرم فقط یه دونه میگذارم و از اون در کل برنامه استفاده می کنم

حالا با اینکار باید برای هر جستجویی یه Query بگذارم که این هم مشکله
آیا میشه به جای استفاده از Parameters کاری کرد که از همون روشی که خودم نوشتم استفاده کنم
ممنون
مگه روشی که دوستمون گفتن چه مشکلی ایجاد میکنه؟
شما پارامتر رو در زمان اجرا میسازید و ازش استفاده می کنید. اگه خواستید از یه جستجو دیگه انجام بدید همون روال قبلتون رو تکرار کنید.

nasr
شنبه 19 آبان 1386, 16:45 عصر
مگه روشی که دوستمون گفتن چه مشکلی ایجاد میکنه؟
شما پارامتر رو در زمان اجرا میسازید و ازش استفاده می کنید. اگه خواستید از یه جستجو دیگه انجام بدید همون روال قبلتون رو تکرار کنید.
ممنون
ببینید من در برنامه ام یه فانکشن نوشته ام به این صورت


function SelectQuery(Query : TADOQuery ; QText : String): String;
begin
Query.SQL.Clear;
Query.SQL.Text := QText;
Query.Active := True;
end;
بعد در کل برنامه اینطوری استفاده می کنم


procedure TForm1.Button3Click(Sender: TObject);
begin
SelectQuery(ADOQuery1,'select * from alum where country = ''' + TntComboBox1.Text + '''');
end;
حالا در این روش باید حتما پارامتر تعریف بشه در غیر اینصورت با tntCombobox مشکل پیدا میشه

ممنون

پرواز
شنبه 19 آبان 1386, 23:21 عصر
اینو یه امتحان بکن شاید جواب داد:
SQL.Add('select * from Alum where a1 = ' + QuotedStr(TntComboBox1.Text));

Hamid_PaK
پنج شنبه 24 آبان 1386, 08:00 صبح
ناصر جان شما بیا و او تابعی که نوشته ای رو توسعه بده و کاری کن که در صورت نیاز از پارامتر نیز پشتیبانی کنه.

یا حق ...