من میخوام متن توسط برنامه من باز بشه و متنش توی یه ادیت ریخته بشه ...
حالا کسی میتونه کمکم کنه!!!
اگه هم راحل برنامه نویسی رو بگید و هم کلید هایی که تو رجیستری نیازه ممنون میشم.....
ممنون.
شاید موضوع تکراری باشه ..
Printable View
من میخوام متن توسط برنامه من باز بشه و متنش توی یه ادیت ریخته بشه ...
حالا کسی میتونه کمکم کنه!!!
اگه هم راحل برنامه نویسی رو بگید و هم کلید هایی که تو رجیستری نیازه ممنون میشم.....
ممنون.
شاید موضوع تکراری باشه ..
منظور شما از متن چی هست ؟
شما می خواهید یک فایل منحصر به فرد را با برنامه خودتان باز کنید ( وقتی که روی یک فایل متنی و یا ... دابل کلیک کردید برنامه شما باز بشه و اون فایل را باز کنه و متن را داخل یک ادیت نشان بده ؟ )
اگه آره فکر کنم در سایت هست اگه پیدا نگردید و یا اگه برداشت من اشتباه بود بگو .
آره منظورم همینه!!!
جست و جو کردم پیدا نکردم!
اونوقت باید فایل اجرایی رو تویه مسیر مشخص قرار بدیم!؟..
ممنون.
کسی نیست جواب بده!؟..
دوستان حق دارن شك كنن به سوالتون آخه سوالتون يا خيلي مبهمه يا خيلي ساده : اگه منظورتون 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;
مثلا اگه فایل txt رو open with کرد و با برنامه من باز کرد متنش توی یه memo ریخته بشه!!نقل قول:
ولي اگه منظورتون يه چيز ديگه اس واضح تر بگيد تا توضيح داده بشه ...
همین.
ممنون.
منظور از فیلتر چیه!؟..نقل قول:
البته اين OpenDiolog فقط فايلهاي Text و سورس پاسكال رو فيلتر ميكنه اگه نميخواين اين اتفاق بيفته فيلتر رو برداريد) :
برای این کار باید فایلتون رو در ریجستری ریجستر کنید و سپس به وسیله ی تابع ParamStr در هنگام اجرای برنامتون آدرس فایلی که به برنامه پاس داده شده رو بخونید و اون رو باز کنید .
الو..نقل قول:
برای این کار باید فایلتون رو در ریجستری ریجستر کنید و سپس به وسیله ی تابع ParamStr در هنگام اجرای برنامتون آدرس فایلی که به برنامه پاس داده شده رو بخونید و اون رو باز کنید .
صدا نمیاد..
بابا من که گفتم هم رجیستری رو باید چیکار کنم و هم ParamStr چیه!؟..
در ضمن چطور بفهمم که به برنامه پارامتر ارسال شده یانه!؟..ممنون.
خوب همون كد پست شماره 4 جواب شماست (فيلتر هم يعني فقط اون نوع فايلها رو باز كنه).نقل قول:
مثلا اگه فایل txt رو open with کرد و با برنامه من باز کرد متنش توی یه memo ریخته بشه!!
همین.
ممنون.
جسارتاً، شما هم كه گير دادين به اين ParamStr، پارامتر ورودي فايل اجرايي چه ربطي به رجيستري داره؟ چرا موضوع رو مي پيچونيد؟ اون يه بحث جدا بود كه تموم شد!نقل قول:
برای این کار باید فایلتون رو در ریجستری ریجستر کنید و سپس به وسیله ی تابع ParamStr در هنگام اجرای برنامتون آدرس فایلی که به برنامه پاس داده شده رو بخونید و اون رو باز کنید .
1. براي پاس دادن از خط فرمان يا shortcut به برنامه اجرايي از پارامتر استفاده ميشه، كه ميشه مسير فايل متني رو از اين طريق به برنامه داد و بعد از ParamCount و ParamStr استفاده كرد، يه نمونه كد واسه اينكار رو هم ميتونين تو FormCreate ببينيد (البته يه Memo اولش بذاريد رو فرم) :2. ولي راه ديگه خوندن مسير فايل از رجيستري هست كه در اينصورت هم نيازي به دادن پارامتر به برنامه نيست، برنامه مستقيم ميره از رجيستري ميخونه، كه بحثش يه موضوع ديگه است ...
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;
if FileExists(ParamStr(idx)) then beginبه نظر من چون قراره آدرس فایل تو سطر 1باشه بهتره به جای idx بنویسم 1نظر شما چیه!؟...
2. ولي راه ديگه خوندن مسير فايل از رجيستري هست كه در اينصورت هم نيازي به دادن پارامتر به برنامه نيست، برنامه مستقيم ميره از رجيستري ميخونه، كه بحثش يه موضوع ديگه است ...
یعنی نباید تورجیستری کاری کرد که وقتی رو فایل متنی دابیل کلیک کرد به برنامهما پارامتر بفرسته!؟..
در مورد :یه سری به HKEY_CLASSES_ROOT در ریجستری بزنید و با محتویاتش آشنا شید تا بدونید برای اینکه یه فرمت خاصی از فایل ها با برنامه ی مورد نظرمون باز شن و بتونیم براشون آیکن در نظر بگیریم باید در این قسمت ثبت بشن !!!نقل قول:
پارامتر ورودي فايل اجرايي چه ربطي به رجيستري داره ؟
و در مورد ::قهقهه:خیلی جالبه ، بحث تموم شده ولی دقیقا جوابی که من به پست دادم رو به عنوان پاسخ به کاربر ارائه میدید !نقل قول:
جسارتاً، شما هم كه گير دادين به اين ParamStr، چرا موضوع رو مي پيچونيد ؟ اون يه بحث جدا بود كه تموم شد !
یکی جواب پست 13 رو بده...
بله درسته .نقل قول:
به نظر من چون قراره آدرس فایل تو سطر 1باشه بهتره به جای idx بنویسم 1نظر شما چیه!؟
چرا ، اگر این کار رو نکنید به طور خودکار فایلهاتون با برنامتون باز نمیشن و باید یک بار OpenWith بکنیشون .نقل قول:
یعنی نباید تورجیستری کاری کرد که وقتی رو فایل متنی دابیل کلیک کرد به برنامهما پارامتر بفرسته!؟..
تا اونجا که یادمه باید تو HKEY_CLASSES_ROOT یه کلید به نام فرمت فایلت میساختی مثلا : xxx. بعدش داخل این کلید یه کلید با نام Shell و داخل اون یه کلید با نام Open و داخلش اون یه کلید با نام command و در اون یه string با محتوای آدرس برنامت ، تا با کلیک روی فایلها مورد نظر ادرس به عنوان پارامتر به برنامه فرستاده شه .
این واسه حالتی هست که بخواین محتویات چند فایل رو تو Memo موردنظر نمایش بدین، اگه قراره فقط واسه یه فایل کار کنه، شما درست می گین.نقل قول:
به نظر من چون قراره آدرس فایل تو سطر 1باشه بهتره به جای idx بنویسم 1نظر شما چیه!؟...
این صحبت شما جدیده و تو سوال اولتون نبود! توضیحش رو پایین آوردم ...نقل قول:
یعنی نباید تورجیستری کاری کرد که وقتی رو فایل متنی دابیل کلیک کرد به برنامهما پارامتر بفرسته!؟..
چشم حتماً سر میزنم. اون موردی که شما می فرمایید بعداً مطرح شد (که با دابل کلیک، فایلهای txt. با برنامه ایشون باز بشه)؛ با اجازه شما SilverSoft، من جواب دوستمون رو بدم: برای اینکار (باز شدن فایلهای txt با برنامه شما) مقدار Default رو در HKEY_CLASSES_ROOT واسه کلید txt. معادل مسیر برنامه خودتون قرار بدید.نقل قول:
یه سری به HKEY_CLASSES_ROOT در ریجستری بزنید و با محتویاتش آشنا شید تا بدونید برای اینکه یه فرمت خاصی از فایل ها با برنامه ی مورد نظرمون باز شن و بتونیم براشون آیکن در نظر بگیریم باید در این قسمت ثبت بشن !!!
شاید من منظور شما رو درست متوجه نشدم، و توضیح اضافه دادم، عذر میخوام.نقل قول:
:قهقهه:خیلی جالبه ، بحث تموم شده ولی دقیقا جوابی که من به پست دادم رو به عنوان پاسخ به کاربر ارائه میدید !
من کاری رو که گفتین کردم و جواب داد!!!
ولی برنامه ای که من میسازم کارش اینه که یه پسوند جدید میسازه...
حالا من چطور برا اون پسوند مشخص که سیستم هم نمیشناسه این کارو بکنم!؟..
در ضمن مثلا برنامه من توسط یه فایل باز شده(تا حالا مشکلی نیست)بعد یه فایل دیگه رو باز میکنه من چطور میتونم کاری کنم که اون فایل دوم تو همون برنامه باز شه و دیگه برانامه 2 بار اجرا نشه!؟..(مثل مدیاپلیر ها)(نمیدونم که منظورم رو متوجه شدید یا نه!؟..
برا آیکون چیمار کنم!؟..
ممنون.
ممنون.
تو پست قبلیم که براتون توضیح دادم برای یه فرمت جدید چی کار کنید .
برای آیکن هم در همون کلید فرمت فایلتون در کنار کلید shell یه کلید با نام DefaultIcon بسازید و در اون یه string با محتوای آدرس فایل آیکن یا فایل اجرایی که میخواهید آیکن اون نمایش داده شه رو وارد کنید .
:چشمک:من هم از شما معذرت میخوام ، کمی تند رفتار کردم .نقل قول:
Saeed_m_Farid
شاید من منظور شما رو درست متوجه نشدم، و توضیح اضافه دادم، عذر میخوام.
می تونید از یک MDI Application استفاده کنید یا از اون الگو بگیرید
ممنون.نقل قول:
برای آیکن هم در همون کلید فرمت فایلتون در کنار کلید shell یه کلید با نام DefaultIcon بسازید و در اون یه string با محتوای آدرس فایل آیکن یا فایل اجرایی که میخواهید آیکن اون نمایش داده شه رو وارد کنید .
الو ...نقل قول:
می تونید از یک MDI Application استفاده کنید یا از اون الگو بگیرید
صدا نمیاد ...
الو..
صدا قط و وصل میشه!!!!
....
منطورشون برنامه هایی مثل word هست که با باز کردن یه فایل جدید فایل قبلی مثل NotePad بسته نمیشه و تو یه فرم فرزند جدید نمایش داده میشه .نقل قول:
می تونید از یک MDI Application استفاده کنید یا از اون الگو بگیرید
موضوع زیاد ساده ای نیست که بشه تو یه پست توضیح داد، جناب کشاورز یه راهنمایی در این مورد کردن، درمورد IPC یا Inter-process Communication بگردین، برای شروع هم میتونین دوتا روش واسه اینکار امتحان کنید :نقل قول:
در ضمن مثلا برنامه من توسط یه فایل باز شده(تا حالا مشکلی نیست)بعد یه فایل دیگه رو باز میکنه من چطور میتونم کاری کنم که اون فایل دوم تو همون برنامه باز شه و دیگه برانامه 2 بار اجرا نشه!؟..(مثل مدیاپلیر ها)(نمیدونم که منظورم رو متوجه شدید یا نه!؟..
- اولی با ارسال پیام بین پروسسها، به این صورت که برنامه سرورتون (همونی که با دابل کلیک باز شده) باید یه listener واسه پیغامهای دریافتی داشته باشه، یعنی یه ویندوز پروسیجر تو برنامه تون داشته باشین که به پیامهای دریافتی عکس العمل نشون بده؛ و از طرف دیگه قابلیت هندل فایلهای مختلف تولید شده با پسوند خودتون رو داشته باشه، یعنی مثلا بازاء هر پیامی - SendMessage رسیده به برنامه شما - بتونه یه تب جدید واسه اون فایل باز کنه و یه Memo رو با محتویات اون فایل مقداردهی کنه و ... (یه مثال ساده از IPC رو میتونید اینجا ببینید)
- روش دیگه استفاده از پایپ هست، که نمیدونم آشنایی دارید یا نه؛ میتونید یه سرور Pipe واسه اینکار ایجاد کنید و منتظر رسیدن بافر از سمت یه کلاینت باشید که به سمت سرور شما پست میشه. بعد عملیات موردنظرتون رو، روی این بافر انجام بدین.
اگه علاقه داشتین و حوصله تون سر نرفت، ادامه بدیم ...
ممنون
فقط اگه به من بگید که چطور با برنامه ام به برنامه دیگه ای مثلا پیامی بفرستیم با متن:ali
و با اونیکی چطور بفهمیم که بیامی به برنامه ما فرستاده شده یا نه!؟..
ممنون.
کسی نیست جواب بده!؟..
بابا جان من جواب بدین!!
دلفی رو یدادی نداره که هنگام در یافت پارامتر به ما خبر بد]!؟..
با رویداد omessage جزء Tappilication می تونید این کار رو انجام بدهید
اولا همیشه همینطوری نیست که شما یه پست بدی، بچه ها 2 دقیقه بعد باید جوابتو بدن! یکمی زحمت بکش جستجو کن ببین جاهای دیگه چی گفتن، تو خود سایت در این مورد (که بنده دو تا سرنخ بهتون دادم تو پست قبلی ام) نکات متنوعی مطح شده که شما نگشتین؛ اگه هم فکر میکنی مطلبی نیست! یه مقدار صبر باید بکنی، و پست اضافی ندی، سنگک پزی نیست!
ثانیا : تا اونجاییکه من میدونم همچین رویدادی تو دلفی نداریم، برای اینکار چون با این پستها میشه فهمید که آدم صبوری نیستین، من راه اول رو واستون باز میکنم (راه دوم پیچیده تر هست و با روحیه شما جور در نمیاد)
شما برای اینکار باید از روالهای ارسال پیام خود ویندوز استفاده کنید؛ توضیحات مفصلی در مورد این مباحث وجود داره که میتونید از MSDN و تاپیکهای مختلف یاست درمورد اونا کسب اطلاع کنید، بنده با فرض اطلاع شما از نحوه عملکرد پیامهای ویندوز، راه حل رو ارائه میدم :
- قبل همه شما باید یه ثابتی برای ارتباط بین برنامه ها داشته باشید که با شماره پیامهای ویندوز قاطی نشه :
const
WMU_OUT_MESSAGE = WM_USER + 1;
- عمل بعدی ایجاد همون رویدادی هست که شما می خواستید، یعنی جایی که به این درخواست رسیدگی بشه، برای اینکار شما باید یه windows procedure بنویسین، تا اگه پیغام رسیده، همونی بود که شما میخواستین، بهش رسیدگی بشه و درغیر اینصورت روال ویندوزی در مورد اون پیگیری بشه، با حدس من در مورد کارکرد برنامه شما، مثلا یه همچین procedure ای میشه :
ضمنا با این روال، شما یکی از پارامترهایی که میتونستین استفاده کنید یعنی LParam رو فعلا استفاده نکردید، به این ترتیب بعدا در صورت گسترش برنامه میتونین از اون هم برای کارهای دیگه (مثلا نحوه نمایش متن موردنظر) استفاده کنید و ...
(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)
// 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;
(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)
- قسمت آخر فرستادن پیام از یه برنامه دیگه به این برنامه است؛ برای اینکار همونطوریکه در بند قبل دیدین، باید آدرس رشته موردنظر رو به برنامه سرور بدین؛ برای اینکار من از رشته مورد نظر یه instance تو RAM درست میکنم و اون آدرس رو به روال هندل پیام که تو بند قبل نوشتیم میدم :
البته باید توجه کنید که برای استفاده از این تابع باید هندل سرور رو داشته باشید، که روش اینکار درصورت جستجو همه جا هست، برای نمونه هم تو سایت Torry میتونید یه نمونه اش رو پیدا کنید، ولی با فرض اینکه شما یه instance از سرورتون دارین میتونید از یکی از توابع زیر برای اینکار استفاده کنید (توجه کنید که تابع اول برای موقعی هست که سرور تو یه ماشین دیگه اس ...) :
(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)
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;
(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)
(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)
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 و ... هم استفاده کرد که با پورت خاصی اطلاعات بین پروسسهای شما رد و بدل میشه و هرکدوم مزایای خودشون رو دارن (این به نظر من ساده ترین راه بود) ...
من که والا مخم پوکید و هیچی نفهمیدم!!!!!!
خوب حالا یکم برم رو این روشی که گفتین تفکر کنم!!!!
میگم مگه نمیشه به جای این کارا آدرس فایل رو تو رجیستری بریزه و برنامه دوم اونو از رجیستری بخونه!؟..
اگه احساس می کنید که به اندازه کافی تفکر کردین، یه مژده بهتون میدم : لازم نیست سمت کلاینت رو شما بنویسین! چون کلاینت شما خود ویندوز هست. پس کار شما خیلی راحت میشه چون نه لازمه که سرور (برنامه خودتون) رو پیدا کنید و نه ایجاد 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;
موفق باشید.
من گیچ شدم !!!یدفه از محیط مبتدی اومدم به میحط پیشرفته!!!!(از هیچی سر در نیاوردم!!!
اما نا امید نمیشم!!!
خوب برا این که خوب درک کنم سعی میکنم سطر به سطر به خودم تفهیم کنم!
سوال:
Mutex := CreateMutex(nil, True, 'MDIEditorTest');
این سطر اصلا چیکار میکنه!؟..
پارامتر هاش چیه!؟..
این کار رو میکنه :
نقل قول:
باید یه کدی بنویسید که با هر بار دابل کلیک، نسخه جدیدی از برنامتون باز نشه؛ برای اینکار، باید بتونید برنامه اول که اجرا شده رو پیدا کنید، برای اینکار یه میوتکس (Mutex) از Application خودتون ایجاد میکنید، که دفعه بعد که دیدین این میوتکس وجود داره فقط پارامترهای رسیده به نسخه جدید رو پاس بدین به قبلیه
(Mutex) از Application
حالا خود این چیه!؟..
اگه اینطوری ادامه بدین، مطمئن باشین مدیرای سایت بهتون اخطار میدن یا تاپیک رو قفل میکنن؛ نمیشه که شما سطر به سطر بپرسین و یه جستحوی ساده نکنید؛ یه یادگاری از امضاء یکی از دوستان :
انسانها سه دسته اند : آنهایی که باینری میفهمند، آنهایی که نمی فهمند و آنهاییکه جستحو کردن نمی دانند!
ولی مطمئن باشید امروز من بیکارم، تا خود صبح هم بپرسید حوابتون رو میدم :چشمک:
انگار الان نمیتون که یاد بگیرم!!!!
آخه خیلی مبتدی هستم!!!!!
بهتره یه مدت اطلاعاتم رو بالا ببرم بعد بیام....
ممنون.
قرار بود نا امید نشین، اونطوریکه شما گفتین مطمئن شدم به این زودیا از کوره در نمیرید؛ ببینین اطلاعات زیر کمکتون میکنه ؟
(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)
//رو انتخاب کنید 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.
(*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*)
Mutex := CreateMutex(nil, True, 'MDIEditorTest');
فعلا تو بقیه قسمات مشکل ندارم فقط نمیتونم کد بالا رو درک کنم!؟..
پارامتر های CreateMutex چیه!؟.
(GetLastError = 0) then begin این هم چیه!؟..
ممنون. و قدردانی از توضیحات کاملتون
دوست عزیز، این سوالات دیگه به سوال اصلی شما مربوط نمیشه، هرکدوم رو سر جاش بپرسید تا هم سایر دوستان کمک کنن و هم مسیر تاپیک عوض نشه؛ این سوال رو تو همون لینکی که تو پست 35 گذاشتم بپرسید تا بدرد دوستان دیگه هم بخوره ...نقل قول:
فعلا تو بقیه قسمات مشکل ندارم فقط نمیتونم کد بالا رو درک کنم!؟..
پارامتر های CreateMutex چیه!؟.
(GetLastError = 0) then begin این هم چیه!؟..
تا اونجایی که من میدونم Application.Run;
برا باز شدن برنامه هست!!!
پس چرا تو وسط برنامه استفاده کردین!؟..
اونجا وسط برنامه نیست! یه پروژه جدید باز کنید، فایل پروژه رو نگاه کنید (Project1 <- Ctrl+F12)، مطمئنا متوجه میشید.
ایول بابا کم کم ناامید میشدم ولی بازم امید گرفتم....
ممنون.
بازم ممنون.
..
......
..
..
من یه چیز دیگه هم پیدا کردم که برام مبهمه!!!!
آخه ما میگیم که اگه هندل پیدا نشد ببندش!!!!
آخه چرا!؟..
if Mutex <> 0 then
CloseHandle(Mutex);
در کل من نفهمیدم !! مگه ما نمیخوایم که هندل وجود داشته باشه و دفعه بعد دیگه برنامه باز نشه!؟..
پس چرا میبندیمش!؟..
من یه چیز رو نمیتونم بفهمم هرچ ه قدر هم تفکر کردم و امتحان کردم دیدم که در هر دو حالت جواب نکیگیرم...
فرض کنیم که xیه هندل است..
حال x<>0 یعنی وجود داره یا وجود نداره..
وقتی x از نوع هندل هست اگر پنجره یا ... اختصاص داده شده بهش وجود نداشته باشه x=0 میشه و در غیر این صورت ( در صورت وجود پنحره یا ... ) x برابر با شماره ی هندل اون پنجره میشه .نقل قول:
فرض کنیم که xیه هندل است..
حال x<>0 یعنی وجود داره یا وجود نداره..
پسif Mutex <> 0 then
CloseHandle(Mutex);
یعنی : اگر پنجره یا ... وجود داشت ببندش .
منظور کدوم پنجره هست!؟..نقل قول:
وقتی x از نوع هندل هست اگر پنجره یا ... اختصاص داده شده بهش وجود نداشته باشه x=0 میشه و در غیر این صورت ( در صورت وجود پنحره یا ... ) x برابر با شماره ی هندل اون پنجره میشه .
منظور فقط پنجره نیست ، پست من رو کامل و با دقت بخونید :نقل قول:
منظور کدوم پنجره هست!؟..
در اینجا منظور هندل Mutex ساخته شده هست .نقل قول:
پنجره یا ...
کلا ما میوتکس رو بزاریم کنار اونوقت چی!؟..
:گریه::گریه::گریه:لطفا شما تا زیاد شدن اطلاعاتتون ، کلا این نوع سوالات و مباحث رو بزارید کنار ...
براي درك مفهوم mutex به كتابهاي سيستمهاي عامل (مثل تاننبام ) مراجه نمائيد. :متفکر: