رفتن به مطلب

Gdi در دلفی

امتیاز دادن به این موضوع:


king75
 اشتراک گذاری

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

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

ارسال های توصیه شده

GDI مخفف کلمه Graphics Device Interfaceو تکنیک رسم گرافیک دو بعدی ویندوزاست. این روش متاسفانه روش بسیار کندی برای ترسم گرافیکی میباشد ولی بدلیل اینکه اساس برنامه نویسی گرافیک است یاد گیری آن بعنوان پایه برنامه نویسی گرافیک برای برنامه نویسان لازم به نظر

میرسد.اولین نکته قابل توجه در این رابطه این است که نباید سعی کنید از GDI برای ایجاد هر جلوه

خیالی گرافیکی استفاده کنید بدلیل اینکه GDI یک تکنیک ابتدایی در گرافیک است . برای استفاده

حرفه ای از گرافیک سعی کنید از DirectX , OpenGL و ... بهره بگیرید. اگرچه شما با کمی خلاقیت قادر ید جلوه های ساده را با GDI ایجاد کنید .

یکی از کلمات عمومی که در GDI زیاد با آن برخورد خواهید کرد DC (Device Context ) است که نشان دهنده همان ناحیه ای است که ترسیم روی آن صورت میگیرد و در دلفی با TCanvas نشان داده میشود . در واقع DC محل نشان دادن خروجی توابع گرافیکی است . بنابرین شما میتوانید از

برخی توابع ترسیم برای ترسیم در صفحه نمایش یا پرینتر استفاده کنید . نکته دیگری که باید مورد

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

مناسب آماده کرده است. در ابتدا برای آشنایی با سازماندهی GDI با معرفی بعضی از کلاسهای

مهم GDI شروع میکنیم :

Pen : برای رسم خطوط ساده ( مثال آن تابع LineTo است.) و ایجاد کادر برای اشکال دیگر استفاده میشود .

Brush : برای پر کردن یک محیط بسته با رنگ استفاده میشود . مثال آن توابع, FillRect FloodFill.

است .

Font :برای تعیین فونت و اندازه فونت در هر متنی که در ترسیم آن را مینویسید استفاده میشود .

Region : یک ناحیه بسته از فضای ویندوز که میتواند یه بیضی ، چهار ضلعی یا یه دوازه وجهی یا هر چیز دیگری باشد .

خوب ، حالا باید شروع به ترسیم کنیم . ابتدا با خطوط و اشکال ساده شروع میکنیم و بعد به سراغ توابع مورد استفاده در ترسیم Bitmap ها میرویم و در آخر راجع به تکنیکهای ترسیم در صفحه نمایش صحبت میکنیم . قبل از هر چیز باید بدانید که مختصات (0و0) نقطه بالا ، سمت چپ است . اگر یک تجسم ریاضی از مختصات داشته باشید ممکن است کمی گیج شوید . فراموش نکنید که در اینجا Y در بالاترین نقطه صفر و به سمت پایین صفحه نمایش مثبت و X در منتهی الیه سمت چپ صفر و به

سمت راست صفحه نمایش مثبت است . در واقع مختصات اینجا بصورت (ارتفاع از بالا ، فاصله از

چپ) میباشد. مثلا (0,50) یک نقطه در سمت چپ و 50 پیکسل پایین تر از بالای صفحه نمایش است.

خطوط و اشکال

رسم خطوط و اشکال خیلی ساده است. چیزی مهمی که اینجا باید بخاطر داشته باشید تفاوت میان Pen و Brush است. بطور ساده از Pen برای رسم خطوط استفاده میشود اگرچه ممکن است این خطوط یک چهار گوش را تشکیل دهد. ولیBrush درون یک ناحیه ی بسته است که بوسیله خطوط بوجود آمده است. دو تابع برای رسم خطوط وجود دارد که هر دو از متعلقات TCanvas هستند .

MoveTo : با استفاده از این تابع موقعیت قلم را جابجا میکنیم . مثال :

Canvas.MoveTo(75,200);

LineTo : با استفاده از این تابع، از موقعیت فعلی قلم به یک نقطه خاص، خط رسم میکنیم . مثال:

Canvas.LineTo(50,150);

شما میتوانید بجای استفاده از MoveTo موقعیت قلم را بوسیله تابع PenPos هم تغییر بدهید . برای مثال:

Canvas.PenPos.X:=150;

Canvas.PenPos.Y:=100;

یا

Canvas.PenPos:=Point(150,100);

به یاد داشته باشید که موقعیت پیش فرض قلم موقعیت (0,0) میباشد. اگر لازم است خط شما از نقطه دیگه ای شروع شود قبل از استفاده از LineTo باید موقعیت قلم را اصلاح کنید . بعد از استفاده از LineTo موقعیت قلم همان نقطه ای است که خط به آن کشیده شده مثلا بعد از اجرای Canvas.LineTo(100;200); موقعیت قلم نقطه (100,200) خواهد بود. خطوط رسم شده بوسیله

Pen (TPen) در Canvas ایجاد میشود . شما براحتی میتوانید پارامترهای قلم را همانطور که

میخواهید تغییر بدهید. مثلا برای تغییر اندازه قلم Canvas.Pen.Width:=4; و برای تغییر رنگ Canvas.Pen.Color:=clBlack; عمل کنید. یک مثال ساده را ببینیم . یک پروژه جدید ایجاد کنید و یک عدد Button روی آن قرار دهید و کد رویداد کلیک Button را بصورت زیر بنویسید.

procedure TForm1.Button1Click(Sender: TObject);

const NUM_LINES = 2000;

var i:integer;

begin

Randomize;

for i := 0 to NUM_LINES - 1 do

begin

Canvas.Pen.Color :=

RGB(Random(256),Random(256),Random(256));

Canvas.LineTo

(Random(ClientWidth),Random(ClientHeight));

end;

end;

در مثال بالا، 2000 خط با جهت های تصادفی و با رنگهای تصادفی فرم را پر میکند . تابع RGB برای

ایجاد رنگ با تعیین مقادیر قرمز، سبز و آبی مورد استفاده قرار میگیرد. RGB(Red,Green,Blue) . این

مقادیر میتواند مابین 0 تا 255 باشد . این تابع به شما مقداری از نوع TColor بر میگرداند . در این

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

قابل استفاده هستند. چند مورد از پر استفاده ترین آنها به قرار زیرند:

Ellipse : برای رسم بیضی . مثال : Canvas.Ellipse(0,0,100,50); (پارامتر ها به ترتیب : X سمت چپ

بیضی ، X سمت راست بیضی ، Y بالای بیضیی ، Y پایین بیضی)

.

FillRect : پر کردن یک چهارگوش با Brush Color ولی بدون خط دور آن . مثال : Canvas.FillRect

(Bounds(0,0,150,200));

FloodFill : پر کردن یک ناحیه یا Brush Color با ایجاد خطوط لبه مثال : Canvas.FloodFill

(10,10,clBlue,fsBorder);

Rectangle : رسم چهارگوش و پرکردن آن با Brosh Color و خطوط لبه آن با Pen Color . مثال :

Canvas.Rectangle( Bounds(20, 20, 50, 50));

RoundRect : ایجاد چهارگوش با گوشه های منحنی. مثال : Canvas.RoundRect(20, 20, 50, 50, 3, 3);

(تابع Bounds یک مقدار TRect برمیگرداند. TRect چهار مقدار top, left, bottom, right را نگه میدارد.

بجای این تابع میتوانید از Rect هم استفاده کنید که تفاوت چندانی با هم ندارند ) .

یک تابع مفید دیگر هم وجود دارد که برای ایجاد متن به کار میرود . این تابع به شما اجازه میدهد که متن مورد نظر خود را با فونت تعیین شده (Canvas font) ایجاد کنید . مثال :

Canvas.TextOut(20,50,'GDI in Delphi');

شما میتوانید نوع قلم ، رنگ و اندازه قلم را به دلخواه خود تغییر دهید. مثال :

Canvas.Font.Name := 'Verdana';

Canvas.Font.Size := 24;

Canvas.Font.Color := clRed;

در زیر یک مثال را میبینیم که 200 شکل را بصورت تصادفی روی فرم رسم میکند .

procedure TForm1.Button1Click(Sender: TObject);;

const

