# Native Code > برنامه نویسی در Delphi > مباحث عمومی دلفی و پاسکال > حرفه ای: ساخت پلاگین برای MMB

## loo30fer

با سلام
میخواستم اگه امکان داره نحوه صحیح و اصلی ساخت پلاگین برای مولتی مدیا بیلدر رو خیلی مقدماتی بگین که  برای افرادی مثل من راحت باشه , دلیل اینکه هم که گفتم نحوه صحیح و اصلی به  دلیل اینکه من سورس های پلاگین های مختلفی رو دیدم که هرکدوم با یک روش  مختلفی نوشته شده بود و بعد از کمپایل اختلاف حجم خیلی زیادی داشتن البته  این رو هم بگم که تمام Function و دستورات Function و Uses های اضافی رو  حذف کرده بودم و بر خلاف این پلاگین هایی که من سورسشون رو داشتم با داشتن 6  الی 13 تا Functions حجمی حدود 300 کیلوبایت که کارایی خاصی هم نداشتن ولی  پلاگین Miscy که با دلفی هم نوشته شده بود با وجود 157 Functions فقط حجمش  571 کیلوبایت بود
با تشکر از دوستان و اساتید برنامه نویس

----------


## Felony

برای پلاگین نویسی برای MMB نیاز به کیت توسعه نرم افزاری ( SDK ) مربوط به اون دارید ، البته این SDK فقط تا دلفی 7 توسعه داده شد و بعد شرکت Media Chance ورشکست شد ؛ این کتابخانه نقش واسط بین پلاگین شما و MMB رو بر عهده داره ، پس شما برای تبادل اطلاعات بین پلاگین و برنامه نوشته شده با MMB باید از دستورات این کتابخانه استفاده کنید ، این کتابخانه توابع مختلفی ارائه میکنه که من نحوه کار با 4 تا از اصلی ترین هاشون رو بهتون میگم .

1- برای دریافت رشته از برنامه MMB به پلاگین باید از TextInput که به صورت یک آرایه تعریف شده استفاده کنید ، TextInput در کد بالا به صورت یک آرایه 5 خونه ای تعریف شده که هر خونش میتونه حاوی یک رشته خاص باشه ، پس با توجه به این توضیح شما میتونید در یک زمان 5 تا رشته رو توسط برنامه MMB تون به پلاگین بفرستید که البته میشه تعداد این رشته ها رو با تغییر در کد بالا افزایش داد که کار سختی هم نیست .

2- برای ارسال رشته از پلاگین به برنامه MMB از TextOutput استفاده میشه که به صورت یک متغییر تعریف شده و در یک زمان مشخص شما میتونید فقط یک رشته رو از پلاکین به برنامه MMB بفرستید که اون هم با ترفندهایی قابل تغییر هست .

3- برای ارسال عدد از برنامه پلاگین از NumInput که به صورت یک آرایه 5 خونه ای هست استفاده میشه ، پس در یک زمان واحد میتونید 5 عدد مختلف رو از برنامه به پلاگین ارسال کنید که قابل تغییر هم هست .

4- برای ارسال عدد از پلاگین به برنامه از NumOutput که یک متغییر هست استفاده میشه .

به عنوان نمونه کد زیر نام و نام خانوادگی رو تو 2 تا رشته جدا از برنامه میگیره و به هم اتصال میدشون و در آخر به برنامه بر میگردونه :
Procedure Test; cdecl;
var 
  FName, LName, FullName: String;
begin
  FName:= TextInput[2];
  LName:= TextInput[1];
  FullName:= FName + ' ' + LName;
  TextOutput:= FullName;
end;
یا کد زیر 2 تا عدد رو از برنامه میگیره و با هم جمع میکنه و به برنامه بر میگردونه :
Procedure Test; cdecl;
var 
  Num1, Num2, Answer: Integer;
begin
  Num1:= NumInput[2];
  Num2:= NumInput[1];
  Answer:= Num1 + Num2;
  NumOutput:= Answer;
end;

این 4 تا رایج ترین موارد برای پلاگین نویسی برای MMB هستن .

- برای اینکه برنامه MMB بتونه توابع مورد نظرتون رو از داخل پلاگین صدا بزنه حتما باید دایرکتیو cdecl رو در آخر توابع ذکیر بکنید .

- در آخر کار باید لیست توابع مورد نیازتون رو برای استفاده برنامه export بکنید ( به نمونه ضمیمه شده مراجعه کنید )

- من SDK رو به 2 صورت درآوردم ، یکی برای پلاگین های non-Visual که نیازی به فرم ندارن و دیگری برای پلاگین های Visual که نیاز به فرم و رسم اشیاء مختلف دارن ؛ این کار برای کاهش حجم پلاگین تولید شده هست ؛ برای ساخت پلاگین های Visual کافیه از SDK مربوط به پلاگین Visual استفاده کنید رو فرم اشیاء مورد نظر رو بزارید .

- برای کم شدن حجم پلاگین از پکر هایی مثل UPX استفاده کنید .

- قبلا با توجه به نیازم این SDK رو برای Delphi 2010 توسعه دادم ولی جایی انتشار نداده بودمش که در ضمیمه به همراه یه نمونه پلاگین قرار دادمش .

----------


## javad p

> و بعد از کمپایل اختلاف حجم خیلی زیادی داشتن البته این رو هم بگم که تمام Function و دستورات Function و Uses های اضافی رو حذف کرده بودم و بر خلاف این پلاگین هایی که من سورسشون رو داشتم با داشتن 6 الی 13 تا Functions حجمی حدود 300 کیلوبایت که کارایی خاصی هم نداشتن ولی پلاگین Miscy که با دلفی هم نوشته شده بود با وجود 157 Functions فقط حجمش 571 کیلوبایت بود


افزایش حجم مربوط به تعداد Functions ها نیست (البته نه کاملا) ولی به میزان خیلی کمی با این مورد مرتبط هست
شما بهتره علاوه بر رعایت موارد پست بالا برای کاهش حجم به کتابخانه هایی که تو فایل هستند دقت کنید. افزایش اصلی حجم به دلیل استفاده کردن از کتابخانه های مختلف هست.

----------


## loo30fer

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


> تمام Function و دستورات Function و Uses های اضافی رو  حذف کرده بودم


 و به سورس آماده اضافه کردن دستورات تبدیلشون کرده بودم و یکی از دلایلی هم که به خاطرش تاکید داشتم روش اصلی پلاگین نویسی گفته بشه اینکه هرکی سورس کار من رو دید گیج نشه که این چه نوع پلاگین نویسی هستش و نتونه کدها رو درک کنه و برای کاربران دیگه هم که روش پلاگین نویسی رو میخونن براشون راحتتر و قابل درک باشه

----------


## javad p

> یکی از دلایلی هم که به خاطرش تاکید داشتم روش اصلی پلاگین نویسی گفته بشه اینکه هرکی سورس کار من رو دید گیج نشه که این چه نوع پلاگین نویسی هستش و نتونه کدها رو درک کنه


زیاد فرق نمیکنه
چون شما نمیتونید از چهارچوب کلی SDK که Media Chance برای این کار در نظر گرفته خارج بشید
اون تفاوتها تو نوشتن plugin ها هم اصلا تو اصل قضیه تاثیری نداره و کسی که دلفی بلد باشه تو اون کدها گیج نمیشه!!

----------


## loo30fer

> کسی که دلفی بلد باشه تو اون کدها گیج نمیشه!!


خوب کسی هم که دلفی بلد باشه حتما پلاگین نویسی برای MMB رو بلده و دیگه نیازی به سورس من نداره من این تاپیک هم رو ایجاد کردم برای افراد مبتدی مثل خودم که زیاد با دلفی آشنایی ندارین و میخوان با نحوه پلاگین نویسی آشنا بشن پس اگه افرادی مثل خودم سورس ها رو نگاه کنن یکم گیج میشن

جناب تاجیک اگه امکان هم داره در مورد هریک از Function های خود پلاگین توضیحی بدین که کاراییش چیه و چرا استفاده میشه (,...SetFile,Draw,SetParentwindow)

----------


## Felony

GetColor : برای تبدیل یک رشته رنگ به TColor .

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

GetWindowsDir : گرفتن مسیر پوشه ویندوز .

GetSystemDir : گرفتن مسیر پوشه System32 .

CallMMBScript : اجرای یک کد اسکریپت از داخل پلاگین .

GetMMBScriptInt : گرفتن مقدار بازکشتی از یک اسکریپت ( عددی ) .

GetMMBScriptStr : گرفتن مقدار بازگشتی از یک اسکریپت ( رشته ) .

hMMBWindow : هندل پنجره برنامه MMB که به وسیله اون میتونید یک شئ یا ... رو به صورت RunTime روش بسازید .

HasIntDlg : با 1 کردن مقدار Result در کد زیر دکمه Properties در قسمت تنضیمات پلاگین تو MMB فعال میشه .

function HasIntDlg: integer; cdecl;
begin
  Result:=0;
end;

وقتی دکمه Properties زده شد میتونید یک فرم به کاربر به عنوان تنضیمات پلاگین نمایش بدید یا ... ( تو پلاگین Silver Access که قبلا نوشتم نمونش هست )  ، برای این کار کودتون رو باید در روال زیر بنویسید :
function _Interface: pChar; cdecl;
begin
  //MessageBox(FindWindow('#32770','MMB PlugIn'),'You can here add e.g.: form with plugin options...','PlugIn Properties',0);
  Result := nil;
end;

موفق باشید .

----------


## loo30fer

تشکر , ببخشید ولی من منظورم رو بد رسوندم منظور من Function های مورد نیاز MMB بود برای مثال :
SetFile,
GetFile,
SetData,
GetData,
SetPath,
Copyright,
GetShortInfo,
GetInfo
GetType,
SetParentwindow,
Draw;

----------


## loo30fer

جناب تاجیک اگه امکان داره در مورد کار Function خود MMB که مطرح کردم توضیحی بدین با تشکر

----------


## Felony

> SetFile,
> GetFile,
> SetData,
> GetData,


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




> SetPath


یک متغییر رشته ای رو به عنوان مسیر مقدار دهی میکنه که کاربرد خاصی نداره ؛ دقت کنید که این SDK ها توسط خود Mediachance ارائه نشده بلکه فقط نسخه اولیه توسط شرکت ارائه شده و این نسخه هایی که دست شماست توسط کاربران توسعه داده شده و هر کاربر بسته به نیازش چیزهایی بهش اضافه کرده که ممکنه استاندارد نباشه ؛ Mediachance فقط برای نسخه اولیه بیلدر که امکان استفاده از پلاگین داشت SDK ارائه کرد و برای نسخه های بعدی کاربرانش SDK ها رو توسعه میدادن ، مثل همین SDK نسخه 2010 که براتون ضمیمه کردمش .




> Copyright,


متن Copyright مربوط به پلاگین رو به صورت رشته بر میگردونه ؛ این متن رو در قسمت بالای کدهای SDK میتونید برای خودتون تغییر بدید :
//PlugIn Info
const
  PluginCopyright = 'Copyright here';




> GetInfo


اطلاعات پلاگین رو به صورت رشته بر میگردونه ( مثل Copyright که بالا توضیح دادم میتونید تغییرش بدید ) .




> GetType


برای استفاده خود بیلدر هست که Mode پلاگین رو به بیلدر اطلاع میده .




> SetParentwindow


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



> Draw


اگر پلاگین حاوی فرم باشه باعث رسم فرم در صفحه پلاگین بیلدر در زمان اجرا برنامه میشه ، اگر پلاگینتون فرم نداره میتونید حذف یا کامنتش کنید .

----------


## loo30fer

ببخشید جناب تاجیک امکان داره در مورد فانکشن SetParentwindow توضیح کاملتری بدین که کارش دقیق چیه و این Mode چی هست و چیکار میکنه و وجودش آیا تو پلاگین الزامیه ؟

و من وقتی سورس پلاگین های مختلف رو نگاه میکنم میبینم همیشه این Uses ها رو بهش دادن که Classes SysUtils, Variants و طبق ساختار جالب دلفی هنگام کمپایل اگه یه Uses یا دستوری کم یا اشتباه باشه خطا میگیره و اجازه کمپایل نمیده و من همیشه هم این Uses ها رو حذف میکنم و میخواهم کمپایل کنم بدون هیچ مشکل یا خطا گیری توسط دلفی کمپایل میشه حالا میخواستم بدونم آیا استفاده از این Uses ها الزامی است و بعد از حذفشون باعث ایجاد اشکالی میشه چون بعد از حذفشون باعث کم شدن حجم محسوس پلاگین میشه

با تشکر

----------


## Felony

> ببخشید جناب تاجیک امکان داره در مورد فانکشن SetParentwindow توضیح کاملتری بدین که کارش دقیق چیه و این Mode چی هست و چیکار میکنه و وجودش آیا تو پلاگین الزامیه ؟


برای ترسیم فرم پلاگین تو بخش Design بیلدر ، خود بیلدر ازش استفاده میکنه ؛ اگر پلاگینتون فرم نداره میتوندی حذفش کنید ولی اگر فرم داره اون کد باعث ترسیم اون فرم میشه .




> و من وقتی سورس پلاگین های مختلف رو نگاه میکنم میبینم همیشه این Uses ها رو بهش دادن که Classes SysUtils, Variants و طبق ساختار جالب دلفی هنگام کمپایل اگه یه Uses یا دستوری کم یا اشتباه باشه خطا میگیره و اجازه کمپایل نمیده و من همیشه هم این Uses ها رو حذف میکنم و میخواهم کمپایل کنم بدون هیچ مشکل یا خطا گیری توسط دلفی کمپایل میشه حالا میخواستم بدونم آیا استفاده از این Uses ها الزامی است و بعد از حذفشون باعث ایجاد اشکالی میشه چون بعد از حذفشون باعث کم شدن حجم محسوس پلاگین میشه


حذفشون مشکلی نداره ، این کتابخانه ها کتابخانه های اصلی هستند که تو بیشتر پروژه ها کاربرد دارن ، برای همین به صورت پیش فرض تو Uses قرار گرفتن ، شما هر کدوم رو که ازش استفاده نمیکنی حذف کن .

----------


## loo30fer

من تابع گرفتن حجم فایل رو تو سورس پلاگین جای دادم حالا نمیدونم چطور براش تعریف کنم که آدرس فایل رو از PluginSet بگیره و بعد از گرفتن حجم چطور به PluginGet بده شرمنده اگه امکان داره برام کدش رو ویرایش کنید میدونم که یک مدت باید با دلفی کار کنم و با نحوه کارش آشنا بشم بعد راحت خودم درستش کنم ولی برای یک کارم که پیاده کردن یک الگوریتم هست نیاز به پلاگین دارم و کسی رو هم نتونستم برای ساختش پیدا کنم و فعلا که مشکل من همین قسمته ممنون میشم کمکم کنید با تشکر
unit PluginInterface;

interface

uses Windows, Messages, SysUtils, PluginInfo;

type
  TPluginMode = (pmDesigner, pmRuntime);

var
  hMMBWindow: Cardinal;
  PluginMode: TPluginMode;
  AppDir: string;
  SR: TSearchRec;

  TextInput: array [1..5] of string;
  TextOutput: string;
  NumInput: array [1..5] of Integer;
  NumOutput: Integer;

  EventKeys: string;

implementation

function Copyright: pChar; cdecl;
begin
  Result := pChar(PluginCopyright);
end;

function GetShortInfo: pChar; cdecl;
begin
  Result := pChar(PluginShortInformation);
end;

function GetInfo: pChar; cdecl;
begin
  Result := pChar(PluginInformation);
end;

function GetType: Integer; cdecl;
begin
  Result := 0;
end;

procedure SetPath(sPath: pChar); cdecl;
begin
  AppDir := sPath;
end;

procedure SetFile(s: pChar); cdecl;
begin
  TextInput[5] := TextInput[4];
  TextInput[4] := TextInput[3];
  TextInput[3] := TextInput[2];
  TextInput[2] := TextInput[1];
  TextInput[1] := s;
end;

function GetFile: pChar; cdecl;
begin
  Result := pChar(TextOutput);
end;

procedure SetData(nData: Integer); cdecl;
begin
  NumInput[5] := NumInput[4];
  NumInput[4] := NumInput[3];
  NumInput[3] := NumInput[2];
  NumInput[2] := NumInput[1];
  NumInput[1] := nData;
end;

function GetData: Integer; cdecl;
begin
  Result := NumOutput;
end;

function MyFileSize(const FileName: String): Int64; cdecl;
begin
  if FindFirst(FileName, faAnyFile, SR)=0 then
    repeat
      Result:= SR.Size;
    until (FindNext(SR)<> 0);
  FindClose(SR);
end;


exports
  Copyright,
  GetShortInfo,
  GetInfo,
  GetType,
  SetPath,
  SetFile,
  GetFile,
  SetData,
  GetData,
  MyFileSize;

end.

----------


## Felony

> من تابع گرفتن حجم فایل رو تو سورس پلاگین جای دادم حالا نمیدونم چطور براش تعریف کنم که آدرس فایل رو از PluginSet بگیره و بعد از گرفتن حجم چطور به PluginGet بده شرمنده اگه امکان داره برام کدش رو ویرایش کنید میدونم که یک مدت باید با دلفی کار کنم و با نحوه کارش آشنا بشم بعد راحت خودم درستش کنم ولی برای یک کارم که پیاده کردن یک الگوریتم هست نیاز به پلاگین دارم و کسی رو هم نتونستم برای ساختش پیدا کنم و فعلا که مشکل من همین قسمته ممنون میشم کمکم کنید با تشکر


اون کار درست نیست ؛ نباید تو SDK چیزی بنویسید ، اون کتابخانه به عنوان رابط شما عمل میکنه نه فایل پلاگینتون و نگهدارنده سورستون ، دقیقا مثل کتابخانه های دیگه دلفی ؛ مثلا شما میخوای کد بنویسی میری تو کتابخانه Windows کد مینویسی ؟

در ضمن بهتون گفتم توسط TextInput و TextOutput متن میفرستی و میگیری و توسط NumInput و NumOutput عدد .

یه پروژه DLL ایجاد میکنی و به لیست Uses هاش PluginInterface رو اضافه میکنی ، پروژه رو ذخیره میکنی و کتابخانه PuginInterface.pas رو هم کنارش میزاری ؛ حالا تو همون فایل DPR که ساختی کدهات رو مینویسی .

----------


## loo30fer

سلام
ببخشید من وقتی برای پلاگین این procedure رو تعریف میکنم و کدش رو خالی میذارم به این شکل :
procedure DeleteFile; cdecl;
begin
end;
مشکلی نیست و کمپایل میکنه ولی وقتی از دستورات خود دلفی استفاده میکنم که با نام procedure همنام هست خطا میگیره و اجازه کمپایل نمیده مثل این کد :
procedure DeleteFile; cdecl;
begin
if DeleteFile('') then
end;
چون اگه بخوام اسم Prodecure رو مثلا به DeleteFileX تغییر بدم زیاد جالب نمیشه , برای این مشکل راه حلی وجود داره یا ساختار دلفی اینطوریه و کاریش نمیشه کرد ؟

----------


## loo30fer

ببخشید یک سوال دیگه هم داشتم
فرض کنید کاربر در MMB دو ScriptTimer ایجاد کرده که هر کدام به طور مداوم هر یک میلی ثانیه یک ورودی رو به پلاگین من میفرستن و فانکشنی رو اجرا میکنن خوب مسلما این فانکشنها همون ابتدای کار اون ورودی رو میگیرن و کار مورد نظر رو انجام میدن حالا وقتی در این تایمرها در اختلاف یک میلی ثانیه ورودی رو میفرستن و فانکشن مورد نظرشون رو اجرا میکنن امکان اینکه تداخلی پیش بیاد و فانکشن FiletSize به جای اینکه ورودی خودش رو که برای مثال C:\File.exe بوده رو ورودی فانکشن FileExists بگیره که D:\File.exe و عملیات اشتباه رو انجام بده هست درسته ؟
آیا برای رفع امکان اتفاق این مشکل تعریف کردن آرایه برای ورودی ها مثل SDK شما این مشکل رو حل میکنه اگه اینطوره ممنون میشم توضیحی در این رابطه بدین که چرا ؟

----------


## loo30fer

همچنان منتظر جواب  :ناراحت:  !!!!!

----------


## Felony

> سلام
> ببخشید من وقتی برای پلاگین این procedure رو تعریف میکنم و کدش رو خالی میذارم به این شکل :
> procedure DeleteFile; cdecl;
> begin
> end;
> مشکلی نیست و کمپایل میکنه ولی وقتی از دستورات خود دلفی استفاده میکنم که با نام procedure همنام هست خطا میگیره و اجازه کمپایل نمیده مثل این کد :
> procedure DeleteFile; cdecl;
> begin
> if DeleteFile('') then
> ...


طبیعی هست شما نام روال رو DeleteFile قرار دادی بعد از تابعی با همون نام استفاده کردی ، Parser بنده خدا نمیتونه این موضوع رو تحلیل کنه ، باید نام روال رو تغییر بدید . 




> ببخشید یک سوال دیگه هم داشتم
> فرض کنید کاربر در MMB دو ScriptTimer ایجاد کرده که هر کدام به طور مداوم هر یک میلی ثانیه یک ورودی رو به پلاگین من میفرستن و فانکشنی رو اجرا میکنن خوب مسلما این فانکشنها همون ابتدای کار اون ورودی رو میگیرن و کار مورد نظر رو انجام میدن حالا وقتی در این تایمرها در اختلاف یک میلی ثانیه ورودی رو میفرستن و فانکشن مورد نظرشون رو اجرا میکنن امکان اینکه تداخلی پیش بیاد و فانکشن FiletSize به جای اینکه ورودی خودش رو که برای مثال C:\File.exe بوده رو ورودی فانکشن FileExists بگیره که D:\File.exe و عملیات اشتباه رو انجام بده هست درسته ؟
> آیا برای رفع امکان اتفاق این مشکل تعریف کردن آرایه برای ورودی ها مثل SDK شما این مشکل رو حل میکنه اگه اینطوره ممنون میشم توضیحی در این رابطه بدین که چرا ؟


 بله امکان اشتباه هست ، SDK هم یک رابط هست وقرار نیست معجزه بکنه ، این وظیفه شما هست که این مشکل رو بر طرف کنید .

- برای حل مشکل میتونید یک StringList تعریف کنید و درخواست هایی که به DLL میرسه رو داخل StringList ذخیره کنید و DLL در عین حال دستورات رو از داخل StringList بخونه و بهشون رسیدگی کنه و جواب مرتبط را به برنامه برگردونه ، مثلا برنامه شما هر چند میلی ثانیه اسم یک فایل رو برای به دست آوردن حجم به پلاگین میفرسته ، شما اسم فایل رو به صورت زیر در StringList ذخیره میکنید :

D:\aFile.txt|FileSize

حالا تو یک تایمر یا Thread در DLL شروع میکنید از اول StringList میخونید و اسم فایل و کاری که باید روش انجام بشه رو استخراج میکنید و عملیات رو انجام میدید و به صورت زیر به بیلدر بر میگردونید :

D:\aFile.txt|174

حالا برنامه مقصد هم اسم فایل و هم حجم فایل رو داره و نه مشکلی پیش میاد چون اسم فایل ها داخل صف در StringList هستند و حتما بهشون رسیدگی میشه ، یادتون نره بعد از خوندن و انجام کار از stringList آیتمی که کارش تموم شده رو حذف کنید .

----------


## loo30fer

جناب تاجیک من اگه بخوام تو پلاگینم که فرمی نداره از کامپوننت استفاده کنم چطور باید اینکار رو بکنم؟؟؟
چون مانند کدی که گذاشتم حتما باید کامپوننت IdMessage باشه کتابخانه مربوطشم رو به Uses اضافه کردم ولی فایده نداره خطا میگیره. با تشکر.
procedure SendMail; cdecl;
begin
   with IdMessage1 do
    begin

----------


## Felony

الان با این توضیحات توقع چه راهنمایی دارید ؟ چی کار کردید که خطا میده ؟ چه خطایی میده ؟
IDMessage1 رو قبل از استفاده نمونه سازی کردید ؟
بهترین راه استفاده از یک Data Module هست .

----------


## loo30fer

> الان با این توضیحات توقع چه راهنمایی دارید ؟ چی کار کردید که خطا میده ؟ چه خطایی میده ؟


خوب از اینکه این توضیحات کامل رو دادین ممنون ولی من برای استفاده از کامپوننت تو پلاگینم نتونستم از هیچ کدوم راهنمایی شما استفاده و به کار بگیرم.



> IDMessage1 رو قبل از استفاده نمونه سازی کردید ؟


نه راستش مشکل منم همینه که چطوری ایجادش کنم.



> بهترین راه استفاده از یک Data Module هست .


میشه در این مورد یکم توضیح بدین که چی هست و چطور کار میکنه یا حداقل یک منبع رو برای من برای فهم این موضوع معرفی کنید ممنون.

----------


## Felony

> نه راستش مشکل منم همینه که چطوری ایجادش کنم.


خسته نباشید ؛ برای اینکه شروع به کار با اشیاء در DLL ها کنید باید با نحوه نمونه سازی اشیاء و مدیریت حافظه اونها به صورت Runtime آشنایی کامل داشته باشید .




> میشه در این مورد یکم توضیح بدین که چی هست و چطور کار میکنه


Data Module تقریبا شبیه یک فرم هست که قابلیت بصری در Runtime نداره ، یعنی در هنگام اجرا چیزی به شما نمایش نمیده ، پس شما نمیتونید روی اون از اشیاء Visual مثل Button , ComboBox, ListBox و ... استفاده کنید ولی در عوض میتونید از اشیاء Non Visual مثل Timer, ADO, Indy و ... استفاده کنید .

با استفاده از Data Module نیازی نیست که شیئ رو هر بار که بهش نیاز دارید Create کنید و در این میان نگران از دست رفتن اطلاعات یا مدیریت حافظش باشید ، کافیه در Entry Point پروژه DLL تون در هنگام بار شدن DLL شئ Data Module رو Create کنید و در هنگام Unload شدن آزادش کنید ، Data Module هم وظیفه مدیریت حافظه اختصاصی به اشیاء قرار گرفته بر روی خودش رو مثل فرم معمولی بر عهده میگیره .

یک نمونه پلاگین براتون نوشتم و ضمیمه کردم .

----------


## loo30fer

سلام
جناب تاجیک من میتونم هندل فرم رو با توجه به تابع SetParentWindow که تو SDK تعریف شده بگیرم که مانند Form1.Handle عمل میکنه ولی اگه بخوام هندل خود برنامه رو بگیرم مانند Application.Handle چیکار باید بکنم ؟ ممنون میشم راهنمایی کنید. با تشکر

----------


## Felony

> ولی اگه بخوام هندل خود برنامه رو بگیرم مانند Application.Handle چیکار باید بکنم ؟


Application.Handle در هیچ جا به جز Delphi معنا نداره ، در زمان طراحیDelphi گروه توسعه دهنده برای پیاده سازی یکسری از امکانات مجبور شدن Delphi رو طوری پیاده سازی کنن که یک فرم مخفی داشته باشه ( Application ) که والد فرم های دیگر برنامه هست و یکسری از عملیات های مدیریتی رو در پشت صحنه انجام میده .

به خودی خود یک Application ( منظور برنامه ) هندلی مثل Application.Handle در Delphi نداره ، حالا شما دقیق بگو چی کار میخوای بکنی ...

----------


## loo30fer

> Application.Handle در هیچ جا به جز Delphi معنا نداره ، در زمان  طراحیDelphi گروه توسعه دهنده برای پیاده سازی یکسری از امکانات مجبور شدن  Delphi رو طوری پیاده سازی کنن که یک فرم مخفی داشته باشه ( Application )  که والد فرم های دیگر برنامه هست و یکسری از عملیات های مدیریتی رو در پشت  صحنه انجام میده .
> 
> به خودی خود یک Application ( منظور برنامه ) هندلی مثل Application.Handle در Delphi نداره


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



> حالا شما دقیق بگو چی کار میخوای بکنی ...


راستش من میخوام آیکون برنامه های بیلدر رو از Taskbar مخفی کنم و از این تابع ShowWindow هم استفاده کردم ولی به جای اینکه ایکونش از تسکبار مخفی بشه کل پروژه مخفی میشد بعد که دقیق بهش توجه کردم فهمیدم من دارم هندل فرم رو بهش میدم نه مثل دلفی هندل برنامه برای همین هم هست که کل فرم مخفی میشه برای همین هم همین سوال رو پرسیدم. اتفاقا یک پلاگین در این رابطه براش وجود داره برای من سوال شده اون از چه روشی استفاده کرده ؟؟
یک سوال دیگر من وقتی تو پلاگین از تابع SendMessage استفاده میکنم تا مثلا یک دستور یا اسکریپت رو تو برنامه اجرا کنم چون توسط برنامه این پلاگین لود میشه این تابع بدرستی کار میکنه و مثلا گفتم اسکریپت رو اجرا کنه که میکنه ولی اگه من این پلاگین رو تو برنامه دیگه لود کنم و بخوام یک اسکریپت رو تو برنامه دیگر که البته هردو با بیلدر ساخته شده هستن اجرا کنم کار نمیکنه البته من هندل اون برنامه رو بدست میارم و به پلاگین میدم ولی کار نمیکنه یکجورایی مثل این میمونه که بیلدر اجازه چنین دسترسی رو به غیر از برنامه خودش نمیده فکر میکنم برای همین هم هست که اجازه ارسال اون مقدار رو به برنامش برای اجرای اسکریپت نمیده , نظر شما چیه دلیل اینکه نمیشه چیه ؟ با تشکر

