1 // Windows Template Library - WTL version 8.0
2 // Copyright (C) Microsoft Corporation. All rights reserved.
4 // This file is a part of the Windows Template Library.
5 // The use and distribution terms for this software are covered by the
6 // Microsoft Permissive License (Ms-PL) which can be found in the file
7 // Ms-PL.txt at the root of this distribution.
10 #define __ATLFRAME_H__
15 #error ATL requires C++ compilation (use a .cpp suffix)
19 #error atlframe.h requires atlapp.h to be included first
23 #error atlframe.h requires atlwin.h to be included first
27 ///////////////////////////////////////////////////////////////////////////////
28 // Classes in this file:
30 // CFrameWindowImpl<T, TBase, TWinTraits>
32 // CMDIFrameWindowImpl<T, TBase, TWinTraits>
33 // CMDIChildWindowImpl<T, TBase, TWinTraits>
37 // CDynamicUpdateUI<T>
39 // CDoubleBufferImpl<T>
40 // CDoubleBufferWindowImpl<T, TBase, TWinTraits>
43 // AtlCreateSimpleToolBar()
49 ///////////////////////////////////////////////////////////////////////////////
50 // CFrameWndClassInfo - Manages frame window Windows class information
52 class CFrameWndClassInfo
56 enum { cchAutoName
= 5 + sizeof(void*) * 2 }; // sizeof(void*) * 2 is the number of digits %p outputs
59 enum { cchAutoName
= MAX_PATH
}; // MAX_PATH because this can be set in the wizard generated CMainFrame::ActivatePreviousInstance to a user defined string.
62 LPCTSTR m_lpszOrigName
;
64 LPCTSTR m_lpszCursorID
;
67 TCHAR m_szAutoName
[cchAutoName
];
68 UINT m_uCommonResourceID
;
71 ATOM
Register(WNDPROC
* pProc
)
75 CWindowCreateCriticalSectionLock lock
;
76 if(FAILED(lock
.Lock()))
78 ATLTRACE2(atlTraceUI
, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
85 HINSTANCE hInst
= ModuleHelper::GetModuleInstance();
87 if (m_lpszOrigName
!= NULL
)
89 ATLASSERT(pProc
!= NULL
);
90 LPCTSTR lpsz
= m_wc
.lpszClassName
;
91 WNDPROC proc
= m_wc
.lpfnWndProc
;
93 WNDCLASSEX wc
= { 0 };
94 wc
.cbSize
= sizeof(WNDCLASSEX
);
95 // try process local class first
96 if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName
, &wc
))
99 if(!::GetClassInfoEx(NULL
, m_lpszOrigName
, &wc
))
106 pWndProc
= m_wc
.lpfnWndProc
;
107 m_wc
.lpszClassName
= lpsz
;
108 m_wc
.lpfnWndProc
= proc
;
112 m_wc
.hCursor
= ::LoadCursor(m_bSystemCursor
? NULL
: hInst
, m_lpszCursorID
);
115 m_wc
.hInstance
= hInst
;
116 m_wc
.style
&= ~CS_GLOBALCLASS
; // we don't register global classes
117 if (m_wc
.lpszClassName
== NULL
)
119 #if (_WIN32_WINNT >= 0x0500) || defined(_WIN64)
120 SecureHelper::wsprintf_x(m_szAutoName
, cchAutoName
, _T("ATL:%p"), &m_wc
);
121 #else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
122 SecureHelper::wsprintf_x(m_szAutoName
, cchAutoName
, _T("ATL:%8.8X"), (DWORD_PTR
)&m_wc
);
123 #endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
124 m_wc
.lpszClassName
= m_szAutoName
;
127 WNDCLASSEX wcTemp
= m_wc
;
128 m_atom
= (ATOM
)::GetClassInfoEx(m_wc
.hInstance
, m_wc
.lpszClassName
, &wcTemp
);
131 if(m_uCommonResourceID
!= 0) // use it if not zero
133 m_wc
.hIcon
= (HICON
)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID
), IMAGE_ICON
, 32, 32, LR_DEFAULTCOLOR
);
134 m_wc
.hIconSm
= (HICON
)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID
), IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
136 m_atom
= ::RegisterClassEx(&m_wc
);
143 if (m_lpszOrigName
!= NULL
)
145 ATLASSERT(pProc
!= NULL
);
146 ATLASSERT(pWndProc
!= NULL
);
153 ATOM
Register(WNDPROC
* pProc
)
157 CWindowCreateCriticalSectionLock lock
;
158 if(FAILED(lock
.Lock()))
160 ATLTRACE2(atlTraceUI
, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
167 HINSTANCE hInst
= ModuleHelper::GetModuleInstance();
169 if (m_lpszOrigName
!= NULL
)
171 ATLASSERT(pProc
!= NULL
);
172 LPCTSTR lpsz
= m_wc
.lpszClassName
;
173 WNDPROC proc
= m_wc
.lpfnWndProc
;
176 // try process local class first
177 if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName
, &wc
))
180 if(!::GetClassInfo(NULL
, m_lpszOrigName
, &wc
))
187 pWndProc
= m_wc
.lpfnWndProc
;
188 m_wc
.lpszClassName
= lpsz
;
189 m_wc
.lpfnWndProc
= proc
;
193 #if defined(GWES_CURSOR) || defined(GWES_MCURSOR)
194 m_wc
.hCursor
= ::LoadCursor(m_bSystemCursor
? NULL
: hInst
, m_lpszCursorID
);
195 #else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
197 #endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
200 m_wc
.hInstance
= hInst
;
201 m_wc
.style
&= ~CS_GLOBALCLASS
; // we don't register global classes
202 if (m_wc
.lpszClassName
== NULL
)
204 wsprintf(m_szAutoName
, _T("ATL:%8.8X"), (DWORD_PTR
)&m_wc
);
205 m_wc
.lpszClassName
= m_szAutoName
;
208 WNDCLASS wcTemp
= m_wc
;
209 m_atom
= (ATOM
)::GetClassInfo(m_wc
.hInstance
, m_wc
.lpszClassName
, &wcTemp
);
212 if(m_uCommonResourceID
!= 0) // use it if not zero
213 m_wc
.hIcon
= (HICON
)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID
), IMAGE_ICON
, 32, 32, LR_DEFAULTCOLOR
);
214 m_atom
= ::RegisterClass(&m_wc
);
221 if (m_lpszOrigName
!= NULL
)
223 ATLASSERT(pProc
!= NULL
);
224 ATLASSERT(pWndProc
!= NULL
);
234 ///////////////////////////////////////////////////////////////////////////////
235 // Macros for declaring frame window WNDCLASS
239 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
240 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
242 static WTL::CFrameWndClassInfo wc = \
244 { sizeof(WNDCLASSEX), 0, StartWindowProc, \
245 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
246 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
251 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
252 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
254 static WTL::CFrameWndClassInfo wc = \
256 { sizeof(WNDCLASSEX), style, StartWindowProc, \
257 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
258 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
263 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
264 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
266 static WTL::CFrameWndClassInfo wc = \
268 { sizeof(WNDCLASSEX), 0, StartWindowProc, \
269 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
270 OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
277 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
278 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
280 static WTL::CFrameWndClassInfo wc = \
282 { 0, StartWindowProc, \
283 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
284 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
289 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
290 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
292 static WTL::CFrameWndClassInfo wc = \
294 { style, StartWindowProc, \
295 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
296 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
301 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
302 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
304 static WTL::CFrameWndClassInfo wc = \
306 { NULL, StartWindowProc, \
307 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \
308 OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
313 #endif // !_WIN32_WCE
316 ///////////////////////////////////////////////////////////////////////////////
319 // Client window command chaining macro (only for frame windows)
320 #define CHAIN_CLIENT_COMMANDS() \
321 if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
322 ::SendMessage(m_hWndClient, uMsg, wParam, lParam);
324 // standard toolbar styles
325 #define ATL_SIMPLE_TOOLBAR_STYLE \
326 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS)
327 // toolbar in a rebar pane
328 #define ATL_SIMPLE_TOOLBAR_PANE_STYLE \
329 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT)
330 // standard rebar styles
331 #if (_WIN32_IE >= 0x0400)
332 #define ATL_SIMPLE_REBAR_STYLE \
333 (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE)
335 #define ATL_SIMPLE_REBAR_STYLE \
336 (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS)
337 #endif // !(_WIN32_IE >= 0x0400)
338 // rebar without borders
339 #if (_WIN32_IE >= 0x0400)
340 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
341 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER)
343 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
344 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER)
345 #endif // !(_WIN32_IE >= 0x0400)
347 // command bar support
348 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
350 #define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND
351 #define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu
352 #define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu
354 struct _AtlFrameWnd_CmdBarPopupMenu
364 #define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu
366 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
369 template <class TBase
= ATL::CWindow
, class TWinTraits
= ATL::CFrameWinTraits
>
370 class ATL_NO_VTABLE CFrameWindowImplBase
: public ATL::CWindowImplBaseT
< TBase
, TWinTraits
>
373 DECLARE_FRAME_WND_CLASS(NULL
, 0)
377 HWND m_hWndStatusBar
;
383 HWND m_hWndCECommandBar
;
386 struct _AtlToolBarData
392 //WORD aItems[wItemCount]
395 { return (WORD
*)(this+1); }
398 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
399 struct _ChevronMenuInfo
402 LPNMREBARCHEVRON lpnm
;
405 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
408 CFrameWindowImplBase() :
410 m_hWndCECommandBar(NULL
),
413 m_hWndStatusBar(NULL
),
419 HWND
Create(HWND hWndParent
, ATL::_U_RECT rect
, LPCTSTR szWindowName
, DWORD dwStyle
, DWORD dwExStyle
, ATL::_U_MENUorID MenuOrID
, ATOM atom
, LPVOID lpCreateParam
)
421 ATLASSERT(m_hWnd
== NULL
);
426 ModuleHelper::AddCreateWndData(&m_thunk
.cd
, this);
428 if(MenuOrID
.m_hMenu
== NULL
&& (dwStyle
& WS_CHILD
))
429 MenuOrID
.m_hMenu
= (HMENU
)(UINT_PTR
)this;
430 if(rect
.m_lpRect
== NULL
)
431 rect
.m_lpRect
= &TBase::rcDefault
;
433 HWND hWnd
= ::CreateWindowEx(dwExStyle
, MAKEINTATOM(atom
), szWindowName
,
434 dwStyle
, rect
.m_lpRect
->left
, rect
.m_lpRect
->top
, rect
.m_lpRect
->right
- rect
.m_lpRect
->left
,
435 rect
.m_lpRect
->bottom
- rect
.m_lpRect
->top
, hWndParent
, MenuOrID
.m_hMenu
,
436 ModuleHelper::GetModuleInstance(), lpCreateParam
);
438 ATLASSERT(hWnd
== NULL
|| m_hWnd
== hWnd
);
443 static HWND
CreateSimpleToolBarCtrl(HWND hWndParent
, UINT nResourceID
, BOOL bInitialSeparator
= FALSE
,
444 DWORD dwStyle
= ATL_SIMPLE_TOOLBAR_STYLE
, UINT nID
= ATL_IDW_TOOLBAR
)
446 HINSTANCE hInst
= ModuleHelper::GetResourceInstance();
447 HRSRC hRsrc
= ::FindResource(hInst
, MAKEINTRESOURCE(nResourceID
), RT_TOOLBAR
);
451 HGLOBAL hGlobal
= ::LoadResource(hInst
, hRsrc
);
455 _AtlToolBarData
* pData
= (_AtlToolBarData
*)::LockResource(hGlobal
);
458 ATLASSERT(pData
->wVersion
== 1);
460 WORD
* pItems
= pData
->items();
461 int nItems
= pData
->wItemCount
+ (bInitialSeparator
? 1 : 0);
462 CTempBuffer
<TBBUTTON
, _WTL_STACK_ALLOC_THRESHOLD
> buff
;
463 TBBUTTON
* pTBBtn
= buff
.Allocate(nItems
);
464 ATLASSERT(pTBBtn
!= NULL
);
468 const int cxSeparator
= 8;
470 // set initial separator (half width)
471 if(bInitialSeparator
)
473 pTBBtn
[0].iBitmap
= cxSeparator
/ 2;
474 pTBBtn
[0].idCommand
= 0;
475 pTBBtn
[0].fsState
= 0;
476 pTBBtn
[0].fsStyle
= TBSTYLE_SEP
;
477 pTBBtn
[0].dwData
= 0;
478 pTBBtn
[0].iString
= 0;
482 for(int i
= 0, j
= bInitialSeparator
? 1 : 0; i
< pData
->wItemCount
; i
++, j
++)
486 pTBBtn
[j
].iBitmap
= nBmp
++;
487 pTBBtn
[j
].idCommand
= pItems
[i
];
488 pTBBtn
[j
].fsState
= TBSTATE_ENABLED
;
489 pTBBtn
[j
].fsStyle
= TBSTYLE_BUTTON
;
490 pTBBtn
[j
].dwData
= 0;
491 pTBBtn
[j
].iString
= 0;
495 pTBBtn
[j
].iBitmap
= cxSeparator
;
496 pTBBtn
[j
].idCommand
= 0;
497 pTBBtn
[j
].fsState
= 0;
498 pTBBtn
[j
].fsStyle
= TBSTYLE_SEP
;
499 pTBBtn
[j
].dwData
= 0;
500 pTBBtn
[j
].iString
= 0;
505 HWND hWnd
= ::CreateWindowEx(0, TOOLBARCLASSNAME
, NULL
, dwStyle
, 0, 0, 100, 100, hWndParent
, (HMENU
)LongToHandle(nID
), ModuleHelper::GetModuleInstance(), NULL
);
514 // The toolbar must go onto the existing CommandBar or MenuBar
515 HWND hWnd
= hWndParent
;
518 ::SendMessage(hWnd
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0L);
520 // check if font is taller than our bitmaps
521 CFontHandle font
= (HFONT
)::SendMessage(hWnd
, WM_GETFONT
, 0, 0L);
523 font
= AtlGetDefaultGuiFont();
526 WORD cyFontHeight
= (WORD
)abs(lf
.lfHeight
);
529 WORD bitsPerPixel
= AtlGetBitmapResourceBitsPerPixel(nResourceID
);
532 COLORREF crMask
= CLR_DEFAULT
;
533 if(bitsPerPixel
== 32)
535 // 32-bit color bitmap with alpha channel (valid for Windows XP and later)
538 HIMAGELIST hImageList
= ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID
), pData
->wWidth
, 1, crMask
, IMAGE_BITMAP
, LR_CREATEDIBSECTION
| LR_DEFAULTSIZE
);
539 ATLASSERT(hImageList
!= NULL
);
540 ::SendMessage(hWnd
, TB_SETIMAGELIST
, 0, (LPARAM
)hImageList
);
543 #endif // !_WIN32_WCE
545 TBADDBITMAP tbab
= { 0 };
547 tbab
.nID
= nResourceID
;
548 ::SendMessage(hWnd
, TB_ADDBITMAP
, nBmp
, (LPARAM
)&tbab
);
551 ::SendMessage(hWnd
, TB_ADDBUTTONS
, nItems
, (LPARAM
)pTBBtn
);
552 ::SendMessage(hWnd
, TB_SETBITMAPSIZE
, 0, MAKELONG(pData
->wWidth
, __max(pData
->wHeight
, cyFontHeight
)));
553 const int cxyButtonMargin
= 7;
554 ::SendMessage(hWnd
, TB_SETBUTTONSIZE
, 0, MAKELONG(pData
->wWidth
+ cxyButtonMargin
, __max(pData
->wHeight
, cyFontHeight
) + cxyButtonMargin
));
560 static HWND
CreateSimpleReBarCtrl(HWND hWndParent
, DWORD dwStyle
= ATL_SIMPLE_REBAR_STYLE
, UINT nID
= ATL_IDW_TOOLBAR
)
562 // Ensure style combinations for proper rebar painting
563 if(dwStyle
& CCS_NODIVIDER
&& dwStyle
& WS_BORDER
)
564 dwStyle
&= ~WS_BORDER
;
565 else if(!(dwStyle
& WS_BORDER
) && !(dwStyle
& CCS_NODIVIDER
))
566 dwStyle
|= CCS_NODIVIDER
;
568 // Create rebar window
569 HWND hWndReBar
= ::CreateWindowEx(0, REBARCLASSNAME
, NULL
, dwStyle
, 0, 0, 100, 100, hWndParent
, (HMENU
)LongToHandle(nID
), ModuleHelper::GetModuleInstance(), NULL
);
570 if(hWndReBar
== NULL
)
572 ATLTRACE2(atlTraceUI
, 0, _T("Failed to create rebar.\n"));
576 // Initialize and send the REBARINFO structure
577 REBARINFO rbi
= { 0 };
578 rbi
.cbSize
= sizeof(REBARINFO
);
580 if(!::SendMessage(hWndReBar
, RB_SETBARINFO
, 0, (LPARAM
)&rbi
))
582 ATLTRACE2(atlTraceUI
, 0, _T("Failed to initialize rebar.\n"));
583 ::DestroyWindow(hWndReBar
);
590 BOOL
CreateSimpleReBar(DWORD dwStyle
= ATL_SIMPLE_REBAR_STYLE
, UINT nID
= ATL_IDW_TOOLBAR
)
592 ATLASSERT(!::IsWindow(m_hWndToolBar
));
593 m_hWndToolBar
= CreateSimpleReBarCtrl(m_hWnd
, dwStyle
, nID
);
594 return (m_hWndToolBar
!= NULL
);
597 static BOOL
AddSimpleReBarBandCtrl(HWND hWndReBar
, HWND hWndBand
, int nID
= 0, LPCTSTR lpstrTitle
= NULL
, BOOL bNewRow
= FALSE
, int cxWidth
= 0, BOOL bFullWidthAlways
= FALSE
)
599 ATLASSERT(::IsWindow(hWndReBar
)); // must be already created
601 // block - check if this is really a rebar
603 TCHAR lpszClassName
[sizeof(REBARCLASSNAME
)] = { 0 };
604 ::GetClassName(hWndReBar
, lpszClassName
, sizeof(REBARCLASSNAME
));
605 ATLASSERT(lstrcmp(lpszClassName
, REBARCLASSNAME
) == 0);
608 ATLASSERT(::IsWindow(hWndBand
)); // must be already created
610 // Get number of buttons on the toolbar
611 int nBtnCount
= (int)::SendMessage(hWndBand
, TB_BUTTONCOUNT
, 0, 0L);
613 // Set band info structure
614 REBARBANDINFO rbBand
= { RunTimeHelper::SizeOf_REBARBANDINFO() };
615 #if (_WIN32_IE >= 0x0400)
616 rbBand
.fMask
= RBBIM_CHILD
| RBBIM_CHILDSIZE
| RBBIM_STYLE
| RBBIM_ID
| RBBIM_SIZE
| RBBIM_IDEALSIZE
;
618 rbBand
.fMask
= RBBIM_CHILD
| RBBIM_CHILDSIZE
| RBBIM_STYLE
| RBBIM_ID
| RBBIM_SIZE
;
619 #endif // !(_WIN32_IE >= 0x0400)
620 if(lpstrTitle
!= NULL
)
621 rbBand
.fMask
|= RBBIM_TEXT
;
622 rbBand
.fStyle
= RBBS_CHILDEDGE
;
623 #if (_WIN32_IE >= 0x0500)
624 if(nBtnCount
> 0) // add chevron style for toolbar with buttons
625 rbBand
.fStyle
|= RBBS_USECHEVRON
;
626 #endif // (_WIN32_IE >= 0x0500)
628 rbBand
.fStyle
|= RBBS_BREAK
;
630 rbBand
.lpText
= (LPTSTR
)lpstrTitle
;
631 rbBand
.hwndChild
= hWndBand
;
632 if(nID
== 0) // calc band ID
633 nID
= ATL_IDW_BAND_FIRST
+ (int)::SendMessage(hWndReBar
, RB_GETBANDCOUNT
, 0, 0L);
636 // Calculate the size of the band
641 bRet
= (BOOL
)::SendMessage(hWndBand
, TB_GETITEMRECT
, nBtnCount
- 1, (LPARAM
)&rcTmp
);
643 rbBand
.cx
= (cxWidth
!= 0) ? cxWidth
: rcTmp
.right
;
644 rbBand
.cyMinChild
= rcTmp
.bottom
- rcTmp
.top
;
647 rbBand
.cxMinChild
= rbBand
.cx
;
649 else if(lpstrTitle
== NULL
)
651 bRet
= (BOOL
)::SendMessage(hWndBand
, TB_GETITEMRECT
, 0, (LPARAM
)&rcTmp
);
653 rbBand
.cxMinChild
= rcTmp
.right
;
657 rbBand
.cxMinChild
= 0;
660 else // no buttons, either not a toolbar or really has no buttons
662 bRet
= ::GetWindowRect(hWndBand
, &rcTmp
);
664 rbBand
.cx
= (cxWidth
!= 0) ? cxWidth
: (rcTmp
.right
- rcTmp
.left
);
665 rbBand
.cxMinChild
= bFullWidthAlways
? rbBand
.cx
: 0;
666 rbBand
.cyMinChild
= rcTmp
.bottom
- rcTmp
.top
;
669 #if (_WIN32_IE >= 0x0400)
670 rbBand
.cxIdeal
= rbBand
.cx
;
671 #endif // (_WIN32_IE >= 0x0400)
674 LRESULT lRes
= ::SendMessage(hWndReBar
, RB_INSERTBAND
, (WPARAM
)-1, (LPARAM
)&rbBand
);
677 ATLTRACE2(atlTraceUI
, 0, _T("Failed to add a band to the rebar.\n"));
681 #if (_WIN32_IE >= 0x0501)
682 DWORD dwExStyle
= (DWORD
)::SendMessage(hWndBand
, TB_GETEXTENDEDSTYLE
, 0, 0L);
683 ::SendMessage(hWndBand
, TB_SETEXTENDEDSTYLE
, 0, dwExStyle
| TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
684 #endif // (_WIN32_IE >= 0x0501)
689 BOOL
AddSimpleReBarBand(HWND hWndBand
, LPCTSTR lpstrTitle
= NULL
, BOOL bNewRow
= FALSE
, int cxWidth
= 0, BOOL bFullWidthAlways
= FALSE
)
691 ATLASSERT(::IsWindow(m_hWndToolBar
)); // must be an existing rebar
692 ATLASSERT(::IsWindow(hWndBand
)); // must be created
693 return AddSimpleReBarBandCtrl(m_hWndToolBar
, hWndBand
, 0, lpstrTitle
, bNewRow
, cxWidth
, bFullWidthAlways
);
696 #if (_WIN32_IE >= 0x0400)
697 void SizeSimpleReBarBands()
699 ATLASSERT(::IsWindow(m_hWndToolBar
)); // must be an existing rebar
701 int nCount
= (int)::SendMessage(m_hWndToolBar
, RB_GETBANDCOUNT
, 0, 0L);
703 for(int i
= 0; i
< nCount
; i
++)
705 REBARBANDINFO rbBand
= { RunTimeHelper::SizeOf_REBARBANDINFO() };
706 rbBand
.fMask
= RBBIM_SIZE
;
707 BOOL bRet
= (BOOL
)::SendMessage(m_hWndToolBar
, RB_GETBANDINFO
, i
, (LPARAM
)&rbBand
);
709 RECT rect
= { 0, 0, 0, 0 };
710 ::SendMessage(m_hWndToolBar
, RB_GETBANDBORDERS
, i
, (LPARAM
)&rect
);
711 rbBand
.cx
+= rect
.left
+ rect
.right
;
712 bRet
= (BOOL
)::SendMessage(m_hWndToolBar
, RB_SETBANDINFO
, i
, (LPARAM
)&rbBand
);
716 #endif // (_WIN32_IE >= 0x0400)
720 BOOL
CreateSimpleStatusBar(LPCTSTR lpstrText
, DWORD dwStyle
= WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| SBARS_SIZEGRIP
, UINT nID
= ATL_IDW_STATUS_BAR
)
722 BOOL
CreateSimpleStatusBar(LPCTSTR lpstrText
, DWORD dwStyle
= WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, UINT nID
= ATL_IDW_STATUS_BAR
)
725 ATLASSERT(!::IsWindow(m_hWndStatusBar
));
726 m_hWndStatusBar
= ::CreateStatusWindow(dwStyle
, lpstrText
, m_hWnd
, nID
);
727 return (m_hWndStatusBar
!= NULL
);
731 BOOL
CreateSimpleStatusBar(UINT nTextID
= ATL_IDS_IDLEMESSAGE
, DWORD dwStyle
= WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| SBARS_SIZEGRIP
, UINT nID
= ATL_IDW_STATUS_BAR
)
733 BOOL
CreateSimpleStatusBar(UINT nTextID
= ATL_IDS_IDLEMESSAGE
, DWORD dwStyle
= WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, UINT nID
= ATL_IDW_STATUS_BAR
)
736 const int cchMax
= 128; // max text length is 127 for status bars (+1 for null)
737 TCHAR szText
[cchMax
];
739 ::LoadString(ModuleHelper::GetResourceInstance(), nTextID
, szText
, cchMax
);
740 return CreateSimpleStatusBar(szText
, dwStyle
, nID
);
744 BOOL
CreateSimpleCECommandBar(LPTSTR pszMenu
= NULL
, WORD iButton
= 0, DWORD dwFlags
= 0, int nCmdBarID
= 1)
746 ATLASSERT(m_hWndCECommandBar
== NULL
);
747 ATLASSERT(m_hWndToolBar
== NULL
);
749 m_hWndCECommandBar
= ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd
, nCmdBarID
);
750 if(m_hWndCECommandBar
== NULL
)
753 m_hWndToolBar
= m_hWndCECommandBar
;
758 bRet
&= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar
, IS_INTRESOURCE(pszMenu
) ? ModuleHelper::GetResourceInstance() : NULL
, pszMenu
, iButton
);
760 bRet
&= ::CommandBar_AddAdornments(m_hWndCECommandBar
, dwFlags
, 0);
765 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
766 BOOL
CreateSimpleCEMenuBar(UINT nToolBarId
= ATL_IDW_MENU_BAR
, DWORD dwFlags
= 0, int nBmpId
= 0, int cBmpImages
= 0)
768 ATLASSERT(m_hWndCECommandBar
== NULL
);
770 SHMENUBARINFO mbi
= { 0 };
771 mbi
.cbSize
= sizeof(mbi
);
772 mbi
.hwndParent
= m_hWnd
;
773 mbi
.dwFlags
= dwFlags
;
774 mbi
.nToolBarId
= nToolBarId
;
775 mbi
.hInstRes
= ModuleHelper::GetResourceInstance();
777 mbi
.cBmpImages
= cBmpImages
;
778 mbi
.hwndMB
= NULL
; // This gets set by SHCreateMenuBar
780 BOOL bRet
= ::SHCreateMenuBar(&mbi
);
783 m_hWndCECommandBar
= mbi
.hwndMB
;
790 void SizeToMenuBar() // for menu bar only
792 ATLASSERT(::IsWindow(m_hWnd
));
793 ATLASSERT(::IsWindow(m_hWndCECommandBar
));
796 GetWindowRect(&rect
);
798 ::GetWindowRect(m_hWndCECommandBar
, &rectMB
);
799 int cy
= ::IsWindowVisible(m_hWndCECommandBar
) ? rectMB
.top
- rect
.top
: rectMB
.bottom
- rect
.top
;
800 SetWindowPos(NULL
, 0, 0, rect
.right
- rect
.left
, cy
, SWP_NOZORDER
| SWP_NOMOVE
);
802 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
805 void UpdateLayout(BOOL bResizeBars
= TRUE
)
808 GetClientRect(&rect
);
810 // position bars and offset their dimensions
811 UpdateBarsPosition(rect
, bResizeBars
);
813 // resize client window
814 if(m_hWndClient
!= NULL
)
815 ::SetWindowPos(m_hWndClient
, NULL
, rect
.left
, rect
.top
,
816 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
817 SWP_NOZORDER
| SWP_NOACTIVATE
);
820 void UpdateBarsPosition(RECT
& rect
, BOOL bResizeBars
= TRUE
)
823 if(m_hWndToolBar
!= NULL
&& ((DWORD
)::GetWindowLong(m_hWndToolBar
, GWL_STYLE
) & WS_VISIBLE
))
827 ::SendMessage(m_hWndToolBar
, WM_SIZE
, 0, 0);
828 ::InvalidateRect(m_hWndToolBar
, NULL
, FALSE
);
831 ::GetWindowRect(m_hWndToolBar
, &rectTB
);
832 rect
.top
+= rectTB
.bottom
- rectTB
.top
;
836 if(m_hWndStatusBar
!= NULL
&& ((DWORD
)::GetWindowLong(m_hWndStatusBar
, GWL_STYLE
) & WS_VISIBLE
))
839 ::SendMessage(m_hWndStatusBar
, WM_SIZE
, 0, 0);
841 ::GetWindowRect(m_hWndStatusBar
, &rectSB
);
842 rect
.bottom
-= rectSB
.bottom
- rectSB
.top
;
846 BOOL
PreTranslateMessage(MSG
* pMsg
)
848 if(m_hAccel
!= NULL
&& ::TranslateAccelerator(m_hWnd
, m_hAccel
, pMsg
))
853 BEGIN_MSG_MAP(CFrameWindowImplBase
)
854 MESSAGE_HANDLER(WM_ERASEBKGND
, OnEraseBackground
)
856 MESSAGE_HANDLER(WM_MENUSELECT
, OnMenuSelect
)
857 #endif // !_WIN32_WCE
858 MESSAGE_HANDLER(WM_SETFOCUS
, OnSetFocus
)
859 MESSAGE_HANDLER(WM_DESTROY
, OnDestroy
)
861 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA
, OnToolTipTextA
)
862 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW
, OnToolTipTextW
)
863 #endif // !_WIN32_WCE
866 LRESULT
OnEraseBackground(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& bHandled
)
868 if(m_hWndClient
!= NULL
) // view will paint itself instead
876 LRESULT
OnMenuSelect(UINT
/*uMsg*/, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
880 if(m_hWndStatusBar
== NULL
)
883 WORD wFlags
= HIWORD(wParam
);
884 if(wFlags
== 0xFFFF && lParam
== NULL
) // menu closing
886 ::SendMessage(m_hWndStatusBar
, SB_SIMPLE
, FALSE
, 0L);
890 const int cchBuff
= 256;
891 TCHAR szBuff
[cchBuff
];
893 if(!(wFlags
& MF_POPUP
))
895 WORD wID
= LOWORD(wParam
);
896 // check for special cases
897 if(wID
>= 0xF000 && wID
< 0xF1F0) // system menu IDs
898 wID
= (WORD
)(((wID
- 0xF000) >> 4) + ATL_IDS_SCFIRST
);
899 else if(wID
>= ID_FILE_MRU_FIRST
&& wID
<= ID_FILE_MRU_LAST
) // MRU items
900 wID
= ATL_IDS_MRU_FILE
;
901 else if(wID
>= ATL_IDM_FIRST_MDICHILD
&& wID
<= ATL_IDM_LAST_MDICHILD
) // MDI child windows
902 wID
= ATL_IDS_MDICHILD
;
904 int nRet
= ::LoadString(ModuleHelper::GetResourceInstance(), wID
, szBuff
, cchBuff
);
905 for(int i
= 0; i
< nRet
; i
++)
907 if(szBuff
[i
] == _T('\n'))
914 ::SendMessage(m_hWndStatusBar
, SB_SIMPLE
, TRUE
, 0L);
915 ::SendMessage(m_hWndStatusBar
, SB_SETTEXT
, (255 | SBT_NOBORDERS
), (LPARAM
)szBuff
);
920 #endif // !_WIN32_WCE
922 LRESULT
OnSetFocus(UINT
, WPARAM
, LPARAM
, BOOL
& bHandled
)
924 if(m_hWndClient
!= NULL
)
925 ::SetFocus(m_hWndClient
);
931 LRESULT
OnDestroy(UINT
, WPARAM
, LPARAM
, BOOL
& bHandled
)
933 if((GetStyle() & (WS_CHILD
| WS_POPUP
)) == 0)
934 ::PostQuitMessage(1);
941 LRESULT
OnToolTipTextA(int idCtrl
, LPNMHDR pnmh
, BOOL
& /*bHandled*/)
943 LPNMTTDISPINFOA pDispInfo
= (LPNMTTDISPINFOA
)pnmh
;
944 pDispInfo
->szText
[0] = 0;
946 if((idCtrl
!= 0) && !(pDispInfo
->uFlags
& TTF_IDISHWND
))
948 const int cchBuff
= 256;
949 char szBuff
[cchBuff
];
951 int nRet
= ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl
, szBuff
, cchBuff
);
952 for(int i
= 0; i
< nRet
; i
++)
954 if(szBuff
[i
] == '\n')
956 SecureHelper::strncpyA_x(pDispInfo
->szText
, _countof(pDispInfo
->szText
), &szBuff
[i
+ 1], _TRUNCATE
);
960 #if (_WIN32_IE >= 0x0300)
961 if(nRet
> 0) // string was loaded, save it
962 pDispInfo
->uFlags
|= TTF_DI_SETITEM
;
963 #endif // (_WIN32_IE >= 0x0300)
969 LRESULT
OnToolTipTextW(int idCtrl
, LPNMHDR pnmh
, BOOL
& /*bHandled*/)
971 LPNMTTDISPINFOW pDispInfo
= (LPNMTTDISPINFOW
)pnmh
;
972 pDispInfo
->szText
[0] = 0;
974 if((idCtrl
!= 0) && !(pDispInfo
->uFlags
& TTF_IDISHWND
))
976 const int cchBuff
= 256;
977 wchar_t szBuff
[cchBuff
];
979 int nRet
= ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl
, szBuff
, cchBuff
);
980 for(int i
= 0; i
< nRet
; i
++)
982 if(szBuff
[i
] == L
'\n')
984 SecureHelper::strncpyW_x(pDispInfo
->szText
, _countof(pDispInfo
->szText
), &szBuff
[i
+ 1], _TRUNCATE
);
988 #if (_WIN32_IE >= 0x0300)
989 if(nRet
> 0) // string was loaded, save it
990 pDispInfo
->uFlags
|= TTF_DI_SETITEM
;
991 #endif // (_WIN32_IE >= 0x0300)
996 #endif // !_WIN32_WCE
998 // Implementation - chevron menu support
999 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1000 bool PrepareChevronMenu(_ChevronMenuInfo
& cmi
)
1002 // get rebar and toolbar
1003 REBARBANDINFO rbbi
= { RunTimeHelper::SizeOf_REBARBANDINFO() };
1004 rbbi
.fMask
= RBBIM_CHILD
;
1005 BOOL bRet
= (BOOL
)::SendMessage(cmi
.lpnm
->hdr
.hwndFrom
, RB_GETBANDINFO
, cmi
.lpnm
->uBand
, (LPARAM
)&rbbi
);
1008 // assume the band is a toolbar
1009 ATL::CWindow wnd
= rbbi
.hwndChild
;
1010 int nCount
= (int)wnd
.SendMessage(TB_BUTTONCOUNT
);
1011 if(nCount
<= 0) // probably not a toolbar
1014 // check if it's a command bar
1015 CMenuHandle menuCmdBar
= (HMENU
)wnd
.SendMessage(CBRM_GETMENU
);
1016 cmi
.bCmdBar
= (menuCmdBar
.m_hMenu
!= NULL
);
1018 // build a menu from hidden items
1020 bRet
= menu
.CreatePopupMenu();
1022 RECT rcClient
= { 0 };
1023 bRet
= wnd
.GetClientRect(&rcClient
);
1025 for(int i
= 0; i
< nCount
; i
++)
1027 TBBUTTON tbb
= { 0 };
1028 bRet
= (BOOL
)wnd
.SendMessage(TB_GETBUTTON
, i
, (LPARAM
)&tbb
);
1030 // skip hidden buttons
1031 if((tbb
.fsState
& TBSTATE_HIDDEN
) != 0)
1033 RECT rcButton
= { 0 };
1034 bRet
= (BOOL
)wnd
.SendMessage(TB_GETITEMRECT
, i
, (LPARAM
)&rcButton
);
1036 bool bEnabled
= ((tbb
.fsState
& TBSTATE_ENABLED
) != 0);
1037 if(rcButton
.right
> rcClient
.right
)
1039 if(tbb
.fsStyle
& BTNS_SEP
)
1041 if(menu
.GetMenuItemCount() > 0)
1042 menu
.AppendMenu(MF_SEPARATOR
);
1044 else if(cmi
.bCmdBar
)
1046 const int cchBuff
= 200;
1047 TCHAR szBuff
[cchBuff
] = { 0 };
1049 mii
.fMask
= MIIM_TYPE
| MIIM_SUBMENU
;
1050 mii
.dwTypeData
= szBuff
;
1052 bRet
= menuCmdBar
.GetMenuItemInfo(i
, TRUE
, &mii
);
1054 // Note: CmdBar currently supports only drop-down items
1055 ATLASSERT(::IsMenu(mii
.hSubMenu
));
1056 bRet
= menu
.AppendMenu(MF_STRING
| MF_POPUP
| (bEnabled
? MF_ENABLED
: MF_GRAYED
), (UINT_PTR
)mii
.hSubMenu
, mii
.dwTypeData
);
1061 // get button's text
1062 const int cchBuff
= 200;
1063 TCHAR szBuff
[cchBuff
] = { 0 };
1064 LPTSTR lpstrText
= szBuff
;
1065 TBBUTTONINFO tbbi
= { 0 };
1066 tbbi
.cbSize
= sizeof(TBBUTTONINFO
);
1067 tbbi
.dwMask
= TBIF_TEXT
;
1068 tbbi
.pszText
= szBuff
;
1069 tbbi
.cchText
= cchBuff
;
1070 if(wnd
.SendMessage(TB_GETBUTTONINFO
, tbb
.idCommand
, (LPARAM
)&tbbi
) == -1 || lstrlen(szBuff
) == 0)
1072 // no text for this button, try a resource string
1074 int nRet
= ::LoadString(ModuleHelper::GetResourceInstance(), tbb
.idCommand
, szBuff
, cchBuff
);
1075 for(int n
= 0; n
< nRet
; n
++)
1077 if(szBuff
[n
] == _T('\n'))
1079 lpstrText
= &szBuff
[n
+ 1];
1084 bRet
= menu
.AppendMenu(MF_STRING
| (bEnabled
? MF_ENABLED
: MF_GRAYED
), tbb
.idCommand
, lpstrText
);
1090 if(menu
.GetMenuItemCount() == 0) // no hidden buttons after all
1093 ::MessageBeep((UINT
)-1);
1101 void DisplayChevronMenu(_ChevronMenuInfo
& cmi
)
1103 #ifndef TPM_VERPOSANIMATION
1104 const UINT TPM_VERPOSANIMATION
= 0x1000L
; // Menu animation flag
1106 // convert chevron rect to screen coordinates
1107 ATL::CWindow wndFrom
= cmi
.lpnm
->hdr
.hwndFrom
;
1108 POINT pt
= { cmi
.lpnm
->rc
.left
, cmi
.lpnm
->rc
.bottom
};
1109 wndFrom
.MapWindowPoints(NULL
, &pt
, 1);
1110 RECT rc
= cmi
.lpnm
->rc
;
1111 wndFrom
.MapWindowPoints(NULL
, &rc
);
1112 // set up flags and rect
1113 UINT uMenuFlags
= TPM_LEFTBUTTON
| TPM_VERTICAL
| TPM_LEFTALIGN
| TPM_TOPALIGN
| (!AtlIsOldWindows() ? TPM_VERPOSANIMATION
: 0);
1114 TPMPARAMS TPMParams
= { 0 };
1115 TPMParams
.cbSize
= sizeof(TPMPARAMS
);
1116 TPMParams
.rcExclude
= rc
;
1117 // check if this window has a command bar
1118 HWND hWndCmdBar
= (HWND
)::SendMessage(m_hWnd
, CBRM_GETCMDBAR
, 0, 0L);
1119 if(::IsWindow(hWndCmdBar
))
1121 CBRPOPUPMENU CBRPopupMenu
= { sizeof(CBRPOPUPMENU
), cmi
.hMenu
, uMenuFlags
, pt
.x
, pt
.y
, &TPMParams
};
1122 ::SendMessage(hWndCmdBar
, CBRM_TRACKPOPUPMENU
, 0, (LPARAM
)&CBRPopupMenu
);
1126 CMenuHandle menu
= cmi
.hMenu
;
1127 menu
.TrackPopupMenuEx(uMenuFlags
, pt
.x
, pt
.y
, m_hWnd
, &TPMParams
);
1131 void CleanupChevronMenu(_ChevronMenuInfo
& cmi
)
1133 CMenuHandle menu
= cmi
.hMenu
;
1134 // if menu is from a command bar, detach submenus so they are not destroyed
1137 for(int i
= menu
.GetMenuItemCount() - 1; i
>=0; i
--)
1138 menu
.RemoveMenu(i
, MF_BYPOSITION
);
1142 // convert chevron rect to screen coordinates
1143 ATL::CWindow wndFrom
= cmi
.lpnm
->hdr
.hwndFrom
;
1144 RECT rc
= cmi
.lpnm
->rc
;
1145 wndFrom
.MapWindowPoints(NULL
, &rc
);
1146 // eat next message if click is on the same button
1148 if(::PeekMessage(&msg
, m_hWnd
, WM_LBUTTONDOWN
, WM_LBUTTONDOWN
, PM_NOREMOVE
) && ::PtInRect(&rc
, msg
.pt
))
1149 ::PeekMessage(&msg
, m_hWnd
, WM_LBUTTONDOWN
, WM_LBUTTONDOWN
, PM_REMOVE
);
1151 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1155 template <class T
, class TBase
= ATL::CWindow
, class TWinTraits
= ATL::CFrameWinTraits
>
1156 class ATL_NO_VTABLE CFrameWindowImpl
: public CFrameWindowImplBase
< TBase
, TWinTraits
>
1159 HWND
Create(HWND hWndParent
= NULL
, ATL::_U_RECT rect
= NULL
, LPCTSTR szWindowName
= NULL
,
1160 DWORD dwStyle
= 0, DWORD dwExStyle
= 0,
1161 HMENU hMenu
= NULL
, LPVOID lpCreateParam
= NULL
)
1163 ATOM atom
= T::GetWndClassInfo().Register(&m_pfnSuperWindowProc
);
1165 dwStyle
= T::GetWndStyle(dwStyle
);
1166 dwExStyle
= T::GetWndExStyle(dwExStyle
);
1168 if(rect
.m_lpRect
== NULL
)
1169 rect
.m_lpRect
= &TBase::rcDefault
;
1171 return CFrameWindowImplBase
< TBase
, TWinTraits
>::Create(hWndParent
, rect
.m_lpRect
, szWindowName
, dwStyle
, dwExStyle
, hMenu
, atom
, lpCreateParam
);
1174 HWND
CreateEx(HWND hWndParent
= NULL
, ATL::_U_RECT rect
= NULL
, DWORD dwStyle
= 0, DWORD dwExStyle
= 0, LPVOID lpCreateParam
= NULL
)
1176 const int cchName
= 256;
1177 TCHAR szWindowName
[cchName
];
1178 szWindowName
[0] = 0;
1180 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID
, szWindowName
, cchName
);
1181 HMENU hMenu
= ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID
));
1182 #else // CE specific
1183 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID
, szWindowName
, cchName
);
1185 // This always needs to be NULL for Windows CE.
1186 // Frame Window menus have to go onto the CommandBar.
1187 // Use CreateSimpleCECommandBar
1189 #endif // _WIN32_WCE
1191 T
* pT
= static_cast<T
*>(this);
1192 HWND hWnd
= pT
->Create(hWndParent
, rect
, szWindowName
, dwStyle
, dwExStyle
, hMenu
, lpCreateParam
);
1195 m_hAccel
= ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID
));
1200 BOOL
CreateSimpleToolBar(UINT nResourceID
= 0, DWORD dwStyle
= ATL_SIMPLE_TOOLBAR_STYLE
, UINT nID
= ATL_IDW_TOOLBAR
)
1202 if(nResourceID
== 0)
1203 nResourceID
= T::GetWndClassInfo().m_uCommonResourceID
;
1205 ATLASSERT(!::IsWindow(m_hWndToolBar
));
1206 m_hWndToolBar
= T::CreateSimpleToolBarCtrl(m_hWnd
, nResourceID
, TRUE
, dwStyle
, nID
);
1207 return (m_hWndToolBar
!= NULL
);
1208 #else // CE specific
1209 HWND hWnd
= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar
, nResourceID
, TRUE
, dwStyle
, nID
);
1210 return (hWnd
!= NULL
);
1211 #endif // _WIN32_WCE
1215 // CE specific variant that returns the handle of the toolbar
1216 HWND
CreateSimpleCEToolBar(UINT nResourceID
= 0, DWORD dwStyle
= ATL_SIMPLE_TOOLBAR_STYLE
, UINT nID
= ATL_IDW_TOOLBAR
)
1218 if(nResourceID
== 0)
1219 nResourceID
= T::GetWndClassInfo().m_uCommonResourceID
;
1221 return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar
, nResourceID
, TRUE
, dwStyle
, nID
);
1223 #endif // _WIN32_WCE
1225 // message map and handlers
1226 typedef CFrameWindowImplBase
< TBase
, TWinTraits
> _baseClass
;
1228 BEGIN_MSG_MAP(CFrameWindowImpl
)
1229 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
1230 #ifndef _ATL_NO_REBAR_SUPPORT
1231 #if (_WIN32_IE >= 0x0400)
1232 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE
, OnReBarAutoSize
)
1233 #endif // (_WIN32_IE >= 0x0400)
1234 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1235 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED
, OnChevronPushed
)
1236 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1237 #endif // !_ATL_NO_REBAR_SUPPORT
1238 CHAIN_MSG_MAP(_baseClass
)
1241 LRESULT
OnSize(UINT
/*uMsg*/, WPARAM wParam
, LPARAM
/*lParam*/, BOOL
& bHandled
)
1243 if(wParam
!= SIZE_MINIMIZED
)
1245 T
* pT
= static_cast<T
*>(this);
1252 #ifndef _ATL_NO_REBAR_SUPPORT
1253 #if (_WIN32_IE >= 0x0400)
1254 LRESULT
OnReBarAutoSize(int /*idCtrl*/, LPNMHDR
/*pnmh*/, BOOL
& /*bHandled*/)
1256 T
* pT
= static_cast<T
*>(this);
1257 pT
->UpdateLayout(FALSE
);
1260 #endif // (_WIN32_IE >= 0x0400)
1262 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1263 LRESULT
OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh
, BOOL
& bHandled
)
1265 T
* pT
= static_cast<T
*>(this);
1266 _ChevronMenuInfo cmi
= { NULL
, (LPNMREBARCHEVRON
)pnmh
, false };
1267 if(!pT
->PrepareChevronMenu(cmi
))
1272 // display a popup menu with hidden items
1273 pT
->DisplayChevronMenu(cmi
);
1275 pT
->CleanupChevronMenu(cmi
);
1278 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1279 #endif // !_ATL_NO_REBAR_SUPPORT
1283 ///////////////////////////////////////////////////////////////////////////////
1284 // AtlCreateSimpleToolBar - helper for creating simple toolbars
1288 inline HWND
AtlCreateSimpleToolBar(HWND hWndParent
, UINT nResourceID
, BOOL bInitialSeparator
= FALSE
,
1289 DWORD dwStyle
= ATL_SIMPLE_TOOLBAR_STYLE
, UINT nID
= ATL_IDW_TOOLBAR
)
1291 return CFrameWindowImplBase
<>::CreateSimpleToolBarCtrl(hWndParent
, nResourceID
, bInitialSeparator
, dwStyle
, nID
);
1294 #endif // !_WIN32_WCE
1297 ///////////////////////////////////////////////////////////////////////////////
1302 #ifndef _WTL_MDIWINDOWMENU_TEXT
1303 #define _WTL_MDIWINDOWMENU_TEXT _T("&Window")
1306 class CMDIWindow
: public ATL::CWindow
1310 HWND m_hWndMDIClient
;
1314 CMDIWindow(HWND hWnd
= NULL
) : ATL::CWindow(hWnd
), m_hWndMDIClient(NULL
), m_hMenu(NULL
)
1317 CMDIWindow
& operator =(HWND hWnd
)
1324 HWND
MDIGetActive(BOOL
* lpbMaximized
= NULL
)
1326 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1327 return (HWND
)::SendMessage(m_hWndMDIClient
, WM_MDIGETACTIVE
, 0, (LPARAM
)lpbMaximized
);
1330 void MDIActivate(HWND hWndChildToActivate
)
1332 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1333 ATLASSERT(::IsWindow(hWndChildToActivate
));
1334 ::SendMessage(m_hWndMDIClient
, WM_MDIACTIVATE
, (WPARAM
)hWndChildToActivate
, 0);
1337 void MDINext(HWND hWndChild
, BOOL bPrevious
= FALSE
)
1339 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1340 ATLASSERT(hWndChild
== NULL
|| ::IsWindow(hWndChild
));
1341 ::SendMessage(m_hWndMDIClient
, WM_MDINEXT
, (WPARAM
)hWndChild
, (LPARAM
)bPrevious
);
1344 void MDIMaximize(HWND hWndChildToMaximize
)
1346 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1347 ATLASSERT(::IsWindow(hWndChildToMaximize
));
1348 ::SendMessage(m_hWndMDIClient
, WM_MDIMAXIMIZE
, (WPARAM
)hWndChildToMaximize
, 0);
1351 void MDIRestore(HWND hWndChildToRestore
)
1353 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1354 ATLASSERT(::IsWindow(hWndChildToRestore
));
1355 ::SendMessage(m_hWndMDIClient
, WM_MDIRESTORE
, (WPARAM
)hWndChildToRestore
, 0);
1358 void MDIDestroy(HWND hWndChildToDestroy
)
1360 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1361 ATLASSERT(::IsWindow(hWndChildToDestroy
));
1362 ::SendMessage(m_hWndMDIClient
, WM_MDIDESTROY
, (WPARAM
)hWndChildToDestroy
, 0);
1365 BOOL
MDICascade(UINT uFlags
= 0)
1367 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1368 return (BOOL
)::SendMessage(m_hWndMDIClient
, WM_MDICASCADE
, (WPARAM
)uFlags
, 0);
1371 BOOL
MDITile(UINT uFlags
= MDITILE_HORIZONTAL
)
1373 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1374 return (BOOL
)::SendMessage(m_hWndMDIClient
, WM_MDITILE
, (WPARAM
)uFlags
, 0);
1377 void MDIIconArrange()
1379 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1380 ::SendMessage(m_hWndMDIClient
, WM_MDIICONARRANGE
, 0, 0);
1383 HMENU
MDISetMenu(HMENU hMenuFrame
, HMENU hMenuWindow
)
1385 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1386 return (HMENU
)::SendMessage(m_hWndMDIClient
, WM_MDISETMENU
, (WPARAM
)hMenuFrame
, (LPARAM
)hMenuWindow
);
1389 HMENU
MDIRefreshMenu()
1391 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1392 return (HMENU
)::SendMessage(m_hWndMDIClient
, WM_MDIREFRESHMENU
, 0, 0);
1395 // Additional operations
1396 static HMENU
GetStandardWindowMenu(HMENU hMenu
)
1398 int nCount
= ::GetMenuItemCount(hMenu
);
1401 int nLen
= ::GetMenuString(hMenu
, nCount
- 2, NULL
, 0, MF_BYPOSITION
);
1404 CTempBuffer
<TCHAR
, _WTL_STACK_ALLOC_THRESHOLD
> buff
;
1405 LPTSTR lpszText
= buff
.Allocate(nLen
+ 1);
1406 if(lpszText
== NULL
)
1408 if(::GetMenuString(hMenu
, nCount
- 2, lpszText
, nLen
+ 1, MF_BYPOSITION
) != nLen
)
1410 if(lstrcmp(lpszText
, _WTL_MDIWINDOWMENU_TEXT
) != 0)
1412 return ::GetSubMenu(hMenu
, nCount
- 2);
1415 void SetMDIFrameMenu()
1417 HMENU hWindowMenu
= GetStandardWindowMenu(m_hMenu
);
1418 MDISetMenu(m_hMenu
, hWindowMenu
);
1420 ::DrawMenuBar(GetMDIFrame());
1423 HWND
GetMDIFrame() const
1425 return ::GetParent(m_hWndMDIClient
);
1429 #endif // !_WIN32_WCE
1432 ///////////////////////////////////////////////////////////////////////////////
1433 // CMDIFrameWindowImpl
1437 // MDI child command chaining macro (only for MDI frame windows)
1438 #define CHAIN_MDI_CHILD_COMMANDS() \
1439 if(uMsg == WM_COMMAND) \
1441 HWND hWndChild = MDIGetActive(); \
1442 if(hWndChild != NULL) \
1443 ::SendMessage(hWndChild, uMsg, wParam, lParam); \
1446 template <class T
, class TBase
= CMDIWindow
, class TWinTraits
= ATL::CFrameWinTraits
>
1447 class ATL_NO_VTABLE CMDIFrameWindowImpl
: public CFrameWindowImplBase
<TBase
, TWinTraits
>
1450 HWND
Create(HWND hWndParent
= NULL
, ATL::_U_RECT rect
= NULL
, LPCTSTR szWindowName
= NULL
,
1451 DWORD dwStyle
= 0, DWORD dwExStyle
= 0,
1452 HMENU hMenu
= NULL
, LPVOID lpCreateParam
= NULL
)
1455 ATOM atom
= T::GetWndClassInfo().Register(&m_pfnSuperWindowProc
);
1457 dwStyle
= T::GetWndStyle(dwStyle
);
1458 dwExStyle
= T::GetWndExStyle(dwExStyle
);
1460 if(rect
.m_lpRect
== NULL
)
1461 rect
.m_lpRect
= &TBase::rcDefault
;
1463 return CFrameWindowImplBase
<TBase
, TWinTraits
>::Create(hWndParent
, rect
.m_lpRect
, szWindowName
, dwStyle
, dwExStyle
, hMenu
, atom
, lpCreateParam
);
1466 HWND
CreateEx(HWND hWndParent
= NULL
, ATL::_U_RECT rect
= NULL
, DWORD dwStyle
= 0, DWORD dwExStyle
= 0, LPVOID lpCreateParam
= NULL
)
1468 const int cchName
= 256;
1469 TCHAR szWindowName
[cchName
];
1470 szWindowName
[0] = 0;
1471 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID
, szWindowName
, cchName
);
1472 HMENU hMenu
= ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID
));
1474 T
* pT
= static_cast<T
*>(this);
1475 HWND hWnd
= pT
->Create(hWndParent
, rect
, szWindowName
, dwStyle
, dwExStyle
, hMenu
, lpCreateParam
);
1478 m_hAccel
= ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID
));
1483 BOOL
CreateSimpleToolBar(UINT nResourceID
= 0, DWORD dwStyle
= ATL_SIMPLE_TOOLBAR_STYLE
, UINT nID
= ATL_IDW_TOOLBAR
)
1485 ATLASSERT(!::IsWindow(m_hWndToolBar
));
1486 if(nResourceID
== 0)
1487 nResourceID
= T::GetWndClassInfo().m_uCommonResourceID
;
1488 m_hWndToolBar
= T::CreateSimpleToolBarCtrl(m_hWnd
, nResourceID
, TRUE
, dwStyle
, nID
);
1489 return (m_hWndToolBar
!= NULL
);
1492 virtual WNDPROC
GetWindowProc()
1494 return MDIFrameWindowProc
;
1497 static LRESULT CALLBACK
MDIFrameWindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1499 CMDIFrameWindowImpl
< T
, TBase
, TWinTraits
>* pThis
= (CMDIFrameWindowImpl
< T
, TBase
, TWinTraits
>*)hWnd
;
1500 // set a ptr to this message and save the old value
1501 #if (_ATL_VER >= 0x0700)
1502 ATL::_ATL_MSG
msg(pThis
->m_hWnd
, uMsg
, wParam
, lParam
);
1503 const ATL::_ATL_MSG
* pOldMsg
= pThis
->m_pCurrentMsg
;
1504 #else // !(_ATL_VER >= 0x0700)
1505 MSG msg
= { pThis
->m_hWnd
, uMsg
, wParam
, lParam
, 0, { 0, 0 } };
1506 const MSG
* pOldMsg
= pThis
->m_pCurrentMsg
;
1507 #endif // !(_ATL_VER >= 0x0700)
1508 pThis
->m_pCurrentMsg
= &msg
;
1509 // pass to the message map to process
1511 BOOL bRet
= pThis
->ProcessWindowMessage(pThis
->m_hWnd
, uMsg
, wParam
, lParam
, lRes
, 0);
1512 // restore saved value for the current message
1513 ATLASSERT(pThis
->m_pCurrentMsg
== &msg
);
1514 pThis
->m_pCurrentMsg
= pOldMsg
;
1515 // do the default processing if message was not handled
1518 if(uMsg
!= WM_NCDESTROY
)
1519 lRes
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
1522 // unsubclass, if needed
1523 LONG_PTR pfnWndProc
= ::GetWindowLongPtr(pThis
->m_hWnd
, GWLP_WNDPROC
);
1524 lRes
= pThis
->DefWindowProc(uMsg
, wParam
, lParam
);
1525 if(pThis
->m_pfnSuperWindowProc
!= ::DefWindowProc
&& ::GetWindowLongPtr(pThis
->m_hWnd
, GWLP_WNDPROC
) == pfnWndProc
)
1526 ::SetWindowLongPtr(pThis
->m_hWnd
, GWLP_WNDPROC
, (LONG_PTR
)pThis
->m_pfnSuperWindowProc
);
1527 #if (_ATL_VER >= 0x0700)
1528 // mark window as destryed
1529 pThis
->m_dwState
|= WINSTATE_DESTROYED
;
1530 #else // !(_ATL_VER >= 0x0700)
1531 // clear out window handle
1532 HWND hWnd
= pThis
->m_hWnd
;
1533 pThis
->m_hWnd
= NULL
;
1534 // clean up after window is destroyed
1535 pThis
->OnFinalMessage(hWnd
);
1536 #endif // !(_ATL_VER >= 0x0700)
1539 #if (_ATL_VER >= 0x0700)
1540 if(pThis
->m_dwState
& WINSTATE_DESTROYED
&& pThis
->m_pCurrentMsg
== NULL
)
1542 // clear out window handle
1543 HWND hWnd
= pThis
->m_hWnd
;
1544 pThis
->m_hWnd
= NULL
;
1545 pThis
->m_dwState
&= ~WINSTATE_DESTROYED
;
1546 // clean up after window is destroyed
1547 pThis
->OnFinalMessage(hWnd
);
1549 #endif // (_ATL_VER >= 0x0700)
1553 // Overriden to call DefWindowProc which uses DefFrameProc
1554 LRESULT
DefWindowProc()
1556 const MSG
* pMsg
= m_pCurrentMsg
;
1559 lRes
= DefWindowProc(pMsg
->message
, pMsg
->wParam
, pMsg
->lParam
);
1563 LRESULT
DefWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1565 return ::DefFrameProc(m_hWnd
, m_hWndMDIClient
, uMsg
, wParam
, lParam
);
1568 BOOL
PreTranslateMessage(MSG
* pMsg
)
1570 if(CFrameWindowImplBase
<TBase
, TWinTraits
>::PreTranslateMessage(pMsg
))
1572 return ::TranslateMDISysAccel(m_hWndMDIClient
, pMsg
);
1575 HWND
CreateMDIClient(HMENU hWindowMenu
= NULL
, UINT nID
= ATL_IDW_CLIENT
, UINT nFirstChildID
= ATL_IDM_FIRST_MDICHILD
)
1577 DWORD dwStyle
= WS_VISIBLE
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| MDIS_ALLCHILDSTYLES
;
1578 DWORD dwExStyle
= WS_EX_CLIENTEDGE
;
1580 CLIENTCREATESTRUCT ccs
= { 0 };
1581 ccs
.hWindowMenu
= hWindowMenu
;
1582 ccs
.idFirstChild
= nFirstChildID
;
1584 if((GetStyle() & (WS_HSCROLL
| WS_VSCROLL
)) != 0)
1586 // parent MDI frame's scroll styles move to the MDICLIENT
1587 dwStyle
|= (GetStyle() & (WS_HSCROLL
| WS_VSCROLL
));
1589 // fast way to turn off the scrollbar bits (without a resize)
1590 ModifyStyle(WS_HSCROLL
| WS_VSCROLL
, 0, SWP_NOREDRAW
| SWP_FRAMECHANGED
);
1593 // Create MDICLIENT window
1594 m_hWndClient
= ::CreateWindowEx(dwExStyle
, _T("MDIClient"), NULL
,
1595 dwStyle
, 0, 0, 1, 1, m_hWnd
, (HMENU
)LongToHandle(nID
),
1596 ModuleHelper::GetModuleInstance(), (LPVOID
)&ccs
);
1597 if (m_hWndClient
== NULL
)
1599 ATLTRACE2(atlTraceUI
, 0, _T("MDI Frame failed to create MDICLIENT.\n"));
1603 // Move it to the top of z-order
1604 ::BringWindowToTop(m_hWndClient
);
1606 // set as MDI client window
1607 m_hWndMDIClient
= m_hWndClient
;
1609 // update to proper size
1610 T
* pT
= static_cast<T
*>(this);
1613 return m_hWndClient
;
1616 typedef CFrameWindowImplBase
<TBase
, TWinTraits
> _baseClass
;
1618 BEGIN_MSG_MAP(CMDIFrameWindowImpl
)
1619 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
1620 MESSAGE_HANDLER(WM_SETFOCUS
, OnSetFocus
)
1621 MESSAGE_HANDLER(WM_MDISETMENU
, OnMDISetMenu
)
1622 #ifndef _ATL_NO_REBAR_SUPPORT
1623 #if (_WIN32_IE >= 0x0400)
1624 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE
, OnReBarAutoSize
)
1625 #endif // (_WIN32_IE >= 0x0400)
1626 #if (_WIN32_IE >= 0x0500)
1627 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED
, OnChevronPushed
)
1628 #endif // (_WIN32_IE >= 0x0500)
1629 #endif // !_ATL_NO_REBAR_SUPPORT
1630 CHAIN_MSG_MAP(_baseClass
)
1633 LRESULT
OnSize(UINT
/*uMsg*/, WPARAM wParam
, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
1635 if(wParam
!= SIZE_MINIMIZED
)
1637 T
* pT
= static_cast<T
*>(this);
1640 // message must be handled, otherwise DefFrameProc would resize the client again
1644 LRESULT
OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& /*bHandled*/)
1646 // don't allow CFrameWindowImplBase to handle this one
1647 return DefWindowProc(uMsg
, wParam
, lParam
);
1650 LRESULT
OnMDISetMenu(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
1656 #ifndef _ATL_NO_REBAR_SUPPORT
1657 #if (_WIN32_IE >= 0x0400)
1658 LRESULT
OnReBarAutoSize(int /*idCtrl*/, LPNMHDR
/*pnmh*/, BOOL
& /*bHandled*/)
1660 T
* pT
= static_cast<T
*>(this);
1661 pT
->UpdateLayout(FALSE
);
1664 #endif // (_WIN32_IE >= 0x0400)
1666 #if (_WIN32_IE >= 0x0500)
1667 LRESULT
OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh
, BOOL
& bHandled
)
1669 T
* pT
= static_cast<T
*>(this);
1670 _ChevronMenuInfo cmi
= { NULL
, (LPNMREBARCHEVRON
)pnmh
, false };
1671 if(!pT
->PrepareChevronMenu(cmi
))
1676 // display a popup menu with hidden items
1677 pT
->DisplayChevronMenu(cmi
);
1679 pT
->CleanupChevronMenu(cmi
);
1682 #endif // (_WIN32_IE >= 0x0500)
1683 #endif // !_ATL_NO_REBAR_SUPPORT
1686 #endif // !_WIN32_WCE
1689 ///////////////////////////////////////////////////////////////////////////////
1690 // CMDIChildWindowImpl
1694 template <class T
, class TBase
= CMDIWindow
, class TWinTraits
= ATL::CMDIChildWinTraits
>
1695 class ATL_NO_VTABLE CMDIChildWindowImpl
: public CFrameWindowImplBase
<TBase
, TWinTraits
>
1698 HWND
Create(HWND hWndParent
, ATL::_U_RECT rect
= NULL
, LPCTSTR szWindowName
= NULL
,
1699 DWORD dwStyle
= 0, DWORD dwExStyle
= 0,
1700 UINT nMenuID
= 0, LPVOID lpCreateParam
= NULL
)
1702 ATOM atom
= T::GetWndClassInfo().Register(&m_pfnSuperWindowProc
);
1705 m_hMenu
= ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nMenuID
));
1707 dwStyle
= T::GetWndStyle(dwStyle
);
1708 dwExStyle
= T::GetWndExStyle(dwExStyle
);
1710 dwExStyle
|= WS_EX_MDICHILD
; // force this one
1711 m_pfnSuperWindowProc
= ::DefMDIChildProc
;
1712 m_hWndMDIClient
= hWndParent
;
1713 ATLASSERT(::IsWindow(m_hWndMDIClient
));
1715 if(rect
.m_lpRect
== NULL
)
1716 rect
.m_lpRect
= &TBase::rcDefault
;
1718 // If the currently active MDI child is maximized, we want to create this one maximized too
1719 ATL::CWindow wndParent
= hWndParent
;
1720 BOOL bMaximized
= FALSE
;
1721 wndParent
.SendMessage(WM_MDIGETACTIVE
, 0, (LPARAM
)&bMaximized
);
1723 wndParent
.SetRedraw(FALSE
);
1725 HWND hWnd
= CFrameWindowImplBase
<TBase
, TWinTraits
>::Create(hWndParent
, rect
.m_lpRect
, szWindowName
, dwStyle
, dwExStyle
, (UINT
)0U, atom
, lpCreateParam
);
1729 // Maximize and redraw everything
1732 wndParent
.SetRedraw(TRUE
);
1733 wndParent
.RedrawWindow(NULL
, NULL
, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1734 ::SetFocus(GetMDIFrame()); // focus will be set back to this window
1736 else if(hWnd
!= NULL
&& ::IsWindowVisible(m_hWnd
) && !::IsChild(hWnd
, ::GetFocus()))
1744 HWND
CreateEx(HWND hWndParent
, ATL::_U_RECT rect
= NULL
, LPCTSTR lpcstrWindowName
= NULL
, DWORD dwStyle
= 0, DWORD dwExStyle
= 0, LPVOID lpCreateParam
= NULL
)
1746 const int cchName
= 256;
1747 TCHAR szWindowName
[cchName
];
1748 szWindowName
[0] = 0;
1749 if(lpcstrWindowName
== NULL
)
1751 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID
, szWindowName
, cchName
);
1752 lpcstrWindowName
= szWindowName
;
1755 T
* pT
= static_cast<T
*>(this);
1756 HWND hWnd
= pT
->Create(hWndParent
, rect
, lpcstrWindowName
, dwStyle
, dwExStyle
, T::GetWndClassInfo().m_uCommonResourceID
, lpCreateParam
);
1759 m_hAccel
= ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID
));
1764 BOOL
CreateSimpleToolBar(UINT nResourceID
= 0, DWORD dwStyle
= ATL_SIMPLE_TOOLBAR_STYLE
, UINT nID
= ATL_IDW_TOOLBAR
)
1766 ATLASSERT(!::IsWindow(m_hWndToolBar
));
1767 if(nResourceID
== 0)
1768 nResourceID
= T::GetWndClassInfo().m_uCommonResourceID
;
1769 m_hWndToolBar
= T::CreateSimpleToolBarCtrl(m_hWnd
, nResourceID
, TRUE
, dwStyle
, nID
);
1770 return (m_hWndToolBar
!= NULL
);
1773 BOOL
UpdateClientEdge(LPRECT lpRect
= NULL
)
1775 // only adjust for active MDI child window
1776 HWND hWndChild
= MDIGetActive();
1777 if(hWndChild
!= NULL
&& hWndChild
!= m_hWnd
)
1780 // need to adjust the client edge style as max/restore happens
1781 DWORD dwStyle
= ::GetWindowLong(m_hWndMDIClient
, GWL_EXSTYLE
);
1782 DWORD dwNewStyle
= dwStyle
;
1783 if(hWndChild
!= NULL
&& ((GetExStyle() & WS_EX_CLIENTEDGE
) == 0) && ((GetStyle() & WS_MAXIMIZE
) != 0))
1784 dwNewStyle
&= ~(WS_EX_CLIENTEDGE
);
1786 dwNewStyle
|= WS_EX_CLIENTEDGE
;
1788 if(dwStyle
!= dwNewStyle
)
1790 // SetWindowPos will not move invalid bits
1791 ::RedrawWindow(m_hWndMDIClient
, NULL
, NULL
,
1792 RDW_INVALIDATE
| RDW_ALLCHILDREN
);
1793 // remove/add WS_EX_CLIENTEDGE to MDI client area
1794 ::SetWindowLong(m_hWndMDIClient
, GWL_EXSTYLE
, dwNewStyle
);
1795 ::SetWindowPos(m_hWndMDIClient
, NULL
, 0, 0, 0, 0,
1796 SWP_FRAMECHANGED
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOSIZE
|
1797 SWP_NOZORDER
| SWP_NOCOPYBITS
);
1799 // return new client area
1801 ::GetClientRect(m_hWndMDIClient
, lpRect
);
1809 typedef CFrameWindowImplBase
<TBase
, TWinTraits
> _baseClass
;
1810 BEGIN_MSG_MAP(CMDIChildWindowImpl
)
1811 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
1812 MESSAGE_HANDLER(WM_WINDOWPOSCHANGED
, OnWindowPosChanged
)
1813 MESSAGE_HANDLER(WM_MOUSEACTIVATE
, OnMouseActivate
)
1814 MESSAGE_HANDLER(WM_MENUSELECT
, OnMenuSelect
)
1815 MESSAGE_HANDLER(WM_MDIACTIVATE
, OnMDIActivate
)
1816 MESSAGE_HANDLER(WM_DESTROY
, OnDestroy
)
1817 #ifndef _ATL_NO_REBAR_SUPPORT
1818 #if (_WIN32_IE >= 0x0400)
1819 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE
, OnReBarAutoSize
)
1820 #endif // (_WIN32_IE >= 0x0400)
1821 #if (_WIN32_IE >= 0x0500)
1822 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED
, OnChevronPushed
)
1823 #endif // (_WIN32_IE >= 0x0500)
1824 #endif // !_ATL_NO_REBAR_SUPPORT
1825 CHAIN_MSG_MAP(_baseClass
)
1828 LRESULT
OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& /*bHandled*/)
1830 DefWindowProc(uMsg
, wParam
, lParam
); // needed for MDI children
1831 if(wParam
!= SIZE_MINIMIZED
)
1833 T
* pT
= static_cast<T
*>(this);
1839 LRESULT
OnWindowPosChanged(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& bHandled
)
1841 // update MDI client edge and adjust MDI child rect
1842 LPWINDOWPOS lpWndPos
= (LPWINDOWPOS
)lParam
;
1844 if(!(lpWndPos
->flags
& SWP_NOSIZE
))
1847 if(UpdateClientEdge(&rectClient
) && ((GetStyle() & WS_MAXIMIZE
) != 0))
1849 ::AdjustWindowRectEx(&rectClient
, GetStyle(), FALSE
, GetExStyle());
1850 lpWndPos
->x
= rectClient
.left
;
1851 lpWndPos
->y
= rectClient
.top
;
1852 lpWndPos
->cx
= rectClient
.right
- rectClient
.left
;
1853 lpWndPos
->cy
= rectClient
.bottom
- rectClient
.top
;
1861 LRESULT
OnMouseActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& /*bHandled*/)
1863 LRESULT lRes
= DefWindowProc(uMsg
, wParam
, lParam
);
1865 // Activate this MDI window if needed
1866 if(lRes
== MA_ACTIVATE
|| lRes
== MA_ACTIVATEANDEAT
)
1868 if(MDIGetActive() != m_hWnd
)
1869 MDIActivate(m_hWnd
);
1875 LRESULT
OnMenuSelect(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& /*bHandled*/)
1877 return ::SendMessage(GetMDIFrame(), uMsg
, wParam
, lParam
);
1880 LRESULT
OnMDIActivate(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& bHandled
)
1882 if((HWND
)lParam
== m_hWnd
&& m_hMenu
!= NULL
)
1884 else if((HWND
)lParam
== NULL
)
1885 ::SendMessage(GetMDIFrame(), WM_MDISETMENU
, 0, 0);
1891 LRESULT
OnDestroy(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& bHandled
)
1895 ::DestroyMenu(m_hMenu
);
1903 #ifndef _ATL_NO_REBAR_SUPPORT
1904 #if (_WIN32_IE >= 0x0400)
1905 LRESULT
OnReBarAutoSize(int /*idCtrl*/, LPNMHDR
/*pnmh*/, BOOL
& /*bHandled*/)
1907 T
* pT
= static_cast<T
*>(this);
1908 pT
->UpdateLayout(FALSE
);
1911 #endif // (_WIN32_IE >= 0x0400)
1913 #if (_WIN32_IE >= 0x0500)
1914 LRESULT
OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh
, BOOL
& bHandled
)
1916 T
* pT
= static_cast<T
*>(this);
1917 _ChevronMenuInfo cmi
= { NULL
, (LPNMREBARCHEVRON
)pnmh
, false };
1918 if(!pT
->PrepareChevronMenu(cmi
))
1923 // display a popup menu with hidden items
1924 pT
->DisplayChevronMenu(cmi
);
1926 pT
->CleanupChevronMenu(cmi
);
1929 #endif // (_WIN32_IE >= 0x0500)
1930 #endif // !_ATL_NO_REBAR_SUPPORT
1933 #endif // !_WIN32_WCE
1936 ///////////////////////////////////////////////////////////////////////////////
1937 // COwnerDraw - MI class for owner-draw support
1943 #if (_ATL_VER < 0x0700)
1946 BOOL
IsMsgHandled() const
1948 return m_bHandledOD
;
1950 void SetMsgHandled(BOOL bHandled
)
1952 m_bHandledOD
= bHandled
;
1954 #endif // (_ATL_VER < 0x0700)
1956 // Message map and handlers
1957 BEGIN_MSG_MAP(COwnerDraw
< T
>)
1958 MESSAGE_HANDLER(WM_DRAWITEM
, OnDrawItem
)
1959 MESSAGE_HANDLER(WM_MEASUREITEM
, OnMeasureItem
)
1960 MESSAGE_HANDLER(WM_COMPAREITEM
, OnCompareItem
)
1961 MESSAGE_HANDLER(WM_DELETEITEM
, OnDeleteItem
)
1963 MESSAGE_HANDLER(OCM_DRAWITEM
, OnDrawItem
)
1964 MESSAGE_HANDLER(OCM_MEASUREITEM
, OnMeasureItem
)
1965 MESSAGE_HANDLER(OCM_COMPAREITEM
, OnCompareItem
)
1966 MESSAGE_HANDLER(OCM_DELETEITEM
, OnDeleteItem
)
1969 LRESULT
OnDrawItem(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& bHandled
)
1971 T
* pT
= static_cast<T
*>(this);
1972 pT
->SetMsgHandled(TRUE
);
1973 pT
->DrawItem((LPDRAWITEMSTRUCT
)lParam
);
1974 bHandled
= pT
->IsMsgHandled();
1975 return (LRESULT
)TRUE
;
1978 LRESULT
OnMeasureItem(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& bHandled
)
1980 T
* pT
= static_cast<T
*>(this);
1981 pT
->SetMsgHandled(TRUE
);
1982 pT
->MeasureItem((LPMEASUREITEMSTRUCT
)lParam
);
1983 bHandled
= pT
->IsMsgHandled();
1984 return (LRESULT
)TRUE
;
1987 LRESULT
OnCompareItem(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& bHandled
)
1989 T
* pT
= static_cast<T
*>(this);
1990 pT
->SetMsgHandled(TRUE
);
1991 bHandled
= pT
->IsMsgHandled();
1992 return (LRESULT
)pT
->CompareItem((LPCOMPAREITEMSTRUCT
)lParam
);
1995 LRESULT
OnDeleteItem(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& bHandled
)
1997 T
* pT
= static_cast<T
*>(this);
1998 pT
->SetMsgHandled(TRUE
);
1999 pT
->DeleteItem((LPDELETEITEMSTRUCT
)lParam
);
2000 bHandled
= pT
->IsMsgHandled();
2001 return (LRESULT
)TRUE
;
2005 void DrawItem(LPDRAWITEMSTRUCT
/*lpDrawItemStruct*/)
2007 // must be implemented
2011 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct
)
2013 if(lpMeasureItemStruct
->CtlType
!= ODT_MENU
)
2015 // return default height for a system font
2016 T
* pT
= static_cast<T
*>(this);
2017 HWND hWnd
= pT
->GetDlgItem(lpMeasureItemStruct
->CtlID
);
2019 TEXTMETRIC tm
= { 0 };
2020 dc
.GetTextMetrics(&tm
);
2022 lpMeasureItemStruct
->itemHeight
= tm
.tmHeight
;
2025 lpMeasureItemStruct
->itemHeight
= ::GetSystemMetrics(SM_CYMENU
);
2028 int CompareItem(LPCOMPAREITEMSTRUCT
/*lpCompareItemStruct*/)
2030 // all items are equal
2034 void DeleteItem(LPDELETEITEMSTRUCT
/*lpDeleteItemStruct*/)
2036 // default - nothing
2041 ///////////////////////////////////////////////////////////////////////////////
2044 // these build the Update UI map inside a class definition
2045 #define BEGIN_UPDATE_UI_MAP(thisClass) \
2046 static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \
2048 static const _AtlUpdateUIMap theMap[] = \
2051 #define UPDATE_ELEMENT(nID, wType) \
2054 #define END_UPDATE_UI_MAP() \
2060 ///////////////////////////////////////////////////////////////////////////////
2061 // CUpdateUI - manages UI elements updating
2070 UPDUI_MENUPOPUP
= 0x0001,
2071 UPDUI_MENUBAR
= 0x0002,
2072 UPDUI_CHILDWINDOW
= 0x0004,
2073 UPDUI_TOOLBAR
= 0x0008,
2074 UPDUI_STATUSBAR
= 0x0010,
2076 UPDUI_ENABLED
= 0x0000,
2077 UPDUI_DISABLED
= 0x0100,
2078 UPDUI_CHECKED
= 0x0200,
2079 UPDUI_CHECKED2
= 0x0400,
2080 UPDUI_RADIO
= 0x0800,
2081 UPDUI_DEFAULT
= 0x1000,
2082 UPDUI_TEXT
= 0x2000,
2084 UPDUI_CLEARDEFAULT
= 0x4000,
2088 struct _AtlUpdateUIElement
2093 bool operator ==(const _AtlUpdateUIElement
& e
) const
2094 { return (m_hWnd
== e
.m_hWnd
&& m_wType
== e
.m_wType
); }
2098 struct _AtlUpdateUIMap
2103 bool operator ==(const _AtlUpdateUIMap
& e
) const
2104 { return (m_nID
== e
.m_nID
&& m_wType
== e
.m_wType
); }
2108 struct _AtlUpdateUIData
2117 bool operator ==(const _AtlUpdateUIData
& e
) const
2118 { return (m_wState
== e
.m_wState
&& m_lpData
== e
.m_lpData
); }
2121 ATL::CSimpleArray
<_AtlUpdateUIElement
> m_UIElements
; // elements data
2122 const _AtlUpdateUIMap
* m_pUIMap
; // static UI data
2123 _AtlUpdateUIData
* m_pUIData
; // instance UI data
2124 WORD m_wDirtyType
; // global dirty flag
2126 bool m_bBlockAccelerators
;
2129 // Constructor, destructor
2130 CUpdateUIBase() : m_pUIMap(NULL
), m_pUIData(NULL
), m_wDirtyType(0), m_bBlockAccelerators(false)
2135 if(m_pUIMap
!= NULL
&& m_pUIData
!= NULL
)
2137 const _AtlUpdateUIMap
* pUIMap
= m_pUIMap
;
2138 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2139 while(pUIMap
->m_nID
!= (WORD
)-1)
2141 if(pUIData
->m_wState
& UPDUI_TEXT
)
2142 delete [] pUIData
->m_lpstrText
;
2146 delete [] m_pUIData
;
2150 // Check for disabled commands
2151 bool UIGetBlockAccelerators() const
2153 return m_bBlockAccelerators
;
2156 bool UISetBlockAccelerators(bool bBlock
)
2158 bool bOld
= m_bBlockAccelerators
;
2159 m_bBlockAccelerators
= bBlock
;
2164 BOOL
UIAddMenuBar(HWND hWnd
) // menu bar (main menu)
2168 _AtlUpdateUIElement e
;
2170 e
.m_wType
= UPDUI_MENUBAR
;
2171 return m_UIElements
.Add(e
);
2174 BOOL
UIAddToolBar(HWND hWnd
) // toolbar
2178 _AtlUpdateUIElement e
;
2180 e
.m_wType
= UPDUI_TOOLBAR
;
2181 return m_UIElements
.Add(e
);
2184 BOOL
UIAddStatusBar(HWND hWnd
) // status bar
2188 _AtlUpdateUIElement e
;
2190 e
.m_wType
= UPDUI_STATUSBAR
;
2191 return m_UIElements
.Add(e
);
2194 BOOL
UIAddChildWindowContainer(HWND hWnd
) // child window
2198 _AtlUpdateUIElement e
;
2200 e
.m_wType
= UPDUI_CHILDWINDOW
;
2201 return m_UIElements
.Add(e
);
2204 // Message map for popup menu updates and accelerator blocking
2205 BEGIN_MSG_MAP(CUpdateUIBase
)
2206 MESSAGE_HANDLER(WM_INITMENUPOPUP
, OnInitMenuPopup
)
2207 MESSAGE_HANDLER(WM_COMMAND
, OnCommand
)
2210 LRESULT
OnInitMenuPopup(UINT
/*uMsg*/, WPARAM wParam
, LPARAM
/*lParam*/, BOOL
& bHandled
)
2213 HMENU hMenu
= (HMENU
)wParam
;
2216 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2219 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2220 while(pMap
->m_nID
!= (WORD
)-1)
2222 if(pMap
->m_wType
& UPDUI_MENUPOPUP
)
2223 UIUpdateMenuBarElement(pMap
->m_nID
, pUIData
, hMenu
);
2230 LRESULT
OnCommand(UINT
/*uMsg*/, WPARAM wParam
, LPARAM
/*lParam*/, BOOL
& bHandled
)
2233 if(m_bBlockAccelerators
&& HIWORD(wParam
) == 1) // accelerators only
2235 int nID
= LOWORD(wParam
);
2236 if((UIGetState(nID
) & UPDUI_DISABLED
) == UPDUI_DISABLED
)
2238 ATLTRACE2(atlTraceUI
, 0, _T("CUpdateUIBase::OnCommand - blocked disabled command 0x%4.4X\n"), nID
);
2239 bHandled
= TRUE
; // eat the command, UI item is disabled
2245 // methods for setting UI element state
2246 BOOL
UIEnable(int nID
, BOOL bEnable
, BOOL bForceUpdate
= FALSE
)
2248 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2249 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2253 for( ; pMap
->m_nID
!= (WORD
)-1; pMap
++, pUIData
++)
2255 if(nID
== (int)pMap
->m_nID
)
2259 if(pUIData
->m_wState
& UPDUI_DISABLED
)
2261 pUIData
->m_wState
|= pMap
->m_wType
;
2262 pUIData
->m_wState
&= ~UPDUI_DISABLED
;
2267 if(!(pUIData
->m_wState
& UPDUI_DISABLED
))
2269 pUIData
->m_wState
|= pMap
->m_wType
;
2270 pUIData
->m_wState
|= UPDUI_DISABLED
;
2275 pUIData
->m_wState
|= pMap
->m_wType
;
2276 if(pUIData
->m_wState
& pMap
->m_wType
)
2277 m_wDirtyType
|= pMap
->m_wType
;
2286 BOOL
UISetCheck(int nID
, int nCheck
, BOOL bForceUpdate
= FALSE
)
2288 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2289 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2293 for( ; pMap
->m_nID
!= (WORD
)-1; pMap
++, pUIData
++)
2295 if(nID
== (int)pMap
->m_nID
)
2300 if((pUIData
->m_wState
& UPDUI_CHECKED
) || (pUIData
->m_wState
& UPDUI_CHECKED2
))
2302 pUIData
->m_wState
|= pMap
->m_wType
;
2303 pUIData
->m_wState
&= ~(UPDUI_CHECKED
| UPDUI_CHECKED2
);
2307 if(!(pUIData
->m_wState
& UPDUI_CHECKED
))
2309 pUIData
->m_wState
|= pMap
->m_wType
;
2310 pUIData
->m_wState
&= ~UPDUI_CHECKED2
;
2311 pUIData
->m_wState
|= UPDUI_CHECKED
;
2315 if(!(pUIData
->m_wState
& UPDUI_CHECKED2
))
2317 pUIData
->m_wState
|= pMap
->m_wType
;
2318 pUIData
->m_wState
&= ~UPDUI_CHECKED
;
2319 pUIData
->m_wState
|= UPDUI_CHECKED2
;
2325 pUIData
->m_wState
|= pMap
->m_wType
;
2326 if(pUIData
->m_wState
& pMap
->m_wType
)
2327 m_wDirtyType
|= pMap
->m_wType
;
2336 // variant that supports bool (checked/not-checked, no intermediate state)
2337 BOOL
UISetCheck(int nID
, bool bCheck
, BOOL bForceUpdate
= FALSE
)
2339 return UISetCheck(nID
, bCheck
? 1 : 0, bForceUpdate
);
2342 BOOL
UISetRadio(int nID
, BOOL bRadio
, BOOL bForceUpdate
= FALSE
)
2344 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2345 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2349 for( ; pMap
->m_nID
!= (WORD
)-1; pMap
++, pUIData
++)
2351 if(nID
== (int)pMap
->m_nID
)
2355 if(!(pUIData
->m_wState
& UPDUI_RADIO
))
2357 pUIData
->m_wState
|= pMap
->m_wType
;
2358 pUIData
->m_wState
|= UPDUI_RADIO
;
2363 if(pUIData
->m_wState
& UPDUI_RADIO
)
2365 pUIData
->m_wState
|= pMap
->m_wType
;
2366 pUIData
->m_wState
&= ~UPDUI_RADIO
;
2371 pUIData
->m_wState
|= pMap
->m_wType
;
2372 if(pUIData
->m_wState
& pMap
->m_wType
)
2373 m_wDirtyType
|= pMap
->m_wType
;
2382 BOOL
UISetText(int nID
, LPCTSTR lpstrText
, BOOL bForceUpdate
= FALSE
)
2384 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2385 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2388 if(lpstrText
== NULL
)
2391 for( ; pMap
->m_nID
!= (WORD
)-1; pMap
++, pUIData
++)
2393 if(nID
== (int)pMap
->m_nID
)
2395 if(pUIData
->m_lpstrText
== NULL
|| lstrcmp(pUIData
->m_lpstrText
, lpstrText
))
2397 delete [] pUIData
->m_lpstrText
;
2398 pUIData
->m_lpstrText
= NULL
;
2399 int nStrLen
= lstrlen(lpstrText
);
2400 ATLTRY(pUIData
->m_lpstrText
= new TCHAR
[nStrLen
+ 1]);
2401 if(pUIData
->m_lpstrText
== NULL
)
2403 ATLTRACE2(atlTraceUI
, 0, _T("UISetText - memory allocation failed\n"));
2406 SecureHelper::strcpy_x(pUIData
->m_lpstrText
, nStrLen
+ 1, lpstrText
);
2407 pUIData
->m_wState
|= (UPDUI_TEXT
| pMap
->m_wType
);
2411 pUIData
->m_wState
|= (UPDUI_TEXT
| pMap
->m_wType
);
2412 if(pUIData
->m_wState
& pMap
->m_wType
)
2413 m_wDirtyType
|= pMap
->m_wType
;
2422 BOOL
UISetDefault(int nID
, BOOL bDefault
, BOOL bForceUpdate
= FALSE
)
2424 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2425 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2429 for( ; pMap
->m_nID
!= (WORD
)-1; pMap
++, pUIData
++)
2431 if(nID
== (int)pMap
->m_nID
)
2435 if((pUIData
->m_wState
& UPDUI_DEFAULT
) == 0)
2437 pUIData
->m_wState
|= pMap
->m_wType
;
2438 pUIData
->m_wState
|= UPDUI_DEFAULT
;
2443 if((pUIData
->m_wState
& UPDUI_DEFAULT
) != 0)
2445 pUIData
->m_wState
|= pMap
->m_wType
;
2446 pUIData
->m_wState
&= ~UPDUI_DEFAULT
;
2447 pUIData
->m_wState
|= UPDUI_CLEARDEFAULT
;
2452 pUIData
->m_wState
|= pMap
->m_wType
;
2453 if(pUIData
->m_wState
& pMap
->m_wType
)
2454 m_wDirtyType
|= pMap
->m_wType
;
2463 // methods for complete state set/get
2464 BOOL
UISetState(int nID
, DWORD dwState
)
2466 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2467 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2470 for( ; pMap
->m_nID
!= (WORD
)-1; pMap
++, pUIData
++)
2472 if(nID
== (int)pMap
->m_nID
)
2474 pUIData
->m_wState
= (WORD
)(dwState
| pMap
->m_wType
);
2475 m_wDirtyType
|= pMap
->m_wType
;
2482 DWORD
UIGetState(int nID
)
2484 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2485 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2488 for( ; pMap
->m_nID
!= (WORD
)-1; pMap
++, pUIData
++)
2490 if(nID
== (int)pMap
->m_nID
)
2491 return pUIData
->m_wState
;
2496 // methods for updating UI
2498 BOOL
UIUpdateMenuBar(BOOL bForceUpdate
= FALSE
, BOOL bMainMenu
= FALSE
)
2500 if(!(m_wDirtyType
& UPDUI_MENUBAR
) && !bForceUpdate
)
2503 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2504 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2508 while(pMap
->m_nID
!= (WORD
)-1)
2510 for(int i
= 0; i
< m_UIElements
.GetSize(); i
++)
2512 if(m_UIElements
[i
].m_wType
== UPDUI_MENUBAR
)
2514 HMENU hMenu
= ::GetMenu(m_UIElements
[i
].m_hWnd
);
2515 if(hMenu
!= NULL
&& (pUIData
->m_wState
& UPDUI_MENUBAR
) && (pMap
->m_wType
& UPDUI_MENUBAR
))
2516 UIUpdateMenuBarElement(pMap
->m_nID
, pUIData
, hMenu
);
2519 ::DrawMenuBar(m_UIElements
[i
].m_hWnd
);
2522 pUIData
->m_wState
&= ~UPDUI_MENUBAR
;
2523 if(pUIData
->m_wState
& UPDUI_TEXT
)
2525 delete [] pUIData
->m_lpstrText
;
2526 pUIData
->m_lpstrText
= NULL
;
2527 pUIData
->m_wState
&= ~UPDUI_TEXT
;
2532 m_wDirtyType
&= ~UPDUI_MENUBAR
;
2535 #endif // !_WIN32_WCE
2537 BOOL
UIUpdateToolBar(BOOL bForceUpdate
= FALSE
)
2539 if(!(m_wDirtyType
& UPDUI_TOOLBAR
) && !bForceUpdate
)
2542 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2543 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2547 while(pMap
->m_nID
!= (WORD
)-1)
2549 for(int i
= 0; i
< m_UIElements
.GetSize(); i
++)
2551 if(m_UIElements
[i
].m_wType
== UPDUI_TOOLBAR
)
2553 if((pUIData
->m_wState
& UPDUI_TOOLBAR
) && (pMap
->m_wType
& UPDUI_TOOLBAR
))
2554 UIUpdateToolBarElement(pMap
->m_nID
, pUIData
, m_UIElements
[i
].m_hWnd
);
2558 pUIData
->m_wState
&= ~UPDUI_TOOLBAR
;
2562 m_wDirtyType
&= ~UPDUI_TOOLBAR
;
2566 BOOL
UIUpdateStatusBar(BOOL bForceUpdate
= FALSE
)
2568 if(!(m_wDirtyType
& UPDUI_STATUSBAR
) && !bForceUpdate
)
2571 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2572 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2576 while(pMap
->m_nID
!= (WORD
)-1)
2578 for(int i
= 0; i
< m_UIElements
.GetSize(); i
++)
2580 if(m_UIElements
[i
].m_wType
== UPDUI_STATUSBAR
)
2582 if((pUIData
->m_wState
& UPDUI_STATUSBAR
) && (pMap
->m_wType
& UPDUI_STATUSBAR
))
2583 UIUpdateStatusBarElement(pMap
->m_nID
, pUIData
, m_UIElements
[i
].m_hWnd
);
2587 pUIData
->m_wState
&= ~UPDUI_STATUSBAR
;
2588 if(pUIData
->m_wState
& UPDUI_TEXT
)
2590 delete [] pUIData
->m_lpstrText
;
2591 pUIData
->m_lpstrText
= NULL
;
2592 pUIData
->m_wState
&= ~UPDUI_TEXT
;
2597 m_wDirtyType
&= ~UPDUI_STATUSBAR
;
2601 BOOL
UIUpdateChildWindows(BOOL bForceUpdate
= FALSE
)
2603 if(!(m_wDirtyType
& UPDUI_CHILDWINDOW
) && !bForceUpdate
)
2606 const _AtlUpdateUIMap
* pMap
= m_pUIMap
;
2607 _AtlUpdateUIData
* pUIData
= m_pUIData
;
2611 while(pMap
->m_nID
!= (WORD
)-1)
2613 for(int i
= 0; i
< m_UIElements
.GetSize(); i
++)
2615 if(m_UIElements
[i
].m_wType
== UPDUI_CHILDWINDOW
)
2617 if((pUIData
->m_wState
& UPDUI_CHILDWINDOW
) && (pMap
->m_wType
& UPDUI_CHILDWINDOW
))
2618 UIUpdateChildWindow(pMap
->m_nID
, pUIData
, m_UIElements
[i
].m_hWnd
);
2622 pUIData
->m_wState
&= ~UPDUI_CHILDWINDOW
;
2623 if(pUIData
->m_wState
& UPDUI_TEXT
)
2625 delete [] pUIData
->m_lpstrText
;
2626 pUIData
->m_lpstrText
= NULL
;
2627 pUIData
->m_wState
&= ~UPDUI_TEXT
;
2632 m_wDirtyType
&= ~UPDUI_CHILDWINDOW
;
2636 // internal element specific methods
2637 static void UIUpdateMenuBarElement(int nID
, _AtlUpdateUIData
* pUIData
, HMENU hMenu
)
2640 if((pUIData
->m_wState
& UPDUI_CLEARDEFAULT
) != 0)
2642 ::SetMenuDefaultItem(hMenu
, (UINT
)-1, 0);
2643 pUIData
->m_wState
&= ~UPDUI_CLEARDEFAULT
;
2645 #endif // !_WIN32_WCE
2648 mii
.fMask
= MIIM_STATE
;
2652 if((pUIData
->m_wState
& UPDUI_DISABLED
) != 0)
2653 mii
.fState
|= MFS_DISABLED
| MFS_GRAYED
;
2655 mii
.fState
|= MFS_ENABLED
;
2657 if((pUIData
->m_wState
& UPDUI_CHECKED
) != 0)
2658 mii
.fState
|= MFS_CHECKED
;
2660 mii
.fState
|= MFS_UNCHECKED
;
2662 if((pUIData
->m_wState
& UPDUI_DEFAULT
) != 0)
2663 mii
.fState
|= MFS_DEFAULT
;
2664 #else // CE specific
2665 // ::SetMenuItemInfo() can't disable or check menu items
2666 // on Windows CE, so we have to do that directly
2667 UINT uEnable
= MF_BYCOMMAND
;
2668 if((pUIData
->m_wState
& UPDUI_DISABLED
) != 0)
2669 uEnable
|= MF_GRAYED
;
2671 uEnable
|= MF_ENABLED
;
2672 ::EnableMenuItem(hMenu
, nID
, uEnable
);
2674 UINT uCheck
= MF_BYCOMMAND
;
2675 if((pUIData
->m_wState
& UPDUI_CHECKED
) != 0)
2676 uCheck
|= MF_CHECKED
;
2678 uCheck
|= MF_UNCHECKED
;
2679 ::CheckMenuItem(hMenu
, nID
, uCheck
);
2680 #endif // _WIN32_WCE
2682 if((pUIData
->m_wState
& UPDUI_TEXT
) != 0)
2684 CMenuItemInfo miiNow
;
2685 miiNow
.fMask
= MIIM_TYPE
;
2687 if(::GetMenuItemInfo(hMenu
, nID
, FALSE
, &miiNow
))
2689 mii
.fMask
|= MIIM_TYPE
;
2690 // MFT_BITMAP and MFT_SEPARATOR don't go together with MFT_STRING
2692 mii
.fType
|= (miiNow
.fType
& ~(MFT_BITMAP
| MFT_SEPARATOR
)) | MFT_STRING
;
2693 #else // CE specific
2694 mii
.fType
|= (miiNow
.fType
& ~(MFT_SEPARATOR
)) | MFT_STRING
;
2695 #endif // _WIN32_WCE
2696 mii
.dwTypeData
= pUIData
->m_lpstrText
;
2700 ::SetMenuItemInfo(hMenu
, nID
, FALSE
, &mii
);
2703 static void UIUpdateToolBarElement(int nID
, _AtlUpdateUIData
* pUIData
, HWND hWndToolBar
)
2705 // Note: only handles enabled/disabled, checked state, and radio (press)
2706 ::SendMessage(hWndToolBar
, TB_ENABLEBUTTON
, nID
, (LPARAM
)(pUIData
->m_wState
& UPDUI_DISABLED
) ? FALSE
: TRUE
);
2707 ::SendMessage(hWndToolBar
, TB_CHECKBUTTON
, nID
, (LPARAM
)(pUIData
->m_wState
& UPDUI_CHECKED
) ? TRUE
: FALSE
);
2708 ::SendMessage(hWndToolBar
, TB_INDETERMINATE
, nID
, (LPARAM
)(pUIData
->m_wState
& UPDUI_CHECKED2
) ? TRUE
: FALSE
);
2709 ::SendMessage(hWndToolBar
, TB_PRESSBUTTON
, nID
, (LPARAM
)(pUIData
->m_wState
& UPDUI_RADIO
) ? TRUE
: FALSE
);
2712 static void UIUpdateStatusBarElement(int nID
, _AtlUpdateUIData
* pUIData
, HWND hWndStatusBar
)
2714 // Note: only handles text
2715 if(pUIData
->m_wState
& UPDUI_TEXT
)
2716 ::SendMessage(hWndStatusBar
, SB_SETTEXT
, nID
, (LPARAM
)pUIData
->m_lpstrText
);
2719 static void UIUpdateChildWindow(int nID
, _AtlUpdateUIData
* pUIData
, HWND hWnd
)
2721 HWND hChild
= ::GetDlgItem(hWnd
, nID
);
2723 ::EnableWindow(hChild
, (pUIData
->m_wState
& UPDUI_DISABLED
) ? FALSE
: TRUE
);
2724 // for check and radio, assume that window is a button
2725 int nCheck
= BST_UNCHECKED
;
2726 if(pUIData
->m_wState
& UPDUI_CHECKED
|| pUIData
->m_wState
& UPDUI_RADIO
)
2727 nCheck
= BST_CHECKED
;
2728 else if(pUIData
->m_wState
& UPDUI_CHECKED2
)
2729 nCheck
= BST_INDETERMINATE
;
2730 ::SendMessage(hChild
, BM_SETCHECK
, nCheck
, 0L);
2731 if(pUIData
->m_wState
& UPDUI_DEFAULT
)
2733 DWORD dwRet
= (DWORD
)::SendMessage(hWnd
, DM_GETDEFID
, 0, 0L);
2734 if(HIWORD(dwRet
) == DC_HASDEFID
)
2736 HWND hOldDef
= ::GetDlgItem(hWnd
, (int)(short)LOWORD(dwRet
));
2737 // remove BS_DEFPUSHBUTTON
2738 ::SendMessage(hOldDef
, BM_SETSTYLE
, BS_PUSHBUTTON
, MAKELPARAM(TRUE
, 0));
2740 ::SendMessage(hWnd
, DM_SETDEFID
, nID
, 0L);
2742 if(pUIData
->m_wState
& UPDUI_TEXT
)
2743 ::SetWindowText(hChild
, pUIData
->m_lpstrText
);
2748 class CUpdateUI
: public CUpdateUIBase
2753 T
* pT
= static_cast<T
*>(this);
2755 const _AtlUpdateUIMap
* pMap
= pT
->GetUpdateUIMap();
2757 ATLASSERT(m_pUIMap
!= NULL
);
2759 for(nCount
= 1; pMap
->m_nID
!= (WORD
)-1; nCount
++)
2762 // check for duplicates (debug only)
2764 for(int i
= 0; i
< nCount
; i
++)
2766 for(int j
= 0; j
< nCount
; j
++)
2768 // shouldn't have duplicates in the update UI map
2770 ATLASSERT(m_pUIMap
[j
].m_nID
!= m_pUIMap
[i
].m_nID
);
2775 ATLTRY(m_pUIData
= new _AtlUpdateUIData
[nCount
]);
2776 ATLASSERT(m_pUIData
!= NULL
);
2778 if(m_pUIData
!= NULL
)
2779 memset(m_pUIData
, 0, sizeof(_AtlUpdateUIData
) * nCount
);
2784 ///////////////////////////////////////////////////////////////////////////////
2785 // CDynamicUpdateUI - allows update elements to dynamically added and removed
2786 // in addition to a static update UI map
2789 class CDynamicUpdateUI
: public CUpdateUIBase
2793 ATL::CSimpleArray
<_AtlUpdateUIMap
> m_arrUIMap
; // copy of the static UI data
2794 ATL::CSimpleArray
<_AtlUpdateUIData
> m_arrUIData
; // instance UI data
2796 // Constructor/destructor
2799 T
* pT
= static_cast<T
*>(this);
2801 const _AtlUpdateUIMap
* pMap
= pT
->GetUpdateUIMap();
2802 ATLASSERT(pMap
!= NULL
);
2806 BOOL bRet
= m_arrUIMap
.Add(*(_AtlUpdateUIMap
*)pMap
);
2811 _AtlUpdateUIData data
= { 0, NULL
};
2812 bRet
= m_arrUIData
.Add(data
);
2816 if(pMap
->m_nID
== (WORD
)-1)
2822 ATLASSERT(m_arrUIMap
.GetSize() == m_arrUIData
.GetSize());
2825 // check for duplicates (debug only)
2826 for(int i
= 0; i
< m_arrUIMap
.GetSize(); i
++)
2828 for(int j
= 0; j
< m_arrUIMap
.GetSize(); j
++)
2830 // shouldn't have duplicates in the update UI map
2832 ATLASSERT(m_arrUIMap
[j
].m_nID
!= m_arrUIMap
[i
].m_nID
);
2837 // Set internal data pointers to point to the new data arrays
2838 m_pUIMap
= m_arrUIMap
.m_aT
;
2839 m_pUIData
= m_arrUIData
.m_aT
;
2844 for(int i
= 0; i
< m_arrUIData
.GetSize(); i
++)
2846 if((m_arrUIData
[i
].m_wState
& UPDUI_TEXT
) != 0)
2847 delete [] m_arrUIData
[i
].m_lpstrText
;
2850 // Reset internal data pointers (memory will be released by CSimpleArray d-tor)
2855 // Methods for dynamically adding and removing update elements
2856 bool UIAddUpdateElement(WORD nID
, WORD wType
)
2858 // check for duplicates
2859 for(int i
= 0; i
< m_arrUIMap
.GetSize(); i
++)
2861 // shouldn't have duplicates in the update UI map
2862 ATLASSERT(m_arrUIMap
[i
].m_nID
!= nID
);
2863 if(m_arrUIMap
[i
].m_nID
== nID
)
2867 bool bRetVal
= false;
2869 // Add new end element
2870 _AtlUpdateUIMap uumEnd
= { (WORD
)-1, 0 };
2871 BOOL bRet
= m_arrUIMap
.Add(uumEnd
);
2876 _AtlUpdateUIData uud
= { 0, NULL
};
2877 bRet
= m_arrUIData
.Add(uud
);
2880 // Set new data to the previous end element
2883 int nSize
= m_arrUIMap
.GetSize();
2884 _AtlUpdateUIMap uum
= { nID
, wType
};
2885 m_arrUIMap
.SetAtIndex(nSize
- 2, uum
);
2886 m_arrUIData
.SetAtIndex(nSize
- 2, uud
);
2888 // Set internal data pointers again, just in case that memory moved
2889 m_pUIMap
= m_arrUIMap
.m_aT
;
2890 m_pUIData
= m_arrUIData
.m_aT
;
2899 bool UIRemoveUpdateElement(WORD nID
)
2901 bool bRetVal
= false;
2903 for(int i
= 0; i
< m_arrUIMap
.GetSize(); i
++)
2905 if(m_arrUIMap
[i
].m_nID
== nID
)
2907 BOOL bRet
= m_arrUIMap
.RemoveAt(i
);
2909 bRet
= m_arrUIData
.RemoveAt(i
);
2922 ///////////////////////////////////////////////////////////////////////////////
2923 // CDialogResize - provides support for resizing dialog controls
2924 // (works for any window that has child controls)
2926 // Put CDialogResize in the list of base classes for a dialog (or even plain window),
2927 // then implement DLGRESIZE map by specifying controls and groups of control
2928 // and using DLSZ_* values to specify how are they supposed to be resized.
2931 // - Resizeable border (WS_THICKFRAME style) should be set in the dialog template
2932 // for top level dialogs (popup or overlapped), so that users can resize the dialog.
2933 // - Some flags cannot be combined; for instance DLSZ_CENTER_X overrides DLSZ_SIZE_X,
2934 // DLSZ_SIZE_X overrides DLSZ_MOVE_X. X and Y flags can be combined.
2935 // - Order of controls is important - group controls are resized and moved based
2936 // on the position of the previous control in a group.
2938 // dialog resize map macros
2939 #define BEGIN_DLGRESIZE_MAP(thisClass) \
2940 static const _AtlDlgResizeMap* GetDlgResizeMap() \
2942 static const _AtlDlgResizeMap theMap[] = \
2945 #define END_DLGRESIZE_MAP() \
2951 #define DLGRESIZE_CONTROL(id, flags) \
2954 #define BEGIN_DLGRESIZE_GROUP() \
2955 { -1, _DLSZ_BEGIN_GROUP },
2957 #define END_DLGRESIZE_GROUP() \
2958 { -1, _DLSZ_END_GROUP },
2965 // Data declarations and members
2968 DLSZ_SIZE_X
= 0x00000001,
2969 DLSZ_SIZE_Y
= 0x00000002,
2970 DLSZ_MOVE_X
= 0x00000004,
2971 DLSZ_MOVE_Y
= 0x00000008,
2972 DLSZ_REPAINT
= 0x00000010,
2973 DLSZ_CENTER_X
= 0x00000020,
2974 DLSZ_CENTER_Y
= 0x00000040,
2976 // internal use only
2977 _DLSZ_BEGIN_GROUP
= 0x00001000,
2978 _DLSZ_END_GROUP
= 0x00002000,
2979 _DLSZ_GRIPPER
= 0x00004000
2982 struct _AtlDlgResizeMap
2985 DWORD m_dwResizeFlags
;
2988 struct _AtlDlgResizeData
2991 DWORD m_dwResizeFlags
;
2994 int GetGroupCount() const
2996 return (int)LOBYTE(HIWORD(m_dwResizeFlags
));
2999 void SetGroupCount(int nCount
)
3001 ATLASSERT(nCount
> 0 && nCount
< 256);
3002 DWORD dwCount
= (DWORD
)MAKELONG(0, MAKEWORD(nCount
, 0));
3003 m_dwResizeFlags
&= 0xFF00FFFF;
3004 m_dwResizeFlags
|= dwCount
;
3007 bool operator ==(const _AtlDlgResizeData
& r
) const
3008 { return (m_nCtlID
== r
.m_nCtlID
&& m_dwResizeFlags
== r
.m_dwResizeFlags
); }
3011 ATL::CSimpleArray
<_AtlDlgResizeData
> m_arrData
;
3013 POINT m_ptMinTrackSize
;
3018 CDialogResize() : m_bGripper(false)
3020 m_sizeDialog
.cx
= 0;
3021 m_sizeDialog
.cy
= 0;
3022 m_ptMinTrackSize
.x
= -1;
3023 m_ptMinTrackSize
.y
= -1;
3027 void DlgResize_Init(bool bAddGripper
= true, bool bUseMinTrackSize
= true, DWORD dwForceStyle
= WS_CLIPCHILDREN
)
3029 T
* pT
= static_cast<T
*>(this);
3030 ATLASSERT(::IsWindow(pT
->m_hWnd
));
3032 DWORD dwStyle
= pT
->GetStyle();
3035 // Debug only: Check if top level dialogs have a resizeable border.
3036 if(((dwStyle
& WS_CHILD
) == 0) && ((dwStyle
& WS_THICKFRAME
) == 0))
3037 ATLTRACE2(atlTraceUI
, 0, _T("DlgResize_Init - warning: top level dialog without the WS_THICKFRAME style - user cannot resize it\n"));
3040 // Force specified styles (default WS_CLIPCHILDREN reduces flicker)
3041 if((dwStyle
& dwForceStyle
) != dwForceStyle
)
3042 pT
->ModifyStyle(0, dwForceStyle
);
3044 // Adding this style removes an empty icon that dialogs with WS_THICKFRAME have.
3045 // Setting icon to NULL is required when XP themes are active.
3046 // Note: This will not prevent adding an icon for the dialog using SetIcon()
3047 if((dwStyle
& WS_CHILD
) == 0)
3049 pT
->ModifyStyleEx(0, WS_EX_DLGMODALFRAME
);
3050 if(pT
->GetIcon(FALSE
) == NULL
)
3051 pT
->SetIcon(NULL
, FALSE
);
3054 // Cleanup in case of multiple initialization
3055 // block: first check for the gripper control, destroy it if needed
3057 ATL::CWindow wndGripper
= pT
->GetDlgItem(ATL_IDW_STATUS_BAR
);
3058 if(wndGripper
.IsWindow() && m_arrData
.GetSize() > 0 && (m_arrData
[0].m_dwResizeFlags
& _DLSZ_GRIPPER
) != 0)
3059 wndGripper
.DestroyWindow();
3061 // clear out everything else
3062 m_arrData
.RemoveAll();
3063 m_sizeDialog
.cx
= 0;
3064 m_sizeDialog
.cy
= 0;
3065 m_ptMinTrackSize
.x
= -1;
3066 m_ptMinTrackSize
.y
= -1;
3068 // Get initial dialog client size
3069 RECT rectDlg
= { 0 };
3070 pT
->GetClientRect(&rectDlg
);
3071 m_sizeDialog
.cx
= rectDlg
.right
;
3072 m_sizeDialog
.cy
= rectDlg
.bottom
;
3075 // Create gripper if requested
3079 // shouldn't exist already
3080 ATLASSERT(!::IsWindow(pT
->GetDlgItem(ATL_IDW_STATUS_BAR
)));
3081 if(!::IsWindow(pT
->GetDlgItem(ATL_IDW_STATUS_BAR
)))
3083 ATL::CWindow wndGripper
;
3084 wndGripper
.Create(_T("SCROLLBAR"), pT
->m_hWnd
, rectDlg
, NULL
, WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| SBS_SIZEBOX
| SBS_SIZEGRIP
| SBS_SIZEBOXBOTTOMRIGHTALIGN
, 0, ATL_IDW_STATUS_BAR
);
3085 ATLASSERT(wndGripper
.IsWindow());
3086 if(wndGripper
.IsWindow())
3089 RECT rectCtl
= { 0 };
3090 wndGripper
.GetWindowRect(&rectCtl
);
3091 ::MapWindowPoints(NULL
, pT
->m_hWnd
, (LPPOINT
)&rectCtl
, 2);
3092 _AtlDlgResizeData data
= { ATL_IDW_STATUS_BAR
, DLSZ_MOVE_X
| DLSZ_MOVE_Y
| DLSZ_REPAINT
| _DLSZ_GRIPPER
, { rectCtl
.left
, rectCtl
.top
, rectCtl
.right
, rectCtl
.bottom
} };
3093 m_arrData
.Add(data
);
3097 #else // CE specific
3098 bAddGripper
; // avoid level 4 warning
3099 #endif // _WIN32_WCE
3101 // Get min track position if requested
3102 if(bUseMinTrackSize
)
3104 if((dwStyle
& WS_CHILD
) != 0)
3107 pT
->GetClientRect(&rect
);
3108 m_ptMinTrackSize
.x
= rect
.right
- rect
.left
;
3109 m_ptMinTrackSize
.y
= rect
.bottom
- rect
.top
;
3114 pT
->GetWindowRect(&rect
);
3115 m_ptMinTrackSize
.x
= rect
.right
- rect
.left
;
3116 m_ptMinTrackSize
.y
= rect
.bottom
- rect
.top
;
3120 // Walk the map and initialize data
3121 const _AtlDlgResizeMap
* pMap
= pT
->GetDlgResizeMap();
3122 ATLASSERT(pMap
!= NULL
);
3123 int nGroupStart
= -1;
3124 for(int nCount
= 1; !(pMap
->m_nCtlID
== -1 && pMap
->m_dwResizeFlags
== 0); nCount
++, pMap
++)
3126 if(pMap
->m_nCtlID
== -1)
3128 switch(pMap
->m_dwResizeFlags
)
3130 case _DLSZ_BEGIN_GROUP
:
3131 ATLASSERT(nGroupStart
== -1);
3132 nGroupStart
= m_arrData
.GetSize();
3134 case _DLSZ_END_GROUP
:
3136 ATLASSERT(nGroupStart
!= -1);
3137 int nGroupCount
= m_arrData
.GetSize() - nGroupStart
;
3138 m_arrData
[nGroupStart
].SetGroupCount(nGroupCount
);
3143 ATLASSERT(FALSE
&& _T("Invalid DLGRESIZE Map Entry"));
3149 // this ID conflicts with the default gripper one
3150 ATLASSERT(m_bGripper
? (pMap
->m_nCtlID
!= ATL_IDW_STATUS_BAR
) : TRUE
);
3152 ATL::CWindow ctl
= pT
->GetDlgItem(pMap
->m_nCtlID
);
3153 ATLASSERT(ctl
.IsWindow());
3154 RECT rectCtl
= { 0 };
3155 ctl
.GetWindowRect(&rectCtl
);
3156 ::MapWindowPoints(NULL
, pT
->m_hWnd
, (LPPOINT
)&rectCtl
, 2);
3158 DWORD dwGroupFlag
= (nGroupStart
!= -1 && m_arrData
.GetSize() == nGroupStart
) ? _DLSZ_BEGIN_GROUP
: 0;
3159 _AtlDlgResizeData data
= { pMap
->m_nCtlID
, pMap
->m_dwResizeFlags
| dwGroupFlag
, { rectCtl
.left
, rectCtl
.top
, rectCtl
.right
, rectCtl
.bottom
} };
3160 m_arrData
.Add(data
);
3163 ATLASSERT((nGroupStart
== -1) && _T("No End Group Entry in the DLGRESIZE Map"));
3166 void DlgResize_UpdateLayout(int cxWidth
, int cyHeight
)
3168 T
* pT
= static_cast<T
*>(this);
3169 ATLASSERT(::IsWindow(pT
->m_hWnd
));
3171 // Restrict minimum size if requested
3172 if(((pT
->GetStyle() & WS_CHILD
) != 0) && m_ptMinTrackSize
.x
!= -1 && m_ptMinTrackSize
.y
!= -1)
3174 if(cxWidth
< m_ptMinTrackSize
.x
)
3175 cxWidth
= m_ptMinTrackSize
.x
;
3176 if(cyHeight
< m_ptMinTrackSize
.y
)
3177 cyHeight
= m_ptMinTrackSize
.y
;
3180 BOOL bVisible
= pT
->IsWindowVisible();
3182 pT
->SetRedraw(FALSE
);
3184 for(int i
= 0; i
< m_arrData
.GetSize(); i
++)
3186 if((m_arrData
[i
].m_dwResizeFlags
& _DLSZ_BEGIN_GROUP
) != 0) // start of a group
3188 int nGroupCount
= m_arrData
[i
].GetGroupCount();
3189 ATLASSERT(nGroupCount
> 0 && i
+ nGroupCount
- 1 < m_arrData
.GetSize());
3190 RECT rectGroup
= m_arrData
[i
].m_rect
;
3193 for(j
= 1; j
< nGroupCount
; j
++)
3195 rectGroup
.left
= __min(rectGroup
.left
, m_arrData
[i
+ j
].m_rect
.left
);
3196 rectGroup
.top
= __min(rectGroup
.top
, m_arrData
[i
+ j
].m_rect
.top
);
3197 rectGroup
.right
= __max(rectGroup
.right
, m_arrData
[i
+ j
].m_rect
.right
);
3198 rectGroup
.bottom
= __max(rectGroup
.bottom
, m_arrData
[i
+ j
].m_rect
.bottom
);
3201 for(j
= 0; j
< nGroupCount
; j
++)
3203 _AtlDlgResizeData
* pDataPrev
= NULL
;
3205 pDataPrev
= &(m_arrData
[i
+ j
- 1]);
3206 pT
->DlgResize_PositionControl(cxWidth
, cyHeight
, rectGroup
, m_arrData
[i
+ j
], true, pDataPrev
);
3209 i
+= nGroupCount
- 1; // increment to skip all group controls
3211 else // one control entry
3213 RECT rectGroup
= { 0, 0, 0, 0 };
3214 pT
->DlgResize_PositionControl(cxWidth
, cyHeight
, rectGroup
, m_arrData
[i
], false);
3219 pT
->SetRedraw(TRUE
);
3221 pT
->RedrawWindow(NULL
, NULL
, RDW_ERASE
| RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_ALLCHILDREN
);
3224 // Message map and handlers
3225 BEGIN_MSG_MAP(CDialogResize
)
3226 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
3228 MESSAGE_HANDLER(WM_GETMINMAXINFO
, OnGetMinMaxInfo
)
3229 #endif // _WIN32_WCE
3232 LRESULT
OnSize(UINT
/*uMsg*/, WPARAM wParam
, LPARAM lParam
, BOOL
& /*bHandled*/)
3234 T
* pT
= static_cast<T
*>(this);
3238 ATL::CWindow wndGripper
= pT
->GetDlgItem(ATL_IDW_STATUS_BAR
);
3239 if(wParam
== SIZE_MAXIMIZED
)
3240 wndGripper
.ShowWindow(SW_HIDE
);
3241 else if(wParam
== SIZE_RESTORED
)
3242 wndGripper
.ShowWindow(SW_SHOW
);
3244 #endif // _WIN32_WCE
3245 if(wParam
!= SIZE_MINIMIZED
)
3247 ATLASSERT(::IsWindow(pT
->m_hWnd
));
3248 pT
->DlgResize_UpdateLayout(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
3254 LRESULT
OnGetMinMaxInfo(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM lParam
, BOOL
& /*bHandled*/)
3256 if(m_ptMinTrackSize
.x
!= -1 && m_ptMinTrackSize
.y
!= -1)
3258 LPMINMAXINFO lpMMI
= (LPMINMAXINFO
)lParam
;
3259 lpMMI
->ptMinTrackSize
= m_ptMinTrackSize
;
3263 #endif // _WIN32_WCE
3266 bool DlgResize_PositionControl(int cxWidth
, int cyHeight
, RECT
& rectGroup
, _AtlDlgResizeData
& data
, bool bGroup
,
3267 _AtlDlgResizeData
* pDataPrev
= NULL
)
3269 T
* pT
= static_cast<T
*>(this);
3270 ATLASSERT(::IsWindow(pT
->m_hWnd
));
3272 RECT rectCtl
= { 0 };
3274 ctl
= pT
->GetDlgItem(data
.m_nCtlID
);
3275 if(!ctl
.GetWindowRect(&rectCtl
))
3277 ::MapWindowPoints(NULL
, pT
->m_hWnd
, (LPPOINT
)&rectCtl
, 2);
3281 if((data
.m_dwResizeFlags
& DLSZ_CENTER_X
) != 0)
3283 int cxRight
= rectGroup
.right
+ cxWidth
- m_sizeDialog
.cx
;
3284 int cxCtl
= data
.m_rect
.right
- data
.m_rect
.left
;
3285 rectCtl
.left
= rectGroup
.left
+ (cxRight
- rectGroup
.left
- cxCtl
) / 2;
3286 rectCtl
.right
= rectCtl
.left
+ cxCtl
;
3288 else if((data
.m_dwResizeFlags
& (DLSZ_SIZE_X
| DLSZ_MOVE_X
)) != 0)
3290 rectCtl
.left
= rectGroup
.left
+ ::MulDiv(data
.m_rect
.left
- rectGroup
.left
, rectGroup
.right
- rectGroup
.left
+ (cxWidth
- m_sizeDialog
.cx
), rectGroup
.right
- rectGroup
.left
);
3292 if((data
.m_dwResizeFlags
& DLSZ_SIZE_X
) != 0)
3294 rectCtl
.right
= rectGroup
.left
+ ::MulDiv(data
.m_rect
.right
- rectGroup
.left
, rectGroup
.right
- rectGroup
.left
+ (cxWidth
- m_sizeDialog
.cx
), rectGroup
.right
- rectGroup
.left
);
3296 if(pDataPrev
!= NULL
)
3298 ATL::CWindow ctlPrev
= pT
->GetDlgItem(pDataPrev
->m_nCtlID
);
3299 RECT rcPrev
= { 0 };
3300 ctlPrev
.GetWindowRect(&rcPrev
);
3301 ::MapWindowPoints(NULL
, pT
->m_hWnd
, (LPPOINT
)&rcPrev
, 2);
3302 int dxAdjust
= (rectCtl
.left
- rcPrev
.right
) - (data
.m_rect
.left
- pDataPrev
->m_rect
.right
);
3303 rcPrev
.right
+= dxAdjust
;
3304 ctlPrev
.SetWindowPos(NULL
, &rcPrev
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOMOVE
);
3309 rectCtl
.right
= rectCtl
.left
+ (data
.m_rect
.right
- data
.m_rect
.left
);
3313 if((data
.m_dwResizeFlags
& DLSZ_CENTER_Y
) != 0)
3315 int cyBottom
= rectGroup
.bottom
+ cyHeight
- m_sizeDialog
.cy
;
3316 int cyCtl
= data
.m_rect
.bottom
- data
.m_rect
.top
;
3317 rectCtl
.top
= rectGroup
.top
+ (cyBottom
- rectGroup
.top
- cyCtl
) / 2;
3318 rectCtl
.bottom
= rectCtl
.top
+ cyCtl
;
3320 else if((data
.m_dwResizeFlags
& (DLSZ_SIZE_Y
| DLSZ_MOVE_Y
)) != 0)
3322 rectCtl
.top
= rectGroup
.top
+ ::MulDiv(data
.m_rect
.top
- rectGroup
.top
, rectGroup
.bottom
- rectGroup
.top
+ (cyHeight
- m_sizeDialog
.cy
), rectGroup
.bottom
- rectGroup
.top
);
3324 if((data
.m_dwResizeFlags
& DLSZ_SIZE_Y
) != 0)
3326 rectCtl
.bottom
= rectGroup
.top
+ ::MulDiv(data
.m_rect
.bottom
- rectGroup
.top
, rectGroup
.bottom
- rectGroup
.top
+ (cyHeight
- m_sizeDialog
.cy
), rectGroup
.bottom
- rectGroup
.top
);
3328 if(pDataPrev
!= NULL
)
3330 ATL::CWindow ctlPrev
= pT
->GetDlgItem(pDataPrev
->m_nCtlID
);
3331 RECT rcPrev
= { 0 };
3332 ctlPrev
.GetWindowRect(&rcPrev
);
3333 ::MapWindowPoints(NULL
, pT
->m_hWnd
, (LPPOINT
)&rcPrev
, 2);
3334 int dxAdjust
= (rectCtl
.top
- rcPrev
.bottom
) - (data
.m_rect
.top
- pDataPrev
->m_rect
.bottom
);
3335 rcPrev
.bottom
+= dxAdjust
;
3336 ctlPrev
.SetWindowPos(NULL
, &rcPrev
, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOMOVE
);
3341 rectCtl
.bottom
= rectCtl
.top
+ (data
.m_rect
.bottom
- data
.m_rect
.top
);
3347 if((data
.m_dwResizeFlags
& DLSZ_CENTER_X
) != 0)
3349 int cxCtl
= data
.m_rect
.right
- data
.m_rect
.left
;
3350 rectCtl
.left
= (cxWidth
- cxCtl
) / 2;
3351 rectCtl
.right
= rectCtl
.left
+ cxCtl
;
3353 else if((data
.m_dwResizeFlags
& (DLSZ_SIZE_X
| DLSZ_MOVE_X
)) != 0)
3355 rectCtl
.right
= data
.m_rect
.right
+ (cxWidth
- m_sizeDialog
.cx
);
3357 if((data
.m_dwResizeFlags
& DLSZ_MOVE_X
) != 0)
3358 rectCtl
.left
= rectCtl
.right
- (data
.m_rect
.right
- data
.m_rect
.left
);
3361 if((data
.m_dwResizeFlags
& DLSZ_CENTER_Y
) != 0)
3363 int cyCtl
= data
.m_rect
.bottom
- data
.m_rect
.top
;
3364 rectCtl
.top
= (cyHeight
- cyCtl
) / 2;
3365 rectCtl
.bottom
= rectCtl
.top
+ cyCtl
;
3367 else if((data
.m_dwResizeFlags
& (DLSZ_SIZE_Y
| DLSZ_MOVE_Y
)) != 0)
3369 rectCtl
.bottom
= data
.m_rect
.bottom
+ (cyHeight
- m_sizeDialog
.cy
);
3371 if((data
.m_dwResizeFlags
& DLSZ_MOVE_Y
) != 0)
3372 rectCtl
.top
= rectCtl
.bottom
- (data
.m_rect
.bottom
- data
.m_rect
.top
);
3376 if((data
.m_dwResizeFlags
& DLSZ_REPAINT
) != 0)
3379 if((data
.m_dwResizeFlags
& (DLSZ_SIZE_X
| DLSZ_SIZE_Y
| DLSZ_MOVE_X
| DLSZ_MOVE_Y
| DLSZ_REPAINT
| DLSZ_CENTER_X
| DLSZ_CENTER_Y
)) != 0)
3380 ctl
.SetWindowPos(NULL
, &rectCtl
, SWP_NOZORDER
| SWP_NOACTIVATE
);
3387 ///////////////////////////////////////////////////////////////////////////////
3388 // CDoubleBufferImpl - Provides double-buffer painting support to any window
3391 class CDoubleBufferImpl
3395 void DoPaint(CDCHandle
/*dc*/)
3397 // must be implemented in a derived class
3401 // Message map and handlers
3402 BEGIN_MSG_MAP(CDoubleBufferImpl
)
3403 MESSAGE_HANDLER(WM_ERASEBKGND
, OnEraseBackground
)
3404 MESSAGE_HANDLER(WM_PAINT
, OnPaint
)
3406 MESSAGE_HANDLER(WM_PRINTCLIENT
, OnPaint
)
3407 #endif // !_WIN32_WCE
3410 LRESULT
OnEraseBackground(UINT
/*uMsg*/, WPARAM
/*wParam*/, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
3412 return 1; // no background painting needed
3415 LRESULT
OnPaint(UINT
/*uMsg*/, WPARAM wParam
, LPARAM
/*lParam*/, BOOL
& /*bHandled*/)
3417 T
* pT
= static_cast<T
*>(this);
3418 ATLASSERT(::IsWindow(pT
->m_hWnd
));
3423 pT
->GetClientRect(&rect
);
3424 CMemoryDC
dcMem((HDC
)wParam
, rect
);
3425 pT
->DoPaint(dcMem
.m_hDC
);
3429 CPaintDC
dc(pT
->m_hWnd
);
3430 CMemoryDC
dcMem(dc
.m_hDC
, dc
.m_ps
.rcPaint
);
3431 pT
->DoPaint(dcMem
.m_hDC
);
3439 ///////////////////////////////////////////////////////////////////////////////
3440 // CDoubleBufferWindowImpl - Implements a double-buffer painting window
3442 template <class T
, class TBase
= ATL::CWindow
, class TWinTraits
= ATL::CControlWinTraits
>
3443 class ATL_NO_VTABLE CDoubleBufferWindowImpl
: public ATL::CWindowImpl
< T
, TBase
, TWinTraits
>, public CDoubleBufferImpl
< T
>
3446 BEGIN_MSG_MAP(CDoubleBufferWindowImpl
)
3447 CHAIN_MSG_MAP(CDoubleBufferImpl
< T
>)
3452 // command bar support
3453 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
3455 #undef CBRM_TRACKPOPUPMENU
3456 #undef CBRM_GETCMDBAR
3458 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
3462 #endif // __ATLFRAME_H__