VSTO 2008 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
VSTO 2008 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

Salı, Ağustos 11, 2009

VSTO 2008 – Calendar İçerisinde Yer Alan Kayıtlara Erişebilmek

Uygulama geliştirirken zaman içerisinde sıklıkla kullanmış olduğumuz Office uygulamalarına uygulama tarafında işlemler yaptırmamız gerekebiliyor. Özellikle de masaüstü ve web uygulamalarında outlook uygulamasına erişebilme ihtiyacımız da sık sık gündeme gelebiliyor. Bu işlemleri de .Net bünyesinde yer alan interop.Outlook ve office isim alanları ile sorunsuzca gerçekleştirebilmemize olanak vardır.

Fakat bazı durumlarda uygulamalar üzerinde office uygulamalarına değil de Office uygulamaların içerisinde uygulamalar geliştirmek gerekebiliyor. Bu noktada yapılması gereken daha önceki yazılarımızdan da açıkladığımız gibi Visual Studio Tools for Office 2008 (VSTO 2008) yardımı ile Office 2007 System uygulamalarına add-in yazmak olacaktır.

Not: Office System 2003 için add-in yazmak istediğimizde VSTO 2005 yardımı ile uygulama geliştirmemiz gerekmektedir. Ayrıca Office System 2003 sürümünün SP1 ve SP2 sürümlerinin bilgisayarınızda kurulu olması gerekmektedir.

Biz bu yazımızda Outlook uygulamasına bir add-in oluşturma yardımı ile takvime kayıtlı olan toplantı ve randevuları görüntüleyeceğiz.

Peki, neden bu tür uygulama ihtiyaç duyabiliriz. Örneğin, Outlook üzerinde yeni bir randevu talebi yaptığınızda aynı zaman aralığına birden fazla kayıt yapabilme olanağınız vardır. Bu işlemi outlook açılırken koyacağınız bir kontrol ile engelleyebilirsiniz. (Not: Yeni bir tablantı talebi esnasında aynı zaman aralığında birden fazla kayıt varsa otomatik olarak reddet seçeneği bulunmaktadır. Ancak bu işlem randevu taleplerinde olmamaktadır.) Ayrıca Outlook uygulamasının sağ köşesinde yer alan todo bar uygulamasında tek günlük gösterilen kayıtları haftalık ya da daha farklı bir varyasyon ile gösterilmesine olanak tanıyabilmeniz mümkündür. Ayrıca bu belirttiğim seçenekler dışında aklımıza gelmeyen daha bir çok ihtimal dahilinde kullanılabilmesi mümkündür.

Bu kadar açıklamadan sonra uygulamamızı sağlayacak olan metodu oluşturalım ve kod üzerinde açıklamaya devam edelim.

Bu aşamada yapılması gereken Visual Studio 2008 yardımı ile yeni bir proje oluşturmak olacaktır. Çalışacak olan proje şablonu ise Office tabının içerisinde yer alan Outlook 2007 add-in olacaktır.

ThisAddin.cs
public void GetAllCalendarItems()
{
    Microsoft.Office.Interop.Outlook.Application oApp = null;
    Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = null;
    Microsoft.Office.Interop.Outlook.MAPIFolder CalendarFolder = null;
    Microsoft.Office.Interop.Outlook.Items outlookCalendarItems = null;

    oApp = new Microsoft.Office.Interop.Outlook.Application();
    mapiNamespace = oApp.GetNamespace("MAPI"); ;
    CalendarFolder = mapiNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);//GetFolder("test");
    outlookCalendarItems = CalendarFolder.Items;
    outlookCalendarItems.IncludeRecurrences = true;

    foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in outlookCalendarItems)
    {
        if (item.IsRecurring)
        {
            Microsoft.Office.Interop.Outlook.RecurrencePattern rp = item.GetRecurrencePattern();
            DateTime first = new DateTime(2008, 8, 31, item.Start.Hour, item.Start.Minute, 0);
            DateTime last = new DateTime(2008, 10, 1);
            Microsoft.Office.Interop.Outlook.AppointmentItem recur = null;

            for (DateTime cur = first; cur <= last; cur = cur.AddDays(1))
            {
                try
                {
                    recur = rp.GetOccurrence(cur);
                    MessageBox.Show(recur.Subject + " -> " + cur.ToLongDateString());
                }
                catch
                { }
            }
        }
        else
        {
            MessageBox.Show(item.Subject + " -> " + item.Start.ToLongDateString());
        }
    }

}

Outlook içerisinde yer alan bir uygulama erişbilmek için Office.Interop.Application sınıfını kullanmak gerekmektedir. Bu sınıf yardımı ile calendar nesnesine erişip işlem yaptırabilmemiz mümkündür. Ayrıca CalendarFolder içerisinde yer alan varsayılan takvime erişebilmek için yukarıdaki kod parçasını kullanabiliriz. Farklı isim bir calendara erişebilmek için ise yan tarafta yorum satırı yapılmış olan bölümü kullanabilmeniz mümkündür. Ayrıca randevular ve toplantıların Appointment sınıfı içerisinde tutulduğundan bir önceki yazımızda bahsetmiştik. Biraz önce calendar içerisinde yer alan değerleri AppointmentItem değerleri ile foreach döngüsü ile döndürdüğümüzde AppointmentItem 'ın değerleri bizim aradığımız sonuçlar olacaktır.

Bu yazımızda Outlook takvime kaydedilen randevu ve toplantılara ilişkin kayıtlara nasıl erişebileceğimizi ve bu değerleri ne amaçla kullanabileceğimizi açıklamaya çalıştık.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com

VSTO 2008 – Kod ile Calendar New Appointment İşlemi

Uygulama geliştirirken zaman içerisinde sıklıkla kullanmış olduğumuz Office uygulamalarına uygulama tarafında işlemler yaptırmamız gerekebiliyor. Özellikle de masaüstü ve web uygulamalarında outlook uygulamasına erişebilme ihtiyacımız da sık sık gündeme gelebiliyor. Bu işlemleri de .Net bünyesinde yer alan interop.Outlook ve office isim alanları ile sorunsuzca gerçekleştirebilmemize olanak vardır.

Fakat bazı durumlarda uygulamalar üzerinde office uygulamalarına değil de Office uygulamaların içerisinde uygulamalar geliştirmek gerekebiliyor. Bu noktada yapılması gereken daha önceki yazılarımızdan da açıkladığımız gibi Visual Studio Tools for Office 2008 (VSTO 2008) yardımı ile Office 2007 System uygulamalarına add-in yazmak olacaktır.

Not: Office System 2003 için add-in yazmak istediğimizde VSTO 2005 yardımı ile uygulam geliştirmemiz gerekmektedir. Ayrıca Office System 2003 sürümünün SP1 ve SP2 sürümlerinin bilgisayarınızda kurulu olması gerekmektedir.

Biz bu yazımızda Outlook için add-in yardımı ile Calendar nesnesine nasıl kayıt eklemeye göz atacağız.

Bu aşamada yapılması gereken Visual Studio 2008 yardımı ile yeni bir proje oluşturmak olacaktır. Çalışacak olan proje şablonu ise Office tabının içerisinde yer alan Outlook 2007 add-in olacaktır.

ThisAddin.cs kod bloğunun içerisinde outlook açıldığı anda yapılacak işlemleri yapabilmeniz mümkündür. İstersenizde mainRegionForm ekleyerek outlook içerisinde istediğiniz bir menünün altında uygulamanızın çalışmasına olanak tanıyabilirsiniz. Biz işlemlerimizi outlook 'un çalışması anında yapacağız.

Visual Studio üzerinden outlook 'ta yeni bir randevu talebi yapabilmemiz için Outlook.Appointment sınıfına ait olan özellikleri kullanmamız yeterli olacaktır. Bu işlemi gerçekleştirmek için gerekli olan kod bloğu aşağıdaki gibi olacaktır.

ThisAddin.cs
Outlook.AppointmentItem newAppointment = (Outlook.AppointmentItem)this.Application.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olAppointmentItem);
newAppointment.Start = DateTime.Now.AddHours(2);
newAppointment.End = DateTime.Now.AddHours(3);
newAppointment.Location = "ConferenceRoom #2345";
newAppointment.Body ="Bla bla şirketi için grup projesidir.";
newAppointment.AllDayEvent = false;
newAppointment.Subject = "Group Project";
newAppointment.Recipients.Add("Turhal Temizer");
Outlook.Recipients sentTo = newAppointment.Recipients;
Outlook.Recipient sentInvite = null;
sentInvite = sentTo.Add("Murat Borlu");
sentInvite.Type = (int)Outlook.OlMeetingRecipientType.olRequired;
sentInvite = sentTo.Add("Hakan Bayısın");
sentInvite.Type = (int)Outlook.OlMeetingRecipientType.olOptional;
sentTo.ResolveAll();
newAppointment.Save();
newAppointment.Display(true);

Belirtmiş olduğumuz bu kod bloğunu ThisStartup olayına eklersek outlook açıldığı anda yeni bir randevu kaydını gerçekleştirecektir.

Aklınıza şöyle bir soru takılabilir. Burada yer alan bütün özelliklere kod içerisinden kayıtlar eklenmiştir. Ben dışarıdan eklenebilen bölümleri form üzerine eklemiş olduğum kontroller yardımı ile yapabilir miyim? Evet yapılabilir. Yazının başında da bahsettiğimiz üzere MainRegionForm olarak geliştirilmiş olan uygulamalarda eklemiş olduğumuz kontrolleri sanki windows form uygulaması geliştirmişiz gibi kullanbilmemiz mümkündür.

Bir sonraki yazımızda Calendara eklemiş olduğumuz kayıtları nasıl listeleyebileceğimizi inceleyemeye çalışacağız.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com

Perşembe, Temmuz 23, 2009

VSTO 2008 - Genel Özellikler ve Outlook 2007 için Form Uygulaması Oluşturulması

Microsoft 'un en çok beğenilen uygulamalarından biri olan Office System 2007 bile bazen ihtiyaçlarımıza cevap veremeyebilir. İşte bu noktada ne yapmalıyız sorusunu kendimize sormaya başlarız. Bu noktada yapmış olduğumuz araştırmalar sonrasında da Visual Studio 2008 ile Office uygulamalarına Add-in yazılabileceğimizi öğreniriz. Peki bu işlemi nasıl gerçekleştirebiliriz ve hangi uygulamaların bilgisayarımızda kurulu olması gerekmektedir.

Gerekli olan uygulamalar:
1.)
Visual Studio 2008
2.) Office System 2007
3.) Windows XP veya üstü bir işletim sistemi

Yukarıda saymış olduğumuz uygulamaları bilgisayara kurduktan sonra artık Office Add-in yardımı ile çalışabilir duruma geliyoruz. Bu eklentileri Visual Studio 2008 ile hazırladığımızda adlandırılma olarak VSTO 2008 olmaktadır.

İşlemleri nasıl yapacağımızı bir örnek üzerinde değerlendirelim. Örnek olarak Outlook 2007 kontaklarını resim olarak listeleyen ve üzerene tıkladığımızda da bize o kişinin kontak detaylarını getirecek. Şimdi adım adım nasıl yapacağımızı incelemeye çalışalım.

İlk yapılması gereken Visual Studio 2008 üzerinde proje oluşturulması olacaktır. Bu işlem için proje şablonları arasından Outlook 2007 Add-in projesini seçeceğiz ve sonrasında karşımıza gelen ekrandan Outlook 2007 Add-in projesini seçtikten sonra geliştirmeye başlayabilir duruma geliyoruz.



Proje şablonunu oluşturduktan sonra ThisAddin isimli sınıf oluşmaktadır. Bu sınıfın ana amacı oluşturulan Add-in açıldığından ve kapatıldığında ne iş yapılacağını açıklamaktadır. Fakat unutulmaması gereken bir nokta var ki o da, oluşturmak istediğimiz Add-in 'nin Outlook ta herhangi bir formun içerisinde mi açılacağı yoksa Outlook ile birlikte mi çalışacağıdır. Biz uygulamamız esnasında içte açılan bir yöntemi tercih edip işlemlerimize devam edelim.

Not: Outlook dışı çalışmasını istiyorsak yapmamız gereken Add->New Item seçeneğinden Windows form ya da WPF Form 'ı ekledikten sonra işlemleri yapmak olacaktır...

ThisAddin sınıfının içerisinde neler varmış bir göz atmak gerekirse,

ThisAddin.cs
namespace Contacts
{
    public partial class ThisAddIn
    {
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion
    }
}

Daha önceden de değindiğimiz üzere ThisAddin sınıfının içerisinde Add-in başladığı ve sonlandığı anda yer alan olaylar yer almaktadır. Outlook içerisinde kontaklar menüsünde uyumlu bir şekilde çalışacak olan içeriğini oluşturmaya başlayalım.

Uygulamanın üzerinde sağ tıklama yaptıktan sonra Add->NewItem adımlarını izliyor ve karşımıza çıkan ekrandan Office tabının içerisinde yer alan Outlook Form Region form şablonunu ekle diyerek işlemlerimize devam ediyoruz.



Ayrıca yukarıdaki ekrandan göreceğiniz üzere Ribbon yer alan formlarda hazırlayabilmemiz mümkündür. Bu kullanım şeklini de zaman içerisinde incelemeye çalışacağız. Seçeneği seçtikten ve ekle dedikten sonra karşımıza çıkan ekranda yeni bir Outlook Form mu tasarlayacağımızı yoksa var olan bir formdan mı yararlanacağımızı sormaktadır.



Yukarıda karşımıza çıkan seçenekten Design a new form region seçeneğini seçerek devam ediyoruz. Bir sonraki ekranda karşımıza ekleyecek olduğumuz formun ekran üzerinde nasıl yer alacağına ilişkin bilgiler girmemizi istemektedir.



Bu adımda Outlook ekranında Ribbon altında yer alan alanın hepsini dolduracak olan ve Ribbon içerisinde yeni bir ek yapacak olan Separate seçeneğini seçeceğiz. Diğer seçeneklerin ne işe yaradığını açıklamak gerekirse,

*Adjoining: Form 'u çalışma alanın alt kısmında tutar ve Add-in 'i var olan bir menü içerisine ekleme yapar.
*Replacement: Varsayılan form alanının içerisine ekleme yapar ve Add-in 'i var olan bir menü içerisine ekleme yapar.
*Replace-All:  Ribbon menüyü bizim istediğimiz şekilde yapılandırır ve Add-in 'i var olan bir menü içerisine ekleme yapar.

Separete seçeneğini tıkladıktan sonra bir sonraki adıma geçiş yapıyoruz. Bu ekranda bizden ekleyecek olduğumuz Add-in görünecek adını, üzerine fare ile tutulduğunda ne gibi bir açıklama vereceğini, açıklamasını ve kullanım alanının içinde nasıl çalışacağını ilişkin bilgiler girmemizi istemektedir.



Form Region 'a ilişkin bilgileri de girdikten sonra bir sonraki adımımızda işlemimizi var olan bir sınıf üzerinde mi yapacağız yoksa biz harici sınıf mı oluşturacağız diye sormaktadır. Yazının başından da hatırlayacağınız üzere örneğimizi kontaklar (Contact) üzerine yapacaktık. Bu durumda karşımıza çıkan ekrandan IPM.Contact seçeneğini seçmek isteklerimizi karşılayacak bir çözüm olacaktır.



Evet artık VSTO (Visual Studio Tools for Office) ile Add-in 'ni boş form ile oluşturmuş oluyoruz. Otomatik hazırlanın formun içerisinde FormRegionClosed ve FormRegionShowing olaylarını incelersek arka planda FormRegionMyContacts sınıfının içerisinde yer alan  kod bloklarına götürdüğünü göreceksiniz.

FormRegionMyContacts.cs
namespace Contacts
{
    partial class FormRegionMyContacts
    {
        #region Form Region Factory

        [Microsoft.Office.Tools.Outlook.FormRegionMessageClass(Microsoft.Office.Tools.Outlook.FormRegionMessageClassAttribute.Contact)]
        [Microsoft.Office.Tools.Outlook.FormRegionName("Contacts.FormRegionMyContacts")]
        public partial class FormRegionMyContactsFactory
        {
            // Occurs before the form region is initialized.
            // To prevent the form region from appearing, set e.Cancel to true.
            // Use e.OutlookItem to get a reference to the current Outlook item.
            private void FormRegionMyContactsFactory_FormRegionInitializing(object sender, Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs e)
            {
            }
        }

        #endregion

        // Occurs before the form region is displayed.
        // Use this.OutlookItem to get a reference to the current Outlook item.
        // Use this.OutlookFormRegion to get a reference to the form region.
        private void FormRegionMyContacts_FormRegionShowing(object sender, System.EventArgs e)
        {
        }

        // Occurs when the form region is closed.
        // Use this.OutlookItem to get a reference to the current Outlook item.
        // Use this.OutlookFormRegion to get a reference to the form region.
        private void FormRegionMyContacts_FormRegionClosed(object sender, System.EventArgs e)
        {
        }
    }
}

Şimdi uygulamamız üzerinde herhangi bir değişiklikte bulunmadığımız haliyle çalıştıralım ve Outlook içerisinde nasıl bir görünüm alacağına göz atalım. Oluşturulmuş olan proje derlendiğinde Outlook 'un otomatik olarak açılacak ve geliştiricinin gerekli testleri yapması için beklemeye başlayacaktır. Daha sonra derleme işlemi sonlandırıldığında Outlook uygulaması da kendisini otomatik olarak kapatacaktır. Biz uygulamamızı kontaklar içerisine eklenmesini istemiştik. Bakalım istediğimiz gerçekleşmiş mi?



Oldukça başarılı... İstediğimiz sonucu almışa benziyoruz. Peki biz bu Add-in 'nin üzerine tıkladığımızda karşımıza nasıl bir form görüntüsü gelecek. Tabii ki boş. Çünkü hiç bir düzenleme işlemi yapmamıştık. Şimdi ise eklemiş olduğumuz Add-in 'i nasıl geliştirebileceğimizi incelemeye çalışalım.

Örneğimizde aynı kategori içerisinde yer alan tüm kişileri göstermek istiyoruz. Yazımızın başında da bahsettiğimiz üzere kontak listemizin hepsini sadece resimleri ile göstermek istiyoruz. bu işlemi gerçekleştirebilmek için OutlookItem nesnesini kullanmamız gerekmektedir. Eriştiğimiz Outlook öğesinin alt özelliklerinde ContactItem 'a erişeceğiz ve bütün kontakları sorunsuzca kullanıcılara getirebileceğiz. Eğer kontaklarımızda kategori uygulanmış ise biz kişileri gösterirken bu kategoriye de göz önüne alarak bir işlem yapmamız gerekmektedir. Bu işlem için string filtre uygulamak mantıklı bir işlem olacaktır. Örneğin Outlook kontakları içerisinde yer alan arkadaşlar grubuna ilişkin kayıtları göstermek istiyorum. Bu noktada yapılması gereken bir ListView içerisine Contact nesnesinin içerisinde yer alan resim özelliklerini bu kontrolde doldurmak olacaktır. Genel olarak istediklerimizi açıkladığımıza göre işlemlerimizi yapmaya devam edebiliriz.

İlk olarak filtre hazırlama işlemini nasıl gerçekleştireceğimize göz atalım.

FormRegionMyContacts.cs
/// <summary>
/// Filtreleme işlemi için yapıldı.
/// </summary>
/// <param name="messageClass">İstenen mesaj sınıfı</param>
/// <param name="categoryList">kontaklar için kategori listesi</param>
/// <returns></returns>
string BuildSQLFilter(string messageClass, string[] categoryList)
{
    //StringBuilder nesnesinin kullanıyoruz.
    StringBuilder filter = new StringBuilder(250);
    //SQL Prefix (Ön eki)
    filter.Append(@"@SQL(");
    //MessageClass yardımı ile duruma özel mesaj verdirir.
    filter.Append(string.Format(@"(""http://schemas.microsoft.com/mapi/proptag/0x001a001e"" = '{0}')",
                        messageClass));
    //Kategori var mı diye kontrol eder ve sonrasında AND koşulunu uygular.
    if (categoryList.Length > 0) filter.Append("AND(");
    //Kategori var mı diye kontrol eder ve sonrasında AND koşulunu uygular.
    for (int index = 0; index < categoryList.Length; index++)
    {
        if (index > 0) filter.Append("OR");
        filter.Append(string.Format(@"(""urn:schemas-microsoft-com:office:office#Keywords"" LIKE '%{0}%')",
                                                    categoryList[index].Trim()));

    }
    //AND blogunun sonu
    if (categoryList.Length > 0) filter.Append(")");
    //SQL blogunun sonu
    filter.Append(")");
    return filter.ToString();
}

Kontaklar içerisinde yer alan kategorilerden isteğimize erişebilir ve içinde yer alan kayıtları görebilir duruma gelmiş bulunuyoruz. Şimdi ise filtre sonucunda gelecek olan kontakları yavaş yavaş göstermeye başlayalım. Outlook dosyaları Outlook.MAPIFolder içerisinde tutmaktadır. Bu durumda dosyalara erişmek istediğimizde bu nesneyi kullanmamız gerekecek. Ayrıca ListView için tablo kullanmak gerekecek. Outlook.Table nesnesini kullanarak bu işlemi de gerçekleştirebilmemiz mümkündür. Ayrıca dikkat etmemiz gereken bir nokta var. Biz bu işlemleri yaparken arka planda çalışmasını sağlayacak bir yapıda kurmamız gerekmektedir. Bu işlemi de uygulamamız esnasında hazırlıyor olmamız gerekmektedir.

Kontaklara eriştikten sonra verilere ulaşmak için kullandığımız yöntem aşağıdaki gibi olacaktır.

FormRegionMyContacts.cs
private readonly Size _imagesize = new Size(50, 75);

// Occurs before the form region is displayed.
// Use this.OutlookItem to get a reference to the current Outlook item.
// Use this.OutlookFormRegion to get a reference to the form region.
private void FormRegionMyContacts_FormRegionShowing(object sender, System.EventArgs e)
{
    Outlook.ContactItem contact;
    Outlook.MAPIFolder folder;
    Outlook.Table table;
    try
    {
        //Outlook ContactItem 'dan değerleri getiriyor...
        contact = this.OutlookItem as Outlook.ContactItem;
        //kontak klasörünü nesne olarak getirir.
        folder = contact.Parent as Outlook.MAPIFolder;

        //kontakları kategorilere göre getirir.
        string categories = contact.Categories ?? string.Empty;
        string[] categoryList = categories.Split(';');

        //Hazırlanmış olan SQL filtre metoduna göre gerekli işlemler gerçekleştiriliyor.
        string filter = BuildSQLFilter("IPM.Contacy", categoryList);
        //filtrelenmiş değerleri tabloya dolduruyoruz.
        table = folder.GetTable(filter.ToString(), Outlook.OlTableContents.olUserItems);
        //Gelen değerleri tablo içerisine kolonlara doldurulur.
        table.Columns.RemoveAll();
        table.Columns.Add("EntryID");
        table.Columns.Add("FileAs");
        table.Columns.Add(@"urn:schemas:contacts:profession");
        table.Columns.Add("Email1Address");
        table.Columns.Add(@"urn:schemas:contacts:businesshomepage");
        table.Columns.Add(
                    @"http://schemas.microsoft.com/mapi/id/{00062004-0000-0000-C000-000000000046}/8062001F");
        table.Columns.Add("Categories");
        // MAPI özelliklerinden resim değerlerini nasıl alacağını göstereceğiz.
        table.Columns.Add(
                    @"http://schemas.microsoft.com/mapi/id/{04200600-0000-0000-C000-000000000046}/8015000B");
        // resim listesi oluşturma ve Resim yok görüntüsnün eklenmesi
        ImageList imageList = new ImageList();
        imageList.ImageSize = _imagesize;
        imageList.ColorDepth = ColorDepth.Depth24Bit;
        //resim listesinde resim yoksa listview üzerinde yer alan resimler resim yok görüntüsünün gözükmesi
        listviewContacts.LargeImageList = imageList;
        imageList.Images.Add(string.Empty, Properties.Resource.NoPicture);

        //Kontaklar ListView 'ın içerisine resimleri ile birlikte dolduruluyor...
        List<string> contactsWithPicture = new List<string>();

        //Outlook kontaklarında Business Card olarak girilmiş olan bilgilerde yer alan
        //resimlerin görütülenmesini sağlamaktadır.
        while (!table.EndOfTable)
        {
            Outlook.Row row = table.GetNextRow();
            //satır bilgileri dolduruluyor.
            ContactInfo info = new ContactInfo(row);
            if (info.HasPicture)
            {
                contactsWithPicture.Add(info.EntryId);
            }
            if (contact.EntryID != info.EntryId)
            {
                ListViewItem listViewItem = this.listviewContacts.Items.Add(info.FileAs, 0);
                listViewItem.Tag = info;
                listViewItem.Name = info.EntryId;
                listViewItem.ToolTipText = info.EmailAddress;
            }
            else
            {
                UpdateBusinessCard(info, GetContactPicture(info.EntryId));
            }

            //uzun süren çalışmaların için arka planda çalışabilme özelliği
            _backgroundWorker = new BackgroundWorker();
            _backgroundWorker.WorkerSupportsCancellation = true;
            _backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);
            _backgroundWorker.RunWorkerAsync(contactsWithPicture);
        }
    }
    finally
    {
        table = null;
        folder = null;
        contact = null;
    }
}

Şimdiye kadar kontaklara ilişkin verileri getirecek ve resim yoksa görüntü yok ekranını gösterecek, ayrıca çok fazla veri gelecekse bu çalışmayı ekran yüklenirken değil de arka planda çalışabilmesine olanak verecek yapının hazırlanması için temel adımları gerçekleştirmiş bulunuyoruz. Şimdi ise yukarıdaki kod bloğunda kullanmış olduğumuz metotların ve event ların içeriklerini doldurma işlemini gerçekleştirelim. Bu amaçla yapacağımız ilk işlem BusinessCard kontak tipini eklenen resimlerin ListView içerisinde gözükmesi olacaktır.

FormRegionMyContacts.cs
private Image GetContactPicture(string entryID)
{
    var contact =
        Globals.ThisAddIn.Application.Session.GetItemFromID(entryID, null) as Outlook.ContactItem;
    Image img = null;
    string tempPath = Environment.GetEnvironmentVariable("TEMP");
    if (contact != null)
    {
        foreach (Outlook.Attachment attachment in contact.Attachments)
        {
            if (attachment.FileName == "ContactPictıre.jpg")
            {
                string fileName = Path.Combine(tempPath, entryID + ".jpg");
                attachment.SaveAsFile(fileName);
                FileStream stream = new FileStream(fileName, FileMode.Open);
                Bitmap bmp = new Bitmap(Image.FromStream(stream, true));
                if (bmp.Width > bmp.Height)
                {
                    Bitmap tempBmp = new Bitmap(_imagesize.Width, _imagesize.Height);
                    Graphics g = Graphics.FromImage(tempBmp);
                    g.FillRectangle(Brushes.White, 0, 0, _imagesize.Width, _imagesize.Height);
   
                    float ratio = (float)bmp.Height / bmp.Width;
                    int newHeight = (int)(ratio * bmp.Height);
                    int top = (_imagesize.Height - newHeight) / 2;
                    g.DrawImage(bmp, new Rectangle(0, top, _imagesize.Width, _imagesize.Height));
                    img = tempBmp;
                    g.Dispose();
                }
                else
                {
                    img = new Bitmap(bmp, _imagesize);
                }
                    stream.Dispose();
                    File.Delete(fileName);
                    break;
            }
        }
    }
    contact = null;
    return img;
}

Arka plan çalışma işlemlerinin detaylarını girelim şimdi de. İlk olarak resimlerin çalışma prensipleri ile alakalı işlem yapmamız gerekmektedir. Hatırlayacağınız üzere BusinessCard görünümünde yer alan resimleri EntryId 'lerinden yararlanarak resimlerini göstereceğimizden bahsetmiştik. Şimdi bu işlemi gerçekleyecek olan kod bloğunu ekleyelim.

FormRegionMyContacts.cs
private void listViewContacts_DoubleClick(object sender, EventArgs e)
{
    Point position = listViewContacts.PointToClient(Control.MousePosition);
    ListViewItem listViewItem =
    listViewContacts.GetItemAt(position.X, position.Y);
    if (listViewItem == null) return;

    OpenItem(listViewItem.Name);
}

private void OpenItem(string entryId)
{
    Outlook.ContactItem contact = Globals.ThisAddIn.Application.Session.GetItemFromID(entryId, null) as Outlook.ContactItem;
    contact.Display(false);
    contact = null;
}

private void listViewContacts_ItemMouseHover(object sender, ListViewItemMouseHoverEventArgs e)
{
    UpdateBusinessCard((ContactInfo)e.Item.Tag, listViewContacts.LargeImageList.Images[e.Item.ImageIndex]);
}

Metotlarımızı hazırlarken çok sık olarak ContactInfo sınıfını oluşturalım. Bu sınıf içerisinde BusinessCard içerisinde yer alan iletişim bilgilerine ilişkin elemanlar yer almaktadır.

ContactInfo.cs
namespace Contacts
{

public class ContactInfo
{

    /// <summary>
    /// Outlook satır ve sütunlarında yer alan bilgiler için kullanırlar
    /// </summary>
    /// <param name="row"></param>
    public ContactInfo(Microsoft.Office.Interop.Outlook.Row row)
    {
        EntryId = (string)row[1];
        FileAs = (string)row[2];
        JobTitle = (string)(row[3] ?? string.Empty);
        EmailAddress = (string)(row[4] ?? string.Empty);
        Homepage = (string)(row[5] ?? string.Empty);
        MessengerAddress = (string)(row[6] ?? string.Empty);
        string categories = (string)(row[7] ?? string.Empty);
        Categories = categories.Split(';');
        HasPicture = (bool)(row[8] ?? false);
    }

    public string EntryId { get; private set; }
    public string FileAs { get; private set; }
    public string JobTitle { get; private set; }
    public string EmailAddress { get; private set; }
    public string Homepage { get; private set; }
    public string MessengerAddress { get; private set; }
    public string[] Categories { get; private set; }
    public bool HasPicture { get; private set; }
    }
}

Sürekli olarak kod tarafında neler yapacağımıza göz attık. Peki bu hazırlamış olduğumuz tasarımın tasarım ekranı nasıldır?



Tasarım tarafında keyfimize istediğimiz .Net kontrolünü kullanabilmemiz mümkündür. Sıra kontak bilgilerinin gösterilmesine geldi. Son kullanıcı resmin üzerine çift tıklama ya da başka bir işlem yaptığında kontak eklediği ekran açılarak değişiklik yapabilmesine olanak tanıyacağız.

FormBusinessCard.cs
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using Microsoft.Office.Interop.Outlook;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Runtime.InteropServices;
using System.Reflection;

namespace Contacts {
    public partial class FormBusinessCard : UserControl {


        public FormBusinessCard() {
            InitializeComponent();
        }

        /// <summary>
        /// BusinessCard dan bilgileri alarak doldurur
        /// </summary>
        /// <param name="info">ContactInfo nesnesi.</param>
        /// <param name="image" >Kontakın resmi</param>
        public void SetContactInfo( ContactInfo info , Image image){
            EntryId = info.EntryId;
            LastFirst.Text = info.FileAs;
            Profession.Text = info.JobTitle;
            Emailaddress.Text = info.EmailAddress;
            Messenger.Text = info.MessengerAddress;
            Homepage.Text = info.Homepage;
            Categories.Text = string.Join("\n", info.Categories);
            Image.Image = image;
        }


        /// <summary>
        /// Outlook ContactItem 'dan EntryId 'yi getirir
        /// </summary>
        public string EntryId { get; set; }
       
        /// <summary>
        /// BusinessCarda çitt tıkladığında olacak işlemler uygulanır.
        /// </summary>
        private void FormBusinessCard_MouseDoubleClick(object sender, MouseEventArgs e) {
            OpenItem(EntryId);
        }

        /// <summary>
        /// Detayları ile kişinin kontak bilgilerini getirir.
        /// </summary>
        /// <param name="entryId">Kontağın entryId 'si</param>
        void OpenItem(string entryId) {
            Outlook.ContactItem contact = Globals.ThisAddIn.Application.Session.GetItemFromID (entryId , null) as Outlook.ContactItem ;
            contact.Display(false);
            contact = null;
        }

        /// <summary>
        /// Ana ekrana link veren link clicked
        /// </summary>
        private void Homepage_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
            ShowHomePageInBrowser(Homepage.Text);
        }

