Windows 7 Goodies in C++: Ribbon a Giriş

Konu sahibi son olarak 3350 gün önce görüldü
Giriş

Ribbon, orjınal olarak Office team tarafından kendi uygulamalarının karmaşık sistemlerinin menülerini ve toolbarlarını değiştirmek için dizayn edilmiştir. Windows 7’de, Microsoft, geçerli Win32 uygulamalarında kullanmak için COM tabanlı yeniden kullanılabilir bir Ribbon eklentisini güncelledi. Geçerli Ribbon, Office, WPF ve MFC deki diğer Ribbon eklentilerinden biraz farklıdır, ama onların hepsi aynı tasarım ve işlevselliği paylaşırlar.

Ribbon’un bir sürü özelliğinden dolayı, bu ilk makale sadece Ribbon’un temellerini ve COM arayüzlerini kapsayacak ve basit bir Ribbon kullanan bir uygulamayı baştan itibaren oluşturulmak için gerekli adımları gösterecek. Eğer Ribbon gelişmelerine yada yakında çıkacak WTL 8.1 Ribbon sınıflarına dalmak isterseniz CodeProject’teki diğer Ribbon makalelerini kontrol edebilirsiniz.

Basit bir kod derlemek için sistem gereksinimleri, Visual Studio 2008, WTL 8.0 ve Windows 7 SDK yeterlidir. Eğer Windows 7 yada Server 2008 R2 kullanıyorsanız, gerekli olan herşeye sahipsiniz demektir. Eğer Vista veya Server 2008 kullanıyorsanız, işletim sisteminizde Ribbon kullanmak için servis pack 2 ve Description of the Platform Update for Windows Server 2008 and the Platform Update for Windows Vista uygulamalarını indirmelisiniz.

Yeni bir uygulamaya başlama
CmainFrame de çalışmaya başlama

WTL AppWizard tarafından oluşturulmuş olan temel SDI uygulaması ile başlayacağız. Bu uygulama bir toolbar’a sahip olmayacak (Ribbon toolbar’ı değiştirdiğinden dolayı), ama bir durum çubuğuna sahip olucak. Görüntüleme penceresi için ayrı bir sınıfı kullanır, ama Ribbon’un gelişmesine ve çalıştırılmasına odaklanacağımız için bu görüntüleme penceresi çok fazla şey yapmayacağız. Daha sonra, ana yapının child kontrollerini tasarlamaya gelindiği zaman, bu görüntüleme penceresi ile daha çok şey yapacağız.

İlk adım, Ribbon’un kullanılması için bize gerekecek tipleri ve arayüzleri tanımlayan, UIRibbon.h’nin include edilmesidir. Uygulamamız bu arayüzlerin ikisinide derleyecektir, ve bu derleme detayları makalenin geri kalan kısmında anahatları ile belirtilecektir. Herşeyden önce, ihtiyaç duyduğumuz herşey, CmainFrame kalıtım listesine IUIApplication’u eklenmesidir, daha sonra 3 metodun stub derlemelerini ekleriz.

ic6as7.jpg


CmainFrame bir COM nesnesi olması gerekene kadar, CcomObjectRootEx’ten türeyecektir. Birde, Run() fonksiyonundaki CmainFrame örneği CcomObjectRootStackEx kullanılarak oluşturulacaktır, IUnknown’un ATL derlemesini kullanmak için:


280ik54.jpg


Uiframework’ün kurulumu

Ribbon ile sahip olduğumuz ilk etkileşim, IUiframework arayüzü aracılığı iledir, CmainFrame Framework’ü başlatmak ve kapatmak için bu arayüzü kullanır, bu nedenle, uygulamanın kullanıldığı sürece bir arayüz işaretçisi tutmak zorundadır.


2e326nn.jpg


CmainFrame: : OnCreate ()’de, Framework’ün COM nesnesini oluştururuz:


24d0uv5.jpg


IUiframework : : Initialize(), Ribbon bulunan pencerenin HWND’sini alır, ve Framework olan IUIApplication arayüzü uygulama ile bağlantı sağlayacaktır, Bu framework, Ribbon’un görsel esas noktaları ile uyumlu olması için, pencerenin görüntüsünü değiştirir. Örnek olarak, framework windows menülerini ve etkin yazı çubuğundaki çizim kontrollerini değiştirir. Bu özelliklerin düzgünce çalıştığını kontrol etmek için, framework WS_CAPTION stili ile ve WS_EX_TOOLWINDOW stili olmadan, üst kısımda bir penceresi olan bir pencere gerektirir.

Eğer pencere bu durumları karşılamaz ise, IUiframework : : Initialize(), ERROR_INVALID_WINDOW_HANDLE hatası döndürecektir.

