1 #include "studiox_includes.h"
2 
3 #ifdef _DEBUG
4 #define new DEBUG_NEW
5 #endif
6 
7 enum resource_export_dlg_test_commands{
8     TEST_CHECK_BINARY_MODE = 1,
9     TEST_CHECK_RES_HEADER_GEN,
10     TEST_CHECK_RESOURCE,
11     TEST_SET_CUSTOM_RESOURCE_NAME,
12     TEST_GENERATE,
13     TEST_CANCEL
14 };
15 
BEGIN_MESSAGE_MAP(resource_export_dlg,express_dialog)16 BEGIN_MESSAGE_MAP(resource_export_dlg, express_dialog)
17     ON_BN_CLICKED(IDOK, &resource_export_dlg::OnBnClickedOk)
18     ON_MESSAGE(STUDIO_TEST, OnTestMessage)
19     ON_BN_CLICKED(IDC_CUSTOM_RESOURCE, &resource_export_dlg::OnBnClickedCustomResource)
20     ON_BN_CLICKED(IDC_BINARY_FORMAT_SREC, &resource_export_dlg::OnSelectSRecord)
21     ON_BN_CLICKED(IDC_BINARY_FORMAT_BIN, &resource_export_dlg::OnSelectBinary)
22 END_MESSAGE_MAP()
23 
24 IMPLEMENT_DYNAMIC(resource_export_dlg, express_dialog)
25 
26 
27 /////////////////////////////////////////////////////////////////////////////////////
28 resource_export_dlg::resource_export_dlg(CWnd *pParent)
29     : express_dialog(resource_export_dlg::IDD, pParent)
30 {
31     IconId = IDB_CHECK;
32     SetTitleText("Select Export Resources");
33     b_modified = FALSE;
34 }
35 
36 /////////////////////////////////////////////////////////////////////////////////////
~resource_export_dlg()37 resource_export_dlg::~resource_export_dlg()
38 {
39 }
40 
41 /////////////////////////////////////////////////////////////////////////////////////
DoDataExchange(CDataExchange * pDX)42 void resource_export_dlg::DoDataExchange(CDataExchange* pDX)
43 {
44     // TODO: Add your specialized code here and/or call the base class
45     DDX_Control(pDX, IDC_RES_VIEW, mResView);
46 
47     studiox_project *project = GetOpenProject();
48     CString text;
49 
50     if (pDX->m_bSaveAndValidate)
51     {
52         CButton *pCheck = (CButton *)GetDlgItem(IDC_BINARY_MODE);
53         if(pCheck->GetCheck() !=project->mHeader.gen_binary)
54         {
55             project->mHeader.gen_binary = pCheck->GetCheck();
56             b_modified = TRUE;
57         }
58 
59         ULONG binary_format;
60         ULONG memory_offset;
61         pCheck = (CButton *)GetDlgItem(IDC_BINARY_FORMAT_SREC);
62         if (pCheck->GetCheck())
63         {
64             binary_format = BINARY_FILE_FORMAT_SREC;
65         }
66         else
67         {
68             binary_format = BINARY_FILE_FORMAT_BIN;
69         }
70 
71         GetDlgItemText(IDC_MEM_OFFSET_EDIT, text);
72         memory_offset = _tcstoul(text.GetBuffer(), NULL, 16);
73 
74         if (binary_format != project->mHeader.binary_file_format ||
75             memory_offset != project->mHeader.memory_offset)
76         {
77             project->mHeader.binary_file_format = binary_format;
78             project->mHeader.memory_offset = memory_offset;
79             b_modified = TRUE;
80         }
81 
82         pCheck = (CButton *)GetDlgItem(IDC_GEN_RES_HEADER);
83         if (pCheck->GetCheck() != project->mHeader.gen_res_header)
84         {
85             project->mHeader.gen_res_header = pCheck->GetCheck();
86             b_modified = TRUE;
87         }
88 
89         pCheck = (CButton *)GetDlgItem(IDC_CUSTOM_RESOURCE);
90         if (pCheck->GetCheck() != project->mHeader.custom_resource_enabled)
91         {
92             project->mHeader.custom_resource_enabled = pCheck->GetCheck();
93             b_modified = TRUE;
94         }
95 
96         if (project->mHeader.custom_resource_enabled)
97         {
98             CString custom_resource_file_name;
99             GetDlgItemText(IDC_CUSTOM_RESOURCE_FILE_NAME, custom_resource_file_name);
100 
101             if (custom_resource_file_name.Compare(project->mHeader.custom_resource_file_name))
102             {
103                 project->mHeader.custom_resource_file_name = custom_resource_file_name;
104                 b_modified = TRUE;
105             }
106         }
107     }
108     else
109     {
110         DDX_Check(pDX, IDC_BINARY_MODE, project->mHeader.gen_binary);
111         DDX_Check(pDX, IDC_GEN_RES_HEADER, project->mHeader.gen_res_header);
112         DDX_Check(pDX, IDC_CUSTOM_RESOURCE, project->mHeader.custom_resource_enabled);
113 
114         int check;
115         check = project->mHeader.binary_file_format & BINARY_FILE_FORMAT_BIN;
116         ((CButton *)GetDlgItem(IDC_BINARY_FORMAT_BIN))->SetCheck(check);
117         check = project->mHeader.binary_file_format & BINARY_FILE_FORMAT_SREC;
118         ((CButton *)GetDlgItem(IDC_BINARY_FORMAT_SREC))->SetCheck(check);
119 
120         if (project->mHeader.memory_offset <= 0xffff)
121         {
122             text.Format(_T("%04x"), project->mHeader.memory_offset);
123         }
124         else if (project->mHeader.memory_offset < 0xffffff)
125         {
126             text.Format(_T("%06x"), project->mHeader.memory_offset);
127         }
128         else
129         {
130             text.Format(_T("%08x"), project->mHeader.memory_offset);
131         }
132         SetDlgItemText(IDC_MEM_OFFSET_EDIT, text);
133         ShowHideMemoryOffset();
134 
135         if (project->mHeader.custom_resource_enabled)
136         {
137             GetDlgItem(IDC_CUSTOM_RESOURCE_FILE_NAME)->ShowWindow(TRUE);
138             SetDlgItemText(IDC_CUSTOM_RESOURCE_FILE_NAME, project->mHeader.custom_resource_file_name);
139         }
140         else
141         {
142             GetDlgItem(IDC_CUSTOM_RESOURCE_FILE_NAME)->ShowWindow(FALSE);
143         }
144     }
145 
146     express_dialog::DoDataExchange(pDX);
147 }
148 
149 /////////////////////////////////////////////////////////////////////////////////////
OnBnClickedCustomResource()150 void resource_export_dlg::OnBnClickedCustomResource()
151 {
152     // TODO: Add your control notification handler code here
153     CButton *binary = (CButton *)GetDlgItem(IDC_CUSTOM_RESOURCE);
154 
155     if (binary->GetCheck())
156     {
157         GetDlgItem(IDC_CUSTOM_RESOURCE_FILE_NAME)->ShowWindow(TRUE);
158     }
159     else
160     {
161         GetDlgItem(IDC_CUSTOM_RESOURCE_FILE_NAME)->ShowWindow(FALSE);
162     }
163 }
164 
165 /////////////////////////////////////////////////////////////////////////////////////
OnSelectSRecord()166 void resource_export_dlg::OnSelectSRecord()
167 {
168     ShowHideMemoryOffset();
169 }
170 
171 /////////////////////////////////////////////////////////////////////////////////////
OnSelectBinary()172 void resource_export_dlg::OnSelectBinary()
173 {
174     ShowHideMemoryOffset();
175 }
176 
177 /////////////////////////////////////////////////////////////////////////////////////
OnInitDialog()178 BOOL resource_export_dlg::OnInitDialog()
179 {
180     express_dialog::OnInitDialog();
181 
182     AddCancelButton();
183     AddSaveButton(_T("Generate"));
184 
185     SetControlAccessibleName(mResView.GetSafeHwnd(), _T("select export resource"));
186     SetControlAccessibleName(GetDlgItem(IDC_CUSTOM_RESOURCE_FILE_NAME)->GetSafeHwnd(), _T("resource file name"));
187     mResView.InitImageList();
188     PopulateResourceTree();
189 
190     return TRUE;
191 }
192 
193 /////////////////////////////////////////////////////////////////////////////////////
OnBnClickedOk()194 void resource_export_dlg::OnBnClickedOk()
195 {
196     express_dialog::OnOK();
197 
198     SaveChecks();
199 
200     if (b_modified)
201     {
202         studiox_project *project = GetOpenProject();
203 
204         project->SetModified();
205     }
206 }
207 
208 /////////////////////////////////////////////////////////////////////////////////////
ShowHideMemoryOffset()209 void resource_export_dlg::ShowHideMemoryOffset()
210 {
211     int check = ((CButton *)GetDlgItem(IDC_BINARY_FORMAT_SREC))->GetCheck();
212 
213     GetDlgItem(IDC_MEM_OFFSET_LABEL)->ShowWindow(check);
214     GetDlgItem(IDC_MEM_OFFSET_EDIT)->ShowWindow(check);
215 }
216 
217 /////////////////////////////////////////////////////////////////////////////////////
PopulateResourceTree()218 void resource_export_dlg::PopulateResourceTree()
219 {
220     HTREEITEM hDisplays;
221 
222     hDisplays = mResView.InsertItem(_T("Displays"));
223     AddDisplays(hDisplays);
224     mResView.Expand(hDisplays, TVE_EXPAND);
225 
226     mResView.SelectSetFirstVisible(mResView.GetRootItem());
227 }
228 
229 /////////////////////////////////////////////////////////////////////////////////////
SaveChecks()230 void resource_export_dlg::SaveChecks()
231 {
232     HTREEITEM hRoot = mResView.GetRootItem();
233     HTREEITEM hCurrent;
234 
235     hCurrent = mResView.FindItem(hRoot, _T("Displays"));
236     SaveDisplayChecks(hCurrent);
237 }
238 
239 
240 /////////////////////////////////////////////////////////////////////////////////////
AddDisplays(HTREEITEM hParent)241 void resource_export_dlg::AddDisplays(HTREEITEM hParent)
242 {
243     studiox_project *project = GetOpenProject();
244 
245     if (!project)
246     {
247         return;
248     }
249 
250     int state;
251 
252     for (int display = 0; display < project->mHeader.num_displays; display++)
253     {
254         HTREEITEM hDisplay = mResView.InsertItem(project->mDisplays[display].name, hParent);
255 
256         for (int theme = 0; theme < project->mDisplays[display].num_themes; theme++)
257         {
258             HTREEITEM hTheme = mResView.InsertItem(project->mDisplays[display].themes[theme].theme_name, hDisplay);
259 
260             HTREEITEM hThemeResource = mResView.InsertItem(_T("color table"), hTheme);
261             if (project->mDisplays[display].themes[theme].gen_color_table)
262             {
263                 mResView.SetItemState(hThemeResource, CUSTOM_TV_STATE_CHECKED);
264             }
265             else
266             {
267                 mResView.SetItemState(hThemeResource, CUSTOM_TV_STATE_UNCHECKED);
268             }
269 
270             hThemeResource = mResView.InsertItem(_T("font table"), hTheme);
271             if (project->mDisplays[display].themes[theme].gen_font_table)
272             {
273                 mResView.SetItemState(hThemeResource, CUSTOM_TV_STATE_CHECKED);
274             }
275             else
276             {
277                 mResView.SetItemState(hThemeResource, CUSTOM_TV_STATE_UNCHECKED);
278             }
279 
280             hThemeResource = mResView.InsertItem(_T("pixelmap table"), hTheme);
281             if (project->mDisplays[display].themes[theme].gen_pixelmap_table)
282             {
283                 mResView.SetItemState(hThemeResource, CUSTOM_TV_STATE_CHECKED);
284             }
285             else
286             {
287                 mResView.SetItemState(hThemeResource, CUSTOM_TV_STATE_UNCHECKED);
288             }
289 
290             state = mResView.GetChildrenState(hTheme);
291             mResView.SetItemState(hTheme, state);
292 
293             mResView.Expand(hTheme, TVE_EXPAND);
294         }
295 
296         HTREEITEM hLanguage = mResView.InsertItem(_T("Languages"), hDisplay);
297         AddLanguages(hLanguage, display);
298         mResView.Expand(hLanguage, TVE_EXPAND);
299 
300         state = mResView.GetChildrenState(hDisplay);
301         mResView.SetItemState(hDisplay, state);
302 
303         mResView.Expand(hDisplay, TVE_EXPAND);
304     }
305 
306     state = mResView.GetChildrenState(hParent);
307     mResView.SetItemState(hParent, state);
308 }
309 
310 /////////////////////////////////////////////////////////////////////////////////////
AddLanguages(HTREEITEM hParent,int display_index)311 void resource_export_dlg::AddLanguages(HTREEITEM hParent, int display_index)
312 {
313     studiox_project *project = GetOpenProject();
314 
315     if (!project)
316     {
317         return;
318     }
319 
320 
321     for (int index = 0; index < project->mHeader.num_languages; index++)
322     {
323         HTREEITEM hLanguage = mResView.InsertItem(project->mHeader.languages[index].name, hParent);
324 
325         if (project->mDisplays[display_index].gen_string_table[index])
326         {
327             mResView.SetItemState(hLanguage, CUSTOM_TV_STATE_CHECKED);
328         }
329         else
330         {
331             mResView.SetItemState(hLanguage, CUSTOM_TV_STATE_UNCHECKED);
332         }
333     }
334 
335     int state = mResView.GetChildrenState(hParent);
336     mResView.SetItemState(hParent, state);
337 }
338 
339 /////////////////////////////////////////////////////////////////////////////////////
SaveDisplayChecks(HTREEITEM hParent)340 void resource_export_dlg::SaveDisplayChecks(HTREEITEM hParent)
341 {
342     studiox_project *project = GetOpenProject();
343 
344     if ((!project) || (!hParent))
345     {
346         return;
347     }
348 
349     HTREEITEM hDisplay = mResView.GetChildItem(hParent);
350     UINT state;
351     BOOL enabled = TRUE;
352 
353     for (int display = 0; display < project->mHeader.num_displays; display++)
354     {
355         if (hDisplay)
356         {
357             state = mResView.GetItemCheckState(hDisplay);
358 
359             if (state == CUSTOM_TV_STATE_UNCHECKED)
360             {
361                 enabled = FALSE;
362             }
363             else
364             {
365                 enabled = TRUE;
366             }
367 
368             if (project->mDisplays[display].enabled != enabled)
369             {
370                 project->mDisplays[display].enabled = enabled;
371                 b_modified = TRUE;
372             }
373 
374             HTREEITEM hTheme = mResView.GetChildItem(hDisplay);
375 
376             for (int theme = 0; theme < project->mDisplays[display].num_themes; theme++)
377             {
378                 state = mResView.GetItemCheckState(hTheme);
379 
380                 if (state == CUSTOM_TV_STATE_UNCHECKED)
381                 {
382                     enabled = FALSE;
383                 }
384                 else
385                 {
386                     enabled = TRUE;
387                 }
388 
389                 if (project->mDisplays[display].themes[theme].enabled != enabled)
390                 {
391                     project->mDisplays[display].themes[theme].enabled = enabled;
392                     b_modified = TRUE;
393                 }
394 
395                 HTREEITEM hThemeResource = mResView.FindItem(hTheme, _T("color table"));
396                 state = mResView.GetItemCheckState(hThemeResource);
397 
398                 if (state == CUSTOM_TV_STATE_UNCHECKED)
399                 {
400                     enabled = FALSE;
401                 }
402                 else
403                 {
404                     enabled = TRUE;
405                 }
406 
407                 if (project->mDisplays[display].themes[theme].gen_color_table != enabled)
408                 {
409                     project->mDisplays[display].themes[theme].gen_color_table = enabled;
410                     b_modified = TRUE;
411                 }
412 
413                 hThemeResource = mResView.FindItem(hTheme, _T("font table"));
414 
415                 state = mResView.GetItemCheckState(hThemeResource);
416 
417                 if (state == CUSTOM_TV_STATE_UNCHECKED)
418                 {
419                     enabled = FALSE;
420                 }
421                 else
422                 {
423                     enabled = TRUE;
424                 }
425 
426                 project->mDisplays[display].themes[theme].gen_font_table = enabled;
427 
428                 hThemeResource = mResView.FindItem(hTheme, _T("pixelmap table"));
429 
430                 state = mResView.GetItemCheckState(hThemeResource);
431 
432                 if (state == CUSTOM_TV_STATE_UNCHECKED)
433                 {
434                     enabled = FALSE;
435                 }
436                 else
437                 {
438                     enabled = TRUE;
439                 }
440 
441                 if (project->mDisplays[display].themes[theme].gen_pixelmap_table != enabled)
442                 {
443                     project->mDisplays[display].themes[theme].gen_pixelmap_table = enabled;
444                     b_modified = TRUE;
445                 }
446 
447                 hTheme = mResView.GetNextSiblingItem(hTheme);
448             }
449 
450             HTREEITEM hLanguage = mResView.FindItem(hDisplay, _T("Languages"));
451             SaveLanguageChecks(hLanguage, display);
452         }
453 
454         hDisplay = mResView.GetNextSiblingItem(hDisplay);
455     }
456 }
457 
458 /////////////////////////////////////////////////////////////////////////////////////
SaveLanguageChecks(HTREEITEM hParent,int display_index)459 void resource_export_dlg::SaveLanguageChecks(HTREEITEM hParent, int display_index)
460 {
461     studiox_project *project = GetOpenProject();
462 
463     if ((!project) || (!hParent))
464     {
465         return;
466     }
467 
468     HTREEITEM hChild = mResView.GetChildItem(hParent);
469     UINT state;
470     BOOL enabled;
471 
472     for (int index = 0; index < project->mHeader.num_languages; index++)
473     {
474         if (hChild)
475         {
476             state = mResView.GetItemCheckState(hChild);
477 
478             if (state == CUSTOM_TV_STATE_UNCHECKED)
479             {
480                 enabled = FALSE;
481             }
482             else
483             {
484                 enabled = TRUE;
485             }
486 
487             if (project->mDisplays[display_index].gen_string_table[index] != enabled)
488             {
489                 project->mDisplays[display_index].gen_string_table[index] = enabled;
490                 b_modified = TRUE;
491             }
492         }
493 
494         hChild = mResView.GetNextSiblingItem(hChild);
495     }
496 }
497 
498 /////////////////////////////////////////////////////////////////////////////////////
PreTranslateMessage(MSG * pMsg)499 BOOL resource_export_dlg::PreTranslateMessage(MSG* pMsg)
500 {
501     // TODO: Add your specialized code here and/or call the base class
502     CWnd* focus_owner = GetFocus();
503 
504     if (focus_owner &&
505         (focus_owner->GetDlgCtrlID() == IDC_MEM_OFFSET_EDIT) &&
506         (pMsg->message == WM_CHAR) &&
507         isprint(pMsg->wParam))
508     {
509         if (pMsg->wParam < '0' || pMsg->wParam > '9')
510         {
511             ErrorMsg("Unaccetable Character. You can only type a number here.", this);
512             return TRUE;
513         }
514     }
515 
516     return express_dialog::PreTranslateMessage(pMsg);
517 }
518 
519 /////////////////////////////////////////////////////////////////////////////////////
OnTestMessage(WPARAM wParam,LPARAM lParam)520 LRESULT resource_export_dlg::OnTestMessage(WPARAM wParam, LPARAM lParam)
521 {
522     CWnd *pWnd = NULL;
523     HTREEITEM item;
524     CStringArray param;
525     CString parent_name;
526     CString resource_name;
527     int check;
528 
529     switch (wParam)
530     {
531     case TEST_CHECK_BINARY_MODE:
532         pWnd = (CButton *)GetDlgItem(IDC_BINARY_MODE);
533         ((CButton *)pWnd)->SetCheck(lParam);
534         SendMessage(WM_COMMAND, MAKEWPARAM(IDC_BINARY_MODE, BN_CLICKED), (LPARAM)pWnd->m_hWnd);
535         break;
536 
537     case TEST_CHECK_RES_HEADER_GEN:
538         pWnd = (CButton *)GetDlgItem(IDC_GEN_RES_HEADER);
539         ((CButton *)pWnd)->SetCheck(lParam);
540         SendMessage(WM_COMMAND, MAKEWPARAM(IDC_GEN_RES_HEADER, BN_CLICKED), (LPARAM)pWnd->m_hWnd);
541         break;
542 
543     case TEST_CHECK_RESOURCE:
544         SplitString(GetTestingParam(0), ',', &param);
545         parent_name = param.GetAt(0);
546         resource_name = param.GetAt(1);
547         check = _tstoi(param.GetAt(2));
548         item = mResView.FindItem(mResView.GetRootItem(), parent_name);
549         if (item)
550         {
551             item = mResView.FindItem(item, resource_name);
552 
553             if (check)
554             {
555                 mResView.SetItemState(item, CUSTOM_TV_STATE_CHECKED);
556             }
557             else
558             {
559                 mResView.SetItemState(item, CUSTOM_TV_STATE_UNCHECKED);
560             }
561 
562             mResView.UpdateChildrenState(item);
563         }
564         break;
565 
566     case TEST_SET_CUSTOM_RESOURCE_NAME:
567         // check on "specify reousrce file name"
568         pWnd = (CButton *)GetDlgItem(IDC_CUSTOM_RESOURCE);
569         ((CButton *)pWnd)->SetCheck(TRUE);
570         SendMessage(WM_COMMAND, MAKEWPARAM(IDC_CUSTOM_RESOURCE, BN_CLICKED), (LPARAM)pWnd->m_hWnd);
571 
572         // set custom resource file name
573         SetDlgItemText(IDC_CUSTOM_RESOURCE_FILE_NAME, GetTestingParam(0));
574         break;
575 
576     case TEST_GENERATE:
577         OnBnClickedOk();
578         break;
579 
580     case TEST_CANCEL:
581         OnCancel();
582         break;
583     }
584 
585     return 0;
586 }
587 
BEGIN_MESSAGE_MAP(CustomTreeCtrl,CTreeCtrl)588 BEGIN_MESSAGE_MAP(CustomTreeCtrl, CTreeCtrl)
589     ON_NOTIFY_REFLECT(NM_CLICK, &CustomTreeCtrl::OnNMClick)
590     ON_NOTIFY_REFLECT(TVN_KEYDOWN, &CustomTreeCtrl::OnTvnKeydown)
591     ON_NOTIFY_REFLECT(TVN_SELCHANGED, &CustomTreeCtrl::OnNodeSelect)
592 END_MESSAGE_MAP()
593 
594 /////////////////////////////////////////////////////////////////////////////////////
595 void CustomTreeCtrl::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
596 {
597     POINT pt;
598     GetCursorPos(&pt);
599     ScreenToClient(&pt);
600     TVHITTESTINFO hti;
601     hti.pt.x = pt.x;
602     hti.pt.y = pt.y;
603     HitTest(&hti);
604 
605     if (hti.flags & TVHT_ONITEMSTATEICON)
606     {
607         SelectItem(hti.hItem);
608         OnSelectItem(hti.hItem);
609     }
610 
611     *pResult = 0;
612 }
613 
614 /////////////////////////////////////////////////////////////////////////////////////
OnTvnKeydown(NMHDR * pNMHDR,LRESULT * pResult)615 void CustomTreeCtrl::OnTvnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
616 {
617     LPNMTVKEYDOWN pTVKeyDown = reinterpret_cast<LPNMTVKEYDOWN>(pNMHDR);
618     // TODO: Add your control notification handler code here
619     if (pTVKeyDown->wVKey == VK_SPACE)
620     {
621         HTREEITEM item = GetSelectedItem();
622 
623         if (item != NULL)
624 
625         {
626             OnSelectItem(item);
627         }
628     }
629 
630     *pResult = 0;
631 }
632 
OnSelectItem(HTREEITEM hItem)633 void CustomTreeCtrl::OnSelectItem(HTREEITEM hItem)
634 {
635     UINT state = GetItemCheckState(hItem);
636 
637     switch (state)
638     {
639     case CUSTOM_TV_STATE_UNCHECKED:
640         break;
641     case CUSTOM_TV_STATE_CHECKED:
642         state = CUSTOM_TV_STATE_PARTIAL_CHECKED;
643         break;
644     case CUSTOM_TV_STATE_PARTIAL_CHECKED:
645         break;
646     }
647 
648     // temporarily change item status
649     SetItemState(hItem, 1 + (state % 3));
650 
651     // update parent state
652     UpdateParentState(hItem);
653 
654     // update children state
655     UpdateChildrenState(hItem);
656 
657     // revert item status
658     SetItemState(hItem, state);
659 
660     CWnd* parent = GetParent();
661 
662     if (parent)
663     {
664         parent->PostMessage(USR_MSG_CHECK_STATE_CHANGE, 1 + (state % 3), (LPARAM)hItem);
665     }
666 }
667 
668 /////////////////////////////////////////////////////////////////////////////////////
OnNodeSelect(NMHDR * ph,LRESULT * pr)669 void CustomTreeCtrl::OnNodeSelect(NMHDR* ph, LRESULT* pr)
670 {
671     HTREEITEM hItem = GetSelectedItem();
672 
673     CWnd* parent = GetParent();
674 
675     if (parent)
676     {
677         parent->PostMessage(USR_MSG_NODE_SELECT, 0, (LPARAM)hItem);
678     }
679 }
680 
681 /////////////////////////////////////////////////////////////////////////////////////
InitImageList()682 void CustomTreeCtrl::InitImageList()
683 {
684     mImageList.Create(16, 16, ILC_COLOR24, 0, 4);
685     CBitmap image;
686     BITMAP  bitmap;
687 
688     image.LoadBitmap(IDB_UNCHECK);
689     image.GetBitmap(&bitmap);
690 
691     //Set item height
692     int height = MulDiv(bitmap.bmHeight, GetSystemDPI(), DEFAULT_DPI_96);
693     SetItemHeight((SHORT)(height + 3));
694 
695     mImageList.Add(&image, RGB(255, 55, 255));
696     mImageList.Add(&image, RGB(255, 55, 255));
697     image.DeleteObject();
698 
699     image.LoadBitmap(IDB_CHECKBOX);
700     mImageList.Add(&image, RGB(255, 55, 255));
701     image.DeleteObject();
702 
703     image.LoadBitmap(IDB_PARTIAL_CHECK);
704     mImageList.Add(&image, RGB(255, 55, 255));
705 
706     //Set image list for the tree view
707     SetImageList(&mImageList, TVSIL_STATE);
708 }
709 
710 /////////////////////////////////////////////////////////////////////////////////////
GetItemCheckState(HTREEITEM hItem)711 UINT CustomTreeCtrl::GetItemCheckState(HTREEITEM hItem)
712 {
713     UINT state = CTreeCtrl::GetItemState(hItem, LVIS_STATEIMAGEMASK);
714 
715     state &= LVIS_STATEIMAGEMASK;
716 
717     switch (state)
718     {
719     case INDEXTOSTATEIMAGEMASK(2):
720         return CUSTOM_TV_STATE_CHECKED;
721 
722     case INDEXTOSTATEIMAGEMASK(3):
723         return CUSTOM_TV_STATE_PARTIAL_CHECKED;
724 
725     default:
726         return CUSTOM_TV_STATE_UNCHECKED;
727     }
728 }
729 
730 /////////////////////////////////////////////////////////////////////////////////////
SelectAllChildren(HTREEITEM hParent,BOOL bFlag)731 void CustomTreeCtrl::SelectAllChildren(HTREEITEM hParent, BOOL bFlag)
732 {
733     HTREEITEM hChild;
734 
735     hChild = GetChildItem(hParent);
736 
737     while (hChild)
738     {
739         SetItemState(hChild, CUSTOM_TV_STATE_CHECKED);
740 
741         SelectAllChildren(hChild, bFlag);
742 
743         hChild = GetNextSiblingItem(hChild);
744     }
745 }
746 
747 /////////////////////////////////////////////////////////////////////////////////////
GetChildrenState(HTREEITEM hParent)748 UINT CustomTreeCtrl::GetChildrenState(HTREEITEM hParent)
749 {
750     HTREEITEM hChild;
751 
752     hChild = GetChildItem(hParent);
753 
754     int check_count = 0;
755     int uncheck_count = 0;
756 
757     while (hChild)
758     {
759         UINT state = GetItemCheckState(hChild);
760 
761         switch (state)
762         {
763         case CUSTOM_TV_STATE_UNCHECKED:
764             uncheck_count++;
765             break;
766 
767         case CUSTOM_TV_STATE_CHECKED:
768             check_count++;
769             break;
770 
771         case CUSTOM_TV_STATE_PARTIAL_CHECKED:
772             return CUSTOM_TV_STATE_PARTIAL_CHECKED;
773 
774         default:
775             break;
776         }
777 
778         hChild = GetNextSiblingItem(hChild);
779     }
780 
781     if (check_count && uncheck_count)
782     {
783         return CUSTOM_TV_STATE_PARTIAL_CHECKED;
784     }
785     else if (check_count == 0)
786     {
787         return CUSTOM_TV_STATE_UNCHECKED;
788     }
789     else
790     {
791         return CUSTOM_TV_STATE_CHECKED;
792     }
793 }
794 
795 /////////////////////////////////////////////////////////////////////////////////////
SetItemState(HTREEITEM hItem,int state)796 void CustomTreeCtrl::SetItemState(HTREEITEM hItem, int state)
797 {
798     switch (state)
799     {
800     case CUSTOM_TV_STATE_UNCHECKED:
801         state = INDEXTOSTATEIMAGEMASK(1);
802         break;
803 
804     case CUSTOM_TV_STATE_CHECKED:
805         state = INDEXTOSTATEIMAGEMASK(2);
806         break;
807 
808     case CUSTOM_TV_STATE_PARTIAL_CHECKED:
809         state = INDEXTOSTATEIMAGEMASK(3);
810         break;
811 
812     default:
813         break;
814     }
815 
816     CTreeCtrl::SetItemState(hItem, state, TVIS_STATEIMAGEMASK);
817 }
818 
819 
820 /////////////////////////////////////////////////////////////////////////////////////
FindItem(HTREEITEM hStart,CString text)821 HTREEITEM CustomTreeCtrl::FindItem(HTREEITEM hStart, CString text)
822 {
823     HTREEITEM hResult = NULL;
824 
825     while (hStart)
826     {
827         CString item_text = GetItemText(hStart);
828         if (item_text.Compare(text) == 0)
829         {
830             hResult = hStart;
831             break;
832         }
833 
834         HTREEITEM hChild = GetChildItem(hStart);
835         if (hChild)
836         {
837             hResult = FindItem(hChild, text);
838 
839             if (hResult)
840             {
841                 break;
842             }
843         }
844 
845         hStart = GetNextSiblingItem(hStart);
846     }
847 
848     return hResult;
849 }
850 
851 /////////////////////////////////////////////////////////////////////////////////////
UpdateParentState(HTREEITEM hChild)852 void CustomTreeCtrl::UpdateParentState(HTREEITEM hChild)
853 {
854     HTREEITEM hParent;
855 
856     hParent = GetParentItem(hChild);
857 
858     if (hParent)
859     {
860         UINT state = GetChildrenState(hParent);
861         SetItemState(hParent, state);
862 
863         UpdateParentState(hParent);
864     }
865 }
866 
867 /////////////////////////////////////////////////////////////////////////////////////
UpdateChildrenState(HTREEITEM hParent)868 void CustomTreeCtrl::UpdateChildrenState(HTREEITEM hParent)
869 {
870     HTREEITEM hChild;
871 
872     hChild = GetChildItem(hParent);
873 
874     UINT state = GetItemCheckState(hParent);
875 
876     while (hChild)
877     {
878         SetItemState(hChild, state);
879 
880         UpdateChildrenState(hChild);
881 
882         hChild = GetNextSiblingItem(hChild);
883     }
884 }
885