PDA

View Full Version : باز شدن متن توسط برنامه من!!!



1485159
چهارشنبه 30 اردیبهشت 1388, 10:16 صبح
من میخوام متن توسط برنامه من باز بشه و متنش توی یه ادیت ریخته بشه ...
حالا کسی میتونه کمکم کنه!!!
اگه هم راحل برنامه نویسی رو بگید و هم کلید هایی که تو رجیستری نیازه ممنون میشم.....
ممنون.
شاید موضوع تکراری باشه ..

as13851365
چهارشنبه 30 اردیبهشت 1388, 11:13 صبح
منظور شما از متن چی هست ؟

شما می خواهید یک فایل منحصر به فرد را با برنامه خودتان باز کنید ( وقتی که روی یک فایل متنی و یا ... دابل کلیک کردید برنامه شما باز بشه و اون فایل را باز کنه و متن را داخل یک ادیت نشان بده ؟ )

اگه آره فکر کنم در سایت هست اگه پیدا نگردید و یا اگه برداشت من اشتباه بود بگو .

1485159
چهارشنبه 30 اردیبهشت 1388, 11:42 صبح
آره منظورم همینه!!!
جست و جو کردم پیدا نکردم!
اونوقت باید فایل اجرایی رو تویه مسیر مشخص قرار بدیم!؟..
ممنون.

1485159
چهارشنبه 30 اردیبهشت 1388, 16:38 عصر
کسی نیست جواب بده!؟..

Saeed_m_Farid
چهارشنبه 30 اردیبهشت 1388, 19:58 عصر
آره منظورم همینه!!!
جست و جو کردم پیدا نکردم!
اونوقت باید فایل اجرایی رو تویه مسیر مشخص قرار بدیم!؟..
ممنون.


کسی نیست جواب بده!؟..
دوستان حق دارن شك كنن به سوالتون آخه سوالتون يا خيلي مبهمه يا خيلي ساده : اگه منظورتون load يه فايل text تو Memo هست كه كد ساده زير با فرض گذاشتن يه دكمه و يه memo رو فرمت جواب ميده (البته اين OpenDiolog فقط فايلهاي Text و سورس پاسكال رو فيلتر ميكنه اگه نميخواين اين اتفاق بيفته فيلتر رو برداريد) :
procedure TForm1.Button1Click(Sender: TObject);
begin
with TOpenDialog.Create(nil) do try
Filter := 'Text files (*.txt)|*.TXT|Pascal files (*.pas)|*.PAS';
if Execute then begin
Memo1.Lines.LoadFromFile(FileName);
end;
finally
Free;
end;
end;
ولي اگه منظورتون يه چيز ديگه اس واضح تر بگيد تا توضيح داده بشه ...

1485159
چهارشنبه 30 اردیبهشت 1388, 21:23 عصر
ولي اگه منظورتون يه چيز ديگه اس واضح تر بگيد تا توضيح داده بشه ...

مثلا اگه فایل txt رو open with کرد و با برنامه من باز کرد متنش توی یه memo ریخته بشه!!
همین.
ممنون.

1485159
چهارشنبه 30 اردیبهشت 1388, 21:26 عصر
البته اين OpenDiolog فقط فايلهاي Text و سورس پاسكال رو فيلتر ميكنه اگه نميخواين اين اتفاق بيفته فيلتر رو برداريد) :

منظور از فیلتر چیه!؟..

Felony
چهارشنبه 30 اردیبهشت 1388, 21:37 عصر
برای این کار باید فایلتون رو در ریجستری ریجستر کنید و سپس به وسیله ی تابع ParamStr در هنگام اجرای برنامتون آدرس فایلی که به برنامه پاس داده شده رو بخونید و اون رو باز کنید .

1485159
چهارشنبه 30 اردیبهشت 1388, 22:02 عصر
برای این کار باید فایلتون رو در ریجستری ریجستر کنید و سپس به وسیله ی تابع ParamStr در هنگام اجرای برنامتون آدرس فایلی که به برنامه پاس داده شده رو بخونید و اون رو باز کنید .

الو..
صدا نمیاد..
بابا من که گفتم هم رجیستری رو باید چیکار کنم و هم ParamStr چیه!؟..

1485159
چهارشنبه 30 اردیبهشت 1388, 22:23 عصر
در ضمن چطور بفهمم که به برنامه پارامتر ارسال شده یانه!؟..ممنون.

Saeed_m_Farid
چهارشنبه 30 اردیبهشت 1388, 22:26 عصر
مثلا اگه فایل txt رو open with کرد و با برنامه من باز کرد متنش توی یه memo ریخته بشه!!
همین.
ممنون. خوب همون كد پست شماره 4 جواب شماست (فيلتر هم يعني فقط اون نوع فايلها رو باز كنه).


برای این کار باید فایلتون رو در ریجستری ریجستر کنید و سپس به وسیله ی تابع ParamStr در هنگام اجرای برنامتون آدرس فایلی که به برنامه پاس داده شده رو بخونید و اون رو باز کنید .جسارتاً، شما هم كه گير دادين به اين ParamStr، پارامتر ورودي فايل اجرايي چه ربطي به رجيستري داره؟ چرا موضوع رو مي پيچونيد؟ اون يه بحث جدا بود كه تموم شد!

1. براي پاس دادن از خط فرمان يا shortcut به برنامه اجرايي از پارامتر استفاده ميشه، كه ميشه مسير فايل متني رو از اين طريق به برنامه داد و بعد از ParamCount و ParamStr استفاده كرد، يه نمونه كد واسه اينكار رو هم ميتونين تو FormCreate ببينيد (البته يه Memo اولش بذاريد رو فرم) :

procedure TForm1.FormCreate(Sender: TObject);
var
idx: Integer;
sl: TStringList;
begin
try
Memo1.Lines.Clear;
sl := TStringList.Create;
for idx := 1 to ParamCount do begin
if FileExists(ParamStr(idx)) then begin
sl.LoadFromFile(ParamStr(idx));
Memo1.Lines.Add(Format('File[%d] = %s : ', [idx, ParamStr(idx)]));
Memo1.Lines.AddStrings(sl);
end else
Memo1.Lines.Add(Format('File[%d] = %s : not found!', [idx, ParamStr(idx)]));
end;
finally
FreeAndNil(sl);
end;
end;
2. ولي راه ديگه خوندن مسير فايل از رجيستري هست كه در اينصورت هم نيازي به دادن پارامتر به برنامه نيست، برنامه مستقيم ميره از رجيستري ميخونه، كه بحثش يه موضوع ديگه است ...

1485159
چهارشنبه 30 اردیبهشت 1388, 23:38 عصر
if FileExists(ParamStr(idx)) then begin
به نظر من چون قراره آدرس فایل تو سطر 1باشه بهتره به جای idx بنویسم 1نظر شما چیه!؟...


2. ولي راه ديگه خوندن مسير فايل از رجيستري هست كه در اينصورت هم نيازي به دادن پارامتر به برنامه نيست، برنامه مستقيم ميره از رجيستري ميخونه، كه بحثش يه موضوع ديگه است ...
یعنی نباید تورجیستری کاری کرد که وقتی رو فایل متنی دابیل کلیک کرد به برنامهما پارامتر بفرسته!؟..

Felony
پنج شنبه 31 اردیبهشت 1388, 01:01 صبح
در مورد :
پارامتر ورودي فايل اجرايي چه ربطي به رجيستري داره ؟
یه سری به HKEY_CLASSES_ROOT در ریجستری بزنید و با محتویاتش آشنا شید تا بدونید برای اینکه یه فرمت خاصی از فایل ها با برنامه ی مورد نظرمون باز شن و بتونیم براشون آیکن در نظر بگیریم باید در این قسمت ثبت بشن !!!

و در مورد :
جسارتاً، شما هم كه گير دادين به اين ParamStr، چرا موضوع رو مي پيچونيد ؟ اون يه بحث جدا بود كه تموم شد !
:قهقهه:خیلی جالبه ، بحث تموم شده ولی دقیقا جوابی که من به پست دادم رو به عنوان پاسخ به کاربر ارائه میدید !

1485159
پنج شنبه 31 اردیبهشت 1388, 08:52 صبح
یکی جواب پست 13 رو بده...

Felony
پنج شنبه 31 اردیبهشت 1388, 10:16 صبح
به نظر من چون قراره آدرس فایل تو سطر 1باشه بهتره به جای idx بنویسم 1نظر شما چیه!؟

بله درسته .

یعنی نباید تورجیستری کاری کرد که وقتی رو فایل متنی دابیل کلیک کرد به برنامهما پارامتر بفرسته!؟..
چرا ، اگر این کار رو نکنید به طور خودکار فایلهاتون با برنامتون باز نمیشن و باید یک بار OpenWith بکنیشون .

تا اونجا که یادمه باید تو HKEY_CLASSES_ROOT یه کلید به نام فرمت فایلت میساختی مثلا : xxx. بعدش داخل این کلید یه کلید با نام Shell و داخل اون یه کلید با نام Open و داخلش اون یه کلید با نام command و در اون یه string با محتوای آدرس برنامت ، تا با کلیک روی فایلها مورد نظر ادرس به عنوان پارامتر به برنامه فرستاده شه .

Saeed_m_Farid
پنج شنبه 31 اردیبهشت 1388, 10:16 صبح
به نظر من چون قراره آدرس فایل تو سطر 1باشه بهتره به جای idx بنویسم 1نظر شما چیه!؟...این واسه حالتی هست که بخواین محتویات چند فایل رو تو Memo موردنظر نمایش بدین، اگه قراره فقط واسه یه فایل کار کنه، شما درست می گین.

یعنی نباید تورجیستری کاری کرد که وقتی رو فایل متنی دابیل کلیک کرد به برنامهما پارامتر بفرسته!؟.. این صحبت شما جدیده و تو سوال اولتون نبود! توضیحش رو پایین آوردم ...

یه سری به HKEY_CLASSES_ROOT در ریجستری بزنید و با محتویاتش آشنا شید تا بدونید برای اینکه یه فرمت خاصی از فایل ها با برنامه ی مورد نظرمون باز شن و بتونیم براشون آیکن در نظر بگیریم باید در این قسمت ثبت بشن !!!
چشم حتماً سر میزنم. اون موردی که شما می فرمایید بعداً مطرح شد (که با دابل کلیک، فایلهای txt. با برنامه ایشون باز بشه)؛ با اجازه شما SilverSoft، من جواب دوستمون رو بدم: برای اینکار (باز شدن فایلهای txt با برنامه شما) مقدار Default رو در HKEY_CLASSES_ROOT واسه کلید txt. معادل مسیر برنامه خودتون قرار بدید.

:قهقهه:خیلی جالبه ، بحث تموم شده ولی دقیقا جوابی که من به پست دادم رو به عنوان پاسخ به کاربر ارائه میدید ! شاید من منظور شما رو درست متوجه نشدم، و توضیح اضافه دادم، عذر میخوام.

1485159
پنج شنبه 31 اردیبهشت 1388, 13:21 عصر
من کاری رو که گفتین کردم و جواب داد!!!
ولی برنامه ای که من میسازم کارش اینه که یه پسوند جدید میسازه...
حالا من چطور برا اون پسوند مشخص که سیستم هم نمیشناسه این کارو بکنم!؟..

در ضمن مثلا برنامه من توسط یه فایل باز شده(تا حالا مشکلی نیست)بعد یه فایل دیگه رو باز میکنه من چطور میتونم کاری کنم که اون فایل دوم تو همون برنامه باز شه و دیگه برانامه 2 بار اجرا نشه!؟..(مثل مدیاپلیر ها)(نمیدونم که منظورم رو متوجه شدید یا نه!؟..
برا آیکون چیمار کنم!؟..
ممنون.
ممنون.

Felony
پنج شنبه 31 اردیبهشت 1388, 13:44 عصر
من کاری رو که گفتین کردم و جواب داد!!!
ولی برنامه ای که من میسازم کارش اینه که یه پسوند جدید میسازه...
حالا من چطور برا اون پسوند مشخص که سیستم هم نمیشناسه این کارو بکنم!؟..

در ضمن مثلا برنامه من توسط یه فایل باز شده(تا حالا مشکلی نیست)بعد یه فایل دیگه رو باز میکنه من چطور میتونم کاری کنم که اون فایل دوم تو همون برنامه باز شه و دیگه برانامه 2 بار اجرا نشه!؟..(مثل مدیاپلیر ها)(نمیدونم که منظورم رو متوجه شدید یا نه!؟..
برا آیکون چیمار کنم!؟..
ممنون.
ممنون.
تو پست قبلیم که براتون توضیح دادم برای یه فرمت جدید چی کار کنید .
برای آیکن هم در همون کلید فرمت فایلتون در کنار کلید shell یه کلید با نام DefaultIcon بسازید و در اون یه string با محتوای آدرس فایل آیکن یا فایل اجرایی که میخواهید آیکن اون نمایش داده شه رو وارد کنید .


Saeed_m_Farid
شاید من منظور شما رو درست متوجه نشدم، و توضیح اضافه دادم، عذر میخوام.
:چشمک:من هم از شما معذرت میخوام ، کمی تند رفتار کردم .

hojjatcroos
پنج شنبه 31 اردیبهشت 1388, 13:46 عصر
می تونید از یک MDI Application استفاده کنید یا از اون الگو بگیرید

1485159
پنج شنبه 31 اردیبهشت 1388, 14:02 عصر
برای آیکن هم در همون کلید فرمت فایلتون در کنار کلید shell یه کلید با نام DefaultIcon بسازید و در اون یه string با محتوای آدرس فایل آیکن یا فایل اجرایی که میخواهید آیکن اون نمایش داده شه رو وارد کنید .


ممنون.

می تونید از یک MDI Application استفاده کنید یا از اون الگو بگیرید

الو ...
صدا نمیاد ...

الو..
صدا قط و وصل میشه!!!!
....

Felony
پنج شنبه 31 اردیبهشت 1388, 14:57 عصر
می تونید از یک MDI Application استفاده کنید یا از اون الگو بگیرید
منطورشون برنامه هایی مثل word هست که با باز کردن یه فایل جدید فایل قبلی مثل NotePad بسته نمیشه و تو یه فرم فرزند جدید نمایش داده میشه .

Saeed_m_Farid
پنج شنبه 31 اردیبهشت 1388, 15:16 عصر
در ضمن مثلا برنامه من توسط یه فایل باز شده(تا حالا مشکلی نیست)بعد یه فایل دیگه رو باز میکنه من چطور میتونم کاری کنم که اون فایل دوم تو همون برنامه باز شه و دیگه برانامه 2 بار اجرا نشه!؟..(مثل مدیاپلیر ها)(نمیدونم که منظورم رو متوجه شدید یا نه!؟..موضوع زیاد ساده ای نیست که بشه تو یه پست توضیح داد، جناب کشاورز یه راهنمایی (http://barnamenevis.org/forum/showpost.php?p=722226&postcount=8) در این مورد کردن، درمورد IPC یا Inter-process Communication بگردین، برای شروع هم میتونین دوتا روش واسه اینکار امتحان کنید :


اولی با ارسال پیام بین پروسسها، به این صورت که برنامه سرورتون (همونی که با دابل کلیک باز شده) باید یه listener واسه پیغامهای دریافتی داشته باشه، یعنی یه ویندوز پروسیجر تو برنامه تون داشته باشین که به پیامهای دریافتی عکس العمل نشون بده؛ و از طرف دیگه قابلیت هندل فایلهای مختلف تولید شده با پسوند خودتون رو داشته باشه، یعنی مثلا بازاء هر پیامی - SendMessage رسیده به برنامه شما - بتونه یه تب جدید واسه اون فایل باز کنه و یه Memo رو با محتویات اون فایل مقداردهی کنه و ... (یه مثال ساده از IPC رو میتونید اینجا (http://www.delphi-central.com/ipc_sendmessage.aspx)ببینید)
روش دیگه استفاده از پایپ هست، که نمیدونم آشنایی دارید یا نه؛ میتونید یه سرور Pipe واسه اینکار ایجاد کنید و منتظر رسیدن بافر از سمت یه کلاینت باشید که به سمت سرور شما پست میشه. بعد عملیات موردنظرتون رو، روی این بافر انجام بدین.

اگه علاقه داشتین و حوصله تون سر نرفت، ادامه بدیم ...

1485159
پنج شنبه 31 اردیبهشت 1388, 15:42 عصر
ممنون
فقط اگه به من بگید که چطور با برنامه ام به برنامه دیگه ای مثلا پیامی بفرستیم با متن:ali
و با اونیکی چطور بفهمیم که بیامی به برنامه ما فرستاده شده یا نه!؟..
ممنون.

1485159
پنج شنبه 31 اردیبهشت 1388, 16:59 عصر
کسی نیست جواب بده!؟..

1485159
پنج شنبه 31 اردیبهشت 1388, 23:55 عصر
بابا جان من جواب بدین!!
دلفی رو یدادی نداره که هنگام در یافت پارامتر به ما خبر بد]!؟..

hojjatcroos
جمعه 01 خرداد 1388, 13:21 عصر
با رویداد omessage جزء Tappilication می تونید این کار رو انجام بدهید

Saeed_m_Farid
جمعه 01 خرداد 1388, 13:46 عصر
ممنون
فقط اگه به من بگید که چطور با برنامه ام به برنامه دیگه ای مثلا پیامی بفرستیم با متن:ali
و با اونیکی چطور بفهمیم که بیامی به برنامه ما فرستاده شده یا نه!؟..
ممنون.


کسی نیست جواب بده!؟..


بابا جان من جواب بدین!!
دلفی رو یدادی نداره که هنگام در یافت پارامتر به ما خبر بد]!؟..

اولا همیشه همینطوری نیست که شما یه پست بدی، بچه ها 2 دقیقه بعد باید جوابتو بدن! یکمی زحمت بکش جستجو کن ببین جاهای دیگه چی گفتن، تو خود سایت در این مورد (که بنده دو تا سرنخ بهتون دادم تو پست قبلی ام) نکات متنوعی مطح شده که شما نگشتین؛ اگه هم فکر میکنی مطلبی نیست! یه مقدار صبر باید بکنی، و پست اضافی ندی، سنگک پزی نیست!

ثانیا : تا اونجاییکه من میدونم همچین رویدادی تو دلفی نداریم، برای اینکار چون با این پستها میشه فهمید که آدم صبوری نیستین، من راه اول رو واستون باز میکنم (راه دوم پیچیده تر هست و با روحیه شما جور در نمیاد)

شما برای اینکار باید از روالهای ارسال پیام خود ویندوز استفاده کنید؛ توضیحات مفصلی در مورد این مباحث وجود داره که میتونید از MSDN و تاپیکهای مختلف یاست درمورد اونا کسب اطلاع کنید، بنده با فرض اطلاع شما از نحوه عملکرد پیامهای ویندوز، راه حل رو ارائه میدم :


قبل همه شما باید یه ثابتی برای ارتباط بین برنامه ها داشته باشید که با شماره پیامهای ویندوز قاطی نشه :
const
WMU_OUT_MESSAGE = WM_USER + 1;

عمل بعدی ایجاد همون رویدادی هست که شما می خواستید، یعنی جایی که به این درخواست رسیدگی بشه، برای اینکار شما باید یه windows procedure بنویسین، تا اگه پیغام رسیده، همونی بود که شما میخواستین، بهش رسیدگی بشه و درغیر اینصورت روال ویندوزی در مورد اون پیگیری بشه، با حدس من در مورد کارکرد برنامه شما، مثلا یه همچین procedure ای میشه :

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)

// in TForm1 public section
procedure MyWndProc(var wndMsg: TMessage); override;

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)

procedure TForm1.MyWndProc(var wndMsg: TMessage);
var
p: PChar;
begin
try
case wndMsg.Msg of

WMU_OUT_MESSAGE:begin
p := PChar(wndMsg.WParam);
if p <> nil then begin
Memo1.Lines.Add(p);
FreeMem(p);
end;
end;

else inherited;
end;
except on exp:Exception do
Memo1.Lines.Add('Exception on MyWndProc['+IntToStr(wndMsg.Msg)+']: '+exp.Message);
end;
end;

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)
ضمنا با این روال، شما یکی از پارامترهایی که میتونستین استفاده کنید یعنی LParam رو فعلا استفاده نکردید، به این ترتیب بعدا در صورت گسترش برنامه میتونین از اون هم برای کارهای دیگه (مثلا نحوه نمایش متن موردنظر) استفاده کنید و ...
قسمت آخر فرستادن پیام از یه برنامه دیگه به این برنامه است؛ برای اینکار همونطوریکه در بند قبل دیدین، باید آدرس رشته موردنظر رو به برنامه سرور بدین؛ برای اینکار من از رشته مورد نظر یه instance تو RAM درست میکنم و اون آدرس رو به روال هندل پیام که تو بند قبل نوشتیم میدم :

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)

procedure SendMyMessage(wHnd: THandle; mess: string);
var
function strdup(s: string): PChar;
begin
Result := AllocMem(Length(s) + 1);
StrPCopy(Result, s);
end;
begin
// wHnd is your server handle
PostMessage(wHnd, TH_EVENT_OUT_MESSAGE, WPARAM(strdup(mess)), 0);
end;

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)

البته باید توجه کنید که برای استفاده از این تابع باید هندل سرور رو داشته باشید، که روش اینکار درصورت جستجو همه جا هست، برای نمونه هم تو سایت Torry (http://www.swissdelphicenter.ch/torry/showcode.php?id=2112) میتونید یه نمونه اش رو پیدا کنید، ولی با فرض اینکه شما یه instance از سرورتون دارین میتونید از یکی از توابع زیر برای اینکار استفاده کنید (توجه کنید که تابع اول برای موقعی هست که سرور تو یه ماشین دیگه اس ...) :

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)

function GetPid(sService: String; sMachine: String = '') : Cardinal;
var
schm,
schs: SC_Handle;
SC_STATUS_TYPE: Cardinal;
lpBuffer: _SERVICE_STATUS_PROCESS;
cbBufSize: DWORD;
pcbBytesNeeded: LPDWORD;
begin
//open the service manager (defined in WinSvc)
schm := OpenSCManager(PChar(sMachine), nil, SC_MANAGER_CONNECT);
//set the status type to SC_STATUS_PROCESS_INFO
//this is currently the only value supported
SC_STATUS_TYPE := $00000000;
//set the buffer size to the size of the record
cbBufSize := sizeof(_SERVICE_STATUS_PROCESS);
if (schm>0) then
begin
//grab the service handle
schs := OpenService(schm, PChar(sService), SERVICE_QUERY_STATUS);
if (schs>0) then
begin
//call the function
QueryServiceStatusEx(
schs,
SC_STATUS_TYPE,
lpBuffer,
cbBufSize,
pcbBytesNeeded);
CloseServiceHandle(schs);
end;
CloseServiceHandle(schm);
end;
Result := lpBuffer.dwProcessId;
end;

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)

function GetProcessID(ProcessName:string):Integer;
var
Handle:tHandle;
Process:tProcessEntry32;
GotProcess:Boolean;
begin
Handle:=CreateToolHelp32SnapShot(TH32CS_SNAPALL,0) ;
Process.dwSize:=SizeOf(Process);
GotProcess := Process32First(Handle,Process);
{$B-}
if GotProcess and (Process.szExeFile<>ProcessName) then
repeat
GotProcess := Process32Next(Handle,Process);
until (not GotProcess) or (Process.szExeFile=ProcessName);
{$B+}
if GotProcess then Result := Process.th32ProcessID
else Result := 0;
CloseHandle(Handle);
end;

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)


در نهایت شما فقط لازمه که مثلا
SendMyMessage(GetProcessID('MyServer'), 'ali'); رو فراخوانی کنید.

پ.ن. : باید بدونین که این همه اون چیزی نیست که لازمه واسه اینکار بدونین، میشه از روشهای دیگه ای مثل socket یا pipe و ... هم استفاده کرد که با پورت خاصی اطلاعات بین پروسسهای شما رد و بدل میشه و هرکدوم مزایای خودشون رو دارن (این به نظر من ساده ترین راه بود) ...

1485159
جمعه 01 خرداد 1388, 15:14 عصر
من که والا مخم پوکید و هیچی نفهمیدم!!!!!!
خوب حالا یکم برم رو این روشی که گفتین تفکر کنم!!!!
میگم مگه نمیشه به جای این کارا آدرس فایل رو تو رجیستری بریزه و برنامه دوم اونو از رجیستری بخونه!؟..

Saeed_m_Farid
جمعه 01 خرداد 1388, 15:44 عصر
من که والا مخم پوکید و هیچی نفهمیدم!!!!!!
خوب حالا یکم برم رو این روشی که گفتین تفکر کنم!!!!
میگم مگه نمیشه به جای این کارا آدرس فایل رو تو رجیستری بریزه و برنامه دوم اونو از رجیستری بخونه!؟..
خوب شما از کجا میفهمید که آدرس نوشته شده تو رجیستری تغییر کرده؟ در اینصورت مثلا باید برنامتون یه تایمر داشته باشه که هی رجیستری رو بخونه و اگه عوض شده بود اونو لود کنه و ...

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

Saeed_m_Farid
جمعه 01 خرداد 1388, 19:17 عصر
خوب حالا یکم برم رو این روشی که گفتین تفکر کنم!!!!اگه احساس می کنید که به اندازه کافی تفکر کردین، یه مژده بهتون میدم : لازم نیست سمت کلاینت رو شما بنویسین! چون کلاینت شما خود ویندوز هست. پس کار شما خیلی راحت میشه چون نه لازمه که سرور (برنامه خودتون) رو پیدا کنید و نه ایجاد instance از پیغامتون ...
مراحل رو ایندفعه میتونید اینجوری طی کنید :


دو تا فرم باید درست کنید :FormStyle اولی رو از نوع fsMDIForm بذارین، که فرم دربرگیرنده فایلهای لود شده شماست، و دومی رو از نوع fsMDIChild که بازاء هر دابل کلیک یه دونه ازش درست میشه (حداقل یه Memo واسه نمایش محتویات فایل، رو فرم دوم بندازید) ، فرم دوم رو باید فقط هنگام دابل کلیک Create کنید پس از لیست AutoCreate باید در بیاریدش.
تنها کدی که تو فرم fsMDIChild قراره بنویسید : Action := caFree هست که وقتی فرم رو می بندید، بسته بشه و نره پایین.
باید یه کدی بنویسید که با هر بار دابل کلیک، نسخه جدیدی از برنامتون باز نشه؛ برای اینکار، باید بتونید برنامه اول که اجرا شده رو پیدا کنید، برای اینکار یه میوتکس (Mutex) از Application خودتون ایجاد میکنید، که دفعه بعد که دیدین این میوتکس وجود داره فقط پارامترهای رسیده به نسخه جدید رو پاس بدین به قبلیه (برای اینکار ویندوز خودش یه نوع پیغام داره بنام WM_COPYDATA که اطلاعات رو بین پروسسها از این طریق میشه انتقال داد) و نسخه جدید رو Terminate کنید، یعنی اینطوری :
program MDI_Editor_Test;

uses
Forms,
Windows,
messages,
SysUtils,
Main_u in 'Main_u.pas' {frmMain},
Child_u in 'Child_u.pas' {frmChild};

var
Mutex,
wndHnd : THandle;

{$R *.res}
var
cds: TCopyDataStruct;
pzData : PChar;
s: string;
begin
Mutex := CreateMutex(nil, True, 'MDIEditorTest');
if (Mutex <> 0) and (GetLastError = 0) then begin
Application.Initialize;
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
if Mutex <> 0 then
CloseHandle(Mutex);
end else begin
s := ParamStr(1);
with cds do begin
dwData := 1;
cbData := Length(s)+1;
pzData := AllocMem(Length(s)+1);
StrPCopy(pzData, s);
lpData := pzData;
end;
wndHnd := FindWindow('TfrmMain', 'MDI Editor Container');
SendMessage(wndHnd,
WM_COPYDATA,
WPARAM(Application.Handle),
LPARAM(@cds));
Application.Terminate;
end;
end.

مرحله بعد، همون روال پردازش پیام رسیده است، که بافر رسیده (یعنی همونی که دفعات دوم به بعد به عنوان پارامتر به برنامتون رسیده) رو پردازش کنه؛ همونطوریکه تو بند قبل گفتم، همون نوع پیغام رو باید پردازش کنید :
procedure TfrmMain.wndproc(var hMsg: TMessage);
var
pzData: PCopyDataStruct;
p: PChar;
begin
case hMsg.Msg of
WM_COPYDATA: begin
pzData := PCopyDataStruct(hMsg.LParam);
if(pzData^.cbData > 0)then
with TfrmChild.Create(Application) do begin
Caption := PChar(pzData.lpData);
memEditor.Lines.LoadFromFile(PChar(pzData.lpData)) ;
end;
end;
else inherited;
end;
end;

مرحله بعد، اولین مرحله بود که یادم رفت بگم! ما باید واسه اولین دفعه که دابل کلیک شده هم یه کاری بکنیم، مثلا تو FormShow باید ببینیم اگه پارامتر رسیده بود، لودش کنیم :


procedure TfrmMain.wndproc(var hMsg: TMessage);
var
pzData: PCopyDataStruct;
p: PChar;
begin
case hMsg.Msg of
WM_COPYDATA: begin
pzData := PCopyDataStruct(hMsg.LParam);
if(pzData^.cbData > 0)then
with TfrmChild.Create(Application) do begin
Caption := PChar(pzData.lpData);
memEditor.Lines.LoadFromFile(PChar(pzData.lpData)) ;
end;
end;
else inherited;
end;
end;
امیدوارم که ایندفعه زیاد مساله رو نپیچونده باشم، و بدرد شما و سایر دوستان بخوره؛ واسه راحتی بیشتر یه پروژه ساده نوشتم و امیدوارم بتونین ازش ایده بگیرید، از اساتید محترم، هم اگه کد من مشکل داشت خیلی لطف میکنن، اگه راهنمایی بفرمایند ...
موفق باشید.

1485159
جمعه 01 خرداد 1388, 19:38 عصر
من گیچ شدم !!!یدفه از محیط مبتدی اومدم به میحط پیشرفته!!!!(از هیچی سر در نیاوردم!!!
اما نا امید نمیشم!!!
خوب برا این که خوب درک کنم سعی میکنم سطر به سطر به خودم تفهیم کنم!
سوال:
Mutex := CreateMutex(nil, True, 'MDIEditorTest');
این سطر اصلا چیکار میکنه!؟..
پارامتر هاش چیه!؟..

Saeed_m_Farid
جمعه 01 خرداد 1388, 19:44 عصر
من گیچ شدم !!!یدفه از محیط مبتدی اومدم به میحط پیشرفته!!!!(از هیچی سر در نیاوردم!!!
اما نا امید نمیشم!!!
خوب برا این که خوب درک کنم سعی میکنم سطر به سطر به خودم تفهیم کنم!
سوال:
Mutex := CreateMutex(nil, True, 'MDIEditorTest');
این سطر اصلا چیکار میکنه!؟..
پارامتر هاش چیه!؟..
این کار رو میکنه :

باید یه کدی بنویسید که با هر بار دابل کلیک، نسخه جدیدی از برنامتون باز نشه؛ برای اینکار، باید بتونید برنامه اول که اجرا شده رو پیدا کنید، برای اینکار یه میوتکس (Mutex) از Application خودتون ایجاد میکنید، که دفعه بعد که دیدین این میوتکس وجود داره فقط پارامترهای رسیده به نسخه جدید رو پاس بدین به قبلیه

1485159
جمعه 01 خرداد 1388, 19:50 عصر
(Mutex) از Application
حالا خود این چیه!؟..

Saeed_m_Farid
جمعه 01 خرداد 1388, 20:19 عصر
(Mutex) از Application حالا خود این چیه!؟..
درباره Mutex , اگه ممکنه یه نمونه کد. (http://barnamenevis.org/forum/showthread.php?t=145856&highlight=Mutex)

Saeed_m_Farid
جمعه 01 خرداد 1388, 20:29 عصر
اگه اینطوری ادامه بدین، مطمئن باشین مدیرای سایت بهتون اخطار میدن یا تاپیک رو قفل میکنن؛ نمیشه که شما سطر به سطر بپرسین و یه جستحوی ساده نکنید؛ یه یادگاری از امضاء یکی از دوستان :
انسانها سه دسته اند : آنهایی که باینری میفهمند، آنهایی که نمی فهمند و آنهاییکه جستحو کردن نمی دانند!
ولی مطمئن باشید امروز من بیکارم، تا خود صبح هم بپرسید حوابتون رو میدم :چشمک:

1485159
جمعه 01 خرداد 1388, 21:04 عصر
انگار الان نمیتون که یاد بگیرم!!!!
آخه خیلی مبتدی هستم!!!!!
بهتره یه مدت اطلاعاتم رو بالا ببرم بعد بیام....
ممنون.

Saeed_m_Farid
جمعه 01 خرداد 1388, 21:36 عصر
انگار الان نمیتون که یاد بگیرم!!!!
آخه خیلی مبتدی هستم!!!!!
بهتره یه مدت اطلاعاتم رو بالا ببرم بعد بیام....
ممنون.
قرار بود نا امید نشین، اونطوریکه شما گفتین مطمئن شدم به این زودیا از کوره در نمیرید؛ ببینین اطلاعات زیر کمکتون میکنه ؟


(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)

//رو انتخاب کنید MDI_Editor_Test فایل پروژه نمونه شما - اگه برنامه رو دانلود کردین کنترل اف12 بزنید و
program MDI_Editor_Test; // نام پروژه که شما ذخیره کرده اید

uses
Forms,
Windows, // برای ثابتها و توابع ویندوز باید اضافه شود
messages, // برای ثابتها و توابع مربوط به پیامها باید اضافه شود
SysUtils, // این یونیت شامل برخی از اساسی ترین ابزارهای سیستمی است
Main_u in 'Main_u.pas' {frmMain}, // نام فرم اصلی برنامه که دربرگیرنده فرمهای فرزند می باشد
Child_u in 'Child_u.pas' {frmChild}; // نمونه فرم فرزند که با هر بار دابل کلیک ایجاد می شود

var
Mutex, // متغیری برای نگهداری هندل میوتکس برنامه مورد نظر ما که فقط یکبار اجرا میشود
wndHnd : THandle; // Main_u.pas برای بدست آوردن فرم نگهدارنده یعنی

{$R *.res}
var
{
متغیری که در صورت فراخوانی مجدد برنامه باید پارامترهای دریافتی
به نسخه اولیه اجرا شده، از طریق آن تحویل شده و نسخه جدید اجرا نشود
}
cds: TCopyDataStruct;
pzData : PChar; // برای نگهداری آدرس پارامتر ارسالی از طریق دابل کلیک
s: string; // قرار است بعداً مسیر فایل دابل کلیک شده در این متغیر ریخته شود
begin
{
ایجاد یک میوتکس از برنامه ما- میوتکس بطور خلاصه مانند یک متغیر سراسری
در ویندوز عمل مینماید که در نواحی بحرانی به پروسس مورد نظر ما
قابلیت دستیابی به منابع سیستم را میدهد و اکثرا برای یکتایی اجرای پروسس کاربرد دارد
}
Mutex := CreateMutex(nil, True, 'MDIEditorTest'); // Mutual exclusion
if (Mutex <> 0) and (GetLastError = 0) then begin // اگر نسخه ای از برنامه قبلا موجود نبود
Application.Initialize;
Application.CreateForm(TfrmMain, frmMain); // تنها فرمی که بصورت خودکار تولید می شود
Application.Run;
if Mutex <> 0 then
CloseHandle(Mutex); // برای اطمینان از عدم اجرای مجدد برنامه بصورت بازگشتی
end else begin // اگر نسخه ای از برنامه قبلا اجرا شده باشد
s := ParamStr(1); // اولین پارامتر ورودی
with cds do begin // این دستور باعث می شود که یک شناسه متعددا ! نوشته نشود
dwData := 1; // کاربرد ندارد و باید مقدار 1 داده بشود
cbData := Length(s)+1; // طول بافری که قرار است به نسخه اجرا شده فرستاده شود
pzData := AllocMem(Length(s)+1); // تخصیص حافظه به بافر برای ارسال به نسخه اجرا شده برنامه
StrPCopy(pzData, s); // آدرس مسیر فایل دابل کلیک شده در متغیر درنظر گرفته شده ریخته می شود
lpData := pzData; // آدرس درون بافری که قرار است فرستاده شود انتساب می یابد
end;
wndHnd := FindWindow('TfrmMain', 'MDI Editor Container'); // برای پیدا کردن پنجره برنامه اجرا شده ما
SendMessage(wndHnd,
WM_COPYDATA,
WPARAM(Application.Handle),
LPARAM(@cds)); // فرستادن ساختار تکمیل شده بافر موردنظر ما به نسخه اجرا شده برنامه مان
Application.Terminate; // بستن نسخه بعدی برای عدم اجرای مجدد - الیته ما جلوی اجرای آنرا گرفته بودیم ولی این خط هم لازم است
end;
end.

(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)

1485159
جمعه 01 خرداد 1388, 22:22 عصر
Mutex := CreateMutex(nil, True, 'MDIEditorTest');

فعلا تو بقیه قسمات مشکل ندارم فقط نمیتونم کد بالا رو درک کنم!؟..
پارامتر های CreateMutex چیه!؟.
(GetLastError = 0) then begin این هم چیه!؟..
ممنون. و قدردانی از توضیحات کاملتون

Saeed_m_Farid
شنبه 02 خرداد 1388, 09:55 صبح
فعلا تو بقیه قسمات مشکل ندارم فقط نمیتونم کد بالا رو درک کنم!؟..
پارامتر های CreateMutex چیه!؟.
(GetLastError = 0) then begin این هم چیه!؟..
دوست عزیز، این سوالات دیگه به سوال اصلی شما مربوط نمیشه، هرکدوم رو سر جاش بپرسید تا هم سایر دوستان کمک کنن و هم مسیر تاپیک عوض نشه؛ این سوال رو تو همون لینکی که تو پست 35 گذاشتم بپرسید تا بدرد دوستان دیگه هم بخوره ...

1485159
شنبه 02 خرداد 1388, 15:52 عصر
تا اونجایی که من میدونم Application.Run;
برا باز شدن برنامه هست!!!
پس چرا تو وسط برنامه استفاده کردین!؟..

Saeed_m_Farid
شنبه 02 خرداد 1388, 16:08 عصر
تا اونجایی که من میدونم Application.Run;
برا باز شدن برنامه هست!!!
پس چرا تو وسط برنامه استفاده کردین!؟..
اونجا وسط برنامه نیست! یه پروژه جدید باز کنید، فایل پروژه رو نگاه کنید (Project1 <- Ctrl+F12)، مطمئنا متوجه میشید.

1485159
شنبه 02 خرداد 1388, 16:23 عصر
اونجا وسط برنامه نیست! یه پروژه جدید باز کنید، فایل پروژه رو نگاه کنید (Project1 <- Ctrl+F12)، مطمئنا متوجه میشید.
ایول بابا کم کم ناامید میشدم ولی بازم امید گرفتم....
ممنون.
بازم ممنون.
..
......
..

..

1485159
یک شنبه 03 خرداد 1388, 10:08 صبح
من یه چیز دیگه هم پیدا کردم که برام مبهمه!!!!
آخه ما میگیم که اگه هندل پیدا نشد ببندش!!!!
آخه چرا!؟..

if Mutex <> 0 then
CloseHandle(Mutex);
در کل من نفهمیدم !! مگه ما نمیخوایم که هندل وجود داشته باشه و دفعه بعد دیگه برنامه باز نشه!؟..
پس چرا میبندیمش!؟..

1485159
یک شنبه 03 خرداد 1388, 11:04 صبح
من یه چیز رو نمیتونم بفهمم هرچ ه قدر هم تفکر کردم و امتحان کردم دیدم که در هر دو حالت جواب نکیگیرم...
فرض کنیم که xیه هندل است..
حال x<>0 یعنی وجود داره یا وجود نداره..

Felony
یک شنبه 03 خرداد 1388, 13:30 عصر
فرض کنیم که xیه هندل است..
حال x<>0 یعنی وجود داره یا وجود نداره..
وقتی x از نوع هندل هست اگر پنجره یا ... اختصاص داده شده بهش وجود نداشته باشه x=0 میشه و در غیر این صورت ( در صورت وجود پنحره یا ... ) x برابر با شماره ی هندل اون پنجره میشه .

پس
if Mutex <> 0 then
CloseHandle(Mutex);
یعنی : اگر پنجره یا ... وجود داشت ببندش .

1485159
یک شنبه 03 خرداد 1388, 13:36 عصر
وقتی x از نوع هندل هست اگر پنجره یا ... اختصاص داده شده بهش وجود نداشته باشه x=0 میشه و در غیر این صورت ( در صورت وجود پنحره یا ... ) x برابر با شماره ی هندل اون پنجره میشه .


منظور کدوم پنجره هست!؟..

Felony
یک شنبه 03 خرداد 1388, 16:08 عصر
منظور کدوم پنجره هست!؟..
منظور فقط پنجره نیست ، پست من رو کامل و با دقت بخونید :

پنجره یا ...

در اینجا منظور هندل Mutex ساخته شده هست .

1485159
یک شنبه 03 خرداد 1388, 16:51 عصر
کلا ما میوتکس رو بزاریم کنار اونوقت چی!؟..

Felony
یک شنبه 03 خرداد 1388, 17:14 عصر
:گریه::گریه::گریه:لطفا شما تا زیاد شدن اطلاعاتتون ، کلا این نوع سوالات و مباحث رو بزارید کنار ...

sib52co
شنبه 10 مرداد 1388, 19:11 عصر
براي درك مفهوم mutex به كتابهاي سيستمهاي عامل (مثل تاننبام ) مراجه نمائيد. :متفکر: