خرید بک لینک

Windows GDI

شروع موضوع توسط littlerabbit ‏9 می 2005 در انجمن منابع آموزشی

  1. littlerabbit

    littlerabbit مدیر بازنشسته کاربر فعال

    تاریخ عضویت:
    ‏13 جولای 2003
    نوشته ها:
    667
    تشکر شده:
    5
    محل سکونت:
    Iran
    در ویندوز همه عناصر ویژوال برای نمایش خود از یک شی به نام 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 استفاده کنید.
     
  2. بازدیدیار - افزایش بازدید سایت و سیگنال های برندخرید بک لینک
  3. littlerabbit

    littlerabbit مدیر بازنشسته کاربر فعال

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

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

    webbi Registered User

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

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

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

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

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