1 // recent_project_win.cpp : implementation file
2 //
3 
4 #include "studiox_includes.h"
5 #include "recent_project_win.h"
6 extern INI_INFO StudioXIni;
7 
8 #ifdef _DEBUG
9 #define new DEBUG_NEW
10 #endif
11 
12 #define NEW_BUTTON_HEIGHT 36
13 #define NEW_BUTTON_WIDTH 190
14 
15 extern CString target_class_name;
16 extern CFont MediumFont;
17 
18 
BEGIN_MESSAGE_MAP(recent_project_win,express_dialog)19 BEGIN_MESSAGE_MAP(recent_project_win, express_dialog)
20  ON_WM_CREATE()
21  ON_WM_SHOWWINDOW()
22  ON_BN_CLICKED(IDC_CREATE_PROJECT, OnBnClickedCreateProject)
23 END_MESSAGE_MAP()
24 
25 ///////////////////////////////////////////////////////////////////////////////
26 recent_project_win::recent_project_win(int width, int height, CWnd* pParent /*=NULL*/)
27 	: express_dialog(width, height)
28 {
29     IconId = IDB_RECENT_PROJECT;
30     SetTitleText("Recent Projects");
31 }
32 
33 ///////////////////////////////////////////////////////////////////////////////
~recent_project_win()34 recent_project_win::~recent_project_win()
35 {
36 }
37 
38 ///////////////////////////////////////////////////////////////////////////////
GetCreateNewProjectButtonSize(CRect & parentSize)39 CRect recent_project_win::GetCreateNewProjectButtonSize(CRect &parentSize)
40 {
41     CRect size;
42 
43     int dpi = GetSystemDPI();
44     int text_scaler = GetTextScaler();
45 
46     size.bottom = parentSize.bottom - 4;
47     size.top = size.bottom - GetScaledValue(NEW_BUTTON_HEIGHT, dpi, text_scaler);
48     size.right = parentSize.right - 4;
49     size.left = size.right - GetScaledValue(NEW_BUTTON_WIDTH, dpi, text_scaler);
50 
51     return size;
52 }
53 
54 ///////////////////////////////////////////////////////////////////////////////
OnCreate(LPCREATESTRUCT lpCreateStruct)55 int recent_project_win::OnCreate(LPCREATESTRUCT lpCreateStruct)
56 {
57     CRect client;
58     CRect size;
59 
60     express_dialog::OnCreate(lpCreateStruct);
61     GetClientRect(&client);
62 
63     int space = MulDiv(10, GetSystemDPI(), DEFAULT_DPI_96);;
64     size.left = client.left + space;
65     size.right = client.right - space;
66     size.top = client.top + m_title_bar_height + space;
67     size.bottom = client.bottom - m_status_bar_height - space;
68 
69     mRecentListFrame.Create(target_class_name, _T("Recent Projects"),
70         WS_VISIBLE | WS_CHILD | WS_TABSTOP, size, this, 0);
71 
72     size = GetCreateNewProjectButtonSize(client);
73     new_button.Create(_T("Create New Project"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_OWNERDRAW | WS_TABSTOP, size, this, IDC_CREATE_PROJECT);
74     new_button.LoadBitmaps(IDB_NEW_PROJECT_NORMAL, IDB_NEW_PROJECT_PRESSED);
75     new_button.SetWindowText(_T("Create New Project..."));
76     return 0;
77 }
78 
79 ///////////////////////////////////////////////////////////////////////////////
OnShowWindow(BOOL Show,UINT status)80 void recent_project_win::OnShowWindow(BOOL Show, UINT status)
81 {
82     if (Show)
83     {
84         mRecentListFrame.UpdateRecentList();
85     }
86     CWnd::OnShowWindow(Show, status);
87 }
88 
89 ///////////////////////////////////////////////////////////////////////////////
UpdateRecentList()90 void recent_project_win::UpdateRecentList()
91 {
92     mRecentListFrame.UpdateRecentList();
93 }
94 
95 ///////////////////////////////////////////////////////////////////////////////
OnBnClickedCreateProject()96 void recent_project_win::OnBnClickedCreateProject()
97 {
98     // TODO: Add your control notification handler code here
99     GetProjectView()->NewProject(this);
100 }
101 
102 ///////////////////////////////////////////////////////////////////////////////
PreTranslateMessage(MSG * pMsg)103 BOOL recent_project_win::PreTranslateMessage(MSG* pMsg)
104 {
105     // TODO: Add your specialized code here and/or call the base class
106     if (pMsg->message == WM_KEYDOWN &&
107         pMsg->wParam == VK_RETURN &&
108         GetFocus() == &new_button)
109     {
110         OnBnClickedCreateProject();
111         return TRUE;
112     }
113 
114     return express_dialog::PreTranslateMessage(pMsg);
115 }
116 
BEGIN_MESSAGE_MAP(recent_list_frame,CWnd)117 BEGIN_MESSAGE_MAP(recent_list_frame, CWnd)
118 ON_WM_CTLCOLOR()
119 ON_WM_CREATE()
120 //ON_WM_SHOWWINDOW()
121 ON_WM_MOUSEMOVE()
122 ON_WM_LBUTTONDOWN()
123 ON_WM_ERASEBKGND()
124 ON_WM_SETFOCUS()
125 ON_WM_KILLFOCUS()
126 END_MESSAGE_MAP()
127 
128 ///////////////////////////////////////////////////////////////////////////////
129 recent_list_frame::recent_list_frame(CWnd* parent)
130 {
131     if (!StudioXIni.recent_project_paths[0].IsEmpty())
132     {
133         mHighlightRow = 0;
134     }
135     else
136     {
137         mHighlightRow = -1;
138     }
139     mHiBrush.CreateSolidBrush(RGB_COLOR_BLUE);
140     mBgBrush.CreateSolidBrush(GetSysColor(CTLCOLOR_DLG));
141     mGrayBrush.CreateSolidBrush(RGB_COLOR_GRAY);
142 }
143 
144 ///////////////////////////////////////////////////////////////////////////////
~recent_list_frame()145 recent_list_frame::~recent_list_frame()
146 {
147 
148 }
149 
150 ///////////////////////////////////////////////////////////////////////////////
OnCreate(LPCREATESTRUCT lpCreateStruct)151 int recent_list_frame::OnCreate(LPCREATESTRUCT lpCreateStruct)
152 {
153     if (CWnd::OnCreate(lpCreateStruct) == -1)
154     {
155         return -1;
156     }
157     int id_list[] = { IDC_RECENT_1, IDC_RECENT_2, IDC_RECENT_3, IDC_RECENT_4, IDC_RECENT_5 };
158     CRect size;
159     GetClientRect(&size);
160 
161     int row_height = GetRowHeight();
162     int space = (size.Height() - row_height * MAX_RECENT_PROJECTS) / (MAX_RECENT_PROJECTS - 1);
163     size.bottom = size.top + row_height;
164 
165     mNumRecentProjects = 0;
166 
167     for (int index = 0; index < MAX_RECENT_PROJECTS; index++)
168     {
169         mRecentList[index].Create(StudioXIni.recent_project_paths[index], WS_VISIBLE | SS_LEFT | SS_WORDELLIPSIS, size, this, id_list[index]);
170         mRecentList[index].SetFont(&MediumFont);
171         SetLiveRegion(mRecentList[index].GetSafeHwnd());
172         size.OffsetRect(0, row_height + space);
173 
174         if (StudioXIni.recent_project_paths[index].IsEmpty())
175         {
176             mRecentList[index].ShowWindow(FALSE);
177         }
178         else
179         {
180             mNumRecentProjects++;
181         }
182     }
183     return 0;
184 }
185 
186 
187 
188 ///////////////////////////////////////////////////////////////////////////////
UpdateRecentList(void)189 void recent_list_frame::UpdateRecentList(void)
190 {
191     mNumRecentProjects = 0;
192     for (int index = 0; index < MAX_RECENT_PROJECTS; index++)
193     {
194         if (!StudioXIni.recent_project_paths[index].IsEmpty())
195         {
196             mRecentList[index].ShowWindow(TRUE);
197             mNumRecentProjects++;
198         }
199         else
200         {
201             mRecentList[index].ShowWindow(FALSE);
202         }
203 
204         mRecentList[index].SetWindowText(StudioXIni.recent_project_paths[index]);
205     }
206 }
207 
208 ///////////////////////////////////////////////////////////////////////////////
FindStatic(CPoint point)209 int recent_list_frame::FindStatic(CPoint point)
210 {
211     int newselect = -1;
212     CString text;
213     CRect size;
214     ClientToScreen(&point);
215 
216     for (int index = 0; index < mNumRecentProjects; index++)
217     {
218         mRecentList[index].GetWindowText(text);
219 
220         if (!text.IsEmpty())
221         {
222             mRecentList[index].GetWindowRect(&size);
223 
224             if (size.PtInRect(point))
225             {
226                 newselect = index;
227                 break;
228             }
229         }
230     }
231 
232     return newselect;
233 }
234 
235 ///////////////////////////////////////////////////////////////////////////////
GetRowHeight()236 int recent_list_frame::GetRowHeight()
237 {
238     CDC* dc = GetDC();
239     CFont* old_font = dc->SelectObject(&MediumFont);
240     int row_height = dc->GetTextExtent(_T("fg"), 1).cy;
241     dc->SelectObject(old_font);
242     ReleaseDC(dc);
243     return row_height;
244 }
245 
246 ///////////////////////////////////////////////////////////////////////////////
OnMouseMove(UINT nFlags,CPoint point)247 void recent_list_frame::OnMouseMove(UINT nFlags, CPoint point)
248 {
249     int newselect = FindStatic(point);
250 
251     if ((newselect >= 0) && (newselect != mHighlightRow))
252     {
253         mRecentList[mHighlightRow].Invalidate(FALSE);
254         mHighlightRow = newselect;
255         mRecentList[mHighlightRow].Invalidate(FALSE);
256     }
257 }
258 
259 ///////////////////////////////////////////////////////////////////////////////
OnLButtonDown(UINT nFlags,CPoint point)260 void recent_list_frame::OnLButtonDown(UINT nFlags, CPoint point)
261 {
262     int newselect = FindStatic(point);
263 
264     if (newselect >= 0)
265     {
266         GetProjectView()->OpenHistoryProject(newselect);
267     }
268 }
269 
270 ///////////////////////////////////////////////////////////////////////////////
PreTranslateMessage(MSG * pMsg)271 BOOL recent_list_frame::PreTranslateMessage(MSG* pMsg)
272 {
273     // TODO: Add your specialized code here and/or call the base class
274     if (pMsg->message == WM_KEYDOWN)
275     {
276         switch (pMsg->wParam)
277         {
278         case VK_UP:
279             if (mHighlightRow > 0)
280             {
281                 mRecentList[mHighlightRow].Invalidate();
282                 mHighlightRow--;
283                 mRecentList[mHighlightRow].Invalidate();
284                 mRecentList[mHighlightRow].NotifyWinEvent(EVENT_OBJECT_LIVEREGIONCHANGED, OBJID_CLIENT, CHILDID_SELF);
285             }
286             return TRUE;
287 
288         case VK_DOWN:
289             if ((mHighlightRow >= 0) && (mHighlightRow < mNumRecentProjects - 1))
290             {
291                 mRecentList[mHighlightRow].Invalidate();
292                 mHighlightRow++;
293                 mRecentList[mHighlightRow].Invalidate();
294                 mRecentList[mHighlightRow].NotifyWinEvent(EVENT_OBJECT_LIVEREGIONCHANGED, OBJID_CLIENT, CHILDID_SELF);
295             }
296             return TRUE;
297 
298         case VK_RETURN:
299             if (mHighlightRow >= 0)
300             {
301                 GetProjectView()->OpenHistoryProject(mHighlightRow);
302             }
303             return TRUE;
304         }
305     }
306 
307     return CWnd::PreTranslateMessage(pMsg);
308 }
309 
310 ///////////////////////////////////////////////////////////////////////////////
OnCtlColor(CDC * pDC,CWnd * pWnd,UINT nCtlColor)311 HBRUSH recent_list_frame::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
312 {
313     if (nCtlColor == CTLCOLOR_STATIC)
314     {
315         if ((mHighlightRow >= 0) &&
316             (&mRecentList[mHighlightRow] == pWnd))
317         {
318             pDC->SetTextColor(RGB_COLOR_WHITE);
319             pDC->SetBkMode(TRANSPARENT);
320 
321             if (GetFocus() == this)
322             {
323                 return mHiBrush;
324             }
325             else
326             {
327                 return mGrayBrush;
328             }
329         }
330     }
331 
332     return CWnd::OnCtlColor(pDC, pWnd, nCtlColor);;
333 }
334 
335 ///////////////////////////////////////////////////////////////////////////////
OnEraseBkgnd(CDC * pDC)336 BOOL recent_list_frame::OnEraseBkgnd(CDC* pDC)
337 {
338     // TODO: Add your message handler code here and/or call default
339     CBrush* pOldBrush = pDC->SelectObject(&mBgBrush);
340 
341     CRect rect;
342     pDC->GetClipBox(&rect);     // Erase the area needed
343 
344     pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
345     pDC->SelectObject(pOldBrush);
346 
347     return TRUE;
348 }
349 
350 ///////////////////////////////////////////////////////////////////////////////
OnSetFocus(CWnd * pOldWnd)351 void recent_list_frame::OnSetFocus(CWnd* pOldWnd)
352 {
353     CWnd::OnSetFocus(pOldWnd);
354 
355     if (mHighlightRow >= 0)
356     {
357         // Invalidate selected row.
358         mRecentList[mHighlightRow].Invalidate();
359 
360         // Raise a UIA LiveRegionChanged
361         // event so that a screen reader is made aware of a change to the LiveRegion.
362         // Make sure the updated text is set on the label before making this call.
363         mRecentList[mHighlightRow].NotifyWinEvent(
364             EVENT_OBJECT_LIVEREGIONCHANGED,
365             OBJID_CLIENT,
366             CHILDID_SELF);
367     }
368 }
369 
370 
OnKillFocus(CWnd * pNewWnd)371 void recent_list_frame::OnKillFocus(CWnd* pNewWnd)
372 {
373     CWnd::OnKillFocus(pNewWnd);
374 
375     if (mHighlightRow >= 0)
376     {
377         // Invalidate selected row.
378         mRecentList[mHighlightRow].Invalidate();
379     }
380 }
381