📄 tabbedmdi.h
字号:
/////////////////////////////////////////////////////////////////////////////
// TabbedMDI.h - Classes that help implement a "Tabbed MDI" interface.
//
// Classes:
// CTabbedMDIFrameWindowImpl -
// Instead of having CMainFrame inherit from
// CMDIFrameWindowImpl, you can have it inherit from
// CTabbedMDIFrameWindowImpl. For an out-of-the box WTL MDI
// application, there are 3 instances of CMDIFrameWindowImpl
// to replace with CTabbedMDIFrameWindowImpl.
// CTabbedMDIChildWindowImpl -
// If you want your MDI child window to have a corresponding
// tab in the MDI tab window, inherit from this class instead
// of from CMDIChildWindowImpl.
// CTabbedMDIClient -
// The CTabbedMDIFrameWindowImpl contains CTabbedMDIClient,
// which subclasses the "MDI Client" window
// (from the OS, that manages the MDI child windows).
// It handles sizing/positioning the tab window,
// calling the appropriate Display, Remove, UpdateText
// for the tabs with the HWND of the active child,
// etc. You can use CTabbedMDIClient without using
// CTabbedMDIFrameWindowImpl. To do so, simply call
// SetTabOwnerParent(m_hWnd) then SubclassWindow(m_hWndMDIClient)
// on a CTabbedMDIClient member variable after calling
// CreateMDIClient in your main frame class.
// CMDITabOwner -
// The MDITabOwner is the parent of the actual tab window
// (such as CDotNetTabCtrl), and sibling to the "MDI Client" window.
// The tab owner tells the MDI child when to display a context
// menu for the tab (the default menu is the window's system menu).
// The tab owner changes the active MDI child when the
// active tab changes. It also does the real work of
// hiding and showing the tabs. It also handles adding,
// removing, and renaming tabs based on an HWND.
// CTabbedMDICommandBarCtrl/CTabbedMDICommandBarCtrlImpl -
// In your MDI application, instead of using CMDICommandBarCtrl,
// use CTabbedMDICommandBarCtrl. It addresses a couple of bugs
// in WTL 7.0's CMDICommandBarCtrl, and allows you to enable
// or disable whether you want to see the document icon
// and min/max/close button in the command bar when the
// child is maximized. To add additional functionality,
// derive your own class from CTabbedMDICommandBarCtrlImpl.
//
//
//
// Written by Daniel Bowen (dbowen@es.com)
// Copyright (c) 2002-2005 Daniel Bowen.
//
// Depends on CustomTabCtrl.h originally by Bjarke Viksoe (bjarke@viksoe.dk)
// with the modifications by Daniel Bowen
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever.
//
// If you find bugs, have suggestions for improvements, etc.,
// please contact the author.
//
// History (Date/Author/Description):
// ----------------------------------
//
// 2005/07/13: Daniel Bowen
// - Namespace qualify the use of more ATL and WTL classes.
// - CTabbedMDIFrameWindowImpl:
// * Add GetMDITabCtrl
//
// 2005/04/12: Daniel Bowen
// - CTabbedMDIClient::OnNcPaint -
// * CDC dc(this->GetWindowDC());
// should be
// CWindowDC dc(this->m_hWnd);
//
// 2005/04/08: Daniel Bowen
// - Generalize support for having the tab control automatically hidden
// if the number of tabs is below a certain count.
// - CMDITabOwnerImpl -
// * Move KeepTabsHidden support into base class CCustomTabOwnerImpl
// * Move HideMDITabsWhenMDIChildNotMaximized to CMDITabOwnerImpl and have
// CTabbedMDIClient forward it's call of the same to the tab owner.
// * Change old "OnAddFirstTab" and "OnRemoveLastTab" to work with
// new refactored support in CCustomTabOwnerImpl. It's now
// OnAddTab and OnRemoveTab with the help of ShowTabControl and
// HideTabControl. The work that used to be done
// in OnAddFirstTab and OnRemoveLastTab is now done in
// ForceShowMDITabControl and ForceHideMDITabControl.
// * Add ShowTabControlIfChildMaximized and HideTabControlIfChildNotMaximized
// that CTabbedMDIClient calls (since this class now tracks
// HideMDITabsWhenMDIChildNotMaximized)
// - CTabbedMDIClient -
// * Move HideMDITabsWhenMDIChildNotMaximized to CMDITabOwnerImpl and have
// CTabbedMDIClient forward it's call of the same to the tab owner.
//
// 2005/03/14: Daniel Bowen
// - Fix warnings when compiling for 64-bit.
//
// 2005/02/03: Daniel Bowen
// - Move registered window messages into TabbedMDIMessages.h
//
// 2004/11/29: Daniel Bowen
// - Update all WM_NOTIFY handlers to check that the notification is
// from the tab control (and not from a sibling like a list view control)
//
// 2004/06/28: Daniel Bowen
// - CMDITabOwnerImpl -
// * Fix GetTabStyles to return DWORD instead of bool
// - CTabbedMDIChildWindowImpl -
// * OnShowTabContextMenu - Add warning in Debug builds if using non SC_* command.
// To use use non SC_* commands, you should override handling
// UWM_MDICHILDSHOWTABCONTEXTMENU
// in a derived class, and do your own context menu there.
// See the "TabDemo" sample for an example.
// - Clean up warnings on level 4
//
// 2004/05/14: Daniel Bowen
// - CMDITabOwnerImpl -
// * Update OnClick handling so it only sets focus to the tab view
// if the selected tab is being clicked. Without this update,
// other code that tries to minimize flickering when switching
// the active view doesn't get called.
// - CTabbedMDIClient
// * Fix bug in SaveModified that checks incoming argument for NULL
//
// 2004/04/29: Daniel Bowen
// - Require WTL version 7.1 or later (because of WTL's CMDICommandBarCtrlImpl)
// - New and changed registered messages for tabbed MDI children:
// * UWM_MDICHILDISMODIFIED - Asks whether the document(s) referenced by a
// tabbed MDI child has been modified, and if so, the LPARAM has an
// ITabbedMDIChildModifiedItem* with which to fill out information.
// Return TRUE if there are one or more modified documents for the child.
// * UWM_MDICHILDSAVEMODIFIED (change meaning slightly) - Tells the tabbed MDI
// child to save any modifications without asking. The LPARAM is an
// ITabbedMDIChildModifiedItem* with additional information. Before, this message
// was used to ask about saving modifications, then saving if the user chose to.
// The asking about modifications is now consolidated in "SaveAllModified"
// (or by doing FindModified, CSaveModifiedItemsDialog, SaveModified).
// * UWM_MDICHILDCLOSEWITHNOPROMPT - Closes the tabbed MDI child bypassing WM_CLOSE
// (so that the user isn't prompted to save modifications - for when they've
// already been asked).
// - CTabbedMDIClient
// * New "HideMDITabsWhenMDIChildNotMaximized". If you call this
// with TRUE, then the MDI tabs are shown when the MDI children
// are maximized, and hidden when they are not maximized.
// * Change "SaveAllModified". It can be used to implement "save all"
// that doesn't prompt, or it can be used to prompt about saving any
// modified documents using a dialog with a checkbox list for modified items
// (which only works with tabbed MDI children).
// * FindModified - Asks all tabbed MDI children whether they have been
// modified, and uses ITabbedMDIChildModifiedList and ITabbedMDIChildModifiedItem
// for extended information.
// * SaveModified - Iterates items in a ITabbedMDIChildModifiedList and
// sends UWM_MDICHILDSAVEMODIFIED to save modifications. If an item has
// sub-items, the "top-level" item is responsible for ensuring that
// modifications are saved.
// * CloseAll - Close all MDI child windows. If bPreferNoPrompt is true,
// try sending UWM_MDICHILDCLOSEWITHNOPROMPT first to the window, so that
// the child is closed and the user is not prompted about any modifications.
// Otherwise send WM_SYSCOMMAND with SC_CLOSE, which sends WM_CLOSE.
// - CMDITabOwnerImpl
// * Have the MDI tab styles default to using the new style
// CTCS_DRAGREARRANGE
// * Respond to NM_CLICK, CTCN_ACCEPTITEMDRAG and CTCN_CANCELITEMDRAG
// from the tab control, and set focus to the tab item's view
//
// 2003/12/16: Daniel Bowen
// - CTabbedMDICommandBarCtrlImpl
// * Update OnMDISetMenu to match CMDICommandBarCtrlImpl::OnMDISetMenu in WTL 7.1
// * Update RefreshMaximizedState to match corresponding code in
// CMDICommandBarCtrlImpl::OnAllHookMessages in WTL 7.1
// * Have RefreshMaximizedState be overrideable (call through pT->)
// * Have RefreshMaximizedState's 2nd parameter indicate whether the document
// icon has changed, instead of whether the child has changed
// (to match what WTL 7.1 is doing in OnAllHookMessages)
/// * NOTE: There is a problem in WTL 7.1 OnAllHookMessages that
// CTabbedMDICommandBarCtrlImpl fixes. See
// http://groups.yahoo.com/group/wtl/message/7627
// for a description of the fix. Future versions of WTL should
// also have this fix.
//
// 2003/08/11: Daniel Bowen
// - CMDITabOwner:
// * Add new "KeepTabsHidden" method.
// * Have the old CMDITabOwner be CMDITabOwnerImpl with new template parameter
// for most derived class so that others can derive from it and
// have things work right. CMDITabOwner now is very simple and
// just inherits from CMDITabOwnerImpl
// - Use "LongToHandle" with return value from GetClassLong
//
// 2003/06/27: Daniel Bowen
// - CMDITabOwner:
// * Use typedefs for thisClass, baseClass, customTabOwnerClass
// * Replace
// DECLARE_WND_CLASS(_T("MdiTabOwner"))
// with
// DECLARE_WND_CLASS_EX(_T("MdiTabOwner"), 0, COLOR_APPWORKSPACE)
// (gets rid of CS_DBLCLKS, CS_HREDRAW and CS_VREDRAW, sets background brush)
// * Have OnAddFirstTab and OnRemoveLastTab call base class versions
// (in case we ever do anything interesting there)
// - Check failure of window creation (DefWindowProc when handling WM_CREATE)
// and return immediately if it failed.
//
// 2003/06/03: Daniel Bowen
// - Fix compile errors for VC 7.1
//
// 2003/02/27: Daniel Bowen
// - Use _U_RECT instead of WTL::_U_RECT.
// For VC7, this means you must #define _WTL_NO_UNION_CLASSES
// before including the WTL header files, or you will
// get compile errors (the ATL7 union classes are defined
// in atlwin.h).
//
// 2002/12/11: Daniel Bowen
// - New UWM_MDICHILDSAVEMODIFIED message sent to MDI child frames.
// The child frame receiving this should see if the "document"
// has been modified, and needs to be saved (usually with a
// yes/no/cancel message box). If the user chooses to cancel,
// return non-zero from the UWM_MDICHILDSAVEMODIFIED handler.
// - CTabbedMDIClient -
// * SaveAllModified - Iterates the MDI child windows, and
// sends UWM_MDICHILDSAVEMODIFIED. If a child returns non-zero,
// the iteration stops. You can also specify whether to
// close the child window after sending UWM_MDICHILDSAVEMODIFIED.
// * CloseAll - Close All MDI child windows. When handling WM_CLOSE,
// the MDI child window should *not* have a "Cancel" option
// if prompting to save a modified document.
//
// 2002/11/27: Daniel Bowen
// - CTabbedMDIChildWindowImpl -
// * When handling WM_MOUSEACTIVATE in CTabbedMDIChildWindowImpl,
// let the message get to the top window before possibly doing
// MDIActivate (more like the MFC code in CMDIChildWnd::OnMouseActivate)
//
// 2002/11/21: Daniel Bowen
// - CMDITabOwner -
// * ModifyTabStyles for use before CMDITabOwner is created as a window
// - CTabbedMDIClient -
// * Expose SetDrawFlat and GetDrawFlat
// * Updates so that drawing flat draws correctly
// - CTabbedMDIChildWindowImpl -
// * Handle WM_MOUSEACTIVATE, and call MDIActivate if
// MDI child is not already active. This solves the problem
// where you have a dialog window as the view of the MDI child,
// and clicking on a child control (edit box, etc.) doesn't
// give focus or activate the MDI child (or activate the app
// if its not active). This code will ideally make its
// way into future versions of WTL.
//
// 2002/09/25: Daniel Bowen
// - CTabbedMDICommandBarCtrl -
// * Break out CTabbedMDICommandBarCtrl into CTabbedMDICommandBarCtrlImpl
// and CTabbedMDICommandBarCtrl (just like CMDICommandBarCtrlImpl
// and CMDICommandBarCtrl).
// You can derive from CTabbedMDICommandBarCtrlImpl
// if you would like to extend functionality (such as providing
// your own handling of WM_MDISETMENU). See the commented out
// sample class after CTabbedMDICommandBarCtrl.
// - CMDITabOwner -
// * Expose "SetTabStyles" and "GetTabStyles" so that you can change
// the tab related styles to something different than the default
// - UWM_MDI... messages -
// * The TabbedMDI related classes use a handful of custom window
// messages. These messages are guaranteed to be unique across
// all windows for a particular windows session by using
// RegisterWindowMessage
//
// Initially, these message IDs were declared as static variables
// and initialized here in the header.
// However, that gave them "internal linkeage". Essentially,
// this meant that there were multiple copies of these variables.
// In Visual C++ 6, there was also a bug that caused the variables
// not to be initialized properly in release mode. So the class
// CTabbedMDIChildWindowImpl ensured their initialization in its
// constructor. The problem was, only the version of the variables
// in the same translation unit got initialized by doing it this way.
//
// These variables are now declared using __declspec(selectany)
// so that there will not be multiple copies. RegisterWindowMessage
// for each message ID is now called in the constructor of the
// struct "RegisterTabbedMDIMessages". If you are using _ATL_MIN_CRT
// or define _TABBEDMDI_MESSAGES_EXTERN_REGISTER, then you must
// have an instance of the "RegisterTabbedMDIMessages" struct in
// one .cpp file. Otherwise, a global instance of the struct will
// be declared in this header file (whose constructor will be called
// by the CRT at load time). If you are not referencing
// TabbedMDI.h in stdafx.h, and have multiple translation units
// including it, then you'll need to do it the
// _TABBEDMDI_MESSAGES_EXTERN_REGISTER way. Also, if you do
// use _ATL_MIN_CRT, you will get a warning unless you define
// _TABBEDMDI_MESSAGES_NO_WARN_ATL_MIN_CRT
//
// 2002/08/26: Daniel Bowen
// - CTabbedMDIClient -
// * Add new template parameter "TTabOwner" to allow easily
// changing the tab owner class used
//
// 2002/06/26: Daniel Bowen
// - CTabbedMDIFrameWindowImpl - Expose "TClient" and "TTabCtrl".
// - CMDITabOwner - Expose "TTabCtrl".
// - CTabbedMDIClient -
// * Expose "TTabCtrl"
// * New method "GetTabOwner" to get a reference to the C++ class
// instance implementing the MDI tab owner window.
// * New method "UseMDIChildIcon" to specify that you want the MDI
// tabs to include the document icon for the MDI child on the
// corresponding tab
//
// 2002/06/12: Daniel Bowen
// - Publish codeproject article. For history prior
// to the release of the article, please see the article
// and the section "Note to previous users"
#ifndef __WTL_TABBED_MDI_H__
#define __WTL_TABBED_MDI_H__
#pragma once
#ifndef __cplusplus
#error Tabbed MDI requires C++ compilation (use a .cpp suffix)
#endif
#ifndef __ATLAPP_H__
#error TabbedMDI.h requires atlapp.h to be included first
#endif
#ifndef __ATLWIN_H__
#error TabbedMDI.h requires atlwin.h to be included first
#endif
#ifndef __ATLFRAME_H__
#error TabbedFrame.h requires atlframe.h to be included first
#endif
#ifndef __ATLCTRLW_H__
#error TabbedFrame.h requires atlctrlw.h to be included first
#endif
#if _WTL_VER < 0x0710
#error TabbedMDI.h requires WTL 7.1 or higher
#endif
#ifndef __CUSTOMTABCTRL_H__
#include "CustomTabCtrl.h"
#endif
#ifndef __WTL_TABBED_FRAME_H__
#include "TabbedFrame.h"
#endif
#ifndef __WTL_TABBED_MDI_MESSAGES_H__
#include "TabbedMDIMessages.h"
#endif
/////////////////////////////////////////////////////////////////////////////
//
// CTabbedMDIFrameWindowImpl
//
/////////////////////////////////////////////////////////////////////////////
template <
class T,
class TClient = CTabbedMDIClient< CDotNetTabCtrl<CTabViewTabItem> >,
class TBase = WTL::CMDIWindow,
class TWinTraits = ATL::CFrameWinTraits>
class ATL_NO_VTABLE CTabbedMDIFrameWindowImpl :
public WTL::CMDIFrameWindowImpl<T, TBase, TWinTraits >
{
public:
// Expose the type of MDI client
typedef typename TClient TClient;
// Expose the type of tab control
typedef typename TClient::TTabCtrl TTabCtrl;
// Member variables
protected:
TClient m_tabbedClient;
// Methods
public:
// Either call the normal "CreateMDIClient"
HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD)
{
HWND hWndClient = baseClass::CreateMDIClient(hWindowMenu, nID, nFirstChildID);
this->SubclassMDIClient();
return hWndClient;
}
// Or, after creating the client, call SubclassMDIClient
BOOL SubclassMDIClient()
{
ATLASSERT(m_hWndMDIClient && ::IsWindow(m_hWndMDIClient));
return m_tabbedClient.SubclassWindow(m_hWndMDIClient);
}
void SetTabOwnerParent(HWND hWndTabOwnerParent)
{
m_tabbedClient.SetTabOwnerParent(hWndTabOwnerParent);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -