Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu bölümde aşağıdaki görevlerin nasıl gerçekleştirebileceğiniz açıklanmaktadır:
- Alt ve Çerçeve Pencere Sınıflarını Kaydetme
- Çerçeve ve Alt Pencere Oluşturma
- Ana ileti döngüsünü yazma
- Çerçeve Penceresi Yordamını Yazma
- Çocuk Pencere Prosedürünü Yazma
- Alt Pencere Oluşturma
Bu görevleri göstermek için, bu bölüm tipik bir çok belgeli arabirim (MDI) uygulaması olan Multipad'den örnekler içerir.
Çocuk ve Çerçeve Pencere Sınıflarını Kaydetme
Tipik bir MDI uygulamasının iki pencere sınıfı kaydetmesi gerekir: biri çerçeve penceresi ve diğeri de alt pencereleri için. Bir uygulama birden fazla belge türünü (örneğin, elektronik tablo ve grafik) destekliyorsa, her tür için bir pencere sınıfı kaydetmesi gerekir.
Çerçeve penceresinin sınıf yapısı, MDI olmayan uygulamalarda ana pencerenin sınıf yapısına benzer. MDI alt pencereleri için sınıf yapısı, MDI olmayan uygulamalarda alt pencerelerin yapısından biraz farklıdır:
- Kullanıcı bir MDI alt penceresini normal bir uygulama penceresiymiş gibi simge durumuna küçültebildiği için sınıf yapısının bir simgesi olmalıdır.
- MDI alt penceresinin kendi menüsü olmadığından, menü adı NULL olmalıdır.
- Sınıf yapısı, pencere yapısında fazladan alan ayırmalıdır. Bu alanla uygulama, dosya adı gibi verileri belirli bir alt pencereyle ilişkilendirebilir.
Aşağıdaki örnek, Multipad'in çerçeve ve alt pencere sınıflarını nasıl kaydettiğini göstermektedir.
BOOL WINAPI InitializeApplication()
{
WNDCLASS wc;
// Register the frame window class.
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) MPFrameWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, IDMULTIPAD);
wc.hCursor = LoadCursor((HANDLE) NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
wc.lpszMenuName = IDMULTIPAD;
wc.lpszClassName = szFrame;
if (!RegisterClass (&wc) )
return FALSE;
// Register the MDI child window class.
wc.lpfnWndProc = (WNDPROC) MPMDIChildWndProc;
wc.hIcon = LoadIcon(hInst, IDNOTE);
wc.lpszMenuName = (LPCTSTR) NULL;
wc.cbWndExtra = CBWNDEXTRA;
wc.lpszClassName = szChild;
if (!RegisterClass(&wc))
return FALSE;
return TRUE;
}
Çerçeve ve Alt Pencere Oluşturma
MDI uygulaması, pencere sınıflarını kaydettikten sonra pencerelerini oluşturabilir. İlk olarak, CreateWindowveya CreateWindowExişlevinikullanarak çerçeve penceresini oluşturur. Uygulama, çerçeve penceresini oluşturduktan sonra CreateWindow veya CreateWindowExkullanarak istemci penceresini yeniden oluşturur. Uygulama, istemci penceresinin sınıf adı olarak MDICLIENT belirtmelidir; MDICLIENT, sistem tarafından tanımlanan önceden kayıtlı bir pencere sınıfıdır. CreateWindow veya CreateWindowExlpvParam parametresi CLIENTCREATESTRUCT yapısına işaret etmelidir. Bu yapı aşağıdaki tabloda açıklanan üyeleri içerir:
| Üye | Açıklama |
|---|---|
| hWindowMenu | MDI alt pencerelerini denetlemek için kullanılan pencere menüsünün tutamacı. Alt pencereler oluşturulurken, uygulama başlıklarını pencere menüsüne menü öğeleri olarak ekler. Daha sonra kullanıcı, pencere menüsündeki başlığına tıklayarak bir alt pencereyi etkinleştirebilir. |
| idFirstChild | İlk MDI alt penceresinin tanımlayıcısını belirtir. Oluşturulan ilk MDI alt penceresine bu tanımlayıcı atanır. Artımlı pencere tanımlayıcılarıyla ek pencereler oluşturulur. Bir alt pencere yok edildiğinde, sistem aralıklarını bitişik tutmak için pencere tanımlayıcılarını hemen yeniden atar. |
Pencere menüsüne bir alt pencerenin başlığı eklendiğinde, sistem alt pencereye bir tanımlayıcı atar. Kullanıcı bir alt pencerenin başlığına tıkladığında, çerçeve penceresi wParam parametresinde tanımlayıcıyı içeren bir WM_COMMAND iletisi alır. idFirstChild üyesi için çerçeve penceresinin menüsündeki menü öğesi tanımlayıcılarıyla çakışmayan bir değer belirtmelisiniz.
Multipad'in çerçeve penceresi yordamı, WM_CREATE iletisini işlerken MDI istemci penceresini oluşturur. Aşağıdaki örnekte istemci penceresinin nasıl oluşturulduğu gösterilmektedir.
case WM_CREATE:
{
CLIENTCREATESTRUCT ccs;
// Retrieve the handle to the window menu and assign the
// first child window identifier.
ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), WINDOWMENU);
ccs.idFirstChild = IDM_WINDOWCHILD;
// Create the MDI client window.
hwndMDIClient = CreateWindow( "MDICLIENT", (LPCTSTR) NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
0, 0, 0, 0, hwnd, (HMENU) 0xCAC, hInst, (LPSTR) &ccs);
ShowWindow(hwndMDIClient, SW_SHOW);
}
break;
Alt pencerelerin başlıkları, pencere menüsünün en altına eklenir. Uygulama, AppendMenu işlevini kullanarak pencere menüsüne dize eklerse, pencere menüsü yeniden boyandığında (alt pencere oluşturulduğunda veya yok edildiğinde) bu dizelerin üzerine alt pencerelerin başlıkları yazılabilir. Pencere menüsüne dize ekleyen bir MDI uygulaması, InsertMenuişlevini kullanmalı ve alt pencere başlıklarının bu yeni dizelerin üzerine yazmadığını doğrulamalıdır.
MDI istemci penceresini oluştururken, pencerenin alt pencereleri üzerine boyanmasını önlemek için WS_CLIPCHILDREN stilini kullanın.
Ana İleti Döngüsü Yazma
Bir MDI uygulamasının ana ileti döngüsü, MDI olmayan uygulama işleme hızlandırıcı anahtarlarınınkine benzer. Fark, MDI ileti döngüsünün uygulama tanımlı hızlandırıcı anahtarlarını denetlemeden önce veya iletiyi göndermeden önce TranslateMDISysAccel işlevini çağırmasıdır.
Aşağıdaki örnekte tipik bir MDI uygulamasının ileti döngüsü gösterilmektedir. Unutmayın ki GetMessage bir hata varsa -1 döndürebilir.
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
if (!TranslateMDISysAccel(hwndMDIClient, &msg) &&
!TranslateAccelerator(hwndFrame, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
TranslateMDISysAccel işlevi, WM_KEYDOWN iletileri WM_SYSCOMMAND iletilere çevirir ve bunları etkin MDI alt penceresine gönderir. İleti bir MDI hızlandırıcı iletisi değilse, işlev FALSEdöndürür. Bu durumda uygulama, uygulama tanımlı hızlandırıcı tuşlarından herhangi birine basılıp basılmadığını belirlemek için TranslateAccelerator işlevini kullanır. Aksi takdirde, döngü iletiyi uygun pencere yordamına iletir.
Çerçeve Penceresi Yordamını Yazma
MDI çerçeve penceresinin pencere yordamı, MDI olmayan bir uygulamanın ana penceresine benzer. Aradaki fark, çerçeve penceresi yordamının işlemediği tüm iletileri DefWindowProc işlevi yerine DefFrameProc işlevine geçirmesidir. Ayrıca, çerçeve penceresi yordamı, işlediği bazı iletileri, aşağıdaki tabloda listelenenler de dahil olmak üzere, iletmeye devam etmelidir.
| İleti | Yanıt |
|---|---|
| WM_COMMAND | Kullanıcının seçtiği MDI alt penceresini etkinleştirir. Bu ileti, kullanıcı MDI çerçeve penceresinin pencere menüsünden bir MDI alt penceresi seçtiğinde gönderilir. Bu iletiye eşlik eden pencere tanımlayıcısı, etkinleştirilecek MDI alt penceresini tanımlar. |
| WM_MENUCHAR | Kullanıcı ALT+ – (eksi) tuş bileşimine bastığında etkin MDI alt penceresinin pencere menüsünü açar. |
| WM_SETFOCUS | Klavye odağını MDI istemci penceresine geçirir ve bu da bunu etkin MDI alt penceresine geçirir. |
| WM_SIZE | MDI istemci penceresini yeni çerçeve penceresinin istemci alanına sığacak şekilde yeniden boyutlandırıyor. Çerçeve penceresi yordamı MDI istemci penceresini farklı bir boyuta boyutlandırıyorsa, iletiyi DefWindowProc işlevine geçirmemelidir. |
Multipad'deki çerçeve penceresi yordamı MPFrameWndProc olarak adlandırılır. MPFrameWndProc tarafından diğer iletilerin işlenmesi, MDI olmayan uygulamalarınkine benzer. WM_COMMAND iletileri Multipad'de yerel olarak tanımlanmış CommandHandler fonksiyonu tarafından işlenir. Multipad'in işlemediği komut iletileri için CommandHandler, DefFrameProc işlevini çağırır. Multipad varsayılan olarak DefFrameProc kullanmıyorsa, pencerenin menü öğesine tıklanarak gönderilen WM_COMMAND iletisi kaybolacağından, kullanıcı pencere menüsünden bir alt pencereyi etkinleştiremez.
Alt Pencere Prosedürünü Yazma
Çerçeve penceresi yordamında olduğu gibi, MDI alt pencere yordamı da iletileri varsayılan olarak işlemek için özel bir işlev kullanır. Alt pencere yordamının işlemediği tüm iletiler, DefWindowProc işlevi yerine DefMDIChildProc işlevine geçirilmelidir. Ayrıca, uygulama iletiyi işlese bile, MDI'nin düzgün çalışabilmesi için bazı pencere yönetimi iletileri DefMDIChildProc'a iletilmelidir. Uygulamanın DefMDIChildProciletmesi gereken mesajlar aşağıdadır.
| İleti | Yanıt |
|---|---|
| WM_CHILDACTIVATE | MDI çocuk pencereleri boyutlandırıldığında, taşındığında veya görüntülendiğinde etkinleştirme işlemi gerçekleştirilir. Bu mesaj iletilmelidir. |
| WM_GETMINMAXINFO | MDI istemci penceresinin geçerli boyutuna göre maksimize edilmiş bir MDI alt penceresinin boyutunu hesaplar. |
| WM_MENUCHAR | İletiyi MDI çerçeve penceresine iletir. |
| WM_MOVE | Varsa MDI istemci kaydırma çubuklarını yeniden hesaplar. |
| WM_SETFOCUS | Çocuk penceresi etkin MDI alt penceresi değilse, onu etkinleştirir. |
| WM_SIZE | Bir pencerenin boyutunu değiştirmek için gerekli işlemleri yapar, özellikle bir MDI çocuk penceresini en üst düzeye çıkarmak veya geri yüklemek için. Bu ileti DefMDIChildProc işlevine geçirilmemesi, son derece istenmeyen sonuçlar üretir. |
| WM_SYSCOMMAND | Pencere (eski adıyla sistem) menü komutlarını işler: SC_NEXTWINDOW, SC_PREVWINDOW, SC_MOVE, SC_SIZEve SC_MAXIMIZE. |
Çocuk Pencere Oluşturma
MDI alt penceresi oluşturmak için bir uygulama createMDIWindowişlevini çağırabilir veya MDI istemci penceresine WM_MDICREATE bir ileti gönderebilir. (Uygulama, MDI alt pencereleri oluşturmak için WS_EX_MDICHILD stiliyle CreateWindowEx işlevini kullanabilir.) Tek iş parçacıklı bir MDI uygulaması, alt pencere oluşturmak için iki yöntemden birini kullanabilir. Çok iş parçacıklı bir MDI uygulamasında, bir iş parçacığı farklı bir iş parçacığında bir alt pencere oluşturmak için CreateMDIWindow veya CreateWindowEx işlevini kullanmalıdır.
WM_MDICREATE iletisinin lParam parametresi, MDICREATESTRUCT yapısına çok uzak bir işaretçidir. Yapı dört boyut üyesi içerir: pencerenin yatay ve dikey konumlarını gösteren x ve yve pencerenin yatay ve dikey uzantılarını gösteren cx ve cy. Bu üyelerden herhangi biri uygulama tarafından açıkça atanabilir veya CW_USEDEFAULTolarak ayarlanabilir. Bu durumda sistem, basamaklı algoritmaya göre bir konum, boyut veya her ikisini birden seçer. Her durumda, dört üyenin de başlatılması gerekir. Multipad, tüm boyutlar için CW_USEDEFAULT kullanır.
MDICREATESTRUCT yapısının son üyesi, pencere için stil bitleri içerebilen stil üyesidir. Pencere stillerinin herhangi bir bileşimine sahip olabilecek bir MDI alt penceresi oluşturmak için MDIS_ALLCHILDSTYLES pencere stilini belirtin. Bu stil belirtilmediğinde, MDI alt penceresinde varsayılan ayarlar olarak WS_MINIMIZE, WS_MAXIMIZE, WS_HSCROLLve WS_VSCROLL stilleri bulunur.
Multipad, MDI alt pencerelerini, yerel olarak tanımladığı AddFile işlevini kullanarak oluşturur (kaynak dosya MPFILE.C'de bulunur). AddFile işlevi, pencerenin MDICREATESTRUCT yapısının szTitle üyesini düzenlenmekte olan dosyanın adına veya "Adsız" olarak atayarak alt pencerenin başlığını ayarlar. szClass üyesi, Multipad'in InitializeApplication işlevinde kayıtlı MDI alt pencere sınıfının adına ayarlanır. hOwner üyesi uygulamanın örnek tanıtıcısına ayarlanmıştır.
Aşağıdaki örnekte, Multipad'deki AddFile işlevi gösterilmektedir.
HWND APIENTRY AddFile(pName)
TCHAR * pName;
{
HWND hwnd;
TCHAR sz[160];
MDICREATESTRUCT mcs;
if (!pName)
{
// If the pName parameter is NULL, load the "Untitled"
// string from the STRINGTABLE resource and set the szTitle
// member of MDICREATESTRUCT.
LoadString(hInst, IDS_UNTITLED, sz, sizeof(sz)/sizeof(TCHAR));
mcs.szTitle = (LPCTSTR) sz;
}
else
// Title the window with the full path and filename,
// obtained by calling the OpenFile function with the
// OF_PARSE flag, which is called before AddFile().
mcs.szTitle = of.szPathName;
mcs.szClass = szChild;
mcs.hOwner = hInst;
// Use the default size for the child window.
mcs.x = mcs.cx = CW_USEDEFAULT;
mcs.y = mcs.cy = CW_USEDEFAULT;
// Give the child window the default style. The styleDefault
// variable is defined in MULTIPAD.C.
mcs.style = styleDefault;
// Tell the MDI client window to create the child window.
hwnd = (HWND) SendMessage (hwndMDIClient, WM_MDICREATE, 0,
(LONG) (LPMDICREATESTRUCT) &mcs);
// If the file is found, read its contents into the child
// window's client area.
if (pName)
{
if (!LoadFile(hwnd, pName))
{
// Cannot load the file; close the window.
SendMessage(hwndMDIClient, WM_MDIDESTROY,
(DWORD) hwnd, 0L);
}
}
return hwnd;
}
WM_MDICREATE iletisinin lParam parametresine geçirilen işaretçi CreateWindow işlevine geçirilir ve WM_CREATE iletisinde geçirilen CREATESTRUCT yapısındaki ilk üye olarak görünür. Multipad'de alt pencere, ek verilerindeki belge değişkenlerini başlatarak ve düzenleme kontrolünün alt penceresini oluşturarak WM_CREATE ileti işleme sırasında kendini başlatır.