Reyza

tenang, senang, sederhana
See also: Other Geeks@INDC

Public

CompositionTarget.Rendering

CompositionTarget.Rendering adalah “kata” yang menarik hari ini. Kata lama bagi orang lain, tapi kata baru bagi saya. Denger-denger, “kata” ini telah diperkenalkan saat Silverlight 2 RTW. Gunanya? Cek contoh berikut ini :

   1: using System;
   2: using System.Windows.Controls;
   3: using System.Windows.Media;
   4:  
   5: namespace SilverlightApplication5
   6: {
   7:     public partial class MainPage : UserControl
   8:     {
   9:         int value = 0;
  10:  
  11:         public MainPage()
  12:         {
  13:             InitializeComponent();
  14:             CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
  15:         }
  16:  
  17:         private void CompositionTarget_Rendering(Object sender, EventArgs e)
  18:         {
  19:             value++;
  20:             label1.Content = value.ToString();
  21:         }
  22:     }
  23: }

Pada baris ke-14 adalah contoh pemberian handler untuk event Rendering. Selanjutnya pada handler CompositionTarget_Rendering berisi perintah untuk menambahkan nilai pada control label1.

Hasilnya :

image  image … dst … dst … image

Dilihat dari contoh tersebut, maka nilai pada label1 akan terus secara cepat. Kenapa proses penambahan bisa terjadi terus menerus ? Jawabannya bisa dilihat pada gambar di bawah ini.

image

Sederhananya, event ini dapat digunakan untuk menjalankan “pekerjaan” yang ingin dilakukan setiap 1 frame di-render. Maka tidak heran apabila contoh kode di atas menghasilkan output penambahan angka.

Apakah penambahan angka itu pasti selalu dilakukan? Apakah event Rendering pasti akan selalu dipanggil?

Kita coba buat kasus seperti gambar di bawah ini :

image

Pada gambar di atas, kotak merah adalah “area aplikasi Silverlight”, sedangkan diluar itu adalah “area HTML”. Pada gambar di atas, halaman ini dapat di-scroll ke bawah sehinggal kotak merah tidak terlihat lagi pada web browser. Bila hal itu dilakukan maka penambahan angka akan terhenti, dengan kata lain bisa dikatakan kalau event Rendering ini tidak dilakukan.

Hal ini bisa menguntungkan dan bisa juga merugikan, tergantung skenario dari aplikasi Silverlight yang dibangun.

Terlepas dari cerita di atas, selanjutnya akan dicontohnya penggunaan event CompositionTarget.Rendering untuk meningkatkan kemampuan aplikasi yang telah ditulis pada posting di sana dan sini. Pada posting kali ini akan dibuat agar aplikasi Silverlight ini dapat menampilkan lebih dari satu gambar. Untuk menampilkan setiap gambar yang di-drag aplikasi Silverlight ini, digunakan event Rendering untuk memeriksa apakah ada data/file yang di-drag.

Pertama, akan ditambahkan kedua property berikut ini :

   1: private int _zindex = 100;
   2: private Queue<FileInfo> _files = new Queue<FileInfo>();

Baris pertama akan digunakan untuk menyimpan nilai z-index terakhir dari suatu objek gambar. Sedangkan baris kedua berfungsi sebagai Collection untuk “menampung” objek gambar.

   1: public MainPage()
   2: {
   3:     InitializeComponent();
   4:  
   5:     CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
   6: }

Selanjutkan menambahkan baris ke-5 pada konstruktor. Kemudian mengubah isi event handler DropArea_Drop menjadi seperti berikut ini.

   1: private void DropArea_Drop(object sender, DragEventArgs e)
   2: {
   3:     if (e.Data != null)
   4:     {
   5:         FileInfo[] files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
   6:  
   7:         foreach (FileInfo fi in files)
   8:         {
   9:             _files.Enqueue(fi);
  10:         }
  11:     }
  12: }

Pada kode sebelumnya, event handler ini berfungsi untuk menampilkan gambar dari file yang di-drop. Sekarang event handler ini hanya berfungsi untuk menambahkan data file yang di-drop ke dalam Collection. Sedangkan untuk menggambar file yang ada di dalam Collection akan dilakukan oleh event handler CompositionTarget_Rendering berikut ini :

   1: private void CompositionTarget_Rendering(Object sender, EventArgs e)
   2: {
   3:     if (_files.Count != 0)
   4:     {
   5:         FileInfo fi = _files.Dequeue();
   6:         DrawImage(fi);
   7:     }
   8: }

Yang dilakukan adalah mengambil data dari Collection kemudian data tersebut digambar dengan menggunakan fungsi DrawImage berikut ini :

   1: private void DrawImage(FileInfo fi)
   2: {
   3:     using (Stream stream = fi.OpenRead())
   4:     {
   5:         try
   6:         {
   7:             BitmapImage bi = null;
   8:  
   9:             bi = new BitmapImage();
  10:             bi.SetSource(stream);
  11:  
  12:             double cx = (double)bi.PixelWidth;
  13:             double cy = (double)bi.PixelHeight;
  14:  
  15:             // resize ukuran gambar yang ditampilkan
  16:             if (cx > 390.0 || cy > 390.0)
  17:             {
  18:                 if (cx >= cy)
  19:                 {
  20:                     cy *= 390.0 / cx;
  21:                     cx = 390.0;
  22:                 }
  23:                 else
  24:                 {
  25:                     cx *= 390.0 / cy;
  26:                     cy = 390.0;
  27:                 }
  28:             }
  29:             Image image = new Image();
  30:             image.Source = bi;
  31:  
  32:             WriteableBitmap wb1 = new WriteableBitmap((int)cx, (int)cy);
  33:             ScaleTransform transform = new ScaleTransform();
  34:             transform.ScaleX = cx / bi.PixelWidth;
  35:             transform.ScaleY = cy / bi.PixelHeight;
  36:             wb1.Render(image, transform);
  37:             wb1.Invalidate();
  38:  
  39:             Image gambar = new Image();
  40:             gambar.Source = wb1;
  41:  
  42:             label1.Content = fi.Name;
  43:             DropArea.Children.Add(gambar);
  44:  
  45:             gambar.MouseLeftButtonDown += new MouseButtonEventHandler(OnButtonDown);
  46:             gambar.MouseMove += new MouseEventHandler(OnMouseMove);
  47:             gambar.MouseLeftButtonUp += new MouseButtonEventHandler(OnButtonUp);
  48:         }
  49:         catch (Exception)
  50:         {
  51:         }
  52:     }
  53: }

Hal lain yang perlu diubah adalah event handler berikut ini :

   1: private void OnButtonDown(object sender, MouseButtonEventArgs e)
   2: {
   3:     ((FrameworkElement)sender).SetValue(Canvas.ZIndexProperty, _zindex++);
   4:  
   5:     _lastx = e.GetPosition(null).X;
   6:     _lasty = e.GetPosition(null).Y;
   7:  
   8:     ((FrameworkElement)sender).CaptureMouse();
   9:     _dragging = true;
  10: }

Pada event handler ini yang ditambahkan adalah pada baris ke-3, yang bertujuan untuk mengubah nilai dari ZIndex dari gambar yang dipilih, sehingga ketika tombol ditekan pada suatu objek gambar, nilai ZIndex objek gambar itu akan bertambah. Artinya bila gambar tersebut tertindih oleh gambar-gambar yang lain, ketika dipilih gambar tersebut akan nyembul di atas gambar-gambar lainnya :)

Berikut hasilnya :

image

Dan berikut solution yang bisa langsung dicoba.

Share this post: | | | |
Posted: Feb 17 2010, 06:42 PM by reyza | with 1 comment(s)
Filed under:

Comments

Reyza said:

Setelah gambar sudah bisa di drop dan ditampilkan pada badan aplikasi Silverlight kemudian digerak-gerakan

# March 9, 2010 7:17 AM