        void ShowHomePageInBrowser(string url){
            Process p = new Process();
            p.StartInfo.FileName = "IExplore.exe";
            p.StartInfo.Arguments = url;
            p.Start();
        }

        /// <summary>
        /// Live messenger 'a tıklandığında kontak ile chat penceresinde konuşulabilmesini sağlar
        /// </summary>
        private void Messenger_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
            ConnectToMessenger(Messenger.Text);
        }

        /// <summary>
        /// Email adresini kullanarak anlık mesajlaşma (messenger) penceresi açar.
        /// </summary>
        /// <param name="email">the emailaddress of the partner</param>
        void ConnectToMessenger(string email) {
            try{
                // Messenger oluşturuluyor.
                Type messengerType = Type.GetTypeFromProgID ("Messenger.UIAutomation.1");
                object comObject = Activator.CreateInstance (messengerType);
   
                // e-mail adreslerine göre kişiler konuşma penceresine davet ediliyor.
                object[] arguments = new object[] { email };
                messengerType.InvokeMember ("InstantMessage", BindingFlags.InvokeMethod,null, comObject, arguments);
                Marshal.ReleaseComObject(comObject);


                } catch(System.Exception ex){
                    MessageBox.Show("Please make sure you have installed the latest Windows Messenger Live and that you are signed-in." );
            }
        }

        private void Emailaddress_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
            SendEmail(LastFirst.Text, Emailaddress.Text);
        }

        /// <summary>
        /// mail adresi oluşturulması isteniyor.
        /// </summary>
        /// <param name="emailAddress">kontakların mail adresleri</param>
        void SendEmail(string name,string emailAddress) {
            Outlook.MailItem mail = Globals.ThisAddIn.Application.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem) as Outlook.MailItem ;
            mail.Recipients.Add (string.Format("{0}<{1}>", name, emailAddress ));
            mail.To = emailAddress;
            mail.Display(false);
            mail = null;
        }
    }
}

Evet artık geliştirme süreçlerimizi tamamlamış oluyoruz. Sıra test yapmaya geldi. Test için yapmamız gereken uygulamamızı çalıştırmak olacaktır. Çalışma esnasında Outlook 2007 (Outlook 2010 üzerinde de sorunsuzca çalışmaktadır.) uygulaması açılacak ve eklemiş olduğumuz Add-in bizim kullanımımız için hazır durumda bulunacaktır.



Uygulamamız sorunsuz bir şekilde çalıştı ve isteklerimizi yapar duruma gelmiştir.

Yazımızı sonlandırmadan önce bu yapmış olduğumuz Add-in 'i son kullanıcıların bilgisayarlarına kurmak istediğimiz ne tür işlemler uygulamamız gerektiğine değinelim. Yazımızın içerisinde de bahsettiğimiz üzere VSTO == Visual Studio Tools for Office 'tir. Bu uygulama tipi ile hazırlanmış örnekler ise *.vsto uzantısı ile oluşturulmaktadır. Eğer ki bilgisayarlarda Visual Studio 2008 kurulu değilse bilgisayarlar vsto uzantısını tanımayacaktır. Bu durumda yapmamız gereken Microsoft Visual Studio Tools for the Microsoft Office System Runtime uygulamasını bilgisayarlara kurmak olacaktır. Sonrasında bilgisayarlar VSTO uzantısını algılayacak ve kurulum işlemini gerçekleştirecektir.

Kurumlar içerisinde çalışan geliştiriciler için en büyük sorun ise bilgisayarlara herhangi bir uygulama kurulmasına izin verilmemesinden kaynaklanmaktadır. Bu uygulama kurulurken ne yapmamız gerekmektedir peki. Bilgisayarlara ilk olarak Admin kullanıcı ile VSTO Runtime 'ı kurmamız gerekmektedir. Sonrasında ise oluşturmuş olduğumuz uygulamayı kurmak istediğimizde herhangi güvenlik engeline takılmadan kurabilmemize olanak tanınacaktır. Peki Runtime kurulurken admin kullanıcısı hakkı isterken neden uygulama kurulurken böyle bir istekte bulunmamaktadır. Çünkü VSTO uygulamaları çalışacakları Office uygulamasını doğrular ve sonrasını kendisini ekler. Yani kurmaz. Bu sebepten ötürüde kurulum esnasında herhangi bir güvenlik kontrolüne takılmayacaktır.

SoSonuç olarak Visual Studio üzerinde VSTO 2008 uygulamasını ne için oluşturacağımızda nasıl oluşturacağımıza kadar örnek üzerinde incelemeye çalıştık. Sonrasında ise geliştirmiş olduğumuz uygulamanın son kullanıcıların bilgisayarlarına nasıl kurulacağını hem kurum bazında hem de küçük işletmeler bazında değinmeye çalıştık.

Uygulamanın kaynak kodlarına buradan erişebilmeniz mümkündür.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com