----------


## ansoft

سلام
آقاي تاجيك با چه كدي ميشه كه پلاگين متن هايي كه از mmb گرفته رو بتونه اينطوري بخونه:
كد mmb
set$='Title|Text|btn|checkbox'
PluginSet("Plugin","set$")
PluginRun("Plugin","MessageBox")


با اين كد همه متن هايي كه به پلاگين ارسال ميشه را در يك بار ارسال به پلاگين ميده و ديگه نميخواد براي هر يك از واژه ها يك ارسالي به پلاگين داشته باشيم.

حالا من ميخوام بدانم كه در دلفي در قسمت messagebox چه كدي بنويسم كه اينها را دريافت كنه؟
لطفا كمي توضيح بديد تا اگر خواستم تعداد set$=Title|Text|btn|checkbox را زياد كنم بتونم.
با تشكر

----------


## javad p

این نمونه کد کمکتون میکنه

 
var
  t1:string;
  t2:array[1..10] of string;
  i,j:Integer;
begin
   t1:=g_String;
   j:=1;
  for i:=1 to Length(t1) do
  begin
 if t1[i]='|' then
 begin
  j:=j+1;
 end
 else
  t2[j]:=t2[j]+t1[i];
 end;


g_String همون set$ هست که پلاگین دریافت میکنه که شما باید با ورودی پلاگینتوم تغییرش بدید
10 هم تعداد تکه هایی هست که براتون میتونه جدا کنه
موفق باشید

----------


## loo30fer

قبلا یک تابع مانند GetArrayItem بیلدر نوشته بودم براتون میذارم:
function GetArrayItem(const TextIn: String; Car: PChar;  const offset: Integer) : String;
var
i,srch: Integer;
begin
for i:=0 to offset do begin
if (i<>offset) then
srch:= PosEx(Car, TextIn+Car,srch+1);
end;
Result:= Copy(TextIn,srch+1,PosEx(Car, TextIn+Car,srch+1)-srch-1);
end;
و نحوه استفاده :
GetArrayItem(TextInput,'|',1)

----------


## ansoft

تشکر
آقای لوسیفر اگه امکان داره بک نمونه مثال کامل با دلفی 7 برام بنویسید . اینجوری نفهمیدم
-
یک سوال دیگه .
چگونه در mmb با پلاگین یک شیء بسازم .
مثلا برای ساخت یک دکمه برنامه عنوان ، موقعیت و ... را دریافت کنه و یک دکمه در mmb بسازه؟

----------


## loo30fer

یک نمونه براتون پیوست کردم.



> چگونه در mmb با پلاگین یک شیء بسازم .


برای ساخت اشیا بدون استفاده از فرم میتونید بدین شکل عمل کنید برای اینکه وقتی از کتابخانه فرم استفاده میکنید پلاگینتون حجم زیادی رو پیدا میکنه.
این hMMBWindow هم متغیر که حاوی هندل پنجره ای است که از پلاگین استفاده میکنه اگه متوجه نشدین یک نگاهی به SDK که جناب تاجیک ضمیمه کردن بندازین و کدها رو بررسی کنید همه چیز دستگیرتون میشه.
var
Button: TButton;
begin
Button:= TButton.Create(nil);
Button.ParentWindow:= hMMBWindow;
end;
موفق باشید.

----------


## javad p

شما با توجه به تازه کار بودنت سخته برات که از کد Button.Create(nil); برای ساخت دکمه استفاده کنی
مخصوصا برای دستور دادن به اون برای بعد
یه دکمه رو فرمت بزار و اونو با پلاگین show و  hide کن

----------


## arash-mmb

با سلام

من آخرش ندونستم اگه همه اینا رو تو دلفی می نویسی ، چطور باید به فایل Dll تبیدلشون کنید؟

----------


## firststep

سلام
اموزش  های اقای عشایری منبع خوبی برای ساخت dll هست
می تونین جستجو کنین

----------


## BORHAN TEC

سلام



> سلام
> اموزش  های اقای عشایری منبع خوبی برای ساخت dll هست
> می تونین جستجو کنین


 به این لینک مراجعه کنید:
http://www.irstu.com/?p=8490
در 5 درس آخر نحوه ساخت و استفاده از dll ها را توضیح داده ام.
موفق باشید...

----------

