| OLD | NEW |
| (Empty) |
| 1 // Windows Template Library - WTL version 8.0 | |
| 2 // Copyright (C) Microsoft Corporation. All rights reserved. | |
| 3 // | |
| 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. | |
| 8 | |
| 9 #ifndef __ATLFRAME_H__ | |
| 10 #define __ATLFRAME_H__ | |
| 11 | |
| 12 #pragma once | |
| 13 | |
| 14 #ifndef __cplusplus | |
| 15 #error ATL requires C++ compilation (use a .cpp suffix) | |
| 16 #endif | |
| 17 | |
| 18 #ifndef __ATLAPP_H__ | |
| 19 #error atlframe.h requires atlapp.h to be included first | |
| 20 #endif | |
| 21 | |
| 22 #ifndef __ATLWIN_H__ | |
| 23 #error atlframe.h requires atlwin.h to be included first | |
| 24 #endif | |
| 25 | |
| 26 | |
| 27 /////////////////////////////////////////////////////////////////////////////// | |
| 28 // Classes in this file: | |
| 29 // | |
| 30 // CFrameWindowImpl<T, TBase, TWinTraits> | |
| 31 // CMDIWindow | |
| 32 // CMDIFrameWindowImpl<T, TBase, TWinTraits> | |
| 33 // CMDIChildWindowImpl<T, TBase, TWinTraits> | |
| 34 // COwnerDraw<T> | |
| 35 // CUpdateUIBase | |
| 36 // CUpdateUI<T> | |
| 37 // CDynamicUpdateUI<T> | |
| 38 // CDialogResize<T> | |
| 39 // CDoubleBufferImpl<T> | |
| 40 // CDoubleBufferWindowImpl<T, TBase, TWinTraits> | |
| 41 // | |
| 42 // Global functions: | |
| 43 // AtlCreateSimpleToolBar() | |
| 44 | |
| 45 | |
| 46 namespace WTL | |
| 47 { | |
| 48 | |
| 49 /////////////////////////////////////////////////////////////////////////////// | |
| 50 // CFrameWndClassInfo - Manages frame window Windows class information | |
| 51 | |
| 52 class CFrameWndClassInfo | |
| 53 { | |
| 54 public: | |
| 55 #ifndef _WIN32_WCE | |
| 56 enum { cchAutoName = 5 + sizeof(void*) * 2 }; // sizeof(void*) * 2 is
the number of digits %p outputs | |
| 57 WNDCLASSEX m_wc; | |
| 58 #else // CE specific | |
| 59 enum { cchAutoName = MAX_PATH }; // MAX_PATH because this can be set i
n the wizard generated CMainFrame::ActivatePreviousInstance to a user defined st
ring. | |
| 60 WNDCLASS m_wc; | |
| 61 #endif // !_WIN32_WCE | |
| 62 LPCTSTR m_lpszOrigName; | |
| 63 WNDPROC pWndProc; | |
| 64 LPCTSTR m_lpszCursorID; | |
| 65 BOOL m_bSystemCursor; | |
| 66 ATOM m_atom; | |
| 67 TCHAR m_szAutoName[cchAutoName]; | |
| 68 UINT m_uCommonResourceID; | |
| 69 | |
| 70 #ifndef _WIN32_WCE | |
| 71 ATOM Register(WNDPROC* pProc) | |
| 72 { | |
| 73 if (m_atom == 0) | |
| 74 { | |
| 75 CWindowCreateCriticalSectionLock lock; | |
| 76 if(FAILED(lock.Lock())) | |
| 77 { | |
| 78 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to l
ock critical section in CFrameWndClassInfo::Register.\n")); | |
| 79 ATLASSERT(FALSE); | |
| 80 return 0; | |
| 81 } | |
| 82 | |
| 83 if(m_atom == 0) | |
| 84 { | |
| 85 HINSTANCE hInst = ModuleHelper::GetModuleInstanc
e(); | |
| 86 | |
| 87 if (m_lpszOrigName != NULL) | |
| 88 { | |
| 89 ATLASSERT(pProc != NULL); | |
| 90 LPCTSTR lpsz = m_wc.lpszClassName; | |
| 91 WNDPROC proc = m_wc.lpfnWndProc; | |
| 92 | |
| 93 WNDCLASSEX wc = { 0 }; | |
| 94 wc.cbSize = sizeof(WNDCLASSEX); | |
| 95 // try process local class first | |
| 96 if(!::GetClassInfoEx(ModuleHelper::GetMo
duleInstance(), m_lpszOrigName, &wc)) | |
| 97 { | |
| 98 // try global class | |
| 99 if(!::GetClassInfoEx(NULL, m_lps
zOrigName, &wc)) | |
| 100 { | |
| 101 lock.Unlock(); | |
| 102 return 0; | |
| 103 } | |
| 104 } | |
| 105 m_wc = wc; | |
| 106 pWndProc = m_wc.lpfnWndProc; | |
| 107 m_wc.lpszClassName = lpsz; | |
| 108 m_wc.lpfnWndProc = proc; | |
| 109 } | |
| 110 else | |
| 111 { | |
| 112 m_wc.hCursor = ::LoadCursor(m_bSystemCur
sor ? NULL : hInst, m_lpszCursorID); | |
| 113 } | |
| 114 | |
| 115 m_wc.hInstance = hInst; | |
| 116 m_wc.style &= ~CS_GLOBALCLASS; // we don't reg
ister global classes | |
| 117 if (m_wc.lpszClassName == NULL) | |
| 118 { | |
| 119 #if (_WIN32_WINNT >= 0x0500) || defined(_WIN64) | |
| 120 SecureHelper::wsprintf_x(m_szAutoName, c
chAutoName, _T("ATL:%p"), &m_wc); | |
| 121 #else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64)) | |
| 122 SecureHelper::wsprintf_x(m_szAutoName, c
chAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc); | |
| 123 #endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64)) | |
| 124 m_wc.lpszClassName = m_szAutoName; | |
| 125 } | |
| 126 | |
| 127 WNDCLASSEX wcTemp = m_wc; | |
| 128 m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance,
m_wc.lpszClassName, &wcTemp); | |
| 129 if (m_atom == 0) | |
| 130 { | |
| 131 if(m_uCommonResourceID != 0) // use it
if not zero | |
| 132 { | |
| 133 m_wc.hIcon = (HICON)::LoadImage(
ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE
_ICON, 32, 32, LR_DEFAULTCOLOR); | |
| 134 m_wc.hIconSm = (HICON)::LoadImag
e(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMA
GE_ICON, 16, 16, LR_DEFAULTCOLOR); | |
| 135 } | |
| 136 m_atom = ::RegisterClassEx(&m_wc); | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 lock.Unlock(); | |
| 141 } | |
| 142 | |
| 143 if (m_lpszOrigName != NULL) | |
| 144 { | |
| 145 ATLASSERT(pProc != NULL); | |
| 146 ATLASSERT(pWndProc != NULL); | |
| 147 *pProc = pWndProc; | |
| 148 } | |
| 149 | |
| 150 return m_atom; | |
| 151 } | |
| 152 #else // CE specific | |
| 153 ATOM Register(WNDPROC* pProc) | |
| 154 { | |
| 155 if (m_atom == 0) | |
| 156 { | |
| 157 CWindowCreateCriticalSectionLock lock; | |
| 158 if(FAILED(lock.Lock())) | |
| 159 { | |
| 160 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to l
ock critical section in CFrameWndClassInfo::Register.\n")); | |
| 161 ATLASSERT(FALSE); | |
| 162 return 0; | |
| 163 } | |
| 164 | |
| 165 if(m_atom == 0) | |
| 166 { | |
| 167 HINSTANCE hInst = ModuleHelper::GetModuleInstanc
e(); | |
| 168 | |
| 169 if (m_lpszOrigName != NULL) | |
| 170 { | |
| 171 ATLASSERT(pProc != NULL); | |
| 172 LPCTSTR lpsz = m_wc.lpszClassName; | |
| 173 WNDPROC proc = m_wc.lpfnWndProc; | |
| 174 | |
| 175 WNDCLASS wc = { 0 }; | |
| 176 // try process local class first | |
| 177 if(!::GetClassInfo(ModuleHelper::GetModu
leInstance(), m_lpszOrigName, &wc)) | |
| 178 { | |
| 179 // try global class | |
| 180 if(!::GetClassInfo(NULL, m_lpszO
rigName, &wc)) | |
| 181 { | |
| 182 lock.Unlock(); | |
| 183 return 0; | |
| 184 } | |
| 185 } | |
| 186 m_wc = wc; | |
| 187 pWndProc = m_wc.lpfnWndProc; | |
| 188 m_wc.lpszClassName = lpsz; | |
| 189 m_wc.lpfnWndProc = proc; | |
| 190 } | |
| 191 else | |
| 192 { | |
| 193 #if defined(GWES_CURSOR) || defined(GWES_MCURSOR) | |
| 194 m_wc.hCursor = ::LoadCursor(m_bSystemCur
sor ? NULL : hInst, m_lpszCursorID); | |
| 195 #else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR)) | |
| 196 m_wc.hCursor = NULL; | |
| 197 #endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR)) | |
| 198 } | |
| 199 | |
| 200 m_wc.hInstance = hInst; | |
| 201 m_wc.style &= ~CS_GLOBALCLASS; // we don't reg
ister global classes | |
| 202 if (m_wc.lpszClassName == NULL) | |
| 203 { | |
| 204 wsprintf(m_szAutoName, _T("ATL:%8.8X"),
(DWORD_PTR)&m_wc); | |
| 205 m_wc.lpszClassName = m_szAutoName; | |
| 206 } | |
| 207 | |
| 208 WNDCLASS wcTemp = m_wc; | |
| 209 m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_
wc.lpszClassName, &wcTemp); | |
| 210 if (m_atom == 0) | |
| 211 { | |
| 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); | |
| 215 } | |
| 216 } | |
| 217 | |
| 218 lock.Unlock(); | |
| 219 } | |
| 220 | |
| 221 if (m_lpszOrigName != NULL) | |
| 222 { | |
| 223 ATLASSERT(pProc != NULL); | |
| 224 ATLASSERT(pWndProc != NULL); | |
| 225 *pProc = pWndProc; | |
| 226 } | |
| 227 | |
| 228 return m_atom; | |
| 229 } | |
| 230 #endif // _WIN32_WCE | |
| 231 }; | |
| 232 | |
| 233 | |
| 234 /////////////////////////////////////////////////////////////////////////////// | |
| 235 // Macros for declaring frame window WNDCLASS | |
| 236 | |
| 237 #ifndef _WIN32_WCE | |
| 238 | |
| 239 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ | |
| 240 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
| 241 { \ | |
| 242 static WTL::CFrameWndClassInfo wc = \ | |
| 243 { \ | |
| 244 { sizeof(WNDCLASSEX), 0, StartWindowProc, \ | |
| 245 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndC
lassName, NULL }, \ | |
| 246 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ | |
| 247 }; \ | |
| 248 return wc; \ | |
| 249 } | |
| 250 | |
| 251 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd
) \ | |
| 252 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
| 253 { \ | |
| 254 static WTL::CFrameWndClassInfo wc = \ | |
| 255 { \ | |
| 256 { sizeof(WNDCLASSEX), style, StartWindowProc, \ | |
| 257 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassNam
e, NULL }, \ | |
| 258 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ | |
| 259 }; \ | |
| 260 return wc; \ | |
| 261 } | |
| 262 | |
| 263 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonReso
urceID) \ | |
| 264 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
| 265 { \ | |
| 266 static WTL::CFrameWndClassInfo wc = \ | |
| 267 { \ | |
| 268 { sizeof(WNDCLASSEX), 0, StartWindowProc, \ | |
| 269 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \ | |
| 270 OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID
\ | |
| 271 }; \ | |
| 272 return wc; \ | |
| 273 } | |
| 274 | |
| 275 #else // CE specific | |
| 276 | |
| 277 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ | |
| 278 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
| 279 { \ | |
| 280 static WTL::CFrameWndClassInfo wc = \ | |
| 281 { \ | |
| 282 { 0, StartWindowProc, \ | |
| 283 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndC
lassName }, \ | |
| 284 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ | |
| 285 }; \ | |
| 286 return wc; \ | |
| 287 } | |
| 288 | |
| 289 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd
) \ | |
| 290 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
| 291 { \ | |
| 292 static WTL::CFrameWndClassInfo wc = \ | |
| 293 { \ | |
| 294 { style, StartWindowProc, \ | |
| 295 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassNam
e }, \ | |
| 296 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ | |
| 297 }; \ | |
| 298 return wc; \ | |
| 299 } | |
| 300 | |
| 301 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonReso
urceID) \ | |
| 302 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
| 303 { \ | |
| 304 static WTL::CFrameWndClassInfo wc = \ | |
| 305 { \ | |
| 306 { NULL, StartWindowProc, \ | |
| 307 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \ | |
| 308 OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResou
rceID \ | |
| 309 }; \ | |
| 310 return wc; \ | |
| 311 } | |
| 312 | |
| 313 #endif // !_WIN32_WCE | |
| 314 | |
| 315 | |
| 316 /////////////////////////////////////////////////////////////////////////////// | |
| 317 // CFrameWindowImpl | |
| 318 | |
| 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); | |
| 323 | |
| 324 // standard toolbar styles | |
| 325 #define ATL_SIMPLE_TOOLBAR_STYLE \ | |
| 326 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOO
LTIPS) | |
| 327 // toolbar in a rebar pane | |
| 328 #define ATL_SIMPLE_TOOLBAR_PANE_STYLE \ | |
| 329 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVID
ER | 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) | |
| 334 #else | |
| 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_VARHEIG
HT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER) | |
| 342 #else | |
| 343 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \ | |
| 344 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIG
HT | RBS_BANDBORDERS | CCS_NODIVIDER) | |
| 345 #endif // !(_WIN32_IE >= 0x0400) | |
| 346 | |
| 347 // command bar support | |
| 348 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) | |
| 349 | |
| 350 #define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar H
WND | |
| 351 #define CBRM_GETMENU (WM_USER + 302) // returns loaded or att
ached menu | |
| 352 #define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu | |
| 353 | |
| 354 struct _AtlFrameWnd_CmdBarPopupMenu | |
| 355 { | |
| 356 int cbSize; | |
| 357 HMENU hMenu; | |
| 358 UINT uFlags; | |
| 359 int x; | |
| 360 int y; | |
| 361 LPTPMPARAMS lptpm; | |
| 362 }; | |
| 363 | |
| 364 #define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu | |
| 365 | |
| 366 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) | |
| 367 | |
| 368 | |
| 369 template <class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits> | |
| 370 class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase,
TWinTraits > | |
| 371 { | |
| 372 public: | |
| 373 DECLARE_FRAME_WND_CLASS(NULL, 0) | |
| 374 | |
| 375 // Data members | |
| 376 HWND m_hWndToolBar; | |
| 377 HWND m_hWndStatusBar; | |
| 378 HWND m_hWndClient; | |
| 379 | |
| 380 HACCEL m_hAccel; | |
| 381 | |
| 382 #ifdef _WIN32_WCE | |
| 383 HWND m_hWndCECommandBar; | |
| 384 #endif // _WIN32_WCE | |
| 385 | |
| 386 struct _AtlToolBarData | |
| 387 { | |
| 388 WORD wVersion; | |
| 389 WORD wWidth; | |
| 390 WORD wHeight; | |
| 391 WORD wItemCount; | |
| 392 //WORD aItems[wItemCount] | |
| 393 | |
| 394 WORD* items() | |
| 395 { return (WORD*)(this+1); } | |
| 396 }; | |
| 397 | |
| 398 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
| 399 struct _ChevronMenuInfo | |
| 400 { | |
| 401 HMENU hMenu; | |
| 402 LPNMREBARCHEVRON lpnm; | |
| 403 bool bCmdBar; | |
| 404 }; | |
| 405 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
| 406 | |
| 407 // Constructor | |
| 408 CFrameWindowImplBase() : | |
| 409 #ifdef _WIN32_WCE | |
| 410 m_hWndCECommandBar(NULL), | |
| 411 #endif // _WIN32_WCE | |
| 412 m_hWndToolBar(NULL), | |
| 413 m_hWndStatusBar(NULL), | |
| 414 m_hWndClient(NULL), | |
| 415 m_hAccel(NULL) | |
| 416 { } | |
| 417 | |
| 418 // Methods | |
| 419 HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DW
ORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCre
ateParam) | |
| 420 { | |
| 421 ATLASSERT(m_hWnd == NULL); | |
| 422 | |
| 423 if(atom == 0) | |
| 424 return NULL; | |
| 425 | |
| 426 ModuleHelper::AddCreateWndData(&m_thunk.cd, this); | |
| 427 | |
| 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; | |
| 432 | |
| 433 HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWin
dowName, | |
| 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); | |
| 437 | |
| 438 ATLASSERT(hWnd == NULL || m_hWnd == hWnd); | |
| 439 | |
| 440 return hWnd; | |
| 441 } | |
| 442 | |
| 443 static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, B
OOL bInitialSeparator = FALSE, | |
| 444 DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL
_IDW_TOOLBAR) | |
| 445 { | |
| 446 HINSTANCE hInst = ModuleHelper::GetResourceInstance(); | |
| 447 HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID)
, RT_TOOLBAR); | |
| 448 if (hRsrc == NULL) | |
| 449 return NULL; | |
| 450 | |
| 451 HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc); | |
| 452 if (hGlobal == NULL) | |
| 453 return NULL; | |
| 454 | |
| 455 _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGloba
l); | |
| 456 if (pData == NULL) | |
| 457 return NULL; | |
| 458 ATLASSERT(pData->wVersion == 1); | |
| 459 | |
| 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); | |
| 465 if(pTBBtn == NULL) | |
| 466 return NULL; | |
| 467 | |
| 468 const int cxSeparator = 8; | |
| 469 | |
| 470 // set initial separator (half width) | |
| 471 if(bInitialSeparator) | |
| 472 { | |
| 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; | |
| 479 } | |
| 480 | |
| 481 int nBmp = 0; | |
| 482 for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCo
unt; i++, j++) | |
| 483 { | |
| 484 if(pItems[i] != 0) | |
| 485 { | |
| 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; | |
| 492 } | |
| 493 else | |
| 494 { | |
| 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; | |
| 501 } | |
| 502 } | |
| 503 | |
| 504 #ifndef _WIN32_WCE | |
| 505 HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle,
0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleIn
stance(), NULL); | |
| 506 if(hWnd == NULL) | |
| 507 { | |
| 508 ATLASSERT(FALSE); | |
| 509 return NULL; | |
| 510 } | |
| 511 #else // CE specific | |
| 512 dwStyle; | |
| 513 nID; | |
| 514 // The toolbar must go onto the existing CommandBar or MenuBar | |
| 515 HWND hWnd = hWndParent; | |
| 516 #endif // _WIN32_WCE | |
| 517 | |
| 518 ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L); | |
| 519 | |
| 520 // check if font is taller than our bitmaps | |
| 521 CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L)
; | |
| 522 if(font.IsNull()) | |
| 523 font = AtlGetDefaultGuiFont(); | |
| 524 LOGFONT lf = { 0 }; | |
| 525 font.GetLogFont(lf); | |
| 526 WORD cyFontHeight = (WORD)abs(lf.lfHeight); | |
| 527 | |
| 528 #ifndef _WIN32_WCE | |
| 529 WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID
); | |
| 530 if(bitsPerPixel > 4) | |
| 531 { | |
| 532 COLORREF crMask = CLR_DEFAULT; | |
| 533 if(bitsPerPixel == 32) | |
| 534 { | |
| 535 // 32-bit color bitmap with alpha channel (valid
for Windows XP and later) | |
| 536 crMask = CLR_NONE; | |
| 537 } | |
| 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)hImageLi
st); | |
| 541 } | |
| 542 else | |
| 543 #endif // !_WIN32_WCE | |
| 544 { | |
| 545 TBADDBITMAP tbab = { 0 }; | |
| 546 tbab.hInst = hInst; | |
| 547 tbab.nID = nResourceID; | |
| 548 ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab); | |
| 549 } | |
| 550 | |
| 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)); | |
| 555 | |
| 556 return hWnd; | |
| 557 } | |
| 558 | |
| 559 #ifndef _WIN32_WCE | |
| 560 static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_S
IMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
| 561 { | |
| 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; | |
| 567 | |
| 568 // Create rebar window | |
| 569 HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwSty
le, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModul
eInstance(), NULL); | |
| 570 if(hWndReBar == NULL) | |
| 571 { | |
| 572 ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n")
); | |
| 573 return NULL; | |
| 574 } | |
| 575 | |
| 576 // Initialize and send the REBARINFO structure | |
| 577 REBARINFO rbi = { 0 }; | |
| 578 rbi.cbSize = sizeof(REBARINFO); | |
| 579 rbi.fMask = 0; | |
| 580 if(!::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi)) | |
| 581 { | |
| 582 ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.
\n")); | |
| 583 ::DestroyWindow(hWndReBar); | |
| 584 return NULL; | |
| 585 } | |
| 586 | |
| 587 return hWndReBar; | |
| 588 } | |
| 589 | |
| 590 BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID
= ATL_IDW_TOOLBAR) | |
| 591 { | |
| 592 ATLASSERT(!::IsWindow(m_hWndToolBar)); | |
| 593 m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID); | |
| 594 return (m_hWndToolBar != NULL); | |
| 595 } | |
| 596 | |
| 597 static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nI
D = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bF
ullWidthAlways = FALSE) | |
| 598 { | |
| 599 ATLASSERT(::IsWindow(hWndReBar)); // must be already created | |
| 600 #ifdef _DEBUG | |
| 601 // block - check if this is really a rebar | |
| 602 { | |
| 603 TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 }; | |
| 604 ::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLA
SSNAME)); | |
| 605 ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0); | |
| 606 } | |
| 607 #endif // _DEBUG | |
| 608 ATLASSERT(::IsWindow(hWndBand)); // must be already created | |
| 609 | |
| 610 // Get number of buttons on the toolbar | |
| 611 int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0,
0L); | |
| 612 | |
| 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 | RBB
IM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE; | |
| 617 #else | |
| 618 rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBB
IM_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 button
s | |
| 625 rbBand.fStyle |= RBBS_USECHEVRON; | |
| 626 #endif // (_WIN32_IE >= 0x0500) | |
| 627 if(bNewRow) | |
| 628 rbBand.fStyle |= RBBS_BREAK; | |
| 629 | |
| 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); | |
| 634 rbBand.wID = nID; | |
| 635 | |
| 636 // Calculate the size of the band | |
| 637 BOOL bRet = FALSE; | |
| 638 RECT rcTmp = { 0 }; | |
| 639 if(nBtnCount > 0) | |
| 640 { | |
| 641 bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBt
nCount - 1, (LPARAM)&rcTmp); | |
| 642 ATLASSERT(bRet); | |
| 643 rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right; | |
| 644 rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; | |
| 645 if(bFullWidthAlways) | |
| 646 { | |
| 647 rbBand.cxMinChild = rbBand.cx; | |
| 648 } | |
| 649 else if(lpstrTitle == NULL) | |
| 650 { | |
| 651 bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMR
ECT, 0, (LPARAM)&rcTmp); | |
| 652 ATLASSERT(bRet); | |
| 653 rbBand.cxMinChild = rcTmp.right; | |
| 654 } | |
| 655 else | |
| 656 { | |
| 657 rbBand.cxMinChild = 0; | |
| 658 } | |
| 659 } | |
| 660 else // no buttons, either not a toolbar or really has no but
tons | |
| 661 { | |
| 662 bRet = ::GetWindowRect(hWndBand, &rcTmp); | |
| 663 ATLASSERT(bRet); | |
| 664 rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rc
Tmp.left); | |
| 665 rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0; | |
| 666 rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; | |
| 667 } | |
| 668 | |
| 669 #if (_WIN32_IE >= 0x0400) | |
| 670 rbBand.cxIdeal = rbBand.cx; | |
| 671 #endif // (_WIN32_IE >= 0x0400) | |
| 672 | |
| 673 // Add the band | |
| 674 LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-
1, (LPARAM)&rbBand); | |
| 675 if(lRes == 0) | |
| 676 { | |
| 677 ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the
rebar.\n")); | |
| 678 return FALSE; | |
| 679 } | |
| 680 | |
| 681 #if (_WIN32_IE >= 0x0501) | |
| 682 DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDS
TYLE, 0, 0L); | |
| 683 ::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBST
YLE_EX_HIDECLIPPEDBUTTONS); | |
| 684 #endif // (_WIN32_IE >= 0x0501) | |
| 685 | |
| 686 return TRUE; | |
| 687 } | |
| 688 | |
| 689 BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL b
NewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE) | |
| 690 { | |
| 691 ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing r
ebar | |
| 692 ATLASSERT(::IsWindow(hWndBand)); // must be created | |
| 693 return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrT
itle, bNewRow, cxWidth, bFullWidthAlways); | |
| 694 } | |
| 695 | |
| 696 #if (_WIN32_IE >= 0x0400) | |
| 697 void SizeSimpleReBarBands() | |
| 698 { | |
| 699 ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing r
ebar | |
| 700 | |
| 701 int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT,
0, 0L); | |
| 702 | |
| 703 for(int i = 0; i < nCount; i++) | |
| 704 { | |
| 705 REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBAND
INFO() }; | |
| 706 rbBand.fMask = RBBIM_SIZE; | |
| 707 BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBAN
DINFO, i, (LPARAM)&rbBand); | |
| 708 ATLASSERT(bRet); | |
| 709 RECT rect = { 0, 0, 0, 0 }; | |
| 710 ::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPAR
AM)&rect); | |
| 711 rbBand.cx += rect.left + rect.right; | |
| 712 bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO
, i, (LPARAM)&rbBand); | |
| 713 ATLASSERT(bRet); | |
| 714 } | |
| 715 } | |
| 716 #endif // (_WIN32_IE >= 0x0400) | |
| 717 #endif // _WIN32_WCE | |
| 718 | |
| 719 #ifndef _WIN32_WCE | |
| 720 BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD |
WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL
_IDW_STATUS_BAR) | |
| 721 #else // CE specific | |
| 722 BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD |
WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR) | |
| 723 #endif // _WIN32_WCE | |
| 724 { | |
| 725 ATLASSERT(!::IsWindow(m_hWndStatusBar)); | |
| 726 m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWn
d, nID); | |
| 727 return (m_hWndStatusBar != NULL); | |
| 728 } | |
| 729 | |
| 730 #ifndef _WIN32_WCE | |
| 731 BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwS
tyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRI
P, UINT nID = ATL_IDW_STATUS_BAR) | |
| 732 #else // CE specific | |
| 733 BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwS
tyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL
_IDW_STATUS_BAR) | |
| 734 #endif // _WIN32_WCE | |
| 735 { | |
| 736 const int cchMax = 128; // max text length is 127 for status b
ars (+1 for null) | |
| 737 TCHAR szText[cchMax]; | |
| 738 szText[0] = 0; | |
| 739 ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szTex
t, cchMax); | |
| 740 return CreateSimpleStatusBar(szText, dwStyle, nID); | |
| 741 } | |
| 742 | |
| 743 #ifdef _WIN32_WCE | |
| 744 BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, D
WORD dwFlags = 0, int nCmdBarID = 1) | |
| 745 { | |
| 746 ATLASSERT(m_hWndCECommandBar == NULL); | |
| 747 ATLASSERT(m_hWndToolBar == NULL); | |
| 748 | |
| 749 m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModule
Instance(), m_hWnd, nCmdBarID); | |
| 750 if(m_hWndCECommandBar == NULL) | |
| 751 return FALSE; | |
| 752 | |
| 753 m_hWndToolBar = m_hWndCECommandBar; | |
| 754 | |
| 755 BOOL bRet = TRUE; | |
| 756 | |
| 757 if(pszMenu != NULL) | |
| 758 bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar,
IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu,
iButton); | |
| 759 | |
| 760 bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags,
0); | |
| 761 | |
| 762 return bRet; | |
| 763 } | |
| 764 | |
| 765 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) | |
| 766 BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwF
lags = 0, int nBmpId = 0, int cBmpImages = 0) | |
| 767 { | |
| 768 ATLASSERT(m_hWndCECommandBar == NULL); | |
| 769 | |
| 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(); | |
| 776 mbi.nBmpId = nBmpId; | |
| 777 mbi.cBmpImages = cBmpImages; | |
| 778 mbi.hwndMB = NULL; // This gets set by SHCreateMenuBar | |
| 779 | |
| 780 BOOL bRet = ::SHCreateMenuBar(&mbi); | |
| 781 if(bRet != FALSE) | |
| 782 { | |
| 783 m_hWndCECommandBar = mbi.hwndMB; | |
| 784 SizeToMenuBar(); | |
| 785 } | |
| 786 | |
| 787 return bRet; | |
| 788 } | |
| 789 | |
| 790 void SizeToMenuBar() // for menu bar only | |
| 791 { | |
| 792 ATLASSERT(::IsWindow(m_hWnd)); | |
| 793 ATLASSERT(::IsWindow(m_hWndCECommandBar)); | |
| 794 | |
| 795 RECT rect = { 0 }; | |
| 796 GetWindowRect(&rect); | |
| 797 RECT rectMB = { 0 }; | |
| 798 ::GetWindowRect(m_hWndCECommandBar, &rectMB); | |
| 799 int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - re
ct.top : rectMB.bottom - rect.top; | |
| 800 SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDE
R | SWP_NOMOVE); | |
| 801 } | |
| 802 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) | |
| 803 #endif // _WIN32_WCE | |
| 804 | |
| 805 void UpdateLayout(BOOL bResizeBars = TRUE) | |
| 806 { | |
| 807 RECT rect = { 0 }; | |
| 808 GetClientRect(&rect); | |
| 809 | |
| 810 // position bars and offset their dimensions | |
| 811 UpdateBarsPosition(rect, bResizeBars); | |
| 812 | |
| 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); | |
| 818 } | |
| 819 | |
| 820 void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE) | |
| 821 { | |
| 822 // resize toolbar | |
| 823 if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBa
r, GWL_STYLE) & WS_VISIBLE)) | |
| 824 { | |
| 825 if(bResizeBars) | |
| 826 { | |
| 827 ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0); | |
| 828 ::InvalidateRect(m_hWndToolBar, NULL, FALSE); | |
| 829 } | |
| 830 RECT rectTB = { 0 }; | |
| 831 ::GetWindowRect(m_hWndToolBar, &rectTB); | |
| 832 rect.top += rectTB.bottom - rectTB.top; | |
| 833 } | |
| 834 | |
| 835 // resize status bar | |
| 836 if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStat
usBar, GWL_STYLE) & WS_VISIBLE)) | |
| 837 { | |
| 838 if(bResizeBars) | |
| 839 ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0); | |
| 840 RECT rectSB = { 0 }; | |
| 841 ::GetWindowRect(m_hWndStatusBar, &rectSB); | |
| 842 rect.bottom -= rectSB.bottom - rectSB.top; | |
| 843 } | |
| 844 } | |
| 845 | |
| 846 BOOL PreTranslateMessage(MSG* pMsg) | |
| 847 { | |
| 848 if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel,
pMsg)) | |
| 849 return TRUE; | |
| 850 return FALSE; | |
| 851 } | |
| 852 | |
| 853 BEGIN_MSG_MAP(CFrameWindowImplBase) | |
| 854 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) | |
| 855 #ifndef _WIN32_WCE | |
| 856 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) | |
| 857 #endif // !_WIN32_WCE | |
| 858 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) | |
| 859 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) | |
| 860 #ifndef _WIN32_WCE | |
| 861 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA) | |
| 862 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW) | |
| 863 #endif // !_WIN32_WCE | |
| 864 END_MSG_MAP() | |
| 865 | |
| 866 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPa
ram*/, BOOL& bHandled) | |
| 867 { | |
| 868 if(m_hWndClient != NULL) // view will paint itself instead | |
| 869 return 1; | |
| 870 | |
| 871 bHandled = FALSE; | |
| 872 return 0; | |
| 873 } | |
| 874 | |
| 875 #ifndef _WIN32_WCE | |
| 876 LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL&
bHandled) | |
| 877 { | |
| 878 bHandled = FALSE; | |
| 879 | |
| 880 if(m_hWndStatusBar == NULL) | |
| 881 return 1; | |
| 882 | |
| 883 WORD wFlags = HIWORD(wParam); | |
| 884 if(wFlags == 0xFFFF && lParam == NULL) // menu closing | |
| 885 { | |
| 886 ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L); | |
| 887 } | |
| 888 else | |
| 889 { | |
| 890 const int cchBuff = 256; | |
| 891 TCHAR szBuff[cchBuff]; | |
| 892 szBuff[0] = 0; | |
| 893 if(!(wFlags & MF_POPUP)) | |
| 894 { | |
| 895 WORD wID = LOWORD(wParam); | |
| 896 // check for special cases | |
| 897 if(wID >= 0xF000 && wID < 0xF1F0) // system me
nu IDs | |
| 898 wID = (WORD)(((wID - 0xF000) >> 4) + ATL
_IDS_SCFIRST); | |
| 899 else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FI
LE_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; | |
| 903 | |
| 904 int nRet = ::LoadString(ModuleHelper::GetResourc
eInstance(), wID, szBuff, cchBuff); | |
| 905 for(int i = 0; i < nRet; i++) | |
| 906 { | |
| 907 if(szBuff[i] == _T('\n')) | |
| 908 { | |
| 909 szBuff[i] = 0; | |
| 910 break; | |
| 911 } | |
| 912 } | |
| 913 } | |
| 914 ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L); | |
| 915 ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NO
BORDERS), (LPARAM)szBuff); | |
| 916 } | |
| 917 | |
| 918 return 1; | |
| 919 } | |
| 920 #endif // !_WIN32_WCE | |
| 921 | |
| 922 LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled) | |
| 923 { | |
| 924 if(m_hWndClient != NULL) | |
| 925 ::SetFocus(m_hWndClient); | |
| 926 | |
| 927 bHandled = FALSE; | |
| 928 return 1; | |
| 929 } | |
| 930 | |
| 931 LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled) | |
| 932 { | |
| 933 if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0) | |
| 934 ::PostQuitMessage(1); | |
| 935 | |
| 936 bHandled = FALSE; | |
| 937 return 1; | |
| 938 } | |
| 939 | |
| 940 #ifndef _WIN32_WCE | |
| 941 LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/) | |
| 942 { | |
| 943 LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh; | |
| 944 pDispInfo->szText[0] = 0; | |
| 945 | |
| 946 if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND)) | |
| 947 { | |
| 948 const int cchBuff = 256; | |
| 949 char szBuff[cchBuff]; | |
| 950 szBuff[0] = 0; | |
| 951 int nRet = ::LoadStringA(ModuleHelper::GetResourceInstan
ce(), idCtrl, szBuff, cchBuff); | |
| 952 for(int i = 0; i < nRet; i++) | |
| 953 { | |
| 954 if(szBuff[i] == '\n') | |
| 955 { | |
| 956 SecureHelper::strncpyA_x(pDispInfo->szTe
xt, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE); | |
| 957 break; | |
| 958 } | |
| 959 } | |
| 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) | |
| 964 } | |
| 965 | |
| 966 return 0; | |
| 967 } | |
| 968 | |
| 969 LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/) | |
| 970 { | |
| 971 LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh; | |
| 972 pDispInfo->szText[0] = 0; | |
| 973 | |
| 974 if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND)) | |
| 975 { | |
| 976 const int cchBuff = 256; | |
| 977 wchar_t szBuff[cchBuff]; | |
| 978 szBuff[0] = 0; | |
| 979 int nRet = ::LoadStringW(ModuleHelper::GetResourceInstan
ce(), idCtrl, szBuff, cchBuff); | |
| 980 for(int i = 0; i < nRet; i++) | |
| 981 { | |
| 982 if(szBuff[i] == L'\n') | |
| 983 { | |
| 984 SecureHelper::strncpyW_x(pDispInfo->szTe
xt, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE); | |
| 985 break; | |
| 986 } | |
| 987 } | |
| 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) | |
| 992 } | |
| 993 | |
| 994 return 0; | |
| 995 } | |
| 996 #endif // !_WIN32_WCE | |
| 997 | |
| 998 // Implementation - chevron menu support | |
| 999 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
| 1000 bool PrepareChevronMenu(_ChevronMenuInfo& cmi) | |
| 1001 { | |
| 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_GETBA
NDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi); | |
| 1006 ATLASSERT(bRet); | |
| 1007 | |
| 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 | |
| 1012 return false; | |
| 1013 | |
| 1014 // check if it's a command bar | |
| 1015 CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU); | |
| 1016 cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL); | |
| 1017 | |
| 1018 // build a menu from hidden items | |
| 1019 CMenuHandle menu; | |
| 1020 bRet = menu.CreatePopupMenu(); | |
| 1021 ATLASSERT(bRet); | |
| 1022 RECT rcClient = { 0 }; | |
| 1023 bRet = wnd.GetClientRect(&rcClient); | |
| 1024 ATLASSERT(bRet); | |
| 1025 for(int i = 0; i < nCount; i++) | |
| 1026 { | |
| 1027 TBBUTTON tbb = { 0 }; | |
| 1028 bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&t
bb); | |
| 1029 ATLASSERT(bRet); | |
| 1030 // skip hidden buttons | |
| 1031 if((tbb.fsState & TBSTATE_HIDDEN) != 0) | |
| 1032 continue; | |
| 1033 RECT rcButton = { 0 }; | |
| 1034 bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)
&rcButton); | |
| 1035 ATLASSERT(bRet); | |
| 1036 bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0); | |
| 1037 if(rcButton.right > rcClient.right) | |
| 1038 { | |
| 1039 if(tbb.fsStyle & BTNS_SEP) | |
| 1040 { | |
| 1041 if(menu.GetMenuItemCount() > 0) | |
| 1042 menu.AppendMenu(MF_SEPARATOR); | |
| 1043 } | |
| 1044 else if(cmi.bCmdBar) | |
| 1045 { | |
| 1046 const int cchBuff = 200; | |
| 1047 TCHAR szBuff[cchBuff] = { 0 }; | |
| 1048 CMenuItemInfo mii; | |
| 1049 mii.fMask = MIIM_TYPE | MIIM_SUBMENU; | |
| 1050 mii.dwTypeData = szBuff; | |
| 1051 mii.cch = cchBuff; | |
| 1052 bRet = menuCmdBar.GetMenuItemInfo(i, TRU
E, &mii); | |
| 1053 ATLASSERT(bRet); | |
| 1054 // Note: CmdBar currently supports only
drop-down items | |
| 1055 ATLASSERT(::IsMenu(mii.hSubMenu)); | |
| 1056 bRet = menu.AppendMenu(MF_STRING | MF_PO
PUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeDat
a); | |
| 1057 ATLASSERT(bRet); | |
| 1058 } | |
| 1059 else | |
| 1060 { | |
| 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) | |
| 1071 { | |
| 1072 // no text for this button, try
a resource string | |
| 1073 lpstrText = _T(""); | |
| 1074 int nRet = ::LoadString(ModuleHe
lper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff); | |
| 1075 for(int n = 0; n < nRet; n++) | |
| 1076 { | |
| 1077 if(szBuff[n] == _T('\n')
) | |
| 1078 { | |
| 1079 lpstrText = &szB
uff[n + 1]; | |
| 1080 break; | |
| 1081 } | |
| 1082 } | |
| 1083 } | |
| 1084 bRet = menu.AppendMenu(MF_STRING | (bEna
bled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText); | |
| 1085 ATLASSERT(bRet); | |
| 1086 } | |
| 1087 } | |
| 1088 } | |
| 1089 | |
| 1090 if(menu.GetMenuItemCount() == 0) // no hidden buttons after al
l | |
| 1091 { | |
| 1092 menu.DestroyMenu(); | |
| 1093 ::MessageBeep((UINT)-1); | |
| 1094 return false; | |
| 1095 } | |
| 1096 | |
| 1097 cmi.hMenu = menu; | |
| 1098 return true; | |
| 1099 } | |
| 1100 | |
| 1101 void DisplayChevronMenu(_ChevronMenuInfo& cmi) | |
| 1102 { | |
| 1103 #ifndef TPM_VERPOSANIMATION | |
| 1104 const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation fl
ag | |
| 1105 #endif | |
| 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)) | |
| 1120 { | |
| 1121 CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.
hMenu, uMenuFlags, pt.x, pt.y, &TPMParams }; | |
| 1122 ::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARA
M)&CBRPopupMenu); | |
| 1123 } | |
| 1124 else | |
| 1125 { | |
| 1126 CMenuHandle menu = cmi.hMenu; | |
| 1127 menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &T
PMParams); | |
| 1128 } | |
| 1129 } | |
| 1130 | |
| 1131 void CleanupChevronMenu(_ChevronMenuInfo& cmi) | |
| 1132 { | |
| 1133 CMenuHandle menu = cmi.hMenu; | |
| 1134 // if menu is from a command bar, detach submenus so they are no
t destroyed | |
| 1135 if(cmi.bCmdBar) | |
| 1136 { | |
| 1137 for(int i = menu.GetMenuItemCount() - 1; i >=0; i--) | |
| 1138 menu.RemoveMenu(i, MF_BYPOSITION); | |
| 1139 } | |
| 1140 // destroy menu | |
| 1141 menu.DestroyMenu(); | |
| 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 | |
| 1147 MSG msg = { 0 }; | |
| 1148 if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, P
M_NOREMOVE) && ::PtInRect(&rc, msg.pt)) | |
| 1149 ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDO
WN, PM_REMOVE); | |
| 1150 } | |
| 1151 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
| 1152 }; | |
| 1153 | |
| 1154 | |
| 1155 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWin
Traits> | |
| 1156 class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinT
raits > | |
| 1157 { | |
| 1158 public: | |
| 1159 HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR sz
WindowName = NULL, | |
| 1160 DWORD dwStyle = 0, DWORD dwExStyle = 0, | |
| 1161 HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) | |
| 1162 { | |
| 1163 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc)
; | |
| 1164 | |
| 1165 dwStyle = T::GetWndStyle(dwStyle); | |
| 1166 dwExStyle = T::GetWndExStyle(dwExStyle); | |
| 1167 | |
| 1168 if(rect.m_lpRect == NULL) | |
| 1169 rect.m_lpRect = &TBase::rcDefault; | |
| 1170 | |
| 1171 return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndPar
ent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam
); | |
| 1172 } | |
| 1173 | |
| 1174 HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dw
Style = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) | |
| 1175 { | |
| 1176 const int cchName = 256; | |
| 1177 TCHAR szWindowName[cchName]; | |
| 1178 szWindowName[0] = 0; | |
| 1179 #ifndef _WIN32_WCE | |
| 1180 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClass
Info().m_uCommonResourceID, szWindowName, cchName); | |
| 1181 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MA
KEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
| 1182 #else // CE specific | |
| 1183 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClass
Info().m_uCommonResourceID, szWindowName, cchName); | |
| 1184 | |
| 1185 // This always needs to be NULL for Windows CE. | |
| 1186 // Frame Window menus have to go onto the CommandBar. | |
| 1187 // Use CreateSimpleCECommandBar | |
| 1188 HMENU hMenu = NULL; | |
| 1189 #endif // _WIN32_WCE | |
| 1190 | |
| 1191 T* pT = static_cast<T*>(this); | |
| 1192 HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle,
dwExStyle, hMenu, lpCreateParam); | |
| 1193 | |
| 1194 if(hWnd != NULL) | |
| 1195 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceI
nstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
| 1196 | |
| 1197 return hWnd; | |
| 1198 } | |
| 1199 | |
| 1200 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPL
E_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
| 1201 { | |
| 1202 if(nResourceID == 0) | |
| 1203 nResourceID = T::GetWndClassInfo().m_uCommonResourceID; | |
| 1204 #ifndef _WIN32_WCE | |
| 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, nResou
rceID, TRUE, dwStyle, nID); | |
| 1210 return (hWnd != NULL); | |
| 1211 #endif // _WIN32_WCE | |
| 1212 } | |
| 1213 | |
| 1214 #ifdef _WIN32_WCE | |
| 1215 // CE specific variant that returns the handle of the toolbar | |
| 1216 HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIM
PLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
| 1217 { | |
| 1218 if(nResourceID == 0) | |
| 1219 nResourceID = T::GetWndClassInfo().m_uCommonResourceID; | |
| 1220 | |
| 1221 return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceI
D, TRUE, dwStyle, nID); | |
| 1222 } | |
| 1223 #endif // _WIN32_WCE | |
| 1224 | |
| 1225 // message map and handlers | |
| 1226 typedef CFrameWindowImplBase< TBase, TWinTraits > _baseClass; | |
| 1227 | |
| 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) | |
| 1239 END_MSG_MAP() | |
| 1240 | |
| 1241 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bH
andled) | |
| 1242 { | |
| 1243 if(wParam != SIZE_MINIMIZED) | |
| 1244 { | |
| 1245 T* pT = static_cast<T*>(this); | |
| 1246 pT->UpdateLayout(); | |
| 1247 } | |
| 1248 bHandled = FALSE; | |
| 1249 return 1; | |
| 1250 } | |
| 1251 | |
| 1252 #ifndef _ATL_NO_REBAR_SUPPORT | |
| 1253 #if (_WIN32_IE >= 0x0400) | |
| 1254 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandl
ed*/) | |
| 1255 { | |
| 1256 T* pT = static_cast<T*>(this); | |
| 1257 pT->UpdateLayout(FALSE); | |
| 1258 return 0; | |
| 1259 } | |
| 1260 #endif // (_WIN32_IE >= 0x0400) | |
| 1261 | |
| 1262 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
| 1263 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) | |
| 1264 { | |
| 1265 T* pT = static_cast<T*>(this); | |
| 1266 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; | |
| 1267 if(!pT->PrepareChevronMenu(cmi)) | |
| 1268 { | |
| 1269 bHandled = FALSE; | |
| 1270 return 1; | |
| 1271 } | |
| 1272 // display a popup menu with hidden items | |
| 1273 pT->DisplayChevronMenu(cmi); | |
| 1274 // cleanup | |
| 1275 pT->CleanupChevronMenu(cmi); | |
| 1276 return 0; | |
| 1277 } | |
| 1278 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
| 1279 #endif // !_ATL_NO_REBAR_SUPPORT | |
| 1280 }; | |
| 1281 | |
| 1282 | |
| 1283 /////////////////////////////////////////////////////////////////////////////// | |
| 1284 // AtlCreateSimpleToolBar - helper for creating simple toolbars | |
| 1285 | |
| 1286 #ifndef _WIN32_WCE | |
| 1287 | |
| 1288 inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInit
ialSeparator = FALSE, | |
| 1289 DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOO
LBAR) | |
| 1290 { | |
| 1291 return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nReso
urceID, bInitialSeparator, dwStyle, nID); | |
| 1292 } | |
| 1293 | |
| 1294 #endif // !_WIN32_WCE | |
| 1295 | |
| 1296 | |
| 1297 /////////////////////////////////////////////////////////////////////////////// | |
| 1298 // CMDIWindow | |
| 1299 | |
| 1300 #ifndef _WIN32_WCE | |
| 1301 | |
| 1302 #ifndef _WTL_MDIWINDOWMENU_TEXT | |
| 1303 #define _WTL_MDIWINDOWMENU_TEXT _T("&Window") | |
| 1304 #endif | |
| 1305 | |
| 1306 class CMDIWindow : public ATL::CWindow | |
| 1307 { | |
| 1308 public: | |
| 1309 // Data members | |
| 1310 HWND m_hWndMDIClient; | |
| 1311 HMENU m_hMenu; | |
| 1312 | |
| 1313 // Constructors | |
| 1314 CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL)
, m_hMenu(NULL) | |
| 1315 { } | |
| 1316 | |
| 1317 CMDIWindow& operator =(HWND hWnd) | |
| 1318 { | |
| 1319 m_hWnd = hWnd; | |
| 1320 return *this; | |
| 1321 } | |
| 1322 | |
| 1323 // Operations | |
| 1324 HWND MDIGetActive(BOOL* lpbMaximized = NULL) | |
| 1325 { | |
| 1326 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1327 return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0,
(LPARAM)lpbMaximized); | |
| 1328 } | |
| 1329 | |
| 1330 void MDIActivate(HWND hWndChildToActivate) | |
| 1331 { | |
| 1332 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1333 ATLASSERT(::IsWindow(hWndChildToActivate)); | |
| 1334 ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChild
ToActivate, 0); | |
| 1335 } | |
| 1336 | |
| 1337 void MDINext(HWND hWndChild, BOOL bPrevious = FALSE) | |
| 1338 { | |
| 1339 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1340 ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild)); | |
| 1341 ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (L
PARAM)bPrevious); | |
| 1342 } | |
| 1343 | |
| 1344 void MDIMaximize(HWND hWndChildToMaximize) | |
| 1345 { | |
| 1346 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1347 ATLASSERT(::IsWindow(hWndChildToMaximize)); | |
| 1348 ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChild
ToMaximize, 0); | |
| 1349 } | |
| 1350 | |
| 1351 void MDIRestore(HWND hWndChildToRestore) | |
| 1352 { | |
| 1353 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1354 ATLASSERT(::IsWindow(hWndChildToRestore)); | |
| 1355 ::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildT
oRestore, 0); | |
| 1356 } | |
| 1357 | |
| 1358 void MDIDestroy(HWND hWndChildToDestroy) | |
| 1359 { | |
| 1360 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1361 ATLASSERT(::IsWindow(hWndChildToDestroy)); | |
| 1362 ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildT
oDestroy, 0); | |
| 1363 } | |
| 1364 | |
| 1365 BOOL MDICascade(UINT uFlags = 0) | |
| 1366 { | |
| 1367 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1368 return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPAR
AM)uFlags, 0); | |
| 1369 } | |
| 1370 | |
| 1371 BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL) | |
| 1372 { | |
| 1373 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1374 return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)
uFlags, 0); | |
| 1375 } | |
| 1376 | |
| 1377 void MDIIconArrange() | |
| 1378 { | |
| 1379 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1380 ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0); | |
| 1381 } | |
| 1382 | |
| 1383 HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow) | |
| 1384 { | |
| 1385 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1386 return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPA
RAM)hMenuFrame, (LPARAM)hMenuWindow); | |
| 1387 } | |
| 1388 | |
| 1389 HMENU MDIRefreshMenu() | |
| 1390 { | |
| 1391 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1392 return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU,
0, 0); | |
| 1393 } | |
| 1394 | |
| 1395 // Additional operations | |
| 1396 static HMENU GetStandardWindowMenu(HMENU hMenu) | |
| 1397 { | |
| 1398 int nCount = ::GetMenuItemCount(hMenu); | |
| 1399 if(nCount == -1) | |
| 1400 return NULL; | |
| 1401 int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSI
TION); | |
| 1402 if(nLen == 0) | |
| 1403 return NULL; | |
| 1404 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff; | |
| 1405 LPTSTR lpszText = buff.Allocate(nLen + 1); | |
| 1406 if(lpszText == NULL) | |
| 1407 return NULL; | |
| 1408 if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYP
OSITION) != nLen) | |
| 1409 return NULL; | |
| 1410 if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0) | |
| 1411 return NULL; | |
| 1412 return ::GetSubMenu(hMenu, nCount - 2); | |
| 1413 } | |
| 1414 | |
| 1415 void SetMDIFrameMenu() | |
| 1416 { | |
| 1417 HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu); | |
| 1418 MDISetMenu(m_hMenu, hWindowMenu); | |
| 1419 MDIRefreshMenu(); | |
| 1420 ::DrawMenuBar(GetMDIFrame()); | |
| 1421 } | |
| 1422 | |
| 1423 HWND GetMDIFrame() const | |
| 1424 { | |
| 1425 return ::GetParent(m_hWndMDIClient); | |
| 1426 } | |
| 1427 }; | |
| 1428 | |
| 1429 #endif // !_WIN32_WCE | |
| 1430 | |
| 1431 | |
| 1432 /////////////////////////////////////////////////////////////////////////////// | |
| 1433 // CMDIFrameWindowImpl | |
| 1434 | |
| 1435 #ifndef _WIN32_WCE | |
| 1436 | |
| 1437 // MDI child command chaining macro (only for MDI frame windows) | |
| 1438 #define CHAIN_MDI_CHILD_COMMANDS() \ | |
| 1439 if(uMsg == WM_COMMAND) \ | |
| 1440 { \ | |
| 1441 HWND hWndChild = MDIGetActive(); \ | |
| 1442 if(hWndChild != NULL) \ | |
| 1443 ::SendMessage(hWndChild, uMsg, wParam, lParam); \ | |
| 1444 } | |
| 1445 | |
| 1446 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTr
aits> | |
| 1447 class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWi
nTraits > | |
| 1448 { | |
| 1449 public: | |
| 1450 HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR sz
WindowName = NULL, | |
| 1451 DWORD dwStyle = 0, DWORD dwExStyle = 0, | |
| 1452 HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) | |
| 1453 { | |
| 1454 m_hMenu = hMenu; | |
| 1455 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc)
; | |
| 1456 | |
| 1457 dwStyle = T::GetWndStyle(dwStyle); | |
| 1458 dwExStyle = T::GetWndExStyle(dwExStyle); | |
| 1459 | |
| 1460 if(rect.m_lpRect == NULL) | |
| 1461 rect.m_lpRect = &TBase::rcDefault; | |
| 1462 | |
| 1463 return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndPare
nt, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam)
; | |
| 1464 } | |
| 1465 | |
| 1466 HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dw
Style = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) | |
| 1467 { | |
| 1468 const int cchName = 256; | |
| 1469 TCHAR szWindowName[cchName]; | |
| 1470 szWindowName[0] = 0; | |
| 1471 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClass
Info().m_uCommonResourceID, szWindowName, cchName); | |
| 1472 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MA
KEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
| 1473 | |
| 1474 T* pT = static_cast<T*>(this); | |
| 1475 HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle,
dwExStyle, hMenu, lpCreateParam); | |
| 1476 | |
| 1477 if(hWnd != NULL) | |
| 1478 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceI
nstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
| 1479 | |
| 1480 return hWnd; | |
| 1481 } | |
| 1482 | |
| 1483 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPL
E_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
| 1484 { | |
| 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); | |
| 1490 } | |
| 1491 | |
| 1492 virtual WNDPROC GetWindowProc() | |
| 1493 { | |
| 1494 return MDIFrameWindowProc; | |
| 1495 } | |
| 1496 | |
| 1497 static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lParam) | |
| 1498 { | |
| 1499 CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameW
indowImpl< 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 | |
| 1510 LRESULT lRes = 0; | |
| 1511 BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wPa
ram, 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 | |
| 1516 if(!bRet) | |
| 1517 { | |
| 1518 if(uMsg != WM_NCDESTROY) | |
| 1519 lRes = pThis->DefWindowProc(uMsg, wParam, lParam
); | |
| 1520 else | |
| 1521 { | |
| 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 != ::DefWindowPro
c && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) | |
| 1526 ::SetWindowLongPtr(pThis->m_hWnd, GWLP_W
NDPROC, (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) | |
| 1537 } | |
| 1538 } | |
| 1539 #if (_ATL_VER >= 0x0700) | |
| 1540 if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg
== NULL) | |
| 1541 { | |
| 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); | |
| 1548 } | |
| 1549 #endif // (_ATL_VER >= 0x0700) | |
| 1550 return lRes; | |
| 1551 } | |
| 1552 | |
| 1553 // Overriden to call DefWindowProc which uses DefFrameProc | |
| 1554 LRESULT DefWindowProc() | |
| 1555 { | |
| 1556 const MSG* pMsg = m_pCurrentMsg; | |
| 1557 LRESULT lRes = 0; | |
| 1558 if (pMsg != NULL) | |
| 1559 lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->
lParam); | |
| 1560 return lRes; | |
| 1561 } | |
| 1562 | |
| 1563 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| 1564 { | |
| 1565 return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lPa
ram); | |
| 1566 } | |
| 1567 | |
| 1568 BOOL PreTranslateMessage(MSG* pMsg) | |
| 1569 { | |
| 1570 if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(
pMsg)) | |
| 1571 return TRUE; | |
| 1572 return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg); | |
| 1573 } | |
| 1574 | |
| 1575 HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT
, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD) | |
| 1576 { | |
| 1577 DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLI
PSIBLINGS | MDIS_ALLCHILDSTYLES; | |
| 1578 DWORD dwExStyle = WS_EX_CLIENTEDGE; | |
| 1579 | |
| 1580 CLIENTCREATESTRUCT ccs = { 0 }; | |
| 1581 ccs.hWindowMenu = hWindowMenu; | |
| 1582 ccs.idFirstChild = nFirstChildID; | |
| 1583 | |
| 1584 if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0) | |
| 1585 { | |
| 1586 // parent MDI frame's scroll styles move to the MDICLIEN
T | |
| 1587 dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL)); | |
| 1588 | |
| 1589 // fast way to turn off the scrollbar bits (without a re
size) | |
| 1590 ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | S
WP_FRAMECHANGED); | |
| 1591 } | |
| 1592 | |
| 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) | |
| 1598 { | |
| 1599 ATLTRACE2(atlTraceUI, 0, _T("MDI Frame failed to create
MDICLIENT.\n")); | |
| 1600 return NULL; | |
| 1601 } | |
| 1602 | |
| 1603 // Move it to the top of z-order | |
| 1604 ::BringWindowToTop(m_hWndClient); | |
| 1605 | |
| 1606 // set as MDI client window | |
| 1607 m_hWndMDIClient = m_hWndClient; | |
| 1608 | |
| 1609 // update to proper size | |
| 1610 T* pT = static_cast<T*>(this); | |
| 1611 pT->UpdateLayout(); | |
| 1612 | |
| 1613 return m_hWndClient; | |
| 1614 } | |
| 1615 | |
| 1616 typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass; | |
| 1617 | |
| 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) | |
| 1631 END_MSG_MAP() | |
| 1632 | |
| 1633 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*
bHandled*/) | |
| 1634 { | |
| 1635 if(wParam != SIZE_MINIMIZED) | |
| 1636 { | |
| 1637 T* pT = static_cast<T*>(this); | |
| 1638 pT->UpdateLayout(); | |
| 1639 } | |
| 1640 // message must be handled, otherwise DefFrameProc would resize
the client again | |
| 1641 return 0; | |
| 1642 } | |
| 1643 | |
| 1644 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHan
dled*/) | |
| 1645 { | |
| 1646 // don't allow CFrameWindowImplBase to handle this one | |
| 1647 return DefWindowProc(uMsg, wParam, lParam); | |
| 1648 } | |
| 1649 | |
| 1650 LRESULT OnMDISetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/
, BOOL& /*bHandled*/) | |
| 1651 { | |
| 1652 SetMDIFrameMenu(); | |
| 1653 return 0; | |
| 1654 } | |
| 1655 | |
| 1656 #ifndef _ATL_NO_REBAR_SUPPORT | |
| 1657 #if (_WIN32_IE >= 0x0400) | |
| 1658 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandl
ed*/) | |
| 1659 { | |
| 1660 T* pT = static_cast<T*>(this); | |
| 1661 pT->UpdateLayout(FALSE); | |
| 1662 return 0; | |
| 1663 } | |
| 1664 #endif // (_WIN32_IE >= 0x0400) | |
| 1665 | |
| 1666 #if (_WIN32_IE >= 0x0500) | |
| 1667 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) | |
| 1668 { | |
| 1669 T* pT = static_cast<T*>(this); | |
| 1670 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; | |
| 1671 if(!pT->PrepareChevronMenu(cmi)) | |
| 1672 { | |
| 1673 bHandled = FALSE; | |
| 1674 return 1; | |
| 1675 } | |
| 1676 // display a popup menu with hidden items | |
| 1677 pT->DisplayChevronMenu(cmi); | |
| 1678 // cleanup | |
| 1679 pT->CleanupChevronMenu(cmi); | |
| 1680 return 0; | |
| 1681 } | |
| 1682 #endif // (_WIN32_IE >= 0x0500) | |
| 1683 #endif // !_ATL_NO_REBAR_SUPPORT | |
| 1684 }; | |
| 1685 | |
| 1686 #endif // !_WIN32_WCE | |
| 1687 | |
| 1688 | |
| 1689 /////////////////////////////////////////////////////////////////////////////// | |
| 1690 // CMDIChildWindowImpl | |
| 1691 | |
| 1692 #ifndef _WIN32_WCE | |
| 1693 | |
| 1694 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CMDIChildWi
nTraits> | |
| 1695 class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase<TBase, TWi
nTraits > | |
| 1696 { | |
| 1697 public: | |
| 1698 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowN
ame = NULL, | |
| 1699 DWORD dwStyle = 0, DWORD dwExStyle = 0, | |
| 1700 UINT nMenuID = 0, LPVOID lpCreateParam = NULL) | |
| 1701 { | |
| 1702 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc)
; | |
| 1703 | |
| 1704 if(nMenuID != 0) | |
| 1705 m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance()
, MAKEINTRESOURCE(nMenuID)); | |
| 1706 | |
| 1707 dwStyle = T::GetWndStyle(dwStyle); | |
| 1708 dwExStyle = T::GetWndExStyle(dwExStyle); | |
| 1709 | |
| 1710 dwExStyle |= WS_EX_MDICHILD; // force this one | |
| 1711 m_pfnSuperWindowProc = ::DefMDIChildProc; | |
| 1712 m_hWndMDIClient = hWndParent; | |
| 1713 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
| 1714 | |
| 1715 if(rect.m_lpRect == NULL) | |
| 1716 rect.m_lpRect = &TBase::rcDefault; | |
| 1717 | |
| 1718 // If the currently active MDI child is maximized, we want to cr
eate this one maximized too | |
| 1719 ATL::CWindow wndParent = hWndParent; | |
| 1720 BOOL bMaximized = FALSE; | |
| 1721 wndParent.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); | |
| 1722 if(bMaximized) | |
| 1723 wndParent.SetRedraw(FALSE); | |
| 1724 | |
| 1725 HWND hWnd = CFrameWindowImplBase<TBase, TWinTraits >::Create(hWn
dParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCrea
teParam); | |
| 1726 | |
| 1727 if(bMaximized) | |
| 1728 { | |
| 1729 // Maximize and redraw everything | |
| 1730 if(hWnd != NULL) | |
| 1731 MDIMaximize(hWnd); | |
| 1732 wndParent.SetRedraw(TRUE); | |
| 1733 wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_
ALLCHILDREN); | |
| 1734 ::SetFocus(GetMDIFrame()); // focus will be set back t
o this window | |
| 1735 } | |
| 1736 else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(
hWnd, ::GetFocus())) | |
| 1737 { | |
| 1738 ::SetFocus(hWnd); | |
| 1739 } | |
| 1740 | |
| 1741 return hWnd; | |
| 1742 } | |
| 1743 | |
| 1744 HWND CreateEx(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR lpcstrW
indowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam =
NULL) | |
| 1745 { | |
| 1746 const int cchName = 256; | |
| 1747 TCHAR szWindowName[cchName]; | |
| 1748 szWindowName[0] = 0; | |
| 1749 if(lpcstrWindowName == NULL) | |
| 1750 { | |
| 1751 ::LoadString(ModuleHelper::GetResourceInstance(), T::Get
WndClassInfo().m_uCommonResourceID, szWindowName, cchName); | |
| 1752 lpcstrWindowName = szWindowName; | |
| 1753 } | |
| 1754 | |
| 1755 T* pT = static_cast<T*>(this); | |
| 1756 HWND hWnd = pT->Create(hWndParent, rect, lpcstrWindowName, dwSty
le, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam); | |
| 1757 | |
| 1758 if(hWnd != NULL) | |
| 1759 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceI
nstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
| 1760 | |
| 1761 return hWnd; | |
| 1762 } | |
| 1763 | |
| 1764 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPL
E_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
| 1765 { | |
| 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); | |
| 1771 } | |
| 1772 | |
| 1773 BOOL UpdateClientEdge(LPRECT lpRect = NULL) | |
| 1774 { | |
| 1775 // only adjust for active MDI child window | |
| 1776 HWND hWndChild = MDIGetActive(); | |
| 1777 if(hWndChild != NULL && hWndChild != m_hWnd) | |
| 1778 return FALSE; | |
| 1779 | |
| 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); | |
| 1785 else | |
| 1786 dwNewStyle |= WS_EX_CLIENTEDGE; | |
| 1787 | |
| 1788 if(dwStyle != dwNewStyle) | |
| 1789 { | |
| 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); | |
| 1798 | |
| 1799 // return new client area | |
| 1800 if (lpRect != NULL) | |
| 1801 ::GetClientRect(m_hWndMDIClient, lpRect); | |
| 1802 | |
| 1803 return TRUE; | |
| 1804 } | |
| 1805 | |
| 1806 return FALSE; | |
| 1807 } | |
| 1808 | |
| 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) | |
| 1826 END_MSG_MAP() | |
| 1827 | |
| 1828 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled
*/) | |
| 1829 { | |
| 1830 DefWindowProc(uMsg, wParam, lParam); // needed for MDI childre
n | |
| 1831 if(wParam != SIZE_MINIMIZED) | |
| 1832 { | |
| 1833 T* pT = static_cast<T*>(this); | |
| 1834 pT->UpdateLayout(); | |
| 1835 } | |
| 1836 return 0; | |
| 1837 } | |
| 1838 | |
| 1839 LRESULT OnWindowPosChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lPar
am, BOOL& bHandled) | |
| 1840 { | |
| 1841 // update MDI client edge and adjust MDI child rect | |
| 1842 LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam; | |
| 1843 | |
| 1844 if(!(lpWndPos->flags & SWP_NOSIZE)) | |
| 1845 { | |
| 1846 RECT rectClient; | |
| 1847 if(UpdateClientEdge(&rectClient) && ((GetStyle() & WS_MA
XIMIZE) != 0)) | |
| 1848 { | |
| 1849 ::AdjustWindowRectEx(&rectClient, GetStyle(), FA
LSE, GetExStyle()); | |
| 1850 lpWndPos->x = rectClient.left; | |
| 1851 lpWndPos->y = rectClient.top; | |
| 1852 lpWndPos->cx = rectClient.right - rectClient.lef
t; | |
| 1853 lpWndPos->cy = rectClient.bottom - rectClient.to
p; | |
| 1854 } | |
| 1855 } | |
| 1856 | |
| 1857 bHandled = FALSE; | |
| 1858 return 1; | |
| 1859 } | |
| 1860 | |
| 1861 LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /
*bHandled*/) | |
| 1862 { | |
| 1863 LRESULT lRes = DefWindowProc(uMsg, wParam, lParam); | |
| 1864 | |
| 1865 // Activate this MDI window if needed | |
| 1866 if(lRes == MA_ACTIVATE || lRes == MA_ACTIVATEANDEAT) | |
| 1867 { | |
| 1868 if(MDIGetActive() != m_hWnd) | |
| 1869 MDIActivate(m_hWnd); | |
| 1870 } | |
| 1871 | |
| 1872 return lRes; | |
| 1873 } | |
| 1874 | |
| 1875 LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bH
andled*/) | |
| 1876 { | |
| 1877 return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam); | |
| 1878 } | |
| 1879 | |
| 1880 LRESULT OnMDIActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, B
OOL& bHandled) | |
| 1881 { | |
| 1882 if((HWND)lParam == m_hWnd && m_hMenu != NULL) | |
| 1883 SetMDIFrameMenu(); | |
| 1884 else if((HWND)lParam == NULL) | |
| 1885 ::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0); | |
| 1886 | |
| 1887 bHandled = FALSE; | |
| 1888 return 1; | |
| 1889 } | |
| 1890 | |
| 1891 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, B
OOL& bHandled) | |
| 1892 { | |
| 1893 if(m_hMenu != NULL) | |
| 1894 { | |
| 1895 ::DestroyMenu(m_hMenu); | |
| 1896 m_hMenu = NULL; | |
| 1897 } | |
| 1898 UpdateClientEdge(); | |
| 1899 bHandled = FALSE; | |
| 1900 return 1; | |
| 1901 } | |
| 1902 | |
| 1903 #ifndef _ATL_NO_REBAR_SUPPORT | |
| 1904 #if (_WIN32_IE >= 0x0400) | |
| 1905 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandl
ed*/) | |
| 1906 { | |
| 1907 T* pT = static_cast<T*>(this); | |
| 1908 pT->UpdateLayout(FALSE); | |
| 1909 return 0; | |
| 1910 } | |
| 1911 #endif // (_WIN32_IE >= 0x0400) | |
| 1912 | |
| 1913 #if (_WIN32_IE >= 0x0500) | |
| 1914 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) | |
| 1915 { | |
| 1916 T* pT = static_cast<T*>(this); | |
| 1917 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; | |
| 1918 if(!pT->PrepareChevronMenu(cmi)) | |
| 1919 { | |
| 1920 bHandled = FALSE; | |
| 1921 return 1; | |
| 1922 } | |
| 1923 // display a popup menu with hidden items | |
| 1924 pT->DisplayChevronMenu(cmi); | |
| 1925 // cleanup | |
| 1926 pT->CleanupChevronMenu(cmi); | |
| 1927 return 0; | |
| 1928 } | |
| 1929 #endif // (_WIN32_IE >= 0x0500) | |
| 1930 #endif // !_ATL_NO_REBAR_SUPPORT | |
| 1931 }; | |
| 1932 | |
| 1933 #endif // !_WIN32_WCE | |
| 1934 | |
| 1935 | |
| 1936 /////////////////////////////////////////////////////////////////////////////// | |
| 1937 // COwnerDraw - MI class for owner-draw support | |
| 1938 | |
| 1939 template <class T> | |
| 1940 class COwnerDraw | |
| 1941 { | |
| 1942 public: | |
| 1943 #if (_ATL_VER < 0x0700) | |
| 1944 BOOL m_bHandledOD; | |
| 1945 | |
| 1946 BOOL IsMsgHandled() const | |
| 1947 { | |
| 1948 return m_bHandledOD; | |
| 1949 } | |
| 1950 void SetMsgHandled(BOOL bHandled) | |
| 1951 { | |
| 1952 m_bHandledOD = bHandled; | |
| 1953 } | |
| 1954 #endif // (_ATL_VER < 0x0700) | |
| 1955 | |
| 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) | |
| 1962 ALT_MSG_MAP(1) | |
| 1963 MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem) | |
| 1964 MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem) | |
| 1965 MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem) | |
| 1966 MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem) | |
| 1967 END_MSG_MAP() | |
| 1968 | |
| 1969 LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL
& bHandled) | |
| 1970 { | |
| 1971 T* pT = static_cast<T*>(this); | |
| 1972 pT->SetMsgHandled(TRUE); | |
| 1973 pT->DrawItem((LPDRAWITEMSTRUCT)lParam); | |
| 1974 bHandled = pT->IsMsgHandled(); | |
| 1975 return (LRESULT)TRUE; | |
| 1976 } | |
| 1977 | |
| 1978 LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, B
OOL& bHandled) | |
| 1979 { | |
| 1980 T* pT = static_cast<T*>(this); | |
| 1981 pT->SetMsgHandled(TRUE); | |
| 1982 pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam); | |
| 1983 bHandled = pT->IsMsgHandled(); | |
| 1984 return (LRESULT)TRUE; | |
| 1985 } | |
| 1986 | |
| 1987 LRESULT OnCompareItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, B
OOL& bHandled) | |
| 1988 { | |
| 1989 T* pT = static_cast<T*>(this); | |
| 1990 pT->SetMsgHandled(TRUE); | |
| 1991 bHandled = pT->IsMsgHandled(); | |
| 1992 return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam); | |
| 1993 } | |
| 1994 | |
| 1995 LRESULT OnDeleteItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BO
OL& bHandled) | |
| 1996 { | |
| 1997 T* pT = static_cast<T*>(this); | |
| 1998 pT->SetMsgHandled(TRUE); | |
| 1999 pT->DeleteItem((LPDELETEITEMSTRUCT)lParam); | |
| 2000 bHandled = pT->IsMsgHandled(); | |
| 2001 return (LRESULT)TRUE; | |
| 2002 } | |
| 2003 | |
| 2004 // Overrideables | |
| 2005 void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/) | |
| 2006 { | |
| 2007 // must be implemented | |
| 2008 ATLASSERT(FALSE); | |
| 2009 } | |
| 2010 | |
| 2011 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) | |
| 2012 { | |
| 2013 if(lpMeasureItemStruct->CtlType != ODT_MENU) | |
| 2014 { | |
| 2015 // return default height for a system font | |
| 2016 T* pT = static_cast<T*>(this); | |
| 2017 HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID); | |
| 2018 CClientDC dc(hWnd); | |
| 2019 TEXTMETRIC tm = { 0 }; | |
| 2020 dc.GetTextMetrics(&tm); | |
| 2021 | |
| 2022 lpMeasureItemStruct->itemHeight = tm.tmHeight; | |
| 2023 } | |
| 2024 else | |
| 2025 lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_
CYMENU); | |
| 2026 } | |
| 2027 | |
| 2028 int CompareItem(LPCOMPAREITEMSTRUCT /*lpCompareItemStruct*/) | |
| 2029 { | |
| 2030 // all items are equal | |
| 2031 return 0; | |
| 2032 } | |
| 2033 | |
| 2034 void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/) | |
| 2035 { | |
| 2036 // default - nothing | |
| 2037 } | |
| 2038 }; | |
| 2039 | |
| 2040 | |
| 2041 /////////////////////////////////////////////////////////////////////////////// | |
| 2042 // Update UI macros | |
| 2043 | |
| 2044 // these build the Update UI map inside a class definition | |
| 2045 #define BEGIN_UPDATE_UI_MAP(thisClass) \ | |
| 2046 static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \ | |
| 2047 { \ | |
| 2048 static const _AtlUpdateUIMap theMap[] = \ | |
| 2049 { | |
| 2050 | |
| 2051 #define UPDATE_ELEMENT(nID, wType) \ | |
| 2052 { nID, wType }, | |
| 2053 | |
| 2054 #define END_UPDATE_UI_MAP() \ | |
| 2055 { (WORD)-1, 0 } \ | |
| 2056 }; \ | |
| 2057 return theMap; \ | |
| 2058 } | |
| 2059 | |
| 2060 /////////////////////////////////////////////////////////////////////////////// | |
| 2061 // CUpdateUI - manages UI elements updating | |
| 2062 | |
| 2063 class CUpdateUIBase | |
| 2064 { | |
| 2065 public: | |
| 2066 // constants | |
| 2067 enum | |
| 2068 { | |
| 2069 // UI element type | |
| 2070 UPDUI_MENUPOPUP = 0x0001, | |
| 2071 UPDUI_MENUBAR = 0x0002, | |
| 2072 UPDUI_CHILDWINDOW = 0x0004, | |
| 2073 UPDUI_TOOLBAR = 0x0008, | |
| 2074 UPDUI_STATUSBAR = 0x0010, | |
| 2075 // state | |
| 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, | |
| 2083 // internal state | |
| 2084 UPDUI_CLEARDEFAULT = 0x4000, | |
| 2085 }; | |
| 2086 | |
| 2087 // element data | |
| 2088 struct _AtlUpdateUIElement | |
| 2089 { | |
| 2090 HWND m_hWnd; | |
| 2091 WORD m_wType; | |
| 2092 | |
| 2093 bool operator ==(const _AtlUpdateUIElement& e) const | |
| 2094 { return (m_hWnd == e.m_hWnd && m_wType == e.m_wType); } | |
| 2095 }; | |
| 2096 | |
| 2097 // map data | |
| 2098 struct _AtlUpdateUIMap | |
| 2099 { | |
| 2100 WORD m_nID; | |
| 2101 WORD m_wType; | |
| 2102 | |
| 2103 bool operator ==(const _AtlUpdateUIMap& e) const | |
| 2104 { return (m_nID == e.m_nID && m_wType == e.m_wType); } | |
| 2105 }; | |
| 2106 | |
| 2107 // instance data | |
| 2108 struct _AtlUpdateUIData | |
| 2109 { | |
| 2110 WORD m_wState; | |
| 2111 union | |
| 2112 { | |
| 2113 void* m_lpData; | |
| 2114 LPTSTR m_lpstrText; | |
| 2115 }; | |
| 2116 | |
| 2117 bool operator ==(const _AtlUpdateUIData& e) const | |
| 2118 { return (m_wState == e.m_wState && m_lpData == e.m_lpData); } | |
| 2119 }; | |
| 2120 | |
| 2121 ATL::CSimpleArray<_AtlUpdateUIElement> m_UIElements; // elements data | |
| 2122 const _AtlUpdateUIMap* m_pUIMap; // static UI data | |
| 2123 _AtlUpdateUIData* m_pUIData; // instance UI da
ta | |
| 2124 WORD m_wDirtyType; // global dirty f
lag | |
| 2125 | |
| 2126 bool m_bBlockAccelerators; | |
| 2127 | |
| 2128 | |
| 2129 // Constructor, destructor | |
| 2130 CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0), m_bB
lockAccelerators(false) | |
| 2131 { } | |
| 2132 | |
| 2133 ~CUpdateUIBase() | |
| 2134 { | |
| 2135 if(m_pUIMap != NULL && m_pUIData != NULL) | |
| 2136 { | |
| 2137 const _AtlUpdateUIMap* pUIMap = m_pUIMap; | |
| 2138 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2139 while(pUIMap->m_nID != (WORD)-1) | |
| 2140 { | |
| 2141 if(pUIData->m_wState & UPDUI_TEXT) | |
| 2142 delete [] pUIData->m_lpstrText; | |
| 2143 pUIMap++; | |
| 2144 pUIData++; | |
| 2145 } | |
| 2146 delete [] m_pUIData; | |
| 2147 } | |
| 2148 } | |
| 2149 | |
| 2150 // Check for disabled commands | |
| 2151 bool UIGetBlockAccelerators() const | |
| 2152 { | |
| 2153 return m_bBlockAccelerators; | |
| 2154 } | |
| 2155 | |
| 2156 bool UISetBlockAccelerators(bool bBlock) | |
| 2157 { | |
| 2158 bool bOld = m_bBlockAccelerators; | |
| 2159 m_bBlockAccelerators = bBlock; | |
| 2160 return bOld; | |
| 2161 } | |
| 2162 | |
| 2163 // Add elements | |
| 2164 BOOL UIAddMenuBar(HWND hWnd) // menu bar (main menu) | |
| 2165 { | |
| 2166 if(hWnd == NULL) | |
| 2167 return FALSE; | |
| 2168 _AtlUpdateUIElement e; | |
| 2169 e.m_hWnd = hWnd; | |
| 2170 e.m_wType = UPDUI_MENUBAR; | |
| 2171 return m_UIElements.Add(e); | |
| 2172 } | |
| 2173 | |
| 2174 BOOL UIAddToolBar(HWND hWnd) // toolbar | |
| 2175 { | |
| 2176 if(hWnd == NULL) | |
| 2177 return FALSE; | |
| 2178 _AtlUpdateUIElement e; | |
| 2179 e.m_hWnd = hWnd; | |
| 2180 e.m_wType = UPDUI_TOOLBAR; | |
| 2181 return m_UIElements.Add(e); | |
| 2182 } | |
| 2183 | |
| 2184 BOOL UIAddStatusBar(HWND hWnd) // status bar | |
| 2185 { | |
| 2186 if(hWnd == NULL) | |
| 2187 return FALSE; | |
| 2188 _AtlUpdateUIElement e; | |
| 2189 e.m_hWnd = hWnd; | |
| 2190 e.m_wType = UPDUI_STATUSBAR; | |
| 2191 return m_UIElements.Add(e); | |
| 2192 } | |
| 2193 | |
| 2194 BOOL UIAddChildWindowContainer(HWND hWnd) // child window | |
| 2195 { | |
| 2196 if(hWnd == NULL) | |
| 2197 return FALSE; | |
| 2198 _AtlUpdateUIElement e; | |
| 2199 e.m_hWnd = hWnd; | |
| 2200 e.m_wType = UPDUI_CHILDWINDOW; | |
| 2201 return m_UIElements.Add(e); | |
| 2202 } | |
| 2203 | |
| 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) | |
| 2208 END_MSG_MAP() | |
| 2209 | |
| 2210 LRESULT OnInitMenuPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/,
BOOL& bHandled) | |
| 2211 { | |
| 2212 bHandled = FALSE; | |
| 2213 HMENU hMenu = (HMENU)wParam; | |
| 2214 if(hMenu == NULL) | |
| 2215 return 1; | |
| 2216 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2217 if(pUIData == NULL) | |
| 2218 return 1; | |
| 2219 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2220 while(pMap->m_nID != (WORD)-1) | |
| 2221 { | |
| 2222 if(pMap->m_wType & UPDUI_MENUPOPUP) | |
| 2223 UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMe
nu); | |
| 2224 pMap++; | |
| 2225 pUIData++; | |
| 2226 } | |
| 2227 return 0; | |
| 2228 } | |
| 2229 | |
| 2230 LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL&
bHandled) | |
| 2231 { | |
| 2232 bHandled = FALSE; | |
| 2233 if(m_bBlockAccelerators && HIWORD(wParam) == 1) // accelerator
s only | |
| 2234 { | |
| 2235 int nID = LOWORD(wParam); | |
| 2236 if((UIGetState(nID) & UPDUI_DISABLED) == UPDUI_DISABLED) | |
| 2237 { | |
| 2238 ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIBase::OnCo
mmand - blocked disabled command 0x%4.4X\n"), nID); | |
| 2239 bHandled = TRUE; // eat the command, UI item i
s disabled | |
| 2240 } | |
| 2241 } | |
| 2242 return 0; | |
| 2243 } | |
| 2244 | |
| 2245 // methods for setting UI element state | |
| 2246 BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE) | |
| 2247 { | |
| 2248 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2249 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2250 if(pUIData == NULL) | |
| 2251 return FALSE; | |
| 2252 | |
| 2253 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
| 2254 { | |
| 2255 if(nID == (int)pMap->m_nID) | |
| 2256 { | |
| 2257 if(bEnable) | |
| 2258 { | |
| 2259 if(pUIData->m_wState & UPDUI_DISABLED) | |
| 2260 { | |
| 2261 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2262 pUIData->m_wState &= ~UPDUI_DISA
BLED; | |
| 2263 } | |
| 2264 } | |
| 2265 else | |
| 2266 { | |
| 2267 if(!(pUIData->m_wState & UPDUI_DISABLED)
) | |
| 2268 { | |
| 2269 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2270 pUIData->m_wState |= UPDUI_DISAB
LED; | |
| 2271 } | |
| 2272 } | |
| 2273 | |
| 2274 if(bForceUpdate) | |
| 2275 pUIData->m_wState |= pMap->m_wType; | |
| 2276 if(pUIData->m_wState & pMap->m_wType) | |
| 2277 m_wDirtyType |= pMap->m_wType; | |
| 2278 | |
| 2279 break; // found | |
| 2280 } | |
| 2281 } | |
| 2282 | |
| 2283 return TRUE; | |
| 2284 } | |
| 2285 | |
| 2286 BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE) | |
| 2287 { | |
| 2288 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2289 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2290 if(pUIData == NULL) | |
| 2291 return FALSE; | |
| 2292 | |
| 2293 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
| 2294 { | |
| 2295 if(nID == (int)pMap->m_nID) | |
| 2296 { | |
| 2297 switch(nCheck) | |
| 2298 { | |
| 2299 case 0: | |
| 2300 if((pUIData->m_wState & UPDUI_CHECKED) |
| (pUIData->m_wState & UPDUI_CHECKED2)) | |
| 2301 { | |
| 2302 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2303 pUIData->m_wState &= ~(UPDUI_CHE
CKED | UPDUI_CHECKED2); | |
| 2304 } | |
| 2305 break; | |
| 2306 case 1: | |
| 2307 if(!(pUIData->m_wState & UPDUI_CHECKED)) | |
| 2308 { | |
| 2309 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2310 pUIData->m_wState &= ~UPDUI_CHEC
KED2; | |
| 2311 pUIData->m_wState |= UPDUI_CHECK
ED; | |
| 2312 } | |
| 2313 break; | |
| 2314 case 2: | |
| 2315 if(!(pUIData->m_wState & UPDUI_CHECKED2)
) | |
| 2316 { | |
| 2317 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2318 pUIData->m_wState &= ~UPDUI_CHEC
KED; | |
| 2319 pUIData->m_wState |= UPDUI_CHECK
ED2; | |
| 2320 } | |
| 2321 break; | |
| 2322 } | |
| 2323 | |
| 2324 if(bForceUpdate) | |
| 2325 pUIData->m_wState |= pMap->m_wType; | |
| 2326 if(pUIData->m_wState & pMap->m_wType) | |
| 2327 m_wDirtyType |= pMap->m_wType; | |
| 2328 | |
| 2329 break; // found | |
| 2330 } | |
| 2331 } | |
| 2332 | |
| 2333 return TRUE; | |
| 2334 } | |
| 2335 | |
| 2336 // variant that supports bool (checked/not-checked, no intermediate stat
e) | |
| 2337 BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE) | |
| 2338 { | |
| 2339 return UISetCheck(nID, bCheck ? 1 : 0, bForceUpdate); | |
| 2340 } | |
| 2341 | |
| 2342 BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE) | |
| 2343 { | |
| 2344 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2345 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2346 if(pUIData == NULL) | |
| 2347 return FALSE; | |
| 2348 | |
| 2349 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
| 2350 { | |
| 2351 if(nID == (int)pMap->m_nID) | |
| 2352 { | |
| 2353 if(bRadio) | |
| 2354 { | |
| 2355 if(!(pUIData->m_wState & UPDUI_RADIO)) | |
| 2356 { | |
| 2357 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2358 pUIData->m_wState |= UPDUI_RADIO
; | |
| 2359 } | |
| 2360 } | |
| 2361 else | |
| 2362 { | |
| 2363 if(pUIData->m_wState & UPDUI_RADIO) | |
| 2364 { | |
| 2365 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2366 pUIData->m_wState &= ~UPDUI_RADI
O; | |
| 2367 } | |
| 2368 } | |
| 2369 | |
| 2370 if(bForceUpdate) | |
| 2371 pUIData->m_wState |= pMap->m_wType; | |
| 2372 if(pUIData->m_wState & pMap->m_wType) | |
| 2373 m_wDirtyType |= pMap->m_wType; | |
| 2374 | |
| 2375 break; // found | |
| 2376 } | |
| 2377 } | |
| 2378 | |
| 2379 return TRUE; | |
| 2380 } | |
| 2381 | |
| 2382 BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE) | |
| 2383 { | |
| 2384 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2385 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2386 if(pUIData == NULL) | |
| 2387 return FALSE; | |
| 2388 if(lpstrText == NULL) | |
| 2389 lpstrText = _T(""); | |
| 2390 | |
| 2391 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
| 2392 { | |
| 2393 if(nID == (int)pMap->m_nID) | |
| 2394 { | |
| 2395 if(pUIData->m_lpstrText == NULL || lstrcmp(pUIDa
ta->m_lpstrText, lpstrText)) | |
| 2396 { | |
| 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) | |
| 2402 { | |
| 2403 ATLTRACE2(atlTraceUI, 0, _T("UIS
etText - memory allocation failed\n")); | |
| 2404 break; | |
| 2405 } | |
| 2406 SecureHelper::strcpy_x(pUIData->m_lpstrT
ext, nStrLen + 1, lpstrText); | |
| 2407 pUIData->m_wState |= (UPDUI_TEXT | pMap-
>m_wType); | |
| 2408 } | |
| 2409 | |
| 2410 if(bForceUpdate) | |
| 2411 pUIData->m_wState |= (UPDUI_TEXT | pMap-
>m_wType); | |
| 2412 if(pUIData->m_wState & pMap->m_wType) | |
| 2413 m_wDirtyType |= pMap->m_wType; | |
| 2414 | |
| 2415 break; // found | |
| 2416 } | |
| 2417 } | |
| 2418 | |
| 2419 return TRUE; | |
| 2420 } | |
| 2421 | |
| 2422 BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE) | |
| 2423 { | |
| 2424 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2425 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2426 if(pUIData == NULL) | |
| 2427 return FALSE; | |
| 2428 | |
| 2429 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
| 2430 { | |
| 2431 if(nID == (int)pMap->m_nID) | |
| 2432 { | |
| 2433 if(bDefault) | |
| 2434 { | |
| 2435 if((pUIData->m_wState & UPDUI_DEFAULT) =
= 0) | |
| 2436 { | |
| 2437 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2438 pUIData->m_wState |= UPDUI_DEFAU
LT; | |
| 2439 } | |
| 2440 } | |
| 2441 else | |
| 2442 { | |
| 2443 if((pUIData->m_wState & UPDUI_DEFAULT) !
= 0) | |
| 2444 { | |
| 2445 pUIData->m_wState |= pMap->m_wTy
pe; | |
| 2446 pUIData->m_wState &= ~UPDUI_DEFA
ULT; | |
| 2447 pUIData->m_wState |= UPDUI_CLEAR
DEFAULT; | |
| 2448 } | |
| 2449 } | |
| 2450 | |
| 2451 if(bForceUpdate) | |
| 2452 pUIData->m_wState |= pMap->m_wType; | |
| 2453 if(pUIData->m_wState & pMap->m_wType) | |
| 2454 m_wDirtyType |= pMap->m_wType; | |
| 2455 | |
| 2456 break; // found | |
| 2457 } | |
| 2458 } | |
| 2459 | |
| 2460 return TRUE; | |
| 2461 } | |
| 2462 | |
| 2463 // methods for complete state set/get | |
| 2464 BOOL UISetState(int nID, DWORD dwState) | |
| 2465 { | |
| 2466 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2467 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2468 if(pUIData == NULL) | |
| 2469 return FALSE; | |
| 2470 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
| 2471 { | |
| 2472 if(nID == (int)pMap->m_nID) | |
| 2473 { | |
| 2474 pUIData->m_wState = (WORD)(dwState | pMap->m_wTy
pe); | |
| 2475 m_wDirtyType |= pMap->m_wType; | |
| 2476 break; // found | |
| 2477 } | |
| 2478 } | |
| 2479 return TRUE; | |
| 2480 } | |
| 2481 | |
| 2482 DWORD UIGetState(int nID) | |
| 2483 { | |
| 2484 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2485 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2486 if(pUIData == NULL) | |
| 2487 return 0; | |
| 2488 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
| 2489 { | |
| 2490 if(nID == (int)pMap->m_nID) | |
| 2491 return pUIData->m_wState; | |
| 2492 } | |
| 2493 return 0; | |
| 2494 } | |
| 2495 | |
| 2496 // methods for updating UI | |
| 2497 #ifndef _WIN32_WCE | |
| 2498 BOOL UIUpdateMenuBar(BOOL bForceUpdate = FALSE, BOOL bMainMenu = FALSE) | |
| 2499 { | |
| 2500 if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate) | |
| 2501 return TRUE; | |
| 2502 | |
| 2503 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2504 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2505 if(pUIData == NULL) | |
| 2506 return FALSE; | |
| 2507 | |
| 2508 while(pMap->m_nID != (WORD)-1) | |
| 2509 { | |
| 2510 for(int i = 0; i < m_UIElements.GetSize(); i++) | |
| 2511 { | |
| 2512 if(m_UIElements[i].m_wType == UPDUI_MENUBAR) | |
| 2513 { | |
| 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_n
ID, pUIData, hMenu); | |
| 2517 } | |
| 2518 if(bMainMenu) | |
| 2519 ::DrawMenuBar(m_UIElements[i].m_hWnd); | |
| 2520 } | |
| 2521 pMap++; | |
| 2522 pUIData->m_wState &= ~UPDUI_MENUBAR; | |
| 2523 if(pUIData->m_wState & UPDUI_TEXT) | |
| 2524 { | |
| 2525 delete [] pUIData->m_lpstrText; | |
| 2526 pUIData->m_lpstrText = NULL; | |
| 2527 pUIData->m_wState &= ~UPDUI_TEXT; | |
| 2528 } | |
| 2529 pUIData++; | |
| 2530 } | |
| 2531 | |
| 2532 m_wDirtyType &= ~UPDUI_MENUBAR; | |
| 2533 return TRUE; | |
| 2534 } | |
| 2535 #endif // !_WIN32_WCE | |
| 2536 | |
| 2537 BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE) | |
| 2538 { | |
| 2539 if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate) | |
| 2540 return TRUE; | |
| 2541 | |
| 2542 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2543 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2544 if(pUIData == NULL) | |
| 2545 return FALSE; | |
| 2546 | |
| 2547 while(pMap->m_nID != (WORD)-1) | |
| 2548 { | |
| 2549 for(int i = 0; i < m_UIElements.GetSize(); i++) | |
| 2550 { | |
| 2551 if(m_UIElements[i].m_wType == UPDUI_TOOLBAR) | |
| 2552 { | |
| 2553 if((pUIData->m_wState & UPDUI_TOOLBAR) &
& (pMap->m_wType & UPDUI_TOOLBAR)) | |
| 2554 UIUpdateToolBarElement(pMap->m_n
ID, pUIData, m_UIElements[i].m_hWnd); | |
| 2555 } | |
| 2556 } | |
| 2557 pMap++; | |
| 2558 pUIData->m_wState &= ~UPDUI_TOOLBAR; | |
| 2559 pUIData++; | |
| 2560 } | |
| 2561 | |
| 2562 m_wDirtyType &= ~UPDUI_TOOLBAR; | |
| 2563 return TRUE; | |
| 2564 } | |
| 2565 | |
| 2566 BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE) | |
| 2567 { | |
| 2568 if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate) | |
| 2569 return TRUE; | |
| 2570 | |
| 2571 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2572 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2573 if(pUIData == NULL) | |
| 2574 return FALSE; | |
| 2575 | |
| 2576 while(pMap->m_nID != (WORD)-1) | |
| 2577 { | |
| 2578 for(int i = 0; i < m_UIElements.GetSize(); i++) | |
| 2579 { | |
| 2580 if(m_UIElements[i].m_wType == UPDUI_STATUSBAR) | |
| 2581 { | |
| 2582 if((pUIData->m_wState & UPDUI_STATUSBAR)
&& (pMap->m_wType & UPDUI_STATUSBAR)) | |
| 2583 UIUpdateStatusBarElement(pMap->m
_nID, pUIData, m_UIElements[i].m_hWnd); | |
| 2584 } | |
| 2585 } | |
| 2586 pMap++; | |
| 2587 pUIData->m_wState &= ~UPDUI_STATUSBAR; | |
| 2588 if(pUIData->m_wState & UPDUI_TEXT) | |
| 2589 { | |
| 2590 delete [] pUIData->m_lpstrText; | |
| 2591 pUIData->m_lpstrText = NULL; | |
| 2592 pUIData->m_wState &= ~UPDUI_TEXT; | |
| 2593 } | |
| 2594 pUIData++; | |
| 2595 } | |
| 2596 | |
| 2597 m_wDirtyType &= ~UPDUI_STATUSBAR; | |
| 2598 return TRUE; | |
| 2599 } | |
| 2600 | |
| 2601 BOOL UIUpdateChildWindows(BOOL bForceUpdate = FALSE) | |
| 2602 { | |
| 2603 if(!(m_wDirtyType & UPDUI_CHILDWINDOW) && !bForceUpdate) | |
| 2604 return TRUE; | |
| 2605 | |
| 2606 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
| 2607 _AtlUpdateUIData* pUIData = m_pUIData; | |
| 2608 if(pUIData == NULL) | |
| 2609 return FALSE; | |
| 2610 | |
| 2611 while(pMap->m_nID != (WORD)-1) | |
| 2612 { | |
| 2613 for(int i = 0; i < m_UIElements.GetSize(); i++) | |
| 2614 { | |
| 2615 if(m_UIElements[i].m_wType == UPDUI_CHILDWINDOW) | |
| 2616 { | |
| 2617 if((pUIData->m_wState & UPDUI_CHILDWINDO
W) && (pMap->m_wType & UPDUI_CHILDWINDOW)) | |
| 2618 UIUpdateChildWindow(pMap->m_nID,
pUIData, m_UIElements[i].m_hWnd); | |
| 2619 } | |
| 2620 } | |
| 2621 pMap++; | |
| 2622 pUIData->m_wState &= ~UPDUI_CHILDWINDOW; | |
| 2623 if(pUIData->m_wState & UPDUI_TEXT) | |
| 2624 { | |
| 2625 delete [] pUIData->m_lpstrText; | |
| 2626 pUIData->m_lpstrText = NULL; | |
| 2627 pUIData->m_wState &= ~UPDUI_TEXT; | |
| 2628 } | |
| 2629 pUIData++; | |
| 2630 } | |
| 2631 | |
| 2632 m_wDirtyType &= ~UPDUI_CHILDWINDOW; | |
| 2633 return TRUE; | |
| 2634 } | |
| 2635 | |
| 2636 // internal element specific methods | |
| 2637 static void UIUpdateMenuBarElement(int nID, _AtlUpdateUIData* pUIData, H
MENU hMenu) | |
| 2638 { | |
| 2639 #ifndef _WIN32_WCE | |
| 2640 if((pUIData->m_wState & UPDUI_CLEARDEFAULT) != 0) | |
| 2641 { | |
| 2642 ::SetMenuDefaultItem(hMenu, (UINT)-1, 0); | |
| 2643 pUIData->m_wState &= ~UPDUI_CLEARDEFAULT; | |
| 2644 } | |
| 2645 #endif // !_WIN32_WCE | |
| 2646 | |
| 2647 CMenuItemInfo mii; | |
| 2648 mii.fMask = MIIM_STATE; | |
| 2649 mii.wID = nID; | |
| 2650 | |
| 2651 #ifndef _WIN32_WCE | |
| 2652 if((pUIData->m_wState & UPDUI_DISABLED) != 0) | |
| 2653 mii.fState |= MFS_DISABLED | MFS_GRAYED; | |
| 2654 else | |
| 2655 mii.fState |= MFS_ENABLED; | |
| 2656 | |
| 2657 if((pUIData->m_wState & UPDUI_CHECKED) != 0) | |
| 2658 mii.fState |= MFS_CHECKED; | |
| 2659 else | |
| 2660 mii.fState |= MFS_UNCHECKED; | |
| 2661 | |
| 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; | |
| 2670 else | |
| 2671 uEnable |= MF_ENABLED; | |
| 2672 ::EnableMenuItem(hMenu, nID, uEnable); | |
| 2673 | |
| 2674 UINT uCheck = MF_BYCOMMAND; | |
| 2675 if((pUIData->m_wState & UPDUI_CHECKED) != 0) | |
| 2676 uCheck |= MF_CHECKED; | |
| 2677 else | |
| 2678 uCheck |= MF_UNCHECKED; | |
| 2679 ::CheckMenuItem(hMenu, nID, uCheck); | |
| 2680 #endif // _WIN32_WCE | |
| 2681 | |
| 2682 if((pUIData->m_wState & UPDUI_TEXT) != 0) | |
| 2683 { | |
| 2684 CMenuItemInfo miiNow; | |
| 2685 miiNow.fMask = MIIM_TYPE; | |
| 2686 miiNow.wID = nID; | |
| 2687 if(::GetMenuItemInfo(hMenu, nID, FALSE, &miiNow)) | |
| 2688 { | |
| 2689 mii.fMask |= MIIM_TYPE; | |
| 2690 // MFT_BITMAP and MFT_SEPARATOR don't go togethe
r with MFT_STRING | |
| 2691 #ifndef _WIN32_WCE | |
| 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; | |
| 2697 } | |
| 2698 } | |
| 2699 | |
| 2700 ::SetMenuItemInfo(hMenu, nID, FALSE, &mii); | |
| 2701 } | |
| 2702 | |
| 2703 static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, H
WND hWndToolBar) | |
| 2704 { | |
| 2705 // Note: only handles enabled/disabled, checked state, and radio
(press) | |
| 2706 ::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIDat
a->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)(pUIDa
ta->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE); | |
| 2709 ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData
->m_wState & UPDUI_RADIO) ? TRUE : FALSE); | |
| 2710 } | |
| 2711 | |
| 2712 static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData,
HWND hWndStatusBar) | |
| 2713 { | |
| 2714 // Note: only handles text | |
| 2715 if(pUIData->m_wState & UPDUI_TEXT) | |
| 2716 ::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pU
IData->m_lpstrText); | |
| 2717 } | |
| 2718 | |
| 2719 static void UIUpdateChildWindow(int nID, _AtlUpdateUIData* pUIData, HWND
hWnd) | |
| 2720 { | |
| 2721 HWND hChild = ::GetDlgItem(hWnd, nID); | |
| 2722 | |
| 2723 ::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FA
LSE : 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 & UPDU
I_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) | |
| 2732 { | |
| 2733 DWORD dwRet = (DWORD)::SendMessage(hWnd, DM_GETDEFID, 0,
0L); | |
| 2734 if(HIWORD(dwRet) == DC_HASDEFID) | |
| 2735 { | |
| 2736 HWND hOldDef = ::GetDlgItem(hWnd, (int)(short)LO
WORD(dwRet)); | |
| 2737 // remove BS_DEFPUSHBUTTON | |
| 2738 ::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTO
N, MAKELPARAM(TRUE, 0)); | |
| 2739 } | |
| 2740 ::SendMessage(hWnd, DM_SETDEFID, nID, 0L); | |
| 2741 } | |
| 2742 if(pUIData->m_wState & UPDUI_TEXT) | |
| 2743 ::SetWindowText(hChild, pUIData->m_lpstrText); | |
| 2744 } | |
| 2745 }; | |
| 2746 | |
| 2747 template <class T> | |
| 2748 class CUpdateUI : public CUpdateUIBase | |
| 2749 { | |
| 2750 public: | |
| 2751 CUpdateUI() | |
| 2752 { | |
| 2753 T* pT = static_cast<T*>(this); | |
| 2754 pT; | |
| 2755 const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap(); | |
| 2756 m_pUIMap = pMap; | |
| 2757 ATLASSERT(m_pUIMap != NULL); | |
| 2758 int nCount; | |
| 2759 for(nCount = 1; pMap->m_nID != (WORD)-1; nCount++) | |
| 2760 pMap++; | |
| 2761 | |
| 2762 // check for duplicates (debug only) | |
| 2763 #ifdef _DEBUG | |
| 2764 for(int i = 0; i < nCount; i++) | |
| 2765 { | |
| 2766 for(int j = 0; j < nCount; j++) | |
| 2767 { | |
| 2768 // shouldn't have duplicates in the update UI ma
p | |
| 2769 if(i != j) | |
| 2770 ATLASSERT(m_pUIMap[j].m_nID != m_pUIMap[
i].m_nID); | |
| 2771 } | |
| 2772 } | |
| 2773 #endif // _DEBUG | |
| 2774 | |
| 2775 ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]); | |
| 2776 ATLASSERT(m_pUIData != NULL); | |
| 2777 | |
| 2778 if(m_pUIData != NULL) | |
| 2779 memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount); | |
| 2780 } | |
| 2781 }; | |
| 2782 | |
| 2783 | |
| 2784 /////////////////////////////////////////////////////////////////////////////// | |
| 2785 // CDynamicUpdateUI - allows update elements to dynamically added and removed | |
| 2786 // in addition to a static update UI map | |
| 2787 | |
| 2788 template <class T> | |
| 2789 class CDynamicUpdateUI : public CUpdateUIBase | |
| 2790 { | |
| 2791 public: | |
| 2792 // Data members | |
| 2793 ATL::CSimpleArray<_AtlUpdateUIMap> m_arrUIMap; // copy of the static
UI data | |
| 2794 ATL::CSimpleArray<_AtlUpdateUIData> m_arrUIData; // instance UI data | |
| 2795 | |
| 2796 // Constructor/destructor | |
| 2797 CDynamicUpdateUI() | |
| 2798 { | |
| 2799 T* pT = static_cast<T*>(this); | |
| 2800 pT; | |
| 2801 const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap(); | |
| 2802 ATLASSERT(pMap != NULL); | |
| 2803 | |
| 2804 for(;;) | |
| 2805 { | |
| 2806 BOOL bRet = m_arrUIMap.Add(*(_AtlUpdateUIMap*)pMap); | |
| 2807 ATLASSERT(bRet); | |
| 2808 | |
| 2809 if(bRet != FALSE) | |
| 2810 { | |
| 2811 _AtlUpdateUIData data = { 0, NULL }; | |
| 2812 bRet = m_arrUIData.Add(data); | |
| 2813 ATLASSERT(bRet); | |
| 2814 } | |
| 2815 | |
| 2816 if(pMap->m_nID == (WORD)-1) | |
| 2817 break; | |
| 2818 | |
| 2819 pMap++; | |
| 2820 } | |
| 2821 | |
| 2822 ATLASSERT(m_arrUIMap.GetSize() == m_arrUIData.GetSize()); | |
| 2823 | |
| 2824 #ifdef _DEBUG | |
| 2825 // check for duplicates (debug only) | |
| 2826 for(int i = 0; i < m_arrUIMap.GetSize(); i++) | |
| 2827 { | |
| 2828 for(int j = 0; j < m_arrUIMap.GetSize(); j++) | |
| 2829 { | |
| 2830 // shouldn't have duplicates in the update UI ma
p | |
| 2831 if(i != j) | |
| 2832 ATLASSERT(m_arrUIMap[j].m_nID != m_arrUI
Map[i].m_nID); | |
| 2833 } | |
| 2834 } | |
| 2835 #endif // _DEBUG | |
| 2836 | |
| 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; | |
| 2840 } | |
| 2841 | |
| 2842 ~CDynamicUpdateUI() | |
| 2843 { | |
| 2844 for(int i = 0; i < m_arrUIData.GetSize(); i++) | |
| 2845 { | |
| 2846 if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0) | |
| 2847 delete [] m_arrUIData[i].m_lpstrText; | |
| 2848 } | |
| 2849 | |
| 2850 // Reset internal data pointers (memory will be released by CSim
pleArray d-tor) | |
| 2851 m_pUIMap = NULL; | |
| 2852 m_pUIData = NULL; | |
| 2853 } | |
| 2854 | |
| 2855 // Methods for dynamically adding and removing update elements | |
| 2856 bool UIAddUpdateElement(WORD nID, WORD wType) | |
| 2857 { | |
| 2858 // check for duplicates | |
| 2859 for(int i = 0; i < m_arrUIMap.GetSize(); i++) | |
| 2860 { | |
| 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) | |
| 2864 return false; | |
| 2865 } | |
| 2866 | |
| 2867 bool bRetVal = false; | |
| 2868 | |
| 2869 // Add new end element | |
| 2870 _AtlUpdateUIMap uumEnd = { (WORD)-1, 0 }; | |
| 2871 BOOL bRet = m_arrUIMap.Add(uumEnd); | |
| 2872 ATLASSERT(bRet); | |
| 2873 | |
| 2874 if(bRet != FALSE) | |
| 2875 { | |
| 2876 _AtlUpdateUIData uud = { 0, NULL }; | |
| 2877 bRet = m_arrUIData.Add(uud); | |
| 2878 ATLASSERT(bRet); | |
| 2879 | |
| 2880 // Set new data to the previous end element | |
| 2881 if(bRet != FALSE) | |
| 2882 { | |
| 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); | |
| 2887 | |
| 2888 // Set internal data pointers again, just in cas
e that memory moved | |
| 2889 m_pUIMap = m_arrUIMap.m_aT; | |
| 2890 m_pUIData = m_arrUIData.m_aT; | |
| 2891 | |
| 2892 bRetVal = true; | |
| 2893 } | |
| 2894 } | |
| 2895 | |
| 2896 return bRetVal; | |
| 2897 } | |
| 2898 | |
| 2899 bool UIRemoveUpdateElement(WORD nID) | |
| 2900 { | |
| 2901 bool bRetVal = false; | |
| 2902 | |
| 2903 for(int i = 0; i < m_arrUIMap.GetSize(); i++) | |
| 2904 { | |
| 2905 if(m_arrUIMap[i].m_nID == nID) | |
| 2906 { | |
| 2907 BOOL bRet = m_arrUIMap.RemoveAt(i); | |
| 2908 ATLASSERT(bRet); | |
| 2909 bRet = m_arrUIData.RemoveAt(i); | |
| 2910 ATLASSERT(bRet); | |
| 2911 | |
| 2912 bRetVal = true; | |
| 2913 break; | |
| 2914 } | |
| 2915 } | |
| 2916 | |
| 2917 return bRetVal; | |
| 2918 } | |
| 2919 }; | |
| 2920 | |
| 2921 | |
| 2922 /////////////////////////////////////////////////////////////////////////////// | |
| 2923 // CDialogResize - provides support for resizing dialog controls | |
| 2924 // (works for any window that has child controls) | |
| 2925 | |
| 2926 // Put CDialogResize in the list of base classes for a dialog (or even plain win
dow), | |
| 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. | |
| 2929 // | |
| 2930 // Notes: | |
| 2931 // - Resizeable border (WS_THICKFRAME style) should be set in the dialog templat
e | |
| 2932 // for top level dialogs (popup or overlapped), so that users can resize the d
ialog. | |
| 2933 // - Some flags cannot be combined; for instance DLSZ_CENTER_X overrides DLSZ_SI
ZE_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. | |
| 2937 | |
| 2938 // dialog resize map macros | |
| 2939 #define BEGIN_DLGRESIZE_MAP(thisClass) \ | |
| 2940 static const _AtlDlgResizeMap* GetDlgResizeMap() \ | |
| 2941 { \ | |
| 2942 static const _AtlDlgResizeMap theMap[] = \ | |
| 2943 { | |
| 2944 | |
| 2945 #define END_DLGRESIZE_MAP() \ | |
| 2946 { -1, 0 }, \ | |
| 2947 }; \ | |
| 2948 return theMap; \ | |
| 2949 } | |
| 2950 | |
| 2951 #define DLGRESIZE_CONTROL(id, flags) \ | |
| 2952 { id, flags }, | |
| 2953 | |
| 2954 #define BEGIN_DLGRESIZE_GROUP() \ | |
| 2955 { -1, _DLSZ_BEGIN_GROUP }, | |
| 2956 | |
| 2957 #define END_DLGRESIZE_GROUP() \ | |
| 2958 { -1, _DLSZ_END_GROUP }, | |
| 2959 | |
| 2960 | |
| 2961 template <class T> | |
| 2962 class CDialogResize | |
| 2963 { | |
| 2964 public: | |
| 2965 // Data declarations and members | |
| 2966 enum | |
| 2967 { | |
| 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, | |
| 2975 | |
| 2976 // internal use only | |
| 2977 _DLSZ_BEGIN_GROUP = 0x00001000, | |
| 2978 _DLSZ_END_GROUP = 0x00002000, | |
| 2979 _DLSZ_GRIPPER = 0x00004000 | |
| 2980 }; | |
| 2981 | |
| 2982 struct _AtlDlgResizeMap | |
| 2983 { | |
| 2984 int m_nCtlID; | |
| 2985 DWORD m_dwResizeFlags; | |
| 2986 }; | |
| 2987 | |
| 2988 struct _AtlDlgResizeData | |
| 2989 { | |
| 2990 int m_nCtlID; | |
| 2991 DWORD m_dwResizeFlags; | |
| 2992 RECT m_rect; | |
| 2993 | |
| 2994 int GetGroupCount() const | |
| 2995 { | |
| 2996 return (int)LOBYTE(HIWORD(m_dwResizeFlags)); | |
| 2997 } | |
| 2998 | |
| 2999 void SetGroupCount(int nCount) | |
| 3000 { | |
| 3001 ATLASSERT(nCount > 0 && nCount < 256); | |
| 3002 DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0)); | |
| 3003 m_dwResizeFlags &= 0xFF00FFFF; | |
| 3004 m_dwResizeFlags |= dwCount; | |
| 3005 } | |
| 3006 | |
| 3007 bool operator ==(const _AtlDlgResizeData& r) const | |
| 3008 { return (m_nCtlID == r.m_nCtlID && m_dwResizeFlags == r.m_dwRes
izeFlags); } | |
| 3009 }; | |
| 3010 | |
| 3011 ATL::CSimpleArray<_AtlDlgResizeData> m_arrData; | |
| 3012 SIZE m_sizeDialog; | |
| 3013 POINT m_ptMinTrackSize; | |
| 3014 bool m_bGripper; | |
| 3015 | |
| 3016 | |
| 3017 // Constructor | |
| 3018 CDialogResize() : m_bGripper(false) | |
| 3019 { | |
| 3020 m_sizeDialog.cx = 0; | |
| 3021 m_sizeDialog.cy = 0; | |
| 3022 m_ptMinTrackSize.x = -1; | |
| 3023 m_ptMinTrackSize.y = -1; | |
| 3024 } | |
| 3025 | |
| 3026 // Operations | |
| 3027 void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = tru
e, DWORD dwForceStyle = WS_CLIPCHILDREN) | |
| 3028 { | |
| 3029 T* pT = static_cast<T*>(this); | |
| 3030 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
| 3031 | |
| 3032 DWORD dwStyle = pT->GetStyle(); | |
| 3033 | |
| 3034 #ifdef _DEBUG | |
| 3035 // Debug only: Check if top level dialogs have a resizeable bord
er. | |
| 3036 if(((dwStyle & WS_CHILD) == 0) && ((dwStyle & WS_THICKFRAME) ==
0)) | |
| 3037 ATLTRACE2(atlTraceUI, 0, _T("DlgResize_Init - warning: t
op level dialog without the WS_THICKFRAME style - user cannot resize it\n")); | |
| 3038 #endif // _DEBUG | |
| 3039 | |
| 3040 // Force specified styles (default WS_CLIPCHILDREN reduces flick
er) | |
| 3041 if((dwStyle & dwForceStyle) != dwForceStyle) | |
| 3042 pT->ModifyStyle(0, dwForceStyle); | |
| 3043 | |
| 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 usi
ng SetIcon() | |
| 3047 if((dwStyle & WS_CHILD) == 0) | |
| 3048 { | |
| 3049 pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME); | |
| 3050 if(pT->GetIcon(FALSE) == NULL) | |
| 3051 pT->SetIcon(NULL, FALSE); | |
| 3052 } | |
| 3053 | |
| 3054 // Cleanup in case of multiple initialization | |
| 3055 // block: first check for the gripper control, destroy it if nee
ded | |
| 3056 { | |
| 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(); | |
| 3060 } | |
| 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; | |
| 3067 | |
| 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; | |
| 3073 | |
| 3074 #ifndef _WIN32_WCE | |
| 3075 // Create gripper if requested | |
| 3076 m_bGripper = false; | |
| 3077 if(bAddGripper) | |
| 3078 { | |
| 3079 // shouldn't exist already | |
| 3080 ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)
)); | |
| 3081 if(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR))) | |
| 3082 { | |
| 3083 ATL::CWindow wndGripper; | |
| 3084 wndGripper.Create(_T("SCROLLBAR"), pT->m_hWnd, r
ectDlg, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEBOX | SBS_SIZEGR
IP | SBS_SIZEBOXBOTTOMRIGHTALIGN, 0, ATL_IDW_STATUS_BAR); | |
| 3085 ATLASSERT(wndGripper.IsWindow()); | |
| 3086 if(wndGripper.IsWindow()) | |
| 3087 { | |
| 3088 m_bGripper = true; | |
| 3089 RECT rectCtl = { 0 }; | |
| 3090 wndGripper.GetWindowRect(&rectCtl); | |
| 3091 ::MapWindowPoints(NULL, pT->m_hWnd, (LPP
OINT)&rectCtl, 2); | |
| 3092 _AtlDlgResizeData data = { ATL_IDW_STATU
S_BAR, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | _DLSZ_GRIPPER, { rectCtl.left,
rectCtl.top, rectCtl.right, rectCtl.bottom } }; | |
| 3093 m_arrData.Add(data); | |
| 3094 } | |
| 3095 } | |
| 3096 } | |
| 3097 #else // CE specific | |
| 3098 bAddGripper; // avoid level 4 warning | |
| 3099 #endif // _WIN32_WCE | |
| 3100 | |
| 3101 // Get min track position if requested | |
| 3102 if(bUseMinTrackSize) | |
| 3103 { | |
| 3104 if((dwStyle & WS_CHILD) != 0) | |
| 3105 { | |
| 3106 RECT rect = { 0 }; | |
| 3107 pT->GetClientRect(&rect); | |
| 3108 m_ptMinTrackSize.x = rect.right - rect.left; | |
| 3109 m_ptMinTrackSize.y = rect.bottom - rect.top; | |
| 3110 } | |
| 3111 else | |
| 3112 { | |
| 3113 RECT rect = { 0 }; | |
| 3114 pT->GetWindowRect(&rect); | |
| 3115 m_ptMinTrackSize.x = rect.right - rect.left; | |
| 3116 m_ptMinTrackSize.y = rect.bottom - rect.top; | |
| 3117 } | |
| 3118 } | |
| 3119 | |
| 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_dwResizeFl
ags == 0); nCount++, pMap++) | |
| 3125 { | |
| 3126 if(pMap->m_nCtlID == -1) | |
| 3127 { | |
| 3128 switch(pMap->m_dwResizeFlags) | |
| 3129 { | |
| 3130 case _DLSZ_BEGIN_GROUP: | |
| 3131 ATLASSERT(nGroupStart == -1); | |
| 3132 nGroupStart = m_arrData.GetSize(); | |
| 3133 break; | |
| 3134 case _DLSZ_END_GROUP: | |
| 3135 { | |
| 3136 ATLASSERT(nGroupStart != -1); | |
| 3137 int nGroupCount = m_arrData.GetS
ize() - nGroupStart; | |
| 3138 m_arrData[nGroupStart].SetGroupC
ount(nGroupCount); | |
| 3139 nGroupStart = -1; | |
| 3140 } | |
| 3141 break; | |
| 3142 default: | |
| 3143 ATLASSERT(FALSE && _T("Invalid DLGRESIZE
Map Entry")); | |
| 3144 break; | |
| 3145 } | |
| 3146 } | |
| 3147 else | |
| 3148 { | |
| 3149 // this ID conflicts with the default gripper on
e | |
| 3150 ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_ID
W_STATUS_BAR) : TRUE); | |
| 3151 | |
| 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)&re
ctCtl, 2); | |
| 3157 | |
| 3158 DWORD dwGroupFlag = (nGroupStart != -1 && m_arrD
ata.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0; | |
| 3159 _AtlDlgResizeData data = { pMap->m_nCtlID, pMap-
>m_dwResizeFlags | dwGroupFlag, { rectCtl.left, rectCtl.top, rectCtl.right, rect
Ctl.bottom } }; | |
| 3160 m_arrData.Add(data); | |
| 3161 } | |
| 3162 } | |
| 3163 ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the D
LGRESIZE Map")); | |
| 3164 } | |
| 3165 | |
| 3166 void DlgResize_UpdateLayout(int cxWidth, int cyHeight) | |
| 3167 { | |
| 3168 T* pT = static_cast<T*>(this); | |
| 3169 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
| 3170 | |
| 3171 // Restrict minimum size if requested | |
| 3172 if(((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -
1 && m_ptMinTrackSize.y != -1) | |
| 3173 { | |
| 3174 if(cxWidth < m_ptMinTrackSize.x) | |
| 3175 cxWidth = m_ptMinTrackSize.x; | |
| 3176 if(cyHeight < m_ptMinTrackSize.y) | |
| 3177 cyHeight = m_ptMinTrackSize.y; | |
| 3178 } | |
| 3179 | |
| 3180 BOOL bVisible = pT->IsWindowVisible(); | |
| 3181 if(bVisible) | |
| 3182 pT->SetRedraw(FALSE); | |
| 3183 | |
| 3184 for(int i = 0; i < m_arrData.GetSize(); i++) | |
| 3185 { | |
| 3186 if((m_arrData[i].m_dwResizeFlags & _DLSZ_BEGIN_GROUP) !=
0) // start of a group | |
| 3187 { | |
| 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; | |
| 3191 | |
| 3192 int j = 1; | |
| 3193 for(j = 1; j < nGroupCount; j++) | |
| 3194 { | |
| 3195 rectGroup.left = __min(rectGroup.left, m
_arrData[i + j].m_rect.left); | |
| 3196 rectGroup.top = __min(rectGroup.top, m_a
rrData[i + j].m_rect.top); | |
| 3197 rectGroup.right = __max(rectGroup.right,
m_arrData[i + j].m_rect.right); | |
| 3198 rectGroup.bottom = __max(rectGroup.botto
m, m_arrData[i + j].m_rect.bottom); | |
| 3199 } | |
| 3200 | |
| 3201 for(j = 0; j < nGroupCount; j++) | |
| 3202 { | |
| 3203 _AtlDlgResizeData* pDataPrev = NULL; | |
| 3204 if(j > 0) | |
| 3205 pDataPrev = &(m_arrData[i + j -
1]); | |
| 3206 pT->DlgResize_PositionControl(cxWidth, c
yHeight, rectGroup, m_arrData[i + j], true, pDataPrev); | |
| 3207 } | |
| 3208 | |
| 3209 i += nGroupCount - 1; // increment to skip all
group controls | |
| 3210 } | |
| 3211 else // one control entry | |
| 3212 { | |
| 3213 RECT rectGroup = { 0, 0, 0, 0 }; | |
| 3214 pT->DlgResize_PositionControl(cxWidth, cyHeight,
rectGroup, m_arrData[i], false); | |
| 3215 } | |
| 3216 } | |
| 3217 | |
| 3218 if(bVisible) | |
| 3219 pT->SetRedraw(TRUE); | |
| 3220 | |
| 3221 pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UP
DATENOW | RDW_ALLCHILDREN); | |
| 3222 } | |
| 3223 | |
| 3224 // Message map and handlers | |
| 3225 BEGIN_MSG_MAP(CDialogResize) | |
| 3226 MESSAGE_HANDLER(WM_SIZE, OnSize) | |
| 3227 #ifndef _WIN32_WCE | |
| 3228 MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo) | |
| 3229 #endif // _WIN32_WCE | |
| 3230 END_MSG_MAP() | |
| 3231 | |
| 3232 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHan
dled*/) | |
| 3233 { | |
| 3234 T* pT = static_cast<T*>(this); | |
| 3235 #ifndef _WIN32_WCE | |
| 3236 if(m_bGripper) | |
| 3237 { | |
| 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); | |
| 3243 } | |
| 3244 #endif // _WIN32_WCE | |
| 3245 if(wParam != SIZE_MINIMIZED) | |
| 3246 { | |
| 3247 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
| 3248 pT->DlgResize_UpdateLayout(GET_X_LPARAM(lParam), GET_Y_L
PARAM(lParam)); | |
| 3249 } | |
| 3250 return 0; | |
| 3251 } | |
| 3252 | |
| 3253 #ifndef _WIN32_WCE | |
| 3254 LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam,
BOOL& /*bHandled*/) | |
| 3255 { | |
| 3256 if(m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1) | |
| 3257 { | |
| 3258 LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; | |
| 3259 lpMMI->ptMinTrackSize = m_ptMinTrackSize; | |
| 3260 } | |
| 3261 return 0; | |
| 3262 } | |
| 3263 #endif // _WIN32_WCE | |
| 3264 | |
| 3265 // Implementation | |
| 3266 bool DlgResize_PositionControl(int cxWidth, int cyHeight, RECT& rectGrou
p, _AtlDlgResizeData& data, bool bGroup, | |
| 3267 _AtlDlgResizeData* pDataPrev = NULL) | |
| 3268 { | |
| 3269 T* pT = static_cast<T*>(this); | |
| 3270 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
| 3271 ATL::CWindow ctl; | |
| 3272 RECT rectCtl = { 0 }; | |
| 3273 | |
| 3274 ctl = pT->GetDlgItem(data.m_nCtlID); | |
| 3275 if(!ctl.GetWindowRect(&rectCtl)) | |
| 3276 return false; | |
| 3277 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2); | |
| 3278 | |
| 3279 if(bGroup) | |
| 3280 { | |
| 3281 if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0) | |
| 3282 { | |
| 3283 int cxRight = rectGroup.right + cxWidth - m_size
Dialog.cx; | |
| 3284 int cxCtl = data.m_rect.right - data.m_rect.left
; | |
| 3285 rectCtl.left = rectGroup.left + (cxRight - rectG
roup.left - cxCtl) / 2; | |
| 3286 rectCtl.right = rectCtl.left + cxCtl; | |
| 3287 } | |
| 3288 else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE
_X)) != 0) | |
| 3289 { | |
| 3290 rectCtl.left = rectGroup.left + ::MulDiv(data.m_
rect.left - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_size
Dialog.cx), rectGroup.right - rectGroup.left); | |
| 3291 | |
| 3292 if((data.m_dwResizeFlags & DLSZ_SIZE_X) != 0) | |
| 3293 { | |
| 3294 rectCtl.right = rectGroup.left + ::MulDi
v(data.m_rect.right - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidt
h - m_sizeDialog.cx), rectGroup.right - rectGroup.left); | |
| 3295 | |
| 3296 if(pDataPrev != NULL) | |
| 3297 { | |
| 3298 ATL::CWindow ctlPrev = pT->GetDl
gItem(pDataPrev->m_nCtlID); | |
| 3299 RECT rcPrev = { 0 }; | |
| 3300 ctlPrev.GetWindowRect(&rcPrev); | |
| 3301 ::MapWindowPoints(NULL, pT->m_hW
nd, (LPPOINT)&rcPrev, 2); | |
| 3302 int dxAdjust = (rectCtl.left - r
cPrev.right) - (data.m_rect.left - pDataPrev->m_rect.right); | |
| 3303 rcPrev.right += dxAdjust; | |
| 3304 ctlPrev.SetWindowPos(NULL, &rcPr
ev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); | |
| 3305 } | |
| 3306 } | |
| 3307 else | |
| 3308 { | |
| 3309 rectCtl.right = rectCtl.left + (data.m_r
ect.right - data.m_rect.left); | |
| 3310 } | |
| 3311 } | |
| 3312 | |
| 3313 if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0) | |
| 3314 { | |
| 3315 int cyBottom = rectGroup.bottom + cyHeight - m_s
izeDialog.cy; | |
| 3316 int cyCtl = data.m_rect.bottom - data.m_rect.top
; | |
| 3317 rectCtl.top = rectGroup.top + (cyBottom - rectGr
oup.top - cyCtl) / 2; | |
| 3318 rectCtl.bottom = rectCtl.top + cyCtl; | |
| 3319 } | |
| 3320 else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE
_Y)) != 0) | |
| 3321 { | |
| 3322 rectCtl.top = rectGroup.top + ::MulDiv(data.m_re
ct.top - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDia
log.cy), rectGroup.bottom - rectGroup.top); | |
| 3323 | |
| 3324 if((data.m_dwResizeFlags & DLSZ_SIZE_Y) != 0) | |
| 3325 { | |
| 3326 rectCtl.bottom = rectGroup.top + ::MulDi
v(data.m_rect.bottom - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeig
ht - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top); | |
| 3327 | |
| 3328 if(pDataPrev != NULL) | |
| 3329 { | |
| 3330 ATL::CWindow ctlPrev = pT->GetDl
gItem(pDataPrev->m_nCtlID); | |
| 3331 RECT rcPrev = { 0 }; | |
| 3332 ctlPrev.GetWindowRect(&rcPrev); | |
| 3333 ::MapWindowPoints(NULL, pT->m_hW
nd, (LPPOINT)&rcPrev, 2); | |
| 3334 int dxAdjust = (rectCtl.top - rc
Prev.bottom) - (data.m_rect.top - pDataPrev->m_rect.bottom); | |
| 3335 rcPrev.bottom += dxAdjust; | |
| 3336 ctlPrev.SetWindowPos(NULL, &rcPr
ev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); | |
| 3337 } | |
| 3338 } | |
| 3339 else | |
| 3340 { | |
| 3341 rectCtl.bottom = rectCtl.top + (data.m_r
ect.bottom - data.m_rect.top); | |
| 3342 } | |
| 3343 } | |
| 3344 } | |
| 3345 else // no group | |
| 3346 { | |
| 3347 if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0) | |
| 3348 { | |
| 3349 int cxCtl = data.m_rect.right - data.m_rect.left
; | |
| 3350 rectCtl.left = (cxWidth - cxCtl) / 2; | |
| 3351 rectCtl.right = rectCtl.left + cxCtl; | |
| 3352 } | |
| 3353 else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE
_X)) != 0) | |
| 3354 { | |
| 3355 rectCtl.right = data.m_rect.right + (cxWidth - m
_sizeDialog.cx); | |
| 3356 | |
| 3357 if((data.m_dwResizeFlags & DLSZ_MOVE_X) != 0) | |
| 3358 rectCtl.left = rectCtl.right - (data.m_r
ect.right - data.m_rect.left); | |
| 3359 } | |
| 3360 | |
| 3361 if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0) | |
| 3362 { | |
| 3363 int cyCtl = data.m_rect.bottom - data.m_rect.top
; | |
| 3364 rectCtl.top = (cyHeight - cyCtl) / 2; | |
| 3365 rectCtl.bottom = rectCtl.top + cyCtl; | |
| 3366 } | |
| 3367 else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE
_Y)) != 0) | |
| 3368 { | |
| 3369 rectCtl.bottom = data.m_rect.bottom + (cyHeight
- m_sizeDialog.cy); | |
| 3370 | |
| 3371 if((data.m_dwResizeFlags & DLSZ_MOVE_Y) != 0) | |
| 3372 rectCtl.top = rectCtl.bottom - (data.m_r
ect.bottom - data.m_rect.top); | |
| 3373 } | |
| 3374 } | |
| 3375 | |
| 3376 if((data.m_dwResizeFlags & DLSZ_REPAINT) != 0) | |
| 3377 ctl.Invalidate(); | |
| 3378 | |
| 3379 if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOV
E_X | DLSZ_MOVE_Y | DLSZ_REPAINT | DLSZ_CENTER_X | DLSZ_CENTER_Y)) != 0) | |
| 3380 ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOAC
TIVATE); | |
| 3381 | |
| 3382 return true; | |
| 3383 } | |
| 3384 }; | |
| 3385 | |
| 3386 | |
| 3387 /////////////////////////////////////////////////////////////////////////////// | |
| 3388 // CDoubleBufferImpl - Provides double-buffer painting support to any window | |
| 3389 | |
| 3390 template <class T> | |
| 3391 class CDoubleBufferImpl | |
| 3392 { | |
| 3393 public: | |
| 3394 // Overrideables | |
| 3395 void DoPaint(CDCHandle /*dc*/) | |
| 3396 { | |
| 3397 // must be implemented in a derived class | |
| 3398 ATLASSERT(FALSE); | |
| 3399 } | |
| 3400 | |
| 3401 // Message map and handlers | |
| 3402 BEGIN_MSG_MAP(CDoubleBufferImpl) | |
| 3403 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) | |
| 3404 MESSAGE_HANDLER(WM_PAINT, OnPaint) | |
| 3405 #ifndef _WIN32_WCE | |
| 3406 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) | |
| 3407 #endif // !_WIN32_WCE | |
| 3408 END_MSG_MAP() | |
| 3409 | |
| 3410 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPa
ram*/, BOOL& /*bHandled*/) | |
| 3411 { | |
| 3412 return 1; // no background painting needed | |
| 3413 } | |
| 3414 | |
| 3415 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /
*bHandled*/) | |
| 3416 { | |
| 3417 T* pT = static_cast<T*>(this); | |
| 3418 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
| 3419 | |
| 3420 if(wParam != NULL) | |
| 3421 { | |
| 3422 RECT rect = { 0 }; | |
| 3423 pT->GetClientRect(&rect); | |
| 3424 CMemoryDC dcMem((HDC)wParam, rect); | |
| 3425 pT->DoPaint(dcMem.m_hDC); | |
| 3426 } | |
| 3427 else | |
| 3428 { | |
| 3429 CPaintDC dc(pT->m_hWnd); | |
| 3430 CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint); | |
| 3431 pT->DoPaint(dcMem.m_hDC); | |
| 3432 } | |
| 3433 | |
| 3434 return 0; | |
| 3435 } | |
| 3436 }; | |
| 3437 | |
| 3438 | |
| 3439 /////////////////////////////////////////////////////////////////////////////// | |
| 3440 // CDoubleBufferWindowImpl - Implements a double-buffer painting window | |
| 3441 | |
| 3442 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlW
inTraits> | |
| 3443 class ATL_NO_VTABLE CDoubleBufferWindowImpl : public ATL::CWindowImpl< T, TBase,
TWinTraits >, public CDoubleBufferImpl< T > | |
| 3444 { | |
| 3445 public: | |
| 3446 BEGIN_MSG_MAP(CDoubleBufferWindowImpl) | |
| 3447 CHAIN_MSG_MAP(CDoubleBufferImpl< T >) | |
| 3448 END_MSG_MAP() | |
| 3449 }; | |
| 3450 | |
| 3451 | |
| 3452 // command bar support | |
| 3453 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) | |
| 3454 #undef CBRM_GETMENU | |
| 3455 #undef CBRM_TRACKPOPUPMENU | |
| 3456 #undef CBRM_GETCMDBAR | |
| 3457 #undef CBRPOPUPMENU | |
| 3458 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) | |
| 3459 | |
| 3460 }; // namespace WTL | |
| 3461 | |
| 3462 #endif // __ATLFRAME_H__ | |
| OLD | NEW |