ورود

View Full Version : قرار دادن عکس در DLL و استفاده از آن موقع اجرا



MOJTABAATEFEH
چهارشنبه 16 تیر 1389, 11:48 صبح
دوستان عزیز سلام
لطفا روش قرار دادن عکس در DLL رو در دلفی بفرمایید به طوری که موقع اجرا بشه از این عکس ها استفاده کرد و در یک Image اون ها رو لود کرد

با تشکر

Felony
چهارشنبه 16 تیر 1389, 15:04 عصر
عکس ها رو به صورت Resource در فایل DLL ذخیره کنید ، در مورد فایل های ریسورس هم بارها بحث شده .

Mahmood_M
چهارشنبه 16 تیر 1389, 15:05 عصر
قرارد ادن فایلهای رسورس درون یک DLL با قرار دادن رسورس درون یک فایل EXE تفاوتی نمیکنه ، یک فایل رسورس بسازید و عکستون رو درونش قرار بدید ، بعد یک پروژه از نوع DLL بسازید و فایل رسورس ساخته شده رو همراه اون کامپایل کنید ( مثل یک فایل EXE ) ، بعد از کامپایل فایل رسورس که حاوی تصویر هست درون DLL قرار میگیره و بعد می تونید ازش استفاده کنید ، این مقاله (http://barnamenevis.org/forum/showthread.php?t=187090) کمکتون می کنه ...

دستورات درون DLL تون در نهایت چیزی شبیه به این میشه :
library MyDLL;

{$R MyRes.RES}

begin
end.

که MyRes.Res هم نام فایل رسورسی هست که فایل تصویر درونش قرار داره ...

برای استفاده از DLL ساخته شده ، اول باید با LoadLibrary اون رو لود کنید ، این تابع بعد از لود DLL ، هندل اون و سایر رسورسها و ... درون اون رو به عنوان یک Module یا Library برمیگردونه ، با داشتن هندل اون می تونید از محتویات اون استفاده کنید
مثلا اگه یک تصویر Bitmap درون DLL قرار داده شده باشه می تونید به صورت زیر اون رو لود کنید :
var
MyBitmap : HBITMAP;
H : THandle;
begin
H := LoadLibrary('MyDLL.dll');
try
MyBitmap := LoadBitmap(H, 'BITMAP');
finally
FreeLibrary(H);
end;
end;

وقتی یک فایل Resource رو همراه فایل اجرایی اصلی برنامه کامپایل می کنید ، فایل رسورس به عنوان بخشی از کل Module فایل اجرایی در میاد و با اجرای برنامه کل ماژول که فایل رسورس هم جزء اون هست لود میشه و میتونید ازش استفاده کنید ولی وقتی فایل رسورس درون یک DLL باشه با شروع به کار فایل اجرایی اصلی برنامه لود نمیشه ، پس باید ابتدا DLL رو که شامل فایل رسورس هست لود کنید و بعد به محتویات رسورس دسترسی داشته باشید ...

موفق باشید ...

MOJTABAATEFEH
چهارشنبه 16 تیر 1389, 17:06 عصر
قرارد ادن فایلهای رسورس درون یک DLL با قرار دادن رسورس درون یک فایل EXE تفاوتی نمیکنه ، یک فایل رسورس بسازید و عکستون رو درونش قرار بدید ، بعد یک پروژه از نوع DLL بسازید و فایل رسورس ساخته شده رو همراه اون کامپایل کنید ( مثل یک فایل EXE ) ، بعد از کامپایل فایل رسورس که حاوی تصویر هست درون DLL قرار میگیره و بعد می تونید ازش استفاده کنید ، این مقاله (http://barnamenevis.org/forum/showthread.php?t=187090) کمکتون می کنه ...

دستورات درون DLL تون در نهایت چیزی شبیه به این میشه :
library MyDLL;

{$R MyRes.RES}

begin
end.

که MyRes.Res هم نام فایل رسورسی هست که فایل تصویر درونش قرار داره ...

برای استفاده از DLL ساخته شده ، اول باید با LoadLibrary اون رو لود کنید ، این تابع بعد از لود DLL ، هندل اون و سایر رسورسها و ... درون اون رو به عنوان یک Module یا Library برمیگردونه ، با داشتن هندل اون می تونید از محتویات اون استفاده کنید
مثلا اگه یک تصویر Bitmap درون DLL قرار داده شده باشه می تونید به صورت زیر اون رو لود کنید :
var
MyBitmap : HBITMAP;
H : THandle;
begin
H := LoadLibrary('MyDLL.dll');
try
MyBitmap := LoadBitmap(H, 'BITMAP');
finally
FreeLibrary(H);
end;
end;

وقتی یک فایل Resource رو همراه فایل اجرایی اصلی برنامه کامپایل می کنید ، فایل رسورس به عنوان بخشی از کل Module فایل اجرایی در میاد و با اجرای برنامه کل ماژول که فایل رسورس هم جزء اون هست لود میشه و میتونید ازش استفاده کنید ولی وقتی فایل رسورس درون یک DLL باشه با شروع به کار فایل اجرایی اصلی برنامه لود نمیشه ، پس باید ابتدا DLL رو که شامل فایل رسورس هست لود کنید و بعد به محتویات رسورس دسترسی داشته باشید ...

موفق باشید ...

ممنون آقا محمود حالا چطور می تونم لیست نام عکسهایی رو که در DLL گذاشتم در یک Combobox نمایش بدم که کاربر بتونه انتخاب کنه؟
و اینکه چطور می تونم از فایل های jpg استفاده کنم؟

با تشکر

SAASTN
چهارشنبه 16 تیر 1389, 22:27 عصر
ممنون آقا محمود حالا چطور می تونم لیست نام عکسهایی رو که در DLL گذاشتم در یک Combobox نمایش بدم که کاربر بتونه انتخاب کنه؟
خوب وقتی قراره از قبل عکس ها رو توی برنامه قرار بدید یعنی تعدادشون مشخصه، پس فقط کافیه Item های ComboBox رو تو Design مقدار دهی کنید! توی OnChangeش هم می نویسید:
const
BitmapNames : array [0 .. BitmapCount - 1 ] of string = ('Bitmap1', 'Bitmap2', .. 'BitmapN');
var
MyBitmap: HBITMAP;
H: THandle;
begin
H := LoadLibrary('MyDLL.dll');
try
MyBitmap := LoadBitmap(H, BitmapNames[ComboBox1.ItemIndex]);
finally
FreeLibrary(H);
end;
end;

و اینکه چطور می تونم از فایل های jpg استفاده کنم؟
یونیت JPEG رو uses کنید.

MOJTABAATEFEH
پنج شنبه 17 تیر 1389, 17:37 عصر
خوب وقتی قراره از قبل عکس ها رو توی برنامه قرار بدید یعنی تعدادشون مشخصه، پس فقط کافیه Item های ComboBox رو تو Design مقدار دهی کنید! توی OnChangeش هم می نویسید:
const
BitmapNames : array [0 .. BitmapCount - 1 ] of string = ('Bitmap1', 'Bitmap2', .. 'BitmapN');
var
MyBitmap: HBITMAP;
H: THandle;
begin
H := LoadLibrary('MyDLL.dll');
try
MyBitmap := LoadBitmap(H, BitmapNames[ComboBox1.ItemIndex]);
finally
FreeLibrary(H);
end;
end;

یونیت JPEG رو uses کنید.

ممنون دوست عزیز ولی می خوام بتونم هر چند وقت این فایل DLL حاوی عکس ها رو عوض کنم بدون اینکه با خود برنامه کاری داشته باشم (Update) پس تعداد عکس ها از قبل مشخص نیست

سوال دوم هم منظورم استفاده از jpg در فایل های ریسورس بود

با تشکر

vcldeveloper
پنج شنبه 17 تیر 1389, 22:43 عصر
سوال دوم هم منظورم استفاده از jpg در فایل های ریسورس بود
Resource رو به صورت RC_DATA ذخیره کنید.

SAASTN
جمعه 18 تیر 1389, 09:18 صبح
ممنون دوست عزیز ولی می خوام بتونم هر چند وقت این فایل DLL حاوی عکس ها رو عوض کنم بدون اینکه با خود برنامه کاری داشته باشم (Update) پس تعداد عکس ها از قبل مشخص نیست
خوب پس DLL قراره تغییر کنه؟
یه راه اینه که توی DLLی که ریسورس عکس ها قرار داره سه تابع هم تعریف کنید، مثل:

function GetPicturesCount: Integer;
function GetPictureName(const Index: Integer): string;
function GetPictureResourceName(const Index: Integer): string;
تابع اول تعداد عکس ها رو برمی گردونه، تابع اسم عکس ها رو برای پرکردن ComboBox و تابع سوم نام ریسورس مربوط به هر کدوم از عکس ها رو.
توی OnCreate فرم برای پر کردن ComboBox می نویسی:
for I := 0 to GetPicturesCount - 1
ComboBox1.Items.Add(GetPictureName(I));

OnChange هم به شکل زیر تغییر می کنه:
var
MyBitmap: HBITMAP;
H: THandle;
begin
H := LoadLibrary('MyDLL.dll');
try
MyBitmap := LoadBitmap(H, GetPictureResourceName(ComboBox1.ItemIndex));
finally
FreeLibrary(H);
end;
end;

MOJTABAATEFEH
یک شنبه 20 تیر 1389, 10:37 صبح
Resource رو به صورت RC_DATA ذخیره کنید.

ممنون آقای کشاورز ولی تو مقاله ای که آقای محمود مهری روی سایت قرار دادن فایل بایستی ذخیره بشه و لی من نمی خوام فایل رو روی کامپیوتر کاربر ذخیره کنم (از فایل DLL خارج کنم)

با تشکر

MOJTABAATEFEH
یک شنبه 20 تیر 1389, 10:39 صبح
خوب پس DLL قراره تغییر کنه؟
یه راه اینه که توی DLLی که ریسورس عکس ها قرار داره سه تابع هم تعریف کنید، مثل:

function GetPicturesCount: Integer;
function GetPictureName(const Index: Integer): string;
function GetPictureResourceName(const Index: Integer): string;تابع اول تعداد عکس ها رو برمی گردونه، تابع اسم عکس ها رو برای پرکردن ComboBox و تابع سوم نام ریسورس مربوط به هر کدوم از عکس ها رو.
توی OnCreate فرم برای پر کردن ComboBox می نویسی:
for I := 0 to GetPicturesCount - 1
ComboBox1.Items.Add(GetPictureName(I));

OnChange هم به شکل زیر تغییر می کنه:
var
MyBitmap: HBITMAP;
H: THandle;
begin
H := LoadLibrary('MyDLL.dll');
try
MyBitmap := LoadBitmap(H, GetPictureResourceName(ComboBox1.ItemIndex));
finally
FreeLibrary(H);
end;
end;

ممنون دوست عزیز لطفا کد تابع ها رو بنویسید

با تشکر

vcldeveloper
یک شنبه 20 تیر 1389, 12:57 عصر
ممنون آقای کشاورز ولی تو مقاله ای که آقای محمود مهری روی سایت قرار دادن فایل بایستی ذخیره بشه و لی من نمی خوام فایل رو روی کامپیوتر کاربر ذخیره کنم (از فایل DLL خارج کنم)
این ربطی به چیزی که پرسیدید، و بهش جواب داده شد، نداره! پرسیدید چطور می تونید فایل JPEG را به صورت Resource ذخیره کنید، جواب گرفتید که باید نوع Resource را RC_DATA تعریف کنید.

این سوالی که الان مطرح کردید، ربطی به اون مورد بالا نداره. برای استفاده از یک Resource بدون ذخیره آن در فایل، می تونید از TResourceStream استفاده کنید.

MOJTABAATEFEH
یک شنبه 20 تیر 1389, 20:52 عصر
خوب پس DLL قراره تغییر کنه؟
یه راه اینه که توی DLLی که ریسورس عکس ها قرار داره سه تابع هم تعریف کنید، مثل:

function GetPicturesCount: Integer;
function GetPictureName(const Index: Integer): string;
function GetPictureResourceName(const Index: Integer): string;تابع اول تعداد عکس ها رو برمی گردونه، تابع اسم عکس ها رو برای پرکردن ComboBox و تابع سوم نام ریسورس مربوط به هر کدوم از عکس ها رو.
توی OnCreate فرم برای پر کردن ComboBox می نویسی:
for I := 0 to GetPicturesCount - 1
ComboBox1.Items.Add(GetPictureName(I));

OnChange هم به شکل زیر تغییر می کنه:
var
MyBitmap: HBITMAP;
H: THandle;
begin
H := LoadLibrary('MyDLL.dll');
try
MyBitmap := LoadBitmap(H, GetPictureResourceName(ComboBox1.ItemIndex));
finally
FreeLibrary(H);
end;
end;

دوست عزیز لطفا متن توابع رو بنویسید چطور لیست عکس ها رو در کمبوباکس قرار بدم


با تشکر

SAASTN
یک شنبه 20 تیر 1389, 21:11 عصر
دوست عزیز لطفا متن توابع رو بنویسید چطور لیست عکس ها رو در کمبوباکس قرار بدم
مراقب باشید که به مصرف گرایی مبتلا نشید.
const
PicturesCount = N;
PictureNames : array [0 .. N - 1] of string =
('PName1', 'PName2, .. , 'PNameN');
PictureResourceNames : array [0 .. n - 1] of string =
('RName1', 'RName2, .. , 'RNameN');' +
'
function GetPicturesCount: Integer;
begin
Result := PicturesCount;
end;

function GetPictureName(const Index: Integer): string;
begin
Result := PictureNames[Index];
end;

function GetPictureResourceName(const Index: Integer): string;
begin
Result := PictureResourceNames[Index];
end;

exports
GetPicturesCount, GetPictureName, GetPictureResourceName;

MOJTABAATEFEH
یک شنبه 20 تیر 1389, 21:48 عصر
مراقب باشید که به مصرف گرایی مبتلا نشید.
const
PicturesCount = N;
PictureNames : array [0 .. N - 1] of string =
('PName1', 'PName2, .. , 'PNameN');
PictureResourceNames : array [0 .. n - 1] of string =
('RName1', 'RName2, .. , 'RNameN');' +
'
function GetPicturesCount: Integer;
begin
Result := PicturesCount;
end;

function GetPictureName(const Index: Integer): string;
begin
Result := PictureNames[Index];
end;

function GetPictureResourceName(const Index: Integer): string;
begin
Result := PictureResourceNames[Index];
end;

exports
GetPicturesCount, GetPictureName, GetPictureResourceName;



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

به هر حال ممنون و موفق باشید

MOJTABAATEFEH
یک شنبه 20 تیر 1389, 22:53 عصر
برای تابعی که اطلاعات رو در کمبوباکس می نویسه چون فراخوانی stdcall خطا می گیره از فراخوانی پیش فرض استفاده کردم همه چیز درست انجام میشه و اطلاعات در کمبو قرار می گیره ولی در نهایت پیغام زیر رو میده


Invalid Pointer Operation


به نظر دوستان مشکل از کجا می تونه باشه؟

با تشکر

Mahmood_M
دوشنبه 21 تیر 1389, 03:16 صبح
برای استفاده از رشته ها در DLL باید یک سری موارد رو رعایت کنید ، برای آشنایی بیشتر و بهتر با نحوه ی به کارگیری رشته ها در DLL بهتره این مقاله ی دو صفحه ای (http://delphi.about.com/od/objectpascalide/l/aa103003a.htm) رو مطالعه کنید ، اگر کمکتون نکرد ، دستوراتی که نوشتید رو در اینجا قرار بدید تا اصلاح بشه ، به نظر میرسه مشکل به خاطر عدم فراخوانی StdCall هست ، از فراخوانی StdCall چه خطایی میگیره ؟

SAASTN
دوشنبه 21 تیر 1389, 05:43 صبح
نه دوست عزیز اینجور نیست اگر توی سایت نگاه کنید و کارکرد من رو ببینید متوجه می شید
خوشحالم که اینطور نیست و ازتون عذر می خوام، ولی دلیل اینکه من اون مطلب رو گفتم این بود که همونطور که دیدید توی کدی که گذاشتم هیچ مسئله تکنیکی یا الگوریتم پیچیده ای وجود نداشت و با کمی فکر می شد بهش رسید.

ولی در نهایت پیغام زیر رو میده
برای پر کردن ComboBox حلقه باید از 0 تا GetPicturesCount -1 بره، درست رعایت کردید؟

MOJTABAATEFEH
دوشنبه 21 تیر 1389, 08:25 صبح
برای پر کردن ComboBox حلقه باید از 0 تا GetPicturesCount -1 بره، درست رعایت کردید؟این مورد رو رعایت کردم

آقای مهری در صورت استفاده از stdcall پیغام ضمیمه رو میده

متن برنامه :




//DLL

const
PicturesCount = 4;
PictureNames: array [0 .. PicturesCount - 1] of string = ('1P' , '2P' , '3P' , '4P');

PictureResourceNames : array [0 .. PicturesCount - 1] of string = ('Pic1' , 'Pic2' , 'Pic3' , 'Pic4');

function GetPicturesCount: Integer;
begin
Result := PicturesCount;
end;

function GetPictureName(const Index: Integer): string;
begin
Result := PictureNames[Index];
end;

function GetPictureResourceName(const Index: Integer): string;
begin
Result := PictureResourceNames[Index];
end;

exports
GetPicturesCount, GetPictureName, GetPictureResourceName;




//Form
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i := 0 to GetPicturesCount - 1 do
ComboBox1.Items.Add(GetPictureResourceName(i));
end;

با تشکر

SAASTN
دوشنبه 21 تیر 1389, 22:43 عصر
آقای مهری در صورت استفاده از stdcall پیغام ضمیمه رو میده
این خطا چیز خاصی رو توضیح نمی ده، هر نوع دسترسی غیر مجاز حافظه ای همچین خطایی رو به دنبال داره.

MOJTABAATEFEH
شنبه 26 تیر 1389, 21:33 عصر
آقای مهری از Delphi.About.com چیز زیادی دستگیرم نشد لطفا روش تصحیح رو بفرمایید
کسی تابحال مشابه این روش رو انجام نداده؟

با تشکر