منتخب بازارچه

Windows GDI

littlerabbit

مدیر بازنشسته
کاربر فعال
تاریخ عضویت
13 جولای 2003
نوشته‌ها
667
لایک‌ها
5
سن
38
محل سکونت
Iran
به نقل از Niloufar :
ممنون ميشم

اين مشخصه DC چيه؟ لطفا همانطور كه فرموديد يه نيمچه سورسكي بذاريد. ممنون
در ویندوز همه عناصر ویژوال برای نمایش خود از یک شی به نام DC یا Device Context استفاده میکنند. در دلفی شی TCanvas شی DC ویندوز را مدیریت میکند.
ام این DC پیست؟ DC به زبان خیلی ساده یک DC یک بوم نقاشی است که کنترل هنگامی که پیغام WM_PAINT و پیغامهای مرتبط با این پیغام را دریافت میکند بایستی خود را در این بوم بکشد.

در اکثر زبانهای برنامه نویسی دو نوع کنترل پشتیبانی میشوند. گروه اول که به پنجره مخسوب میشوند و هر کدام یک دستگیره دارند. (یک Handle ) مثل یک دکمه یا یک List . این عناصر برای خود یک DC مستقل دارند. به عبارتی همه پنجره ها یک DC دارند. این DC را میتوان خیلی ساده و با استفاده از تابع GetDC گرفت (برای اطلاعات بیشتر به MSDN مراجعه کنید- در این پست بیشتر آشنایی با مفاهیم مد نظر است نه معرفی کامل توابع - شاید در پستهای بعدی. )
اما بعضی زبانهای برنامه نویسی مثل وی بی و دلفی کنترلهایی دارند که Window Less هستند یا به عبارتی Handle ندارند. این کنترلها کنترلهای مستقلی نیستند و جزیی از کنترل والد محسوب میشوند و DC مستقلی ندارند و زبان برنامه نویسی یک DC مجازی که در حقیقت یک برش از DC کنترلی است که اینها جزئی از آن هستند را در اختیار شما میگذارد. کنترل هایی شبیه Label در هر دو زبان. (در دلفی به طور عمومی کنترلهای خانواده TGraphicalControl )
این DC ها مستقل نیستند و در صورتی که جز خصایص یک کنترل نباشند راه ساده ای برای گرفتن آنها نیست. (برای پنجره ها به راحتی و با همان تابع که گفتم میتوان این کار را انجام داد)
اما در اینجا مفاهیم زیاد دیگری مطرح میشود. دو مفهوم اولیه Brush و Pen هستند. بعد مفاهیم دیگری نظیر Font و Region و ROP مطرح میشوند.
1- Brush

این عنصر چیزی شبیه قلم مو است. به عبارتی هر DC یک Brush دارد که این Brush میتواند با تابع SelectObject عوض شود (این تابع را هم بعدا توضیح میدهیم ) یک Brush چند خصیصه مهم دارد. یکی الگوی نقاشی است. الگویی که میتواند حالتهای مختلفی داشته باشد. از حالت جامد (توپر) تا Hash (خط خطی) وقتی شما یک شی را با یکی از توابع مورد نظر خودتان نقاشی میکنید آن شی اگر تو پر باشد با این Brush رنگ خواهد شد. مثلا اگر یک Brush به صورت Solid داشته باشید و یک دایره بکشید آن دایره به صورت Solid پر میشود.

2- Pen
این عنصر شباهت زیادی به Brush دارد اما برای نقاشی حاشیه ها استفاده میشود (نمیدانم شاید حاشیه واژه مناسبی نباشد) بهتر است بگویم خطهای مرزی. مثلا وقتی یک دایره میکشید خود دایره (و نه داخل آن) با Pen فعلی DC نقاشی میشود.

3- Font
این یکی که به اندازه کافی تابلو هست!!!

4 - Region

این مفهوم ، به نوعی برشی از یک DC را نشان میدهد. به عبارتی یک DC همیشه به صورت مستطیل است اما این Region آن را میتواند به تکه های غیر مستطیلی تقسیم کند (روشی که شما میتوانید فرمتان را از حالت استاندارد و مربعی خارج کنید) یا هر کنترل دیگزی را.

4- ROP
این یک مفهوم مستقل نیست و این اسم اسم رسمی آن محسوب نمیشود چون تابع SetROP2 برای تغییر آن استفاده میشود من عنوان ROP را برای آن انتخاب کرده ام. این به معنی طریقه ترکیب دو خط (یا محدوده ) با هم است.. مثلا فرض کنید اگر در حالت XOR باشید و یک شکل را دوبار در یک جا نقاشی کنید دفعه دوم شی پاک میشود.

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

1- GetDC
کد:
HDC GetDC(
  HWND hWnd   // handle to window
);
این تابع یک دستگیره به یک پنجره میگیرد و DC آن پنجره را برمیگرداند. چند نکته در مورد این تابع مهم است: این تابع Single Thread ست و DC گرفته شده نباید در یک Thread دیگر استفاده شود.
این تابع DC مربوط به Client Area را برمیگرداند.
اگر به جای آرگومان عدد صفر پاس داده شود DC کل صفحه نمایش برگردانده میشود. (تمام صفحه) البته بهتر اینست که اول توسط تابع
کد:
HWND GetDesktopWindow(VOID);
دستگیره Desktop گرفته شده و سپس آن را به این تابع پاس بدهید.
بعد از پایان کار با DC باید DC گرفته شده را با کمک تابع
کد:
int ReleaseDC(
  HWND hWnd,  // handle to window
  HDC hDC     // handle to DC
);
آزاد کرد. این فوق العاده مهم است _خصوصا در ویمندوزهای 9X ) آرگومان اول همان است که به تابع GetDC فرستاده شده و آرگومان دوم بازگشتی تابع GetDC است .
تابع دیگری که امروز احتیاج است تابع
کد:
BOOL BitBlt(
  HDC hdcDest, // handle to destination DC
  int nXDest,  // x-coord of destination upper-left corner
  int nYDest,  // y-coord of destination upper-left corner
  int nWidth,  // width of destination rectangle
  int nHeight, // height of destination rectangle
  HDC hdcSrc,  // handle to source DC
  int nXSrc,   // x-coordinate of source upper-left corner
  int nYSrc,   // y-coordinate of source upper-left corner
  DWORD dwRop  // raster operation code
);
است. این تابع یک قسمت از یک DC را در DC دیگر کپی میکند. آرگومانها به ترتیب : DC مقصد (جایی که باید تصویر در آن کپی شود) دومی و سومی به ترتیب X و Y گوشه بالا سمت راست مربعی است که قرار است تصویر در آن قرار بگیرد (با ابن تابع میتوان یک مستطیل را در یک مستطیل در یک DC دیگر با نسبت 1 به 1 کپی کرد ) چهار و پنج عرض و ارتفاع مستطیل آرگومان ششم DC مبدا است آرگومانهای 7 و 8 X, Y مستطیل lمبدا است (طبیعی است که طول و عرض همان طول و عرض مقصد است و نیازی به فرستادن دوباره آنها نیست چون این تابع به صورت 1 به 1 کپی میکند.) آرگومان آخر نحوه کپی را نشان میدهد. لیست معتبر برای آرگومان آخر را در MSDN ببینید.برای منظور ما SRCCPY کافیست (مبدا را عینا در مقصد کپی میکند)
من یک برنامه کوچک نوشته ام که از صفحه Desktop عکس میگیرد و آنرا اینجا میگذارم و توضیح میدهم. چون کد وی بی با دلفی کمی متفاوت است هر دو را جداگانه توضیح میدهم.

1- VB
کد:
'Snap window for VB
'Author : Forud
'Create Date : 1381/6/5
'Add Comment in 1381/6/6
'If this code works, it was written by me.
'   If not, I don't know who wrote it.
'               Cyber Rabbit
'           >:)---->:|:<----(:<
' http://cyberrabbits.net
Option Explicit
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal XSrc As Long, ByVal YSrc As Long, ByVal dwRop As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long

'Snap desktop and save it in Windows temp path.Only load and unload this form.
Private Sub Form_Load()

    Dim X As Long, Y As Long
    Dim XSrc As Long, YSrc As Long
    Dim dwRop As Long, hwndSrc As Long, hSrcDC As Long
    Dim Res As Long
    ScaleMode = vbPixels
    Move -1, -1, Screen.Width + 1, Screen.Height + 1
    dwRop = &HCC0020  'SRCCPY
    hwndSrc = GetDesktopWindow()
    hSrcDC = GetDC(hwndSrc)
    Res = BitBlt(hdc, 0, 0, ScaleWidth, _
    ScaleHeight, hSrcDC, 0, 0, dwRop)
    Res = ReleaseDC(hwndSrc, hSrcDC)
    Show
    SavePicture Image, App.Path & "\Snap.bmp"
    End
End Sub
در گام اول فرم را به اندازه کل صفحه در می آوریم بعد از گرفتن دستگیره دسکتاپ با تابع GetDC هم DC آن را میگیریم.بعد با تابع BitBlt تمام DC دسکتاپ را در DC فرم کپی میکنیم. دقت کنید چون خود وی بی خصیصه DC فرم را دارد (hDC) بنابر این نیازی نیست که با تابع GetDC آن را دوباره بگیرید (گر چه غلط هم نیست)
در مرحله آخر عکس روی فرم را ذخیره میکنیم.

2- دلفی
کد:
program GetScrnBmp;

uses
  Windows, Graphics;

var
  B                 : TBitmap;
  Dc                : HDC;
  HWndDesk          : HWND;
begin

  B := TBitmap.Create;

  B.Width := GetSystemMetrics(SM_CXSCREEN); {Screen.Width}
  B.Height := GetSystemMetrics(SM_CYSCREEN); {Screen.Height}
  HWndDesk := GetDesktopWindow;
  Dc := GetDc(HWndDesk);
  try
    BitBlt(B.Canvas.handle, 0, 0, B.Width, B.Height, GetDc(0), 0, 0, SRCCOPY);
  finally
    ReleaseDC(HWndDesk, Dc);
  end;
  B.SaveToFile('Screen.bmp');
  B.Free;
end.
این یکی کمی ساده تر از وی بی است. چون دلفی اشیای جالبی چون TBitmap را دارد دیگر نیازی به وجود یک فرم نیست. یک BitMap ایجاد شده و در DC این Bitmap نقاشی میشود. بقیه مراحل دقیقا شبیه همان نسخه وی بی است. تا یادم نرفته برای گرفتن دستگیره یک DC در دلفی از Canvas.Handle استفاده کنید.
 

littlerabbit

مدیر بازنشسته
کاربر فعال
تاریخ عضویت
13 جولای 2003
نوشته‌ها
667
لایک‌ها
5
سن
38
محل سکونت
Iran
کسی چیزی در این باره نمیدونه بحثو ادامه بده؟؟؟ حسابی ذوقم خشکید!!!! دست کم یکی یه تابعی چیزی رو از MSDN ترجمه کنه. مثلا StretchBlt یا MaskBlt یا FloodFillیا هر چیز دیگه . شما یکی بنویسید من 3 تا !!! فقط بنویسید! نذارید اینم مثل بقیه ..... باشه که یه کاری رو دسته جمعی انجام داده باشیم.

اینم بگم من اینا رو بلدم به اندازه خودم . فقط دوست دارم اینجا از این حالت مرده در بیاد.
 

webbi

Registered User
تاریخ عضویت
1 ژانویه 2007
نوشته‌ها
87
لایک‌ها
1
محل سکونت
Tehran
ممنون از این پست.

دو سوال در باره GDI دارم

1-اگر ما یک تصویر را در پشت (توسط GDI) رسم کردیم ( و یا با استفاده از FillRec و یا بقیه متد های رسم تصویری، رسم کردیم)، سپس در جلوی آن یک عکس دیگر رسم کردیم، آیا می شود بدون رسم دوباره عکس پشت عکس رو را حذف کرد، یعنی فقط عکس بالایی حذف شود بدون اینکه پاییی را دوباره رسم کنیم.

2- آیا در GDI (و نه در +GDI) می توان یک Bitmap را با زاویه دلخواه چرخواند؟

ممنون​
 
بالا