Commit before breaking everything
[matches/honours.git] / research / transmission_spectroscopy / TOF / Win32++ / include / tab.h
1 // Win32++   Version 7.3\r
2 // Released: 30th November 2011\r
3 //\r
4 //      David Nash\r
5 //      email: [email protected]\r
6 //      url: https://sourceforge.net/projects/win32-framework\r
7 //\r
8 //\r
9 // Copyright (c) 2005-2011  David Nash\r
10 //\r
11 // Permission is hereby granted, free of charge, to\r
12 // any person obtaining a copy of this software and\r
13 // associated documentation files (the "Software"),\r
14 // to deal in the Software without restriction, including\r
15 // without limitation the rights to use, copy, modify,\r
16 // merge, publish, distribute, sublicense, and/or sell\r
17 // copies of the Software, and to permit persons to whom\r
18 // the Software is furnished to do so, subject to the\r
19 // following conditions:\r
20 //\r
21 // The above copyright notice and this permission notice\r
22 // shall be included in all copies or substantial portions\r
23 // of the Software.\r
24 //\r
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF\r
26 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\r
27 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\r
28 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\r
29 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
30 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
31 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
32 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\r
33 // OR OTHER DEALINGS IN THE SOFTWARE.\r
34 //\r
35 ////////////////////////////////////////////////////////\r
36 \r
37 \r
38 ///////////////////////////////////////////////////////\r
39 // tab.h\r
40 //  Declaration of the CTab and CMDITab classes\r
41 \r
42 #ifndef _WIN32XX_TAB_H_\r
43 #define _WIN32XX_TAB_H_\r
44 \r
45 #include "wincore.h"\r
46 #include "dialog.h"\r
47 #include "gdi.h"\r
48 #include "default_resource.h"\r
49 \r
50 namespace Win32xx\r
51 {\r
52 \r
53         struct TabPageInfo\r
54         {\r
55                 TCHAR szTabText[MAX_MENU_STRING];\r
56                 int iImage;                     // index of this tab's image\r
57                 int idTab;                      // identifier for this tab (optional)\r
58                 CWnd* pView;            // pointer to the view window\r
59         };\r
60 \r
61         class CTab : public CWnd\r
62         {\r
63         protected:\r
64                 // Declaration of the CSelectDialog class, a nested class of CTab\r
65                 // It creates the dialog to choose which tab to activate\r
66                 class CSelectDialog : public CDialog\r
67                 {\r
68                 public:\r
69                         CSelectDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent = NULL);\r
70                         virtual ~CSelectDialog() {}\r
71                         virtual void AddItem(LPCTSTR szString);\r
72                         virtual BOOL IsTab() const { return FALSE; }\r
73 \r
74                 protected:\r
75                         virtual BOOL OnInitDialog();\r
76                         virtual void OnOK();\r
77                         virtual void OnCancel() { EndDialog(-2); }\r
78 \r
79                 private:\r
80                         CSelectDialog(const CSelectDialog&);                            // Disable copy construction\r
81                         CSelectDialog& operator = (const CSelectDialog&); // Disable assignment operator\r
82 \r
83                         std::vector<CString> m_vItems;\r
84                         int IDC_LIST;\r
85 \r
86                 };\r
87         public:\r
88                 CTab();\r
89                 virtual ~CTab();\r
90                 virtual int  AddTabPage(WndPtr pView, LPCTSTR szTabText, HICON hIcon, UINT idTab);\r
91                 virtual int  AddTabPage(WndPtr pView, LPCTSTR szTabText, int nID_Icon, UINT idTab = 0);\r
92                 virtual int  AddTabPage(WndPtr pView, LPCTSTR szTabText);\r
93                 virtual CRect GetCloseRect() const;\r
94                 virtual CRect GetListRect() const;\r
95                 virtual HMENU GetListMenu();\r
96                 virtual BOOL GetTabsAtTop() const;\r
97                 virtual int  GetTabIndex(CWnd* pWnd) const;\r
98                 virtual TabPageInfo GetTabPageInfo(UINT nTab) const;\r
99                 virtual int GetTextHeight() const;\r
100                 virtual void RecalcLayout();\r
101                 virtual void RemoveTabPage(int nPage);\r
102                 virtual void SelectPage(int nPage);\r
103                 virtual void SetFixedWidth(BOOL bEnabled);\r
104                 virtual void SetOwnerDraw(BOOL bEnabled);\r
105                 virtual void SetShowButtons(BOOL bShow);\r
106                 virtual void SetTabIcon(int i, HICON hIcon);\r
107                 virtual void SetTabsAtTop(BOOL bTop);\r
108                 virtual void SetTabText(UINT nTab, LPCTSTR szText);\r
109                 virtual void SwapTabs(UINT nTab1, UINT nTab2);\r
110 \r
111                 // Attributes\r
112                 std::vector <TabPageInfo>& GetAllTabs() const { return (std::vector <TabPageInfo>&) m_vTabPageInfo; }\r
113                 HIMAGELIST GetImageList() const { return m_himlTab; }\r
114                 BOOL GetShowButtons() const { return m_bShowButtons; }\r
115                 int GetTabHeight() const { return m_nTabHeight; }\r
116                 CWnd* GetActiveView() const             { return m_pActiveView; }\r
117                 void SetTabHeight(int nTabHeight) { m_nTabHeight = nTabHeight; NotifyChanged();}\r
118 \r
119                 // Wrappers for Win32 Macros\r
120                 void AdjustRect(BOOL fLarger, RECT *prc) const;\r
121                 int  GetCurFocus() const;\r
122                 int  GetCurSel() const;\r
123                 BOOL GetItem(int iItem, LPTCITEM pitem) const;\r
124                 int  GetItemCount() const;\r
125                 int  HitTest(TCHITTESTINFO& info) const;\r
126                 void SetCurFocus(int iItem) const;\r
127                 int  SetCurSel(int iItem) const;\r
128                 DWORD SetItemSize(int cx, int cy) const;\r
129                 int  SetMinTabWidth(int cx) const;\r
130                 void SetPadding(int cx, int cy) const;\r
131 \r
132         protected:\r
133                 virtual void    DrawCloseButton(CDC& DrawDC);\r
134                 virtual void    DrawListButton(CDC& DrawDC);\r
135                 virtual void    DrawTabs(CDC& dcMem);\r
136                 virtual void    DrawTabBorders(CDC& dcMem, CRect& rcTab);\r
137                 virtual void    OnCreate();\r
138                 virtual void    OnLButtonDown(WPARAM wParam, LPARAM lParam);\r
139                 virtual void    OnLButtonUp(WPARAM wParam, LPARAM lParam);\r
140                 virtual void    OnMouseLeave(WPARAM wParam, LPARAM lParam);\r
141                 virtual void    OnMouseMove(WPARAM wParam, LPARAM lParam);\r
142                 virtual LRESULT OnNCHitTest(WPARAM wParam, LPARAM lParam);\r
143                 virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);\r
144                 virtual void    NotifyChanged();\r
145                 virtual void    Paint();\r
146                 virtual void    PreCreate(CREATESTRUCT& cs);\r
147                 virtual void    PreRegisterClass(WNDCLASS &wc);\r
148                 virtual void    SetTabSize();\r
149                 virtual void    ShowListDialog();\r
150                 virtual void    ShowListMenu();\r
151                 virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
152 \r
153         private:\r
154                 CTab(const CTab&);                              // Disable copy construction\r
155                 CTab& operator = (const CTab&); // Disable assignment operator\r
156 \r
157                 SIZE  GetMaxTabSize() const;\r
158                 void ShowActiveView(CWnd* pView);\r
159 \r
160                 std::vector<TabPageInfo> m_vTabPageInfo;\r
161                 std::vector<WndPtr> m_vTabViews;\r
162                 CFont m_Font;\r
163                 HIMAGELIST m_himlTab;\r
164                 HMENU m_hListMenu;\r
165                 CWnd* m_pActiveView;\r
166                 BOOL m_bShowButtons;    // Show or hide the close and list button\r
167                 BOOL m_IsTracking;\r
168                 BOOL m_IsClosePressed;\r
169                 BOOL m_IsListPressed;\r
170                 BOOL m_IsListMenuActive;\r
171                 int m_nTabHeight;\r
172         };\r
173 \r
174         ////////////////////////////////////////\r
175         // Declaration of the CTabbedMDI class\r
176         class CTabbedMDI : public CWnd\r
177         {\r
178         public:\r
179                 CTabbedMDI();\r
180                 virtual ~CTabbedMDI();\r
181                 virtual CWnd* AddMDIChild(CWnd* pView, LPCTSTR szTabText, int idMDIChild = 0);\r
182                 virtual void  CloseActiveMDI();\r
183                 virtual void  CloseAllMDIChildren();\r
184                 virtual void  CloseMDIChild(int nTab);\r
185                 virtual CWnd* GetActiveMDIChild() const;\r
186                 virtual int       GetActiveMDITab() const;\r
187                 virtual CWnd* GetMDIChild(int nTab) const;\r
188                 virtual int   GetMDIChildCount() const;\r
189                 virtual int   GetMDIChildID(int nTab) const;\r
190                 virtual LPCTSTR GetMDIChildTitle(int nTab) const;\r
191                 virtual HMENU GetListMenu() const { return GetTab().GetListMenu(); }\r
192                 virtual CTab& GetTab() const    {return (CTab&)m_Tab;}\r
193                 virtual BOOL LoadRegistrySettings(CString strRegistryKeyName);\r
194                 virtual void RecalcLayout();\r
195                 virtual BOOL SaveRegistrySettings(CString strRegistryKeyName);\r
196                 virtual void SetActiveMDIChild(CWnd* pWnd);\r
197                 virtual void SetActiveMDITab(int nTab);\r
198 \r
199         protected:\r
200                 virtual HWND    Create(CWnd* pParent);\r
201                 virtual CWnd*   NewMDIChildFromID(int idMDIChild);\r
202                 virtual void    OnCreate();\r
203                 virtual void    OnDestroy(WPARAM wParam, LPARAM lParam);\r
204                 virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);\r
205                 virtual void    OnWindowPosChanged(WPARAM wParam, LPARAM lParam);\r
206                 virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
207 \r
208         private:\r
209                 CTabbedMDI(const CTabbedMDI&);                          // Disable copy construction\r
210                 CTabbedMDI& operator = (const CTabbedMDI&); // Disable assignment operator\r
211 \r
212                 CTab m_Tab;\r
213         };\r
214 \r
215 }\r
216 \r
217 \r
218 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
219 \r
220 \r
221 namespace Win32xx\r
222 {\r
223 \r
224         /////////////////////////////////////////////////////////////\r
225         // Definitions for the CSelectDialog class nested within CTab\r
226         //\r
227         inline CTab::CSelectDialog::CSelectDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent) :\r
228                                         CDialog(lpTemplate, pParent), IDC_LIST(121)\r
229         {\r
230         }\r
231 \r
232         inline BOOL CTab::CSelectDialog::OnInitDialog()\r
233         {\r
234                 for (UINT u = 0; u < m_vItems.size(); ++u)\r
235                 {\r
236                         SendDlgItemMessage(IDC_LIST, LB_ADDSTRING, 0, (LPARAM) m_vItems[u].c_str());\r
237                 }\r
238 \r
239                 return true;\r
240         }\r
241 \r
242         inline void CTab::CSelectDialog::AddItem(LPCTSTR szString)\r
243         {\r
244                 m_vItems.push_back(szString);\r
245         }\r
246 \r
247         inline void CTab::CSelectDialog::OnOK()\r
248         {\r
249                 int iSelect = (int)SendDlgItemMessage(IDC_LIST, LB_GETCURSEL, 0, 0);\r
250                 if (iSelect != LB_ERR) \r
251                         EndDialog(iSelect);\r
252                 else\r
253                         EndDialog(-2);\r
254         }\r
255 \r
256 \r
257         //////////////////////////////////////////////////////////\r
258         // Definitions for the CTab class\r
259         //\r
260         inline CTab::CTab() : m_hListMenu(NULL), m_pActiveView(NULL), m_bShowButtons(FALSE), m_IsTracking(FALSE), m_IsClosePressed(FALSE),\r
261                                                         m_IsListPressed(FALSE), m_IsListMenuActive(FALSE), m_nTabHeight(0)\r
262         {\r
263                 // Create and assign the image list\r
264                 m_himlTab = ImageList_Create(16, 16, ILC_MASK|ILC_COLOR32, 0, 0);\r
265 \r
266                 // Set the tab control's font\r
267                 NONCLIENTMETRICS info = {0};\r
268                 info.cbSize = GetSizeofNonClientMetrics();\r
269                 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);\r
270                 m_Font.CreateFontIndirect(&info.lfStatusFont);\r
271         }\r
272 \r
273         inline CTab::~CTab()\r
274         {\r
275                 ImageList_Destroy(m_himlTab);\r
276                 \r
277                 if (IsMenu(m_hListMenu)) ::DestroyMenu(m_hListMenu);\r
278         }\r
279 \r
280         inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText, HICON hIcon, UINT idTab)\r
281         {\r
282                 assert(pView.get());\r
283                 assert(lstrlen(szTabText) < MAX_MENU_STRING);\r
284 \r
285                 m_vTabViews.push_back(pView);\r
286 \r
287                 TabPageInfo tpi = {0};\r
288                 tpi.pView = pView.get();\r
289                 tpi.idTab = idTab;\r
290                 lstrcpyn(tpi.szTabText, szTabText, MAX_MENU_STRING);\r
291                 if (hIcon)\r
292                         tpi.iImage = ImageList_AddIcon(GetImageList(), hIcon);\r
293                 else\r
294                         tpi.iImage = -1;\r
295 \r
296                 int iNewPage = (int)m_vTabPageInfo.size();\r
297                 m_vTabPageInfo.push_back(tpi);\r
298 \r
299                 if (m_hWnd)\r
300                 {\r
301                         TCITEM tie = {0};\r
302                         tie.mask = TCIF_TEXT | TCIF_IMAGE;\r
303                         tie.iImage = tpi.iImage;\r
304                         tie.pszText = tpi.szTabText;\r
305                         TabCtrl_InsertItem(m_hWnd, iNewPage, &tie);\r
306 \r
307                         SetTabSize();\r
308                         SelectPage(iNewPage);\r
309                         NotifyChanged();\r
310                 }\r
311 \r
312                 return iNewPage;\r
313         }\r
314 \r
315         inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText, int idIcon, UINT idTab /* = 0*/)\r
316         {\r
317                 HICON hIcon = (HICON)LoadImage(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(idIcon), IMAGE_ICON, 0, 0, LR_SHARED);\r
318                 return AddTabPage(pView, szTabText, hIcon, idTab);\r
319         }\r
320 \r
321         inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText)\r
322         {\r
323                 return AddTabPage(pView, szTabText, (HICON)0, 0);\r
324         }\r
325 \r
326         inline void CTab::DrawCloseButton(CDC& DrawDC)\r
327         {\r
328                 // The close button isn't displayed on Win95\r
329                 if (GetWinVersion() == 1400)  return;\r
330 \r
331                 if (!m_bShowButtons) return;\r
332                 if (!GetActiveView()) return;\r
333                 if (!(GetWindowLongPtr(GWL_STYLE) & TCS_FIXEDWIDTH)) return;\r
334                 if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)) return;\r
335 \r
336                 // Determine the close button's drawing position relative to the window\r
337                 CRect rcClose = GetCloseRect();\r
338 \r
339                 CPoint pt = GetCursorPos();\r
340                 ScreenToClient(pt);\r
341                 UINT uState = rcClose.PtInRect(pt)? m_IsClosePressed? 2: 1: 0;\r
342 \r
343                 // Draw the outer highlight for the close button\r
344                 if (!IsRectEmpty(&rcClose))\r
345                 {\r
346                         switch (uState)\r
347                         {\r
348                         case 0:\r
349                                 {\r
350                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));\r
351 \r
352                                         DrawDC.MoveTo(rcClose.left, rcClose.bottom);\r
353                                         DrawDC.LineTo(rcClose.right, rcClose.bottom);\r
354                                         DrawDC.LineTo(rcClose.right, rcClose.top);\r
355                                         DrawDC.LineTo(rcClose.left, rcClose.top);\r
356                                         DrawDC.LineTo(rcClose.left, rcClose.bottom);\r
357                                         break;\r
358                                 }\r
359 \r
360                         case 1:\r
361                                 {\r
362                                         // Draw outline, white at top, black on bottom\r
363                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));\r
364                                         DrawDC.MoveTo(rcClose.left, rcClose.bottom);\r
365                                         DrawDC.LineTo(rcClose.right, rcClose.bottom);\r
366                                         DrawDC.LineTo(rcClose.right, rcClose.top);\r
367                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
368                                         DrawDC.LineTo(rcClose.left, rcClose.top);\r
369                                         DrawDC.LineTo(rcClose.left, rcClose.bottom);\r
370                                 }\r
371 \r
372                                 break;\r
373                         case 2:\r
374                                 {\r
375                                         // Draw outline, black on top, white on bottom\r
376                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
377                                         DrawDC.MoveTo(rcClose.left, rcClose.bottom);\r
378                                         DrawDC.LineTo(rcClose.right, rcClose.bottom);\r
379                                         DrawDC.LineTo(rcClose.right, rcClose.top);\r
380                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));\r
381                                         DrawDC.LineTo(rcClose.left, rcClose.top);\r
382                                         DrawDC.LineTo(rcClose.left, rcClose.bottom);\r
383                                 }\r
384                                 break;\r
385                         }\r
386 \r
387                         // Manually draw close button\r
388                         DrawDC.CreatePen(PS_SOLID, 1, RGB(64, 64, 64));\r
389 \r
390                         DrawDC.MoveTo(rcClose.left + 3, rcClose.top +3);\r
391                         DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -2);\r
392 \r
393                         DrawDC.MoveTo(rcClose.left + 4, rcClose.top +3);\r
394                         DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -3);\r
395 \r
396                         DrawDC.MoveTo(rcClose.left + 3, rcClose.top +4);\r
397                         DrawDC.LineTo(rcClose.right - 3, rcClose.bottom -2);\r
398 \r
399                         DrawDC.MoveTo(rcClose.right -3, rcClose.top +3);\r
400                         DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -2);\r
401 \r
402                         DrawDC.MoveTo(rcClose.right -3, rcClose.top +4);\r
403                         DrawDC.LineTo(rcClose.left + 3, rcClose.bottom -2);\r
404 \r
405                         DrawDC.MoveTo(rcClose.right -4, rcClose.top +3);\r
406                         DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -3);\r
407                 }\r
408         }\r
409 \r
410         inline void CTab::DrawListButton(CDC& DrawDC)\r
411         {\r
412                 // The list button isn't displayed on Win95\r
413                 if (GetWinVersion() == 1400)  return;\r
414 \r
415                 if (!m_bShowButtons) return;\r
416                 if (!GetActiveView()) return;\r
417                 if (!(GetWindowLongPtr(GWL_STYLE) & TCS_FIXEDWIDTH)) return;\r
418                 if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)) return;\r
419 \r
420                 // Determine the list button's drawing position relative to the window\r
421                 CRect rcList = GetListRect();\r
422 \r
423                 CPoint pt = GetCursorPos();\r
424                 ScreenToClient(pt);\r
425                 UINT uState = rcList.PtInRect(pt)? 1: 0;\r
426                 if (m_IsListMenuActive) uState = 2;\r
427 \r
428                 // Draw the outer highlight for the list button\r
429                 if (!IsRectEmpty(&rcList))\r
430                 {\r
431                         switch (uState)\r
432                         {\r
433                         case 0:\r
434                                 {\r
435                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));\r
436 \r
437                                         DrawDC.MoveTo(rcList.left, rcList.bottom);\r
438                                         DrawDC.LineTo(rcList.right, rcList.bottom);\r
439                                         DrawDC.LineTo(rcList.right, rcList.top);\r
440                                         DrawDC.LineTo(rcList.left, rcList.top);\r
441                                         DrawDC.LineTo(rcList.left, rcList.bottom);\r
442                                         break;\r
443                                 }\r
444 \r
445                         case 1:\r
446                                 {\r
447                                         // Draw outline, white at top, black on bottom\r
448                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));\r
449                                         DrawDC.MoveTo(rcList.left, rcList.bottom);\r
450                                         DrawDC.LineTo(rcList.right, rcList.bottom);\r
451                                         DrawDC.LineTo(rcList.right, rcList.top);\r
452                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
453                                         DrawDC.LineTo(rcList.left, rcList.top);\r
454                                         DrawDC.LineTo(rcList.left, rcList.bottom);\r
455                                 }\r
456 \r
457                                 break;\r
458                         case 2:\r
459                                 {\r
460                                         // Draw outline, black on top, white on bottom\r
461                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
462                                         DrawDC.MoveTo(rcList.left, rcList.bottom);\r
463                                         DrawDC.LineTo(rcList.right, rcList.bottom);\r
464                                         DrawDC.LineTo(rcList.right, rcList.top);\r
465                                         DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));\r
466                                         DrawDC.LineTo(rcList.left, rcList.top);\r
467                                         DrawDC.LineTo(rcList.left, rcList.bottom);\r
468                                 }\r
469                                 break;\r
470                         }\r
471 \r
472                         // Manually draw list button\r
473                         DrawDC.CreatePen(PS_SOLID, 1, RGB(64, 64, 64));\r
474 \r
475                         int MaxLength = (int)(0.65 * rcList.Width());\r
476                         int topGap = 1 + rcList.Height()/3;\r
477                         for (int i = 0; i <= MaxLength/2; i++)\r
478                         {\r
479                                 int Length = MaxLength - 2*i;\r
480                                 DrawDC.MoveTo(rcList.left +1 + (rcList.Width() - Length)/2, rcList.top +topGap +i);\r
481                                 DrawDC.LineTo(rcList.left +1 + (rcList.Width() - Length)/2 + Length, rcList.top +topGap +i);\r
482                         }\r
483                 }\r
484         }\r
485 \r
486         inline void CTab::DrawTabs(CDC& dcMem)\r
487         {\r
488                 // Draw the tab buttons:\r
489                 for (int i = 0; i < TabCtrl_GetItemCount(m_hWnd); ++i)\r
490                 {\r
491                         CRect rcItem;\r
492                         TabCtrl_GetItemRect(m_hWnd, i, &rcItem);\r
493                         if (!rcItem.IsRectEmpty())\r
494                         {\r
495                                 if (i == TabCtrl_GetCurSel(m_hWnd))\r
496                                 {\r
497                                         dcMem.CreateSolidBrush(RGB(248,248,248));\r
498                                         dcMem.SetBkColor(RGB(248,248,248));\r
499                                 }\r
500                                 else\r
501                                 {\r
502                                         dcMem.CreateSolidBrush(RGB(200,200,200));\r
503                                         dcMem.SetBkColor(RGB(200,200,200));\r
504                                 }\r
505 \r
506                                 dcMem.CreatePen(PS_SOLID, 1, RGB(160, 160, 160));\r
507                                 dcMem.RoundRect(rcItem.left+1, rcItem.top, rcItem.right+2, rcItem.bottom, 6, 6);\r
508 \r
509                                 if (rcItem.Width() >= 24)\r
510                                 {\r
511                                         TCHAR szText[30];\r
512                                         TCITEM tcItem = {0};\r
513                                         tcItem.mask = TCIF_TEXT | TCIF_IMAGE;\r
514                                         tcItem.cchTextMax = 30;\r
515                                         tcItem.pszText = szText;\r
516                                         TabCtrl_GetItem(m_hWnd, i, &tcItem);\r
517                                         int xImage;\r
518                                         int yImage;\r
519                                         int yOffset = 0;\r
520                                         if (ImageList_GetIconSize(m_himlTab, &xImage, &yImage))\r
521                                                 yOffset = (rcItem.Height() - yImage)/2;\r
522 \r
523                                         // Draw the icon\r
524                                         ImageList_Draw(m_himlTab, tcItem.iImage, dcMem, rcItem.left+5, rcItem.top+yOffset, ILD_NORMAL);\r
525 \r
526                                         // Draw the text\r
527                                         ::SelectObject(dcMem, m_Font);\r
528 \r
529                                         // Calculate the size of the text\r
530                                         CRect rcText = rcItem;\r
531 \r
532                                         int iImageSize = 20;\r
533                                         int iPadding = 4;\r
534                                         if (tcItem.iImage >= 0)\r
535                                                 rcText.left += iImageSize;\r
536 \r
537                                         rcText.left += iPadding;\r
538                                         dcMem.DrawText(szText, -1, rcText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);\r
539                                 }\r
540                         }\r
541                 }\r
542         }\r
543 \r
544         inline void CTab::DrawTabBorders(CDC& dcMem, CRect& rcTab)\r
545         {\r
546                 BOOL IsBottomTab = (BOOL)GetWindowLongPtr(GWL_STYLE) & TCS_BOTTOM;\r
547 \r
548                 // Draw a lighter rectangle touching the tab buttons\r
549                 CRect rcItem;\r
550                 TabCtrl_GetItemRect(m_hWnd, 0, &rcItem);\r
551                 int left = rcItem.left +1;\r
552                 int right = rcTab.right;\r
553                 int top = rcTab.bottom;\r
554                 int bottom = top + 3;\r
555 \r
556                 if (!IsBottomTab)\r
557                 {\r
558                         bottom = MAX(rcTab.top, m_nTabHeight +4);\r
559                         top = bottom -3;\r
560                 }\r
561 \r
562                 dcMem.CreateSolidBrush(RGB(248,248,248));\r
563                 dcMem.CreatePen(PS_SOLID, 1, RGB(248,248,248));\r
564                 if (!rcItem.IsRectEmpty())\r
565                 {\r
566                         dcMem.Rectangle(left, top, right, bottom);\r
567 \r
568                         // Draw a darker line below the rectangle\r
569                         dcMem.CreatePen(PS_SOLID, 1, RGB(160, 160, 160));\r
570                         if (IsBottomTab)\r
571                         {\r
572                                 dcMem.MoveTo(left-1, bottom);\r
573                                 dcMem.LineTo(right, bottom);\r
574                         }\r
575                         else\r
576                         {\r
577                                 dcMem.MoveTo(left-1, top-1);\r
578                                 dcMem.LineTo(right, top-1);\r
579                         }\r
580 \r
581                         // Draw a lighter line over the darker line for the selected tab\r
582                         dcMem.CreatePen(PS_SOLID, 1, RGB(248,248,248));\r
583                         TabCtrl_GetItemRect(m_hWnd, TabCtrl_GetCurSel(m_hWnd), &rcItem);\r
584                         OffsetRect(&rcItem, 1, 1);\r
585 \r
586                         if (IsBottomTab)\r
587                         {\r
588                                 dcMem.MoveTo(rcItem.left, bottom);\r
589                                 dcMem.LineTo(rcItem.right, bottom);\r
590                         }\r
591                         else\r
592                         {\r
593                                 dcMem.MoveTo(rcItem.left, top-1);\r
594                                 dcMem.LineTo(rcItem.right, top-1);\r
595                         }\r
596                 }\r
597         }\r
598 \r
599         inline CRect CTab::GetCloseRect() const\r
600         {\r
601                 CRect rcClose;\r
602                 if (GetShowButtons())\r
603                 {\r
604                         rcClose= GetClientRect();\r
605                         int Gap = 2;\r
606                         int cx = GetSystemMetrics(SM_CXSMICON) -1;\r
607                         int cy = GetSystemMetrics(SM_CYSMICON) -1;\r
608                         rcClose.right -= Gap;\r
609                         rcClose.left = rcClose.right - cx;\r
610 \r
611                         if (GetTabsAtTop())\r
612                                 rcClose.top = Gap;\r
613                         else\r
614                                 rcClose.top = MAX(Gap, rcClose.bottom - m_nTabHeight);\r
615 \r
616                         rcClose.bottom = rcClose.top + cy;\r
617                 }\r
618                 return rcClose;\r
619         }\r
620 \r
621         inline HMENU CTab::GetListMenu()\r
622         {\r
623                 if (IsMenu(m_hListMenu))\r
624                         ::DestroyMenu(m_hListMenu);\r
625                 \r
626                 m_hListMenu = CreatePopupMenu();\r
627 \r
628                 // Add the menu items\r
629                 for(UINT u = 0; u < MIN(GetAllTabs().size(), 9); ++u)\r
630                 {\r
631                         TCHAR szMenuString[MAX_MENU_STRING+1];\r
632                         TCHAR szTabText[MAX_MENU_STRING];\r
633                         lstrcpyn(szTabText, GetAllTabs()[u].szTabText, MAX_MENU_STRING -4);\r
634                         wsprintf(szMenuString, _T("&%d %s"), u+1, szTabText);\r
635                         AppendMenu(m_hListMenu, MF_STRING, IDW_FIRSTCHILD +u, szMenuString);\r
636                 }\r
637                 if (GetAllTabs().size() >= 10)\r
638                         AppendMenu(m_hListMenu, MF_STRING, IDW_FIRSTCHILD +9, _T("More Windows"));\r
639 \r
640                 // Add a checkmark to the menu\r
641                 int iSelected = GetCurSel();\r
642                 if (iSelected < 9)\r
643                         CheckMenuItem(m_hListMenu, iSelected, MF_BYPOSITION|MF_CHECKED);\r
644 \r
645                 return m_hListMenu;\r
646         }\r
647 \r
648         inline CRect CTab::GetListRect() const\r
649         {\r
650                 CRect rcList;\r
651                 if (GetShowButtons())\r
652                 {\r
653                         CRect rcClose = GetCloseRect();\r
654                         rcList = rcClose;\r
655                         rcList.OffsetRect( -(rcClose.Width() + 2), 0);\r
656                         rcList.InflateRect(-1, 0);\r
657                 }\r
658                 return rcList;\r
659         }\r
660 \r
661         inline SIZE CTab::GetMaxTabSize() const\r
662         {\r
663                 CSize Size;\r
664 \r
665                 for (int i = 0; i < TabCtrl_GetItemCount(m_hWnd); i++)\r
666                 {\r
667                         CClientDC dcClient(this);\r
668                         ::SelectObject(dcClient, m_Font);\r
669                         std::vector<TCHAR> vTitle(MAX_MENU_STRING, _T('\0'));\r
670                         TCHAR* pszTitle = &vTitle.front();\r
671                         TCITEM tcItem = {0};\r
672                         tcItem.mask = TCIF_TEXT |TCIF_IMAGE;\r
673                         tcItem.cchTextMax = MAX_MENU_STRING;\r
674                         tcItem.pszText = pszTitle;\r
675                         TabCtrl_GetItem(m_hWnd, i, &tcItem);\r
676                         CSize TempSize = dcClient.GetTextExtentPoint32(pszTitle, lstrlen(pszTitle));\r
677 \r
678                         int iImageSize = 0;\r
679                         int iPadding = 6;\r
680                         if (tcItem.iImage >= 0)\r
681                                 iImageSize = 20;\r
682                         TempSize.cx += iImageSize + iPadding;\r
683 \r
684                         if (TempSize.cx > Size.cx)\r
685                                 Size = TempSize;\r
686                 }\r
687 \r
688                 return Size;\r
689         }\r
690 \r
691         inline BOOL CTab::GetTabsAtTop() const\r
692         // Returns TRUE if the contol's tabs are placed at the top\r
693         {\r
694                 DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);\r
695                 return (!(dwStyle & TCS_BOTTOM));\r
696         }\r
697 \r
698         inline int CTab::GetTextHeight() const\r
699         {\r
700                 CClientDC dcClient(this);\r
701                 ::SelectObject(dcClient, m_Font);\r
702                 CSize szText = dcClient.GetTextExtentPoint32(_T("Text"), lstrlen(_T("Text")));\r
703                 return szText.cy;\r
704         }\r
705 \r
706         inline int CTab::GetTabIndex(CWnd* pWnd) const\r
707         {\r
708                 assert(pWnd);\r
709 \r
710                 for (int i = 0; i < (int)m_vTabPageInfo.size(); ++i)\r
711                 {\r
712                         if (m_vTabPageInfo[i].pView == pWnd)\r
713                                 return i;\r
714                 }\r
715 \r
716                 return -1;\r
717         }\r
718 \r
719         inline TabPageInfo CTab::GetTabPageInfo(UINT nTab) const\r
720         {\r
721                 assert (nTab < m_vTabPageInfo.size());\r
722 \r
723                 return m_vTabPageInfo[nTab];\r
724         }\r
725 \r
726         inline void CTab::NotifyChanged()\r
727         {\r
728                 NMHDR nmhdr = {0};\r
729                 nmhdr.hwndFrom = m_hWnd;\r
730                 nmhdr.code = UWM_TAB_CHANGED;\r
731                 GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&nmhdr);\r
732         }\r
733 \r
734         inline void CTab::OnCreate()\r
735         {\r
736                 SetFont(&m_Font, TRUE);\r
737                 \r
738                 // Assign ImageList unless we are owner drawn\r
739                 if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED))\r
740                         TabCtrl_SetImageList(m_hWnd, m_himlTab);\r
741 \r
742                 for (int i = 0; i < (int)m_vTabPageInfo.size(); ++i)\r
743                 {\r
744                         // Add tabs for each view.\r
745                         TCITEM tie = {0};\r
746                         tie.mask = TCIF_TEXT | TCIF_IMAGE;\r
747                         tie.iImage = m_vTabPageInfo[i].iImage;\r
748                         tie.pszText = m_vTabPageInfo[i].szTabText;\r
749                         TabCtrl_InsertItem(m_hWnd, i, &tie);\r
750                 }\r
751 \r
752                 int HeightGap = 5;\r
753                 SetTabHeight(MAX(20, (GetTextHeight() + HeightGap)));\r
754                 SelectPage(0);\r
755         }\r
756 \r
757         inline void CTab::OnLButtonDown(WPARAM /*wParam*/, LPARAM lParam)\r
758         {\r
759                 CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));\r
760 \r
761                 if (GetCloseRect().PtInRect(pt))\r
762                 {\r
763                         m_IsClosePressed = TRUE;\r
764                         SetCapture();\r
765                         CClientDC dc(this);\r
766                         DrawCloseButton(dc);\r
767                 }\r
768                 else\r
769                         m_IsClosePressed = FALSE;\r
770 \r
771                 if (GetListRect().PtInRect(pt))\r
772                 {\r
773                         ShowListMenu();\r
774                 }\r
775         }\r
776 \r
777         inline void CTab::OnLButtonUp(WPARAM /*wParam*/, LPARAM lParam)\r
778         {\r
779                 ReleaseCapture();\r
780                 CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));\r
781                 if (m_IsClosePressed && GetCloseRect().PtInRect(pt))\r
782                 {\r
783                         RemoveTabPage(GetCurSel());\r
784                         if (GetActiveView())\r
785                                 GetActiveView()->RedrawWindow();\r
786                 }\r
787 \r
788                 m_IsClosePressed = FALSE;\r
789         }\r
790 \r
791         inline void CTab::OnMouseLeave(WPARAM /*wParam*/, LPARAM /*lParam*/)\r
792         {\r
793                 CClientDC dc(this);\r
794                 DrawCloseButton(dc);\r
795                 DrawListButton(dc);\r
796 \r
797                 m_IsTracking = FALSE;\r
798         }\r
799 \r
800         inline void CTab::OnMouseMove(WPARAM /*wParam*/, LPARAM /*lParam*/)\r
801         {\r
802                 if (!m_IsListMenuActive && m_IsListPressed)\r
803                 {\r
804                         m_IsListPressed = FALSE;\r
805                 }\r
806 \r
807                 if (!m_IsTracking)\r
808                 {\r
809                         TRACKMOUSEEVENT TrackMouseEventStruct = {0};\r
810                         TrackMouseEventStruct.cbSize = sizeof(TrackMouseEventStruct);\r
811                         TrackMouseEventStruct.dwFlags = TME_LEAVE;\r
812                         TrackMouseEventStruct.hwndTrack = m_hWnd;\r
813                         _TrackMouseEvent(&TrackMouseEventStruct);\r
814                         m_IsTracking = TRUE;\r
815                 }\r
816 \r
817                 CClientDC dc(this);\r
818                 DrawCloseButton(dc);\r
819                 DrawListButton(dc);\r
820         }\r
821 \r
822         inline LRESULT CTab::OnNCHitTest(WPARAM wParam, LPARAM lParam)\r
823         {\r
824                 // Ensure we have an arrow cursor when the tab has no view window\r
825                 if (0 == GetAllTabs().size())\r
826                         SetCursor(LoadCursor(NULL, IDC_ARROW));\r
827 \r
828                 // Cause WM_LBUTTONUP and WM_LBUTTONDOWN messages to be sent for buttons\r
829                 CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));\r
830                 ScreenToClient(pt);\r
831                 if (GetCloseRect().PtInRect(pt)) return HTCLIENT;\r
832                 if (GetListRect().PtInRect(pt))  return HTCLIENT;\r
833 \r
834                 return CWnd::WndProcDefault(WM_NCHITTEST, wParam, lParam);\r
835         }\r
836 \r
837         inline LRESULT CTab::OnNotifyReflect(WPARAM wParam, LPARAM lParam)\r
838         {\r
839                 UNREFERENCED_PARAMETER(wParam);\r
840 \r
841                 switch (((LPNMHDR)lParam)->code)\r
842                 {\r
843                 case TCN_SELCHANGE:\r
844                         {\r
845                                 // Display the newly selected tab page\r
846                                 int nPage = GetCurSel();\r
847                                 ShowActiveView(m_vTabPageInfo[nPage].pView);\r
848                         }\r
849                         break;\r
850                 }\r
851 \r
852                 return 0L;\r
853         }\r
854 \r
855         inline void CTab::Paint()\r
856         {\r
857                 // Microsoft's drawing for a tab control is rubbish, so we do our own.\r
858                 // We use double buffering and regions to eliminate flicker\r
859 \r
860                 // Create the memory DC and bitmap\r
861                 CClientDC dcView(this);\r
862                 CMemDC dcMem(&dcView);\r
863                 CRect rcClient = GetClientRect();\r
864                 dcMem.CreateCompatibleBitmap(&dcView, rcClient.Width(), rcClient.Height());\r
865 \r
866                 if (0 == GetItemCount())\r
867                 {\r
868                         // No tabs, so simply display a grey background and exit\r
869                         COLORREF rgbDialog = GetSysColor(COLOR_BTNFACE);\r
870                         dcView.SolidFill(rgbDialog, rcClient);\r
871                         return;\r
872                 }\r
873 \r
874                 // Create a clipping region. Its the overall tab window's region,\r
875                 //  less the region belonging to the individual tab view's client area\r
876                 CRgn rgnSrc1 = ::CreateRectRgn(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);\r
877                 CRect rcTab = GetClientRect();\r
878                 TabCtrl_AdjustRect(m_hWnd, FALSE, &rcTab);\r
879                 if (rcTab.Height() < 0)\r
880                         rcTab.top = rcTab.bottom;\r
881                 if (rcTab.Width() < 0)\r
882                         rcTab.left = rcTab.right;\r
883 \r
884                 CRgn rgnSrc2 = ::CreateRectRgn(rcTab.left, rcTab.top, rcTab.right, rcTab.bottom);\r
885                 CRgn rgnClip = ::CreateRectRgn(0, 0, 0, 0);\r
886                 ::CombineRgn(rgnClip, rgnSrc1, rgnSrc2, RGN_DIFF);\r
887 \r
888                 // Use the region in the memory DC to paint the grey background\r
889                 dcMem.SelectClipRgn(&rgnClip);\r
890                 HWND hWndParent = ::GetParent(m_hWnd);\r
891                 CDC dcParent = ::GetDC(hWndParent);\r
892                 HBRUSH hBrush = (HBRUSH) SendMessage(hWndParent, WM_CTLCOLORDLG, (WPARAM)dcParent.GetHDC(), (LPARAM)hWndParent);\r
893                 ::SelectObject(dcMem, hBrush);\r
894                 dcMem.PaintRgn(&rgnClip);\r
895 \r
896                 // Draw the tab buttons on the memory DC:\r
897                 DrawTabs(dcMem);\r
898 \r
899                 // Draw buttons and tab borders\r
900                 DrawCloseButton(dcMem);\r
901                 DrawListButton(dcMem);\r
902                 DrawTabBorders(dcMem, rcTab);\r
903 \r
904                 // Now copy our from our memory DC to the window DC\r
905                 dcView.SelectClipRgn(&rgnClip);\r
906                 dcView.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY);\r
907         }\r
908 \r
909         inline void CTab::PreCreate(CREATESTRUCT &cs)\r
910         {\r
911                 // For Tabs on the bottom, add the TCS_BOTTOM style\r
912                 cs.style = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;\r
913         }\r
914 \r
915         inline void CTab::PreRegisterClass(WNDCLASS &wc)\r
916         {\r
917                 wc.lpszClassName = WC_TABCONTROL;\r
918         }\r
919 \r
920         inline void CTab::RecalcLayout()\r
921         {\r
922                 if (IsWindow())\r
923                 {\r
924                         if (GetActiveView())\r
925                         {\r
926                                 // Set the tab sizes\r
927                                 SetTabSize();\r
928 \r
929                                 // Position the View over the tab control's display area\r
930                                 CRect rc = GetClientRect();\r
931                                 TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);\r
932                                 GetActiveView()->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);\r
933                         }\r
934                         else\r
935                                 RedrawWindow();\r
936                 }\r
937         }\r
938 \r
939         inline void CTab::RemoveTabPage(int nPage)\r
940         {\r
941                 if ((nPage < 0) || (nPage > (int)m_vTabPageInfo.size() -1))\r
942                         return;\r
943 \r
944                 // Remove the tab\r
945                 TabCtrl_DeleteItem(m_hWnd, nPage);\r
946 \r
947                 // Remove the TapPageInfo entry\r
948                 std::vector<TabPageInfo>::iterator itTPI = m_vTabPageInfo.begin() + nPage;\r
949                 CWnd* pView = (*itTPI).pView;\r
950                 int iImage = (*itTPI).iImage;\r
951                 if (iImage >= 0)\r
952                         TabCtrl_RemoveImage(m_hWnd, iImage);\r
953 \r
954                 if (pView == m_pActiveView)\r
955                         m_pActiveView = 0;\r
956 \r
957                 (*itTPI).pView->Destroy();\r
958                 m_vTabPageInfo.erase(itTPI);\r
959 \r
960                 std::vector<WndPtr>::iterator itView;\r
961                 for (itView = m_vTabViews.begin(); itView < m_vTabViews.end(); ++itView)\r
962                 {\r
963                         if ((*itView).get() == pView)\r
964                         {\r
965                                 m_vTabViews.erase(itView);\r
966                                 break;\r
967                         }\r
968                 }\r
969 \r
970                 if (IsWindow())\r
971                 {\r
972                         if (m_vTabPageInfo.size() > 0)\r
973                         {\r
974                                 SetTabSize();\r
975                                 SelectPage(0);\r
976                         }\r
977                         else\r
978                                 ShowActiveView(NULL);\r
979 \r
980                         NotifyChanged();\r
981                 }\r
982         }\r
983 \r
984         inline void CTab::SelectPage(int nPage)\r
985         {\r
986                 if ((nPage >= 0) && (nPage < GetItemCount()))\r
987                 {\r
988                         if (nPage != GetCurSel())\r
989                                 SetCurSel(nPage);\r
990                         \r
991                         ShowActiveView(m_vTabPageInfo[nPage].pView);\r
992                 }\r
993         }\r
994 \r
995         inline void CTab::SetFixedWidth(BOOL bEnabled)\r
996         {\r
997                 DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);\r
998                 if (bEnabled)\r
999                         SetWindowLongPtr(GWL_STYLE, dwStyle | TCS_FIXEDWIDTH);\r
1000                 else\r
1001                         SetWindowLongPtr(GWL_STYLE, dwStyle & ~TCS_FIXEDWIDTH);\r
1002 \r
1003                 RecalcLayout();\r
1004         }\r
1005 \r
1006         inline void CTab::SetOwnerDraw(BOOL bEnabled)\r
1007         // Enable or disable owner draw\r
1008         {\r
1009                 DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);\r
1010                 if (bEnabled)\r
1011                 {\r
1012                         SetWindowLongPtr(GWL_STYLE, dwStyle | TCS_OWNERDRAWFIXED);\r
1013                         TabCtrl_SetImageList(m_hWnd, NULL);\r
1014                 }\r
1015                 else\r
1016                 {\r
1017                         SetWindowLongPtr(GWL_STYLE, dwStyle & ~TCS_OWNERDRAWFIXED);\r
1018                         TabCtrl_SetImageList(m_hWnd, m_himlTab);\r
1019                 }\r
1020 \r
1021                 RecalcLayout();\r
1022         }\r
1023 \r
1024         inline void CTab::SetShowButtons(BOOL bShow)\r
1025         {\r
1026                 m_bShowButtons = bShow;\r
1027                 RecalcLayout();\r
1028         }\r
1029 \r
1030         inline void CTab::SetTabIcon(int i, HICON hIcon)\r
1031         // Changes or sets the tab's icon\r
1032         {\r
1033                 assert (GetItemCount() > i);\r
1034                 TCITEM tci = {0};\r
1035                 tci.mask = TCIF_IMAGE;\r
1036                 GetItem(i, &tci);\r
1037                 if (tci.iImage >= 0)\r
1038                 {\r
1039                         ImageList_ReplaceIcon(GetImageList(), i, hIcon);\r
1040                 }\r
1041                 else\r
1042                 {\r
1043                         int iImage = ImageList_AddIcon(GetImageList(), hIcon);\r
1044                         tci.iImage = iImage;\r
1045                         TabCtrl_SetItem(m_hWnd, i, &tci);\r
1046                         m_vTabPageInfo[i].iImage = iImage;\r
1047                 }\r
1048         }       \r
1049 \r
1050         inline void CTab::SetTabsAtTop(BOOL bTop)\r
1051         // Positions the tabs at the top or botttom of the control\r
1052         {\r
1053                 DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);\r
1054 \r
1055                 if (bTop)\r
1056                         dwStyle &= ~TCS_BOTTOM;\r
1057                 else\r
1058                         dwStyle |= TCS_BOTTOM;\r
1059 \r
1060                 SetWindowLongPtr(GWL_STYLE, dwStyle);\r
1061                 RecalcLayout();\r
1062         }\r
1063 \r
1064         inline void CTab::SetTabSize()\r
1065         {\r
1066                 if (GetItemCount() > 0)\r
1067                 {\r
1068                         CRect rc = GetClientRect();\r
1069                         TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);\r
1070 \r
1071                         int xGap = 2;\r
1072                         if (m_bShowButtons) xGap += GetCloseRect().Width() + GetListRect().Width() +2;\r
1073 \r
1074                         int nItemWidth = MIN( GetMaxTabSize().cx, (rc.Width() - xGap)/GetItemCount() );\r
1075                         nItemWidth = MAX(nItemWidth, 0);\r
1076                         SendMessage(TCM_SETITEMSIZE, 0L, MAKELPARAM(nItemWidth, m_nTabHeight));\r
1077                         NotifyChanged();\r
1078                 } \r
1079         }\r
1080 \r
1081         inline void CTab::SetTabText(UINT nTab, LPCTSTR szText)\r
1082         {\r
1083                 // Allows the text to be changed on an existing tab\r
1084                 if (nTab < GetAllTabs().size())\r
1085                 {\r
1086                         TCITEM Item = {0};\r
1087                         std::vector<TCHAR> vTChar(MAX_MENU_STRING+1, _T('\0'));\r
1088                         TCHAR* pTChar = &vTChar.front();\r
1089                         lstrcpyn(pTChar, szText, MAX_MENU_STRING);\r
1090                         Item.mask = TCIF_TEXT;\r
1091                         Item.pszText = pTChar;\r
1092 \r
1093                         if (TabCtrl_SetItem(m_hWnd, nTab, &Item))\r
1094                                 lstrcpyn(m_vTabPageInfo[nTab].szTabText, pTChar, MAX_MENU_STRING);\r
1095                 }\r
1096         }\r
1097 \r
1098         inline void CTab::ShowActiveView(CWnd* pView)\r
1099         // Sets or changes the View window displayed within the tab page\r
1100         {\r
1101                 // Hide the old view\r
1102                 if (GetActiveView() && (GetActiveView()->IsWindow()))\r
1103                         GetActiveView()->ShowWindow(SW_HIDE);\r
1104 \r
1105                 // Assign the view window\r
1106                 m_pActiveView = pView;\r
1107 \r
1108                 if (m_pActiveView && m_hWnd)\r
1109                 {\r
1110                         if (!m_pActiveView->IsWindow())\r
1111                         {\r
1112                                 // The tab control is already created, so create the new view too\r
1113                                 GetActiveView()->Create(this);\r
1114                         }\r
1115         \r
1116                         // Position the View over the tab control's display area\r
1117                         CRect rc = GetClientRect();\r
1118                         TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);\r
1119                         GetActiveView()->SetWindowPos(0, rc, SWP_SHOWWINDOW);\r
1120                         GetActiveView()->SetFocus();\r
1121                 }\r
1122         }\r
1123 \r
1124         inline void CTab::ShowListMenu()\r
1125         // Displays the list of windows in a popup menu\r
1126         {\r
1127                 if (!m_IsListPressed)\r
1128                 {\r
1129                         m_IsListPressed = TRUE;\r
1130                         HMENU hMenu = GetListMenu();\r
1131         \r
1132                         CPoint pt(GetListRect().left, GetListRect().top + GetTabHeight());\r
1133                         ClientToScreen(pt);\r
1134 \r
1135                         // Choosing the frame's hwnd for the menu's messages will automatically theme the popup menu\r
1136                         HWND MenuHwnd = GetAncestor()->GetHwnd();\r
1137                         int nPage = 0;\r
1138                         m_IsListMenuActive = TRUE;\r
1139                         nPage = TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, MenuHwnd, NULL) - IDW_FIRSTCHILD;\r
1140                         if ((nPage >= 0) && (nPage < 9)) SelectPage(nPage);\r
1141                         if (nPage == 9) ShowListDialog();\r
1142                         m_IsListMenuActive = FALSE;\r
1143                 }\r
1144 \r
1145                 CClientDC dc(this);\r
1146                 DrawListButton(dc);\r
1147         }\r
1148 \r
1149         inline void CTab::ShowListDialog()\r
1150         {\r
1151                 // Definition of a dialog template which displays a List Box\r
1152                 unsigned char dlg_Template[] =\r
1153                 {\r
1154                         0x01,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xc8,0x00,0xc8,0x90,0x03,\r
1155                         0x00,0x00,0x00,0x00,0x00,0xdc,0x00,0x8e,0x00,0x00,0x00,0x00,0x00,0x53,0x00,0x65,\r
1156                         0x00,0x6c,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x57,0x00,0x69,0x00,0x6e,\r
1157                         0x00,0x64,0x00,0x6f,0x00,0x77,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x4d,\r
1158                         0x00,0x53,0x00,0x20,0x00,0x53,0x00,0x68,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x20,\r
1159                         0x00,0x44,0x00,0x6c,0x00,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
1160                         0x00,0x00,0x00,0x01,0x00,0x01,0x50,0x40,0x00,0x7a,0x00,0x25,0x00,0x0f,0x00,0x01,\r
1161                         0x00,0x00,0x00,0xff,0xff,0x80,0x00,0x4f,0x00,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,\r
1162                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x50,0x7a,0x00,0x7a,0x00,0x25,\r
1163                         0x00,0x0f,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0x80,0x00,0x43,0x00,0x61,0x00,0x6e,\r
1164                         0x00,0x63,0x00,0x65,0x00,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
1165                         0x00,0x02,0x00,0x01,0x01,0x21,0x50,0x06,0x00,0x06,0x00,0xcf,0x00,0x6d,0x00,0x79,\r
1166                         0x00,0x00,0x00,0xff,0xff,0x83,0x00,0x00,0x00,0x00,0x00\r
1167                 };\r
1168 \r
1169                 // Display the modal dialog. The dialog is defined in the dialog template rather\r
1170                 // than in the resource script (rc) file.\r
1171                 CSelectDialog MyDialog((LPCDLGTEMPLATE) dlg_Template);\r
1172                 for(UINT u = 0; u < GetAllTabs().size(); ++u)\r
1173                 {\r
1174                         MyDialog.AddItem(GetAllTabs()[u].szTabText);\r
1175                 }\r
1176 \r
1177                 int iSelected = (int)MyDialog.DoModal();\r
1178                 if (iSelected >= 0) SelectPage(iSelected);\r
1179         }\r
1180 \r
1181         inline void CTab::SwapTabs(UINT nTab1, UINT nTab2)\r
1182         {\r
1183                 if ((nTab1 < GetAllTabs().size()) && (nTab2 < GetAllTabs().size()) && (nTab1 != nTab2))\r
1184                 {\r
1185                         int nPage = GetCurSel();\r
1186                         TabPageInfo T1 = GetTabPageInfo(nTab1);\r
1187                         TabPageInfo T2 = GetTabPageInfo(nTab2);\r
1188                         int nLength = 30;\r
1189                         std::vector<TCHAR> vTChar1( nLength+1, _T('\0') );      // vector for TCHAR array\r
1190                         std::vector<TCHAR> vTChar2( nLength+1, _T('\0') );      // vector for TCHAR array\r
1191 \r
1192                         TCITEM Item1 = {0};\r
1193                         Item1.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT;\r
1194                         Item1.cchTextMax = nLength;\r
1195                         Item1.pszText = &vTChar1.front();\r
1196                         GetItem(nTab1, &Item1);\r
1197                         \r
1198                         TCITEM Item2 = {0};\r
1199                         Item2.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT;\r
1200                         Item2.cchTextMax = nLength;\r
1201                         Item2.pszText = &vTChar2.front();\r
1202                         GetItem(nTab2, &Item2);\r
1203                         \r
1204                         TabCtrl_SetItem(m_hWnd, nTab1, &Item2);\r
1205                         TabCtrl_SetItem(m_hWnd, nTab2, &Item1); \r
1206                         m_vTabPageInfo[nTab1] = T2;\r
1207                         m_vTabPageInfo[nTab2] = T1;\r
1208                         SelectPage(nPage);\r
1209                 }\r
1210         }\r
1211 \r
1212         inline LRESULT CTab::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
1213         {\r
1214                 switch(uMsg)\r
1215                 {\r
1216                 case WM_DESTROY:\r
1217                         // Required for Windows NT\r
1218                         {\r
1219                                 for (int i = GetItemCount()-1; i >= 0; --i)\r
1220                                 {\r
1221                                         RemoveTabPage(i);\r
1222                                 }\r
1223                         }\r
1224                         break;\r
1225                 case WM_PAINT:\r
1226                         if (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)\r
1227                         {\r
1228                                 // Remove all pending paint requests\r
1229                                 PAINTSTRUCT ps;\r
1230                                 ::BeginPaint(m_hWnd, &ps);\r
1231                                 ::EndPaint(m_hWnd, &ps);\r
1232 \r
1233                                 // Now call our local Paint\r
1234                                 Paint();\r
1235                                 return 0;\r
1236                         }\r
1237                         break;\r
1238                 case WM_ERASEBKGND:\r
1239                         if (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)\r
1240                                 return 0;\r
1241                         break;\r
1242                 case WM_KILLFOCUS:\r
1243                         m_IsClosePressed = FALSE;\r
1244                         break;\r
1245                 case WM_LBUTTONDBLCLK:\r
1246                 case WM_LBUTTONDOWN:\r
1247                         OnLButtonDown(wParam, lParam);\r
1248                         break;\r
1249                 case WM_LBUTTONUP:\r
1250                         OnLButtonUp(wParam, lParam);\r
1251                         break;\r
1252                 case WM_MOUSEMOVE:\r
1253                         OnMouseMove(wParam, lParam);\r
1254                         break;\r
1255                 case WM_MOUSELEAVE:\r
1256                         OnMouseLeave(wParam, lParam);\r
1257                         break;\r
1258                 case WM_NCHITTEST:\r
1259                         return OnNCHitTest(wParam, lParam);\r
1260 \r
1261                 case WM_WINDOWPOSCHANGING:\r
1262                         // A little hack to reduce tab flicker\r
1263                         if (IsWindowVisible() && (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED))\r
1264                         {\r
1265                                 LPWINDOWPOS pWinPos = (LPWINDOWPOS)lParam;\r
1266                                 pWinPos->flags |= SWP_NOREDRAW;\r
1267                         }\r
1268 \r
1269                         break;\r
1270 \r
1271                 case WM_WINDOWPOSCHANGED:\r
1272                         RecalcLayout();\r
1273                         break;\r
1274                 }\r
1275 \r
1276                 // pass unhandled messages on for default processing\r
1277                 return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
1278         }\r
1279 \r
1280         // Wrappers for Win32 Macros\r
1281         inline void CTab::AdjustRect(BOOL fLarger, RECT *prc) const\r
1282         {\r
1283                 assert(::IsWindow(m_hWnd));\r
1284                 TabCtrl_AdjustRect(m_hWnd, fLarger, prc);\r
1285         }\r
1286 \r
1287         inline int CTab::GetCurFocus() const\r
1288         {\r
1289                 assert(::IsWindow(m_hWnd));\r
1290                 return TabCtrl_GetCurFocus(m_hWnd);\r
1291         }\r
1292 \r
1293         inline int CTab::GetCurSel() const\r
1294         {\r
1295                 assert(::IsWindow(m_hWnd));\r
1296                 return TabCtrl_GetCurSel(m_hWnd);\r
1297         }\r
1298 \r
1299         inline BOOL CTab::GetItem(int iItem, LPTCITEM pitem) const\r
1300         {\r
1301                 assert(::IsWindow(m_hWnd));\r
1302                 return TabCtrl_GetItem(m_hWnd, iItem, pitem);\r
1303         }\r
1304 \r
1305         inline int CTab::GetItemCount() const\r
1306         {\r
1307                 assert(::IsWindow(m_hWnd));\r
1308                 return TabCtrl_GetItemCount(m_hWnd);\r
1309         }\r
1310 \r
1311         inline int CTab::HitTest(TCHITTESTINFO& info) const\r
1312         {\r
1313                 assert(::IsWindow(m_hWnd));\r
1314                 return TabCtrl_HitTest(m_hWnd, &info);\r
1315         }\r
1316 \r
1317         inline void CTab::SetCurFocus(int iItem) const\r
1318         {\r
1319                 assert(::IsWindow(m_hWnd));\r
1320                 TabCtrl_SetCurFocus(m_hWnd, iItem);\r
1321         }\r
1322 \r
1323         inline int CTab::SetCurSel(int iItem) const\r
1324         {\r
1325                 assert(::IsWindow(m_hWnd));\r
1326                 return TabCtrl_SetCurSel(m_hWnd, iItem);\r
1327         }\r
1328 \r
1329         inline DWORD CTab::SetItemSize(int cx, int cy) const\r
1330         {\r
1331                 assert(::IsWindow(m_hWnd));\r
1332                 return TabCtrl_SetItemSize(m_hWnd, cx, cy);\r
1333         }\r
1334 \r
1335         inline int CTab::SetMinTabWidth(int cx) const\r
1336         {\r
1337                 assert(::IsWindow(m_hWnd));\r
1338                 return TabCtrl_SetMinTabWidth(m_hWnd, cx);\r
1339         }\r
1340 \r
1341         inline void CTab::SetPadding(int cx, int cy) const\r
1342         {\r
1343                 assert(::IsWindow(m_hWnd));\r
1344                 TabCtrl_SetPadding(m_hWnd, cx, cy);\r
1345         }\r
1346 \r
1347         ////////////////////////////////////////\r
1348         // Definitions for the CTabbedMDI class\r
1349         inline CTabbedMDI::CTabbedMDI()\r
1350         {\r
1351                 GetTab().SetShowButtons(TRUE);\r
1352         }\r
1353 \r
1354         inline CTabbedMDI::~CTabbedMDI()\r
1355         {\r
1356         }\r
1357 \r
1358         inline CWnd* CTabbedMDI::AddMDIChild(CWnd* pView, LPCTSTR szTabText, int idMDIChild /*= 0*/)\r
1359         {\r
1360                 assert(pView);\r
1361                 assert(lstrlen(szTabText) < MAX_MENU_STRING);\r
1362 \r
1363                 GetTab().AddTabPage(WndPtr(pView), szTabText, 0, idMDIChild);\r
1364 \r
1365                 // Fake a WM_MOUSEACTIVATE to propogate focus change to dockers\r
1366                 if (IsWindow())\r
1367                         GetParent()->SendMessage(WM_MOUSEACTIVATE, (WPARAM)GetAncestor(), MAKELPARAM(HTCLIENT,WM_LBUTTONDOWN));\r
1368 \r
1369                 return pView;\r
1370         }\r
1371 \r
1372         inline void CTabbedMDI::CloseActiveMDI()\r
1373         {\r
1374                 int nTab = GetTab().GetCurSel();\r
1375                 if (nTab >= 0)\r
1376                         GetTab().RemoveTabPage(nTab);\r
1377 \r
1378                 RecalcLayout();\r
1379         }\r
1380 \r
1381         inline void CTabbedMDI::CloseAllMDIChildren()\r
1382         {\r
1383                 while (GetMDIChildCount() > 0)\r
1384                 {\r
1385                         GetTab().RemoveTabPage(0);\r
1386                 }\r
1387         }\r
1388 \r
1389         inline void CTabbedMDI::CloseMDIChild(int nTab)\r
1390         {\r
1391                 GetTab().RemoveTabPage(nTab);\r
1392 \r
1393                 if (GetActiveMDIChild())\r
1394                         GetActiveMDIChild()->RedrawWindow();\r
1395         }\r
1396 \r
1397         inline HWND CTabbedMDI::Create(CWnd* pParent /* = NULL*/)\r
1398         {\r
1399                 CLIENTCREATESTRUCT clientcreate ;\r
1400                 clientcreate.hWindowMenu  = m_hWnd;\r
1401                 clientcreate.idFirstChild = IDW_FIRSTCHILD ;\r
1402                 DWORD dwStyle = WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES;\r
1403 \r
1404                 // Create the MDICLIENT view window\r
1405                 if (!CreateEx(0, _T("MDICLIENT"), _T(""),\r
1406                         dwStyle, 0, 0, 0, 0, pParent, NULL, (PSTR) &clientcreate))\r
1407                                 throw CWinException(_T("CMDIClient::Create ... CreateEx failed"));\r
1408 \r
1409                 return m_hWnd;\r
1410         }\r
1411 \r
1412         inline CWnd* CTabbedMDI::GetActiveMDIChild() const\r
1413         {\r
1414                 CWnd* pView = NULL;\r
1415                 int nTab = GetTab().GetCurSel();\r
1416                 if (nTab >= 0)\r
1417                 {\r
1418                         TabPageInfo tbi = GetTab().GetTabPageInfo(nTab);\r
1419                         pView = tbi.pView;\r
1420                 }\r
1421 \r
1422                 return pView;\r
1423         }\r
1424 \r
1425         inline int CTabbedMDI::GetActiveMDITab() const\r
1426         {\r
1427                 return GetTab().GetCurSel();\r
1428         }\r
1429 \r
1430         inline CWnd* CTabbedMDI::GetMDIChild(int nTab) const\r
1431         {\r
1432                 assert(nTab >= 0);\r
1433                 assert(nTab < GetMDIChildCount());\r
1434                 return GetTab().GetTabPageInfo(nTab).pView;\r
1435         }\r
1436 \r
1437         inline int CTabbedMDI::GetMDIChildCount() const\r
1438         {\r
1439                 return (int) GetTab().GetAllTabs().size();\r
1440         }\r
1441 \r
1442         inline int   CTabbedMDI::GetMDIChildID(int nTab) const\r
1443         {\r
1444                 assert(nTab >= 0);\r
1445                 assert(nTab < GetMDIChildCount());\r
1446                 return GetTab().GetTabPageInfo(nTab).idTab;\r
1447         }\r
1448 \r
1449         inline LPCTSTR CTabbedMDI::GetMDIChildTitle(int nTab) const\r
1450         {\r
1451                 assert(nTab >= 0);\r
1452                 assert(nTab < GetMDIChildCount());\r
1453                 return GetTab().GetTabPageInfo(nTab).szTabText;\r
1454         }\r
1455 \r
1456         inline BOOL CTabbedMDI::LoadRegistrySettings(CString strRegistryKeyName)\r
1457         {\r
1458                 BOOL bResult = FALSE;\r
1459 \r
1460                 if (!strRegistryKeyName.IsEmpty())\r
1461                 {\r
1462                         CString strKey = _T("Software\\") + strRegistryKeyName + _T("\\MDI Children");\r
1463                         HKEY hKey = 0;\r
1464                         RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey);\r
1465                         if (hKey)\r
1466                         {\r
1467                                 DWORD dwType = REG_BINARY;\r
1468                                 DWORD BufferSize = sizeof(TabPageInfo);\r
1469                                 TabPageInfo tbi = {0};\r
1470                                 int i = 0;\r
1471                                 TCHAR szNumber[16];\r
1472                                 CString strSubKey = _T("MDI Child ");\r
1473                                 strSubKey += _itot(i, szNumber, 10);\r
1474 \r
1475                                 // Fill the DockList vector from the registry\r
1476                                 while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&tbi, &BufferSize))\r
1477                                 {\r
1478                                         CWnd* pWnd = NewMDIChildFromID(tbi.idTab);\r
1479                                         if (pWnd)\r
1480                                         {\r
1481                                                 AddMDIChild(pWnd, tbi.szTabText, tbi.idTab);\r
1482                                                 i++;\r
1483                                                 strSubKey = _T("MDI Child ");\r
1484                                                 strSubKey += _itot(i, szNumber, 10);\r
1485                                                 bResult = TRUE;\r
1486                                         }\r
1487                                         else\r
1488                                         {\r
1489                                                 TRACE(_T("Failed to get TabbedMDI info from registry"));\r
1490                                                 bResult = FALSE;\r
1491                                                 break;\r
1492                                         }\r
1493                                 }\r
1494 \r
1495                                 // Load Active MDI Tab from the registry\r
1496                                 strSubKey = _T("Active MDI Tab");\r
1497                                 int nTab;\r
1498                                 dwType = REG_DWORD;\r
1499                                 BufferSize = sizeof(int);\r
1500                                 if(ERROR_SUCCESS == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&nTab, &BufferSize))\r
1501                                         SetActiveMDITab(nTab);\r
1502                                 else\r
1503                                         SetActiveMDITab(0);\r
1504 \r
1505                                 RegCloseKey(hKey);\r
1506                         }\r
1507                 }\r
1508 \r
1509                 if (!bResult)\r
1510                         CloseAllMDIChildren();\r
1511 \r
1512                 return bResult;\r
1513         }\r
1514 \r
1515         inline CWnd* CTabbedMDI::NewMDIChildFromID(int /*idMDIChild*/)\r
1516         {\r
1517                 // Override this function to create new MDI children from IDs as shown below\r
1518                 CWnd* pView = NULL;\r
1519         /*      switch(idTab)\r
1520                 {\r
1521                 case ID_SIMPLE:\r
1522                         pView = new CViewSimple;\r
1523                         break;\r
1524                 case ID_RECT:\r
1525                         pView = new CViewRect;\r
1526                         break;\r
1527                 default:\r
1528                         TRACE(_T("Unknown MDI child ID\n"));\r
1529                         break;\r
1530                 } */\r
1531 \r
1532                 return pView;\r
1533         }\r
1534 \r
1535         inline void CTabbedMDI::OnCreate()\r
1536         {\r
1537                 GetTab().Create(this);\r
1538                 GetTab().SetFixedWidth(TRUE);\r
1539                 GetTab().SetOwnerDraw(TRUE);\r
1540         }\r
1541 \r
1542         inline void CTabbedMDI::OnDestroy(WPARAM /*wParam*/, LPARAM /*lParam*/ )\r
1543         {\r
1544                 CloseAllMDIChildren();\r
1545         }\r
1546 \r
1547         inline LRESULT CTabbedMDI::OnNotify(WPARAM /*wParam*/, LPARAM lParam)\r
1548         {\r
1549                 LPNMHDR pnmhdr = (LPNMHDR)lParam;\r
1550                 if (pnmhdr->code == UWM_TAB_CHANGED)\r
1551                         RecalcLayout();\r
1552 \r
1553                 return 0L;\r
1554         }\r
1555 \r
1556         inline void CTabbedMDI::OnWindowPosChanged(WPARAM /*wParam*/, LPARAM /*lParam*/)\r
1557         {\r
1558                 RecalcLayout();\r
1559         }\r
1560 \r
1561         inline void CTabbedMDI::RecalcLayout()\r
1562         {\r
1563                 if (GetTab().IsWindow())\r
1564                 {\r
1565                         if (GetTab().GetItemCount() >0)\r
1566                         {\r
1567                                 CRect rcClient = GetClientRect();\r
1568                                 GetTab().SetWindowPos(NULL, rcClient, SWP_SHOWWINDOW);\r
1569                                 GetTab().UpdateWindow();\r
1570                         }\r
1571                         else\r
1572                         {\r
1573                                 CRect rcClient = GetClientRect();\r
1574                                 GetTab().SetWindowPos(NULL, rcClient, SWP_HIDEWINDOW);\r
1575                                 Invalidate();\r
1576                         }\r
1577                 }\r
1578         }\r
1579 \r
1580         inline BOOL CTabbedMDI::SaveRegistrySettings(CString strRegistryKeyName)\r
1581         {\r
1582                 if (!strRegistryKeyName.IsEmpty())\r
1583                 {\r
1584                         CString strKeyName = _T("Software\\") + strRegistryKeyName;\r
1585                         HKEY hKey = NULL;\r
1586                         HKEY hKeyMDIChild = NULL;\r
1587 \r
1588                         try\r
1589                         {\r
1590                                 if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))\r
1591                                         throw (CWinException(_T("RegCreateKeyEx Failed")));\r
1592 \r
1593                                 RegDeleteKey(hKey, _T("MDI Children"));\r
1594                                 if (ERROR_SUCCESS != RegCreateKeyEx(hKey, _T("MDI Children"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyMDIChild, NULL))\r
1595                                         throw (CWinException(_T("RegCreateKeyEx Failed")));\r
1596 \r
1597                                 for (int i = 0; i < GetMDIChildCount(); ++i)\r
1598                                 {\r
1599                                         TCHAR szNumber[16];\r
1600                                         CString strSubKey = _T("MDI Child ");\r
1601                                         strSubKey += _itot(i, szNumber, 10);\r
1602                                         TabPageInfo pdi = GetTab().GetTabPageInfo(i);\r
1603                                         if (ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, strSubKey, 0, REG_BINARY, (LPBYTE)&pdi, sizeof(TabPageInfo)))\r
1604                                                 throw (CWinException(_T("RegSetValueEx Failed")));\r
1605                                 }\r
1606 \r
1607                                 // Add Active Tab to the registry\r
1608                                 CString strSubKey = _T("Active MDI Tab");\r
1609                                 int nTab = GetActiveMDITab();\r
1610                                 if(ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, strSubKey, 0, REG_DWORD, (LPBYTE)&nTab, sizeof(int)))\r
1611                                         throw (CWinException(_T("RegSetValueEx failed")));\r
1612 \r
1613                                 RegCloseKey(hKeyMDIChild);\r
1614                                 RegCloseKey(hKey);\r
1615                         }\r
1616                         catch (const CWinException& e)\r
1617                         {\r
1618                                 // Roll back the registry changes by deleting the subkeys\r
1619                                 if (hKey)\r
1620                                 {\r
1621                                         if (hKeyMDIChild)\r
1622                                         {\r
1623                                                 RegDeleteKey(hKeyMDIChild, _T("MDI Children"));\r
1624                                                 RegCloseKey(hKeyMDIChild);\r
1625                                         }\r
1626 \r
1627                                         RegDeleteKey(HKEY_CURRENT_USER, strKeyName);\r
1628                                         RegCloseKey(hKey);\r
1629                                 }\r
1630 \r
1631                                 e.what();\r
1632                                 return FALSE;\r
1633                         }\r
1634                 }\r
1635 \r
1636                 return TRUE;\r
1637         }\r
1638 \r
1639         inline void CTabbedMDI::SetActiveMDIChild(CWnd* pWnd)\r
1640         {\r
1641                 assert(pWnd);\r
1642                 int nPage = GetTab().GetTabIndex(pWnd);\r
1643                 if (nPage >= 0)\r
1644                         GetTab().SelectPage(nPage);\r
1645         }\r
1646 \r
1647         inline void CTabbedMDI::SetActiveMDITab(int iTab)\r
1648         {\r
1649                 assert(::IsWindow(m_hWnd));\r
1650                 assert(GetTab().IsWindow());\r
1651                 GetTab().SelectPage(iTab);\r
1652         }\r
1653 \r
1654         inline LRESULT CTabbedMDI::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
1655         {\r
1656                 switch(uMsg)\r
1657                 {\r
1658                 case WM_DESTROY:\r
1659                         OnDestroy(wParam, lParam);\r
1660                         break;\r
1661 \r
1662                 case WM_WINDOWPOSCHANGED:\r
1663                         OnWindowPosChanged(wParam, lParam);\r
1664                         break;\r
1665                 }\r
1666 \r
1667                 return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
1668         }\r
1669 \r
1670 } // namespace Win32xx\r
1671 \r
1672 #endif  // _WIN32XX_TAB_H_\r

UCC git Repository :: git.ucc.asn.au