NUM_SHAPES = 200;

var

i,ShapeLeft,ShapeTop: Integer;

begin

for i := 0 to NUM_SHAPES - 1 do

begin

Canvas.Brush.Color :=

RGB(Random(256),Random(256),Random(256));

ShapeLeft := Random(ClientWidth);

ShapeTop := Random(ClientHeight);

case Random(3) of

0: Canvas.Rectangle(ShapeLeft,

ShapeTop,

ShapeLeft + Random(50),

ShapeTop + Random(50));

1: Canvas.Ellipse(ShapeLeft,

ShapeTop,

ShapeLeft + Random(50),

ShapeTop + Random(50));

2: begin

Canvas.Font.Size := 10 + Random(7);

Canvas.TextOut ( ShapeLeft, ShapeTop, 'Delphi');

end;

end;

end;

end;

در مثال بالا وقتی برنامه را اجرا میکنید فرم برنامه در حال اجرا را کمینه (Minimize) کنید و دوباره آنرا به حالت اول برگردانید . میبینید که خطوط پاک شدند . اصلا نگران نباشید. ناپدید شدن اشکالی که شما رسم کردید یکی از امتیازات مهم GDI است و برمیگردد به تفاوت بین Drawing و Panting.

Drawing: Drawing بهمان صورتی است که در مثال قبل مشاهده فرمودید. گرافیک ایجاد شده بوسیله آن تا وقتی وجود دارد که پنجره Refresh نشده باشد.

Painting: هر گاه یک پنجره نیاز به Refresh شدن دارد ویندوز یک پیام به پنجره مورد نظر ارسال

میکند. این پیام میتواند Handle رویداد OnPaint فرم باشد . پس وقتی شما گرافیک مورد نظر خود را در رویداد OnPaint تعریف کنید جلوه ایجاد شده در هنگام Refresh ناپدید نمیشود. این تفاوت اساسی

بین این دو است. Drawing فقط یک رویداد موقتی است در صورتی که Painting هر گاه پنجره احتیاج به Refresh داشته باشد فرا خونده میشود.

بطور کلی اگه خواسته باشیم در صفحه بوسیله Drawing ترسم را انجام دهیم در حالیکه این

تغییرات موقتی ایجاد شده به نحوی ذخیره شوند چند راه وجود دارد. یک را استفاده از Bitmap است به این صورت که میتوانیم یک Bitmap ایجاد کنیم و این تغییرات را همزمان با صفحه نمایش در

Bitmap هم اعمال کنیم و بعد در زمان لازم این Bitmap را در صفحه نمایش، نمایش بدهیم.

استفاده از Handle ها

اگر چه هنگام استفاده از دلفی شما میتوانید بدون نگرانی از توابع گرافیکی دلفی استفاده کنید با این حال دسترسی شما به API ویندوز، بصورت مستقیم هم به هیچ وجه محدود نشده است. اما برای استفاده از توابع API ویندوز، این توابع از شما HDC میخواهند. اما میدانید HDC چیست؟

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

خصوصیت در خود دارند. مثلا:

Form1.Canvas.Handle

توضیح دستگیره ها در Win32.hlp دلفی به این صورت است:

"An application must obtain an object handle and use this handle to examine or modify the system resource (or both). In the Microsoft® Win32® application programming interface (API), handles are usually implemented as indirect pointers, but this is not always the case."

HDC ها یک نوع دستگیره هستند که مشخص کننده بخشی از فضای زمینه (Device Context) می باشند. همانطور که گفته شد TCanvas بیشترین توابع DC (فضای زمینه) را دارد. کافیست دستگیره TCanvas آبجکت مورد نظر را در توابع API ویندوز استفاده کنید.

Abject .Canvas.Handle

در اینجا برخی از توابع API که معادل VCL آنها گفته شد را ببینید.

VCL

WINDOWS API

Canvas.TextOut(x,y,myString);

TextOut(Canvas.Handle, x, y, PChar(myString), Length(String));

Canvas.FloodFill(X, Y, Color,fsBorder);

ExtFloodFill(Canvas.Handle, x, y, YourColour, FLOODFILLBORDER);

Canvas.LineTo(x,y);

LineTo(Canvas.Handle, x, y);

Canvas.MoveTo(x,y);

MoveToEx(Canvas.Handle, x, y, nil);

بطور کلی توابع بهمان صورت قابل استفاده هستند با این تفاوت که اول باید Handle را پاس کنید. بخاطر داشته باشید که شما میتوانید دستگیره ها متفاوت برای Drawing در محلهای مختلف استفاده کنید. مثلا از Bitmap1.Canvas.Handle برای یک Bitmap و از Form1.Canvas.Handle برای فرم.

دقت داشته باشید که برای استفاده از داده رشته ای در این توابع، داده مورد نظر باید از نوع PChar باشد. (مثلا تابع TextOut()). گاهی ممکن است شما مجبور باشید طول رشته را نیز در تابع وارد کنید که در این صورت کافیست از تابع Length استفاده کنید.

Bitmap چیست؟

رسم خطوط و اشکال به روش فوق روش مفیدی است ولی توانایی شما برای رسم عکسها مستلزم شناخت و استفاده از Bitmap هاست.

آبجکتی که معمولا برای رسم تصاویر استفاده میشود Bitmap است. Bitmap یک آبجکت گرافیکی است که دارای دو قسمت میباشد 1- هدری شامل اطلاعات مهمی درباره تصویر است (شامل طول، ارتفاع، اطلاعات رنگ و...) 2- بخشی که شامل داده های خود تصویر است (شامل یک آرایه بزرگ ار رنگ هر پیکسل). خوشبختانه شما نباید برای استفاده از Bitmap هیچ نگرانی داشته باشید بدلیل اینکه کلاس Bitmap از قبل در دلفی وجود داشته که TBitmap نامیده میشود. Bitmap ها خارق العاده هستند، آنها به ما آزادی عمل خیلی زیادی نسبت به خطوط و اشکال میدهند. شما حتی میتوانید Bitmap ها را بوسیله برنامه مورد نظرتان ایجاد نمایید و در برنامه خودتان از آنها استفاده نمایید. لازم است اول یک مثال از استفاده از Bitmap ها ببینیم.

procedure Form1.DrawBitmap(const Filename: String; const x,y: Integer);

var

Bmp: TBitmap;

begin

if not FileExists(Filename) then

begin

ShowMessage('The bitmap ' + Filename + ' was not found!');

Exit;

end;

Bmp := TBitmap.Create;

try

Bmp.LoadFromFile(Filename);

Canvas.Draw(x, y, Bmp);

finally

Bmp.Free;

end;

end;

این تابع سعی در نمایش دادن تصویر Filename روی فرم در موقعیت (x,y) دارد. اگر شما قصد ندارید آبجکت های مورد نظر را در زمان راه اندازی (Run-Time) ایجاد کنید من شدیدا استفاده از اشاره گرها را توصیه میکنم. بهر حال در بالای رویه، Bitmap را ایجاد کنید و تصویر مورد نظر را در آن لود نمایید. استفاده از بلوک Try … Finally هم شما را از عدم ایجاد خطا مطمئن مینمایید حتی در صورت وجود فایل با فرمت نا معتبر. روش استفاده شده در مثال بالا همیشه موثر نیست. این روش ابتدا وجود فایل را چک میکند سپس Bitmap را ایجاد کرده و پس از استفاده آزاد میکند. یک روش بهتر برای استفاده و نمایش تصویر، ایجاد Bitmap و لود کردن تصویر در FormCreate و آزاد کردن آن در FormDestory است. این روش موثر تر است و در سراسر عمل قابل دسترسی است.

توابع رسم در GDI

TCanvas توابع رسم زیادی دارد که همه آنها با TGraphic سر و کار دارند. TGraphic کلاس پایه آبجکت های گرافیکی در دلفی است. برخی از مثال های آن عبارتند از: TBitmap برای Bitmap ها، Ticon برای icon ها، TMetafile برای Metafile ها و TJPEGImage برای JPEG ها. در زیر لیست سایر تابع رسم در GDI را میبینید.(تمام این توابع متدهای Tcanvas هستند.)

نام

توضیح

مثال

Draw

رسم تصویر در نقطه مورد نظر.

Canvas.Draw(5,10,MyGraphic);

StrechDraw

رسم تصویر در محدوده مورد نظر با ایجاد وضعیت ارتجاعی.

Canvas.StretchDraw( Bounds(0,0,32,32), MyGraphic);

CopyRect

کپی کردن بخشی از یک Tcanvas به دیگری و ایجاد حالت ارتجاعی در صورت لزوم

Canvas.CopyRect( Bounds(0,0,32,32), MyBmp.Canvas, Bounds(0, 0, 640, 480));

همه این توابع راحت و آسان هستند اگرچه تابعی که در زیر با آن آشنا میشوید کمی مشکل تر است و نیاز به دقت بیشتری دارد. این تابع BitBlt است.

function BitBlt(

hdcDest: HDC; // handle to destination device context

nXDest, // x-coordinate of destination rectangle's upper-left corner

nYDest, // y-coordinate of destination rectangle's upper-left corner

nWidth, // width of destination rectangle

nHeight: Integer; // height of destination rectangle

hdcSrc: HDC; // handle to source device context

nXSrc, // x-coordinate of source rectangle's upper-left corner

nYSrc: Integer; // y-coordinate of source rectangle's upper-left corner

dwRop: DWORD // raster operation code

): Boolean;

همانطور که میبینید این تابع برای ترسیم تصویر یک DC در محدوده یک DC دیگر است. درک این تابع کمی مشکل به نظر میرسد ولی با وجود Canvas.Draw شما احتمالا نیازی به استفاده از این تابع

پیدا نخواهید کرد. برای درک بهتر این تابع به مثال زیر توجه فرمایید.

procedure TForm1.Button1Click(Sender: TObject);

var MyBitmap:TBitmap;

begin

MyBitmap:=TBitmap.Create;

MyBitmap.Width:=Screen.Width;

MyBitmap.Height:=screen.Height;

BitBlt(MyBitmap.canvas.handle, 0, 0, MyBitmap.width, MyBitmap.height, GetDC(0),0,0,Srccopy);

image1.Picture.Bitmap:= MyBitmap;

MyBitmap.Free;

end;

در مثال بالا برنامه بوسیله این تابع از صفحه نمایش عکس گرفته و در Image1 نمایش داده میشود. از تابع GetDC برای بدست آوردن دستگیره فضای زمینه یک ناحیه که Handle آن را داریم استفاده

میکنیم. در این مثال برای اشاره به تمامی صفحه نمایش مقدار صفر را در تابع GetDC قرار میدهیم

.

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

موارد استفاده از TImage و تنظیم کردن خاصیت Picture آن در زمان طراحی، برای نمایش تصویر از زمان راه اندازی است. این روش گذشته از دقت در محل روی فرم، حرکت دادن تصویر روی فرم را در زمان اجرا آسانتر میکند.

لینک به دیدگاه
به اشتراک گذاری در سایت های دیگر

  • پاسخ 0
  • ایجاد شد
  • آخرین پاسخ

بهترین ارسال کنندگان این موضوع

روزهای محبوب

بهترین ارسال کنندگان این موضوع

در تاپیک ها، اگر سوال يا نظر خاصي نداريد لطفا فقط از دکمه می پسندم و ... استفاده کنيد. نظراتي مانند مرسی، خوب بود، ممنون و ... شامل اسپم هستند و باعث کاهش کيفيت پست ها مي شوند.

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

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

به گفتگو بپیوندید

هم اکنون می توانید مطلب خود را ارسال نمایید و بعداً ثبت نام کنید. اگر حساب کاربری دارید، برای ارسال با حساب کاربری خود اکنون وارد شوید .

مهمان
ارسال پاسخ به این موضوع ...

×   شما در حال چسباندن محتوایی با قالب بندی هستید.   حذف قالب بندی

  تنها استفاده از 75 اموجی مجاز می باشد.

×   لینک شما به صورت اتوماتیک جای گذاری شد.   نمایش به صورت لینک

×   محتوای قبلی شما بازگردانی شد.   پاک کردن محتوای ویرایشگر

×   شما مستقیما نمی توانید تصویر خود را قرار دهید. یا آن را اینجا بارگذاری کنید یا از یک URL قرار دهید.

 اشتراک گذاری

×
×
  • اضافه کردن...