Framework’ü tam anlamıyla kapatmak ve kullandığı kaynağı serbest bırakmak için, birde WM_DESTROY handler’in deki IUiframework : : Destroy()’u çağımamız gerekir


2e1zn0y.jpg


IUiframework : : Initialize() ’a çağrımızı eklememizin ardından, frame penceremiz şu şekilde gözükecektir.


korqc.jpg


Ribbon’umuzun içeriğini henüz tanımlamadığımızdan dolayı henüz hiçbir Ribbon yoktur, tabiki, ama framework, menü çıkarmaya benzer zorunlu görsel eklentiler meydana getirdi.

Bir Ribbon’u Uygulamaya Eklemek

Ribbon, daha önce kullandığınız UI bileşenlerinden farklı çalışır. Tasarım ilkelerinden biri bir Ribbon’un içeriğinin tanımının, görsel tasarımından ayrı olması gerektiğidir. Bir uygulama Ribbon’da hangi komutların görüntülendiğini, bunların nasıl organize edildiğini ve gruplandırıldığını ayrıntılı olarak belirtebilir ve daha fazlasını. Ama uygulama, Ribbon’un aslında nasıl görüneceğini sınırlandırır. Bu iletişim kaynakları gibi GUI’nin oluşturulmasının mevcut yollarından daha az uyumluluk sorunu ile gelecekte Microsoft’un Ribbon’un görünüşünün değiştirmesine izin verir.

Bir Ribbon tanımlamanın adımları:
1- Ribbon’un içeriğini tanımlayan bir XML belgesi oluşturunuz ve bu dosyayı projenize ekleyin.
2- Uicc aracı ile XML belgesini derleyin.
3- Uicc’nin meydana getirdiği dosyaları uygulamanın kaynaklarına ekleyin.
4- Derlenen tanımı kullanan bir Ribbon oluşturmak için IUiframework ::LoadUI() çağırın.

XML dosyasına dalmadan önce, Ribbon’un bileşenlerini tam olarak tanımamız gerekir.

Ribbon Bölümleri

Ribbon birçok yerde, bir komut tasarımını kullanır, Bir komut, bir butondan daha fazladır, aslında bu, Ribbonda tıklayabileceğin ve bununla birçok şey yapabileceğin herhangi birşeydir. Komutlar, bir text etiketi, bir ikon, bir kısayol tuşu gibi çeşitli özelliklere sahiptirler. Bir kere komut listesini oluşturduğunuzda, komutların dışında Ribbon’un diğer bölümlerini oluşturmaya başlarsınız.

Burada çeşitli Ribbon bölümlerinin görüntülendiği Paint penceresinin bir görüntüsü vardır.

20t01t4.jpg


1-Uygulama menüsü: İlk tabın solundaki buton, uygulama menüsünü açar. Görünüşünü özelleştirmek için izin vermemesine rağmen, bu komutun kendisidir, Menü diğer komutlarıda içerir.
2-Hızlı erişim toolbarı (QAT): QAT, Ribbon’un pencerenin başlık kısmında çizdiği bir araç çubuğudur. Diğer komutları sağ tıklayıp gelen menüden Hızlı erişim araç çubuğuna ekle seçeneği yardımı ile bu araç çubuğuna ekleyebilirsiniz. QAT’ın sağ tarafında bulunan aşağı ok tuşu, araç çubuğundaki komutları özelleştirebileceğimiz ve Ribbon ve QAT’ın görünümünü değiştirebileceğimiz bir menü görüntüler
3-Tablar: Tab dizisi, XML dosyasında tanımladığın tüm tabları görüntüler. Her tab bir komuttur, ve bir yada daha fazla işlem grubunu kapsar
4-Gruplar: Herbir grup komut koleksiyonudur. Bir grup altta isteğe bağlı bir etikete sahiptir, ve Ribbon grupların arasındaki ayırıcıları çizer. Ara sıra, grup yerine kullanılan terim yığınını görebilirdiniz. Bu resmi bir terim değildir, ama Office takımı tarafından ilk Ribbon oluşturulduğunda kullanılmıştı, ve blog mesajları gibi gayri resmi yazılan materiyallerde kullanılır.

XML Dosyasına Başlamak

Başlangıç noktamız olan XML dosya iskeletimiz burdadır:

9fux6x.jpg


Dikkat ederseniz, XAML benzer şekilde "object.property" adlandırma kuralları ile bazı özellikler child taglarını kullanmak için yazılmıştır. Örnek olarak, <Application.Commands>, <Application> tagının Commands özelliğini tanımlar.

Ilk adım <Ribbon> bölümlerinde kullanacağımız birkaç komutu oluşturmak içindir, Herbir komut, bir <Command> tagını tanımlar. <Command> daha sonra göreceğimiz birkaç özelliğe sahiptir, ama şuan için, Name ve LabelTitle olan iki tanesini kullanacağız, Name özelliği XML dosyasının sonundaki komutu tanımlayan bir stringdir, ve LabelTitle UI bileşeninin text’inin atandığı bir stringdir.

Bir buton oluştumak için, onu yerleştireceğimiz bir grup ve tab’a gerek duyarız, böylece 3 komutla başlarız.

1zexez9.jpg


(Microsoft benim gördüğüm örneklerinde, tüm komut isimlerinin öneklerinde "cmd" kullanmıştır, ama ben herbir komutun işlevine göre daha tanımlayıcı önekler tercih ettim) Sonra bir grup içinde bir tab, bir grup ve buton kontrolleri oluştururuz.


muh3id.jpg


Bu bir grup içeren bir tab oluşturur. Tab özelliklerinin çoğu <Command> tagı ile ilişkili olarak gelir. Burada dolaylı bir seviye bulunur: Tab’ın text’inin ne olduğunu belirtmezsiniz, tabın hangi komutu olduğunu belirtirsiniz, Ribbon, ilgili <Command> etiketinde text’i arar. Benzer şekilde, grubun etiketi grbHello komutunun LabelTitle özelliğinden gelir. Şuan için SizeDefinition özniteliği hakkında endişelenmeyin, Ribbon’un grubun içindeki kontrolleri nasıl ayarlayacağını bilmesi için gerekli olan bir şeydir sadece.

Sonunda, burada , tıklanan sıradan bir buton oluşturan <Button> etiketi bulunur, Birçok yerde aynı komutlara sahip olunmasını mümkün kıldığı için <Command> etiketlerinde,özelliklerin ayrımı, butonlar için daha kullanışlıdır, ve bu ayrılığın olması ile, komutların görüleceği heryerde aynı özellikleri tekrarlamak zorunda olmazsınız.
 
Ribbon XML Dosyasının Derlenmesi

Şimdi, Ribbon tanımlama dosyamızı oluşturduk, bunu uygulamamıza dahil etmemiz gerekir. Eğer yazılan XML dosyasını ribbon.xml üzerine kaydedeceksek, Project menüsünden Add Existing seçeneğini seçip ribbon.xml dosyasını seçerek, Visual Studio projemize bunu ekleriz.

Sonraki aşama, XML dosyasını Ribbon’un anlayacağı binary formata çevirecek (uicc.exe) derleyicisini çağırmaktır. Ribbon.xml için özellikleri açın, ve Custom build step ayarlarından, komut satırı alanına aşağıdakileri girin.


ur8fm.jpg


uicc, ribbon.xml derlendiği zaman, 3 dosya oluşturur.
1-Ribbon.bml derlenen çıktı, Microsoft örneklerinde .bml uzantısını kullanır, ve bende takıma uydum
2-Ribbonids.h: XML içerisinde tanımlanan tüm stringler ve komutlar için #define komutlarına sahip A C başlık dosyasıdır.
3-Ribbon.rc: XML de referans edilen string ve iconların tanımlarının olduğu kaynak tanım dosyasıdır. Ribbon.bml den alınan yaygın kaynak tiplerinden biridir. /name anahtarı kaynağın ismini kontrol eder. Bu örnekte, isim HELLORIBBON_RIBBON dur. /name anahtarında hangi isim belirtilirse belirtilsin, altçizgi "_RIBBON" eklenir.

Çıktı alanına "$(InputName).bml;$(InputName)ids.h;$(InputName).r c" komut ayarlamalarını yaparak uicc’nin hangi dosyaları oluşturduğunu Visual Studio’ya bildirmeliyiz.

Sonra, ribbon.rc’deki kaynakları, uygulamamızın kaynaklarına ekleriz, Kaynak Görüntüleme tabından, HelloRibbon.rc’ye sağ tıklarız ve Resource Includes seçeneğini seçeriz. Derleme zamanı editleme kutusuna:

#include "ribbon.rc" ekleyin.

Şimdi, uygulamamız derlenecektir, ribbon.rc’de listelenen herhangi bir kaynağı, uygulamamızın kaynakları kapsayacaktır. Uicc, birde XML dosyasının herhangi bir hata içermediğini ve Ribbon’un tasarım kurallarını bozan herhangi bir hatanın olup olmadığınıda denetler (örneğin, bir grupta bir komutun birden fazla gözükmesi gibi), Eğer uicc herhangi bir hata bulursa, derleme başarısız olur ve proje oluşturulmayacaktır.

Ribbon’u Yüklemek

Son aşama, XML’nin derlenen versiyonunu kullanan Ribbon’un yüklenmesidir, CmainFrame::OnCreate() den IUiframework::LoadUI() i çağırarak bunu yaparız.

25i7tpx.jpg


IUiframework::LoadUI() iki parametre alır, derlenen XML ve kaynak ismini içeren HMODULE.

Bu değişikliklerden sonra uygulamamızı derlediğimizde, XML etiketlerinin eksik olduğuna dair birçift önemsenmeyecek hata mesajı alırırz, ve ilk Ribbon’umuzu görürüz!!


2dh7cj4.jpg


UICC Hatalarını Düzeltmek

Devam etmeden önce, UICC’den alınan ApplicationMenu ve QuickAccessToolbar özelliklerinin eksik olduğuna dair hata mesajlarını düzeltelim. Herbir bileşen için bir komuta ihtiyaç duyarız.


sl02le.jpg


Daha sonra <Ribbon> etiketinin altına yeni etiketler ekleriz


1zqaq7c.jpg


Bu alandaki tüm gerekli bileşenlerin değişiklikleri ile uicc artık daha fazla uyarı vermeyecektir.

Ribbon’a Bağlanmak

Ribbon yapısını kurmak ve parçalara ayırmak için kullandığımız, IUiframework arayüzünü daha önceden görmüştük, Ribbon ile direk bağlantı kurmak için kullanılan bir diğer arayüz daha mevcuttur: IUIRibbon. Ribbon, IUIApplication::OnViewChanged() aracılığı ile arayüzden uygulamamıza geçer, bu nedenle, bu metoda doldurarak başlayacağız.

İlk olarak, IUIRibbon arayüzünü tutacak olan CmainFrame’ye bir üye ekleyelim.

// In MainFrm.h:
CComQIPtr<IUIRibbon> m_pRibbon;

Ribbon oluşturulduğu, yokedildiği ve yeniden boyutlandırıldığı zaman, CmainFrame::OnViewChanged() çağrılır (Teknik olarak, uygulama görüntüleri ile ilgilenir, özellikle Ribbon ile değil, ama Ribbon şimdiye kadar tanımlanan tek görüntüdür) OnViewChanged için parametreler:
1-uViewID: Görüntü ID, güncel olarak her zaman 0’dır
2-nType: Görüntü tipi, güncel olarak her zaman UI_VIEWTYPE_RIBBON.
3-pView: Görüntü tarafından sağlanan bir IUnknown arayüzüdür.
4-nVerb: Görüntünün hareketinin yaptığı davranış: UI_VIEWVERB_CREATE, UI_VIEWVERB_DESTROY yada UI_VIEWVERB_SIZE
5-nReason : Güncel olarak kullanılmaz

nVerb, UI_VIEWVERB_CREATE olduğu durumda, Ribbon oluşturulur ve bir IUIRibbon arayüzü için doğrulayabiliriz, nVerb, UI_VIEWVERB_DESTROY olduğu durumda, Ribbon ayrılır, böylece IUIRibbon arayüzünü serbest bırakırız


2w53mdw.jpg


Daha ilginç durum ise nVerb, UI_VIEWVERB_SIZE olduğu durumdur, Bu bize Ribbon’un boyutunun değiştirildiğini, gizlendiğini veya görüntülendiğini anlatır, Bu etkiler, ana pencerenin tasarımını etkileyeceği için, ana pencerenin tasarımındaki ve piksellerindeki yeni yüksekliği alırız.


157kr29.jpg


CframeWindowsImpl::UpdateLayout(), WTL destekli—rebars, toolbars ve status bar-- gibi bar türlerinin çeşitlerinin pozisyonlarıdır ve sonrasında, kalan boşluğu almak için, görüntüleme penceresinin konumlarıdır. WTL, Ribbon hakkında bilgiye sahip olmadığı için, UpdateLayout()’ı override etmemiz ve hesaplamaların kısımları olarak Ribbon’un yüksekliğini kullanmamız gerekir. Override’miz, CframeWindowsImpl::UpdateLayout()’a oldukça benzer, ama m_cyRibbon’a bakarak, müşteri alanının üst kısmında kaç pixel ayrılacağını kararlaştırır:


1pbcxg.jpg


UpdateLayout() overridemizi ekledikten sonra, Ribbon’u en az idirmeyi deneyebilirsin ve görüntü penceremiz buna uygun olarak yeniden boyutlandırılacaktır:


i2rpya.jpg


Eğer pencereyi yeterince küçültürseniz, Ribbon kendisini tamamen gizleyecektir, UpdateLayout()’umuz bu durumu bile ele alır.
 
Geri