2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * FILE: base/applications/rapps/gui.cpp
5 * PURPOSE: GUI classes for RAPPS
6 * COPYRIGHT: Copyright 2015 David Quintana (gigaherz@gmail.com)
7 * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
12 #include "crichedit.h"
14 #include "asyncinet.h"
18 #include <shlobj_undoc.h>
19 #include <shlguid_undoc.h>
26 #include <shellutils.h>
31 #define SEARCH_TIMER_ID 'SR'
32 #define TREEVIEW_ICON_SIZE 24
36 // **** CSideTreeView ****
38 CSideTreeView::CSideTreeView() :
40 hImageTreeView(ImageList_Create(TREEVIEW_ICON_SIZE
, TREEVIEW_ICON_SIZE
,
41 GetSystemColorDepth() | ILC_MASK
,
46 HTREEITEM
CSideTreeView::AddItem(HTREEITEM hParent
, ATL::CStringW
&Text
, INT Image
, INT SelectedImage
, LPARAM lParam
)
48 return CUiWindow
<CTreeView
>::AddItem(hParent
, const_cast<LPWSTR
>(Text
.GetString()), Image
, SelectedImage
, lParam
);
51 HTREEITEM
CSideTreeView::AddCategory(HTREEITEM hRootItem
, UINT TextIndex
, UINT IconIndex
)
57 hIcon
= (HICON
)LoadImageW(hInst
,
58 MAKEINTRESOURCE(IconIndex
),
65 Index
= ImageList_AddIcon(hImageTreeView
, hIcon
);
69 szText
.LoadStringW(TextIndex
);
70 return AddItem(hRootItem
, szText
, Index
, Index
, TextIndex
);
73 HIMAGELIST
CSideTreeView::SetImageList()
75 return CUiWindow
<CTreeView
>::SetImageList(hImageTreeView
, TVSIL_NORMAL
);
78 VOID
CSideTreeView::DestroyImageList()
81 ImageList_Destroy(hImageTreeView
);
84 CSideTreeView::~CSideTreeView()
88 // **** CSideTreeView ****
92 // **** CMainWindow ****
94 CMainWindow::CMainWindow() :
96 SelectedEnumType(ENUM_ALL_INSTALLED
)
100 CMainWindow::~CMainWindow()
105 VOID
CMainWindow::InitCategoriesList()
107 HTREEITEM hRootItemInstalled
, hRootItemAvailable
;
109 hRootItemInstalled
= m_TreeView
->AddCategory(TVI_ROOT
, IDS_INSTALLED
, IDI_CATEGORY
);
110 m_TreeView
->AddCategory(hRootItemInstalled
, IDS_APPLICATIONS
, IDI_APPS
);
111 m_TreeView
->AddCategory(hRootItemInstalled
, IDS_UPDATES
, IDI_APPUPD
);
113 m_TreeView
->AddCategory(TVI_ROOT
, IDS_SELECTEDFORINST
, IDI_SELECTEDFORINST
);
115 hRootItemAvailable
= m_TreeView
->AddCategory(TVI_ROOT
, IDS_AVAILABLEFORINST
, IDI_CATEGORY
);
116 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_AUDIO
, IDI_CAT_AUDIO
);
117 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_VIDEO
, IDI_CAT_VIDEO
);
118 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_GRAPHICS
, IDI_CAT_GRAPHICS
);
119 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_GAMES
, IDI_CAT_GAMES
);
120 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_INTERNET
, IDI_CAT_INTERNET
);
121 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_OFFICE
, IDI_CAT_OFFICE
);
122 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_DEVEL
, IDI_CAT_DEVEL
);
123 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_EDU
, IDI_CAT_EDU
);
124 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_ENGINEER
, IDI_CAT_ENGINEER
);
125 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_FINANCE
, IDI_CAT_FINANCE
);
126 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_SCIENCE
, IDI_CAT_SCIENCE
);
127 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_TOOLS
, IDI_CAT_TOOLS
);
128 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_DRIVERS
, IDI_CAT_DRIVERS
);
129 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_LIBS
, IDI_CAT_LIBS
);
130 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_THEMES
, IDI_CAT_THEMES
);
131 m_TreeView
->AddCategory(hRootItemAvailable
, IDS_CAT_OTHER
, IDI_CAT_OTHER
);
133 m_TreeView
->SetImageList();
134 m_TreeView
->Expand(hRootItemInstalled
, TVE_EXPAND
);
135 m_TreeView
->Expand(hRootItemAvailable
, TVE_EXPAND
);
136 m_TreeView
->SelectItem(hRootItemAvailable
);
139 BOOL
CMainWindow::CreateStatusBar()
141 m_StatusBar
= new CUiWindow
<CStatusBar
>();
142 m_StatusBar
->m_VerticalAlignment
= UiAlign_RightBtm
;
143 m_StatusBar
->m_HorizontalAlignment
= UiAlign_Stretch
;
144 m_ClientPanel
->Children().Append(m_StatusBar
);
146 return m_StatusBar
->Create(m_hWnd
, (HMENU
)IDC_STATUSBAR
) != NULL
;
149 BOOL
CMainWindow::CreateTreeView()
151 m_TreeView
= new CSideTreeView();
152 m_TreeView
->m_VerticalAlignment
= UiAlign_Stretch
;
153 m_TreeView
->m_HorizontalAlignment
= UiAlign_Stretch
;
154 m_VSplitter
->First().Append(m_TreeView
);
156 return m_TreeView
->Create(m_hWnd
) != NULL
;
159 BOOL
CMainWindow::CreateApplicationView()
161 m_ApplicationView
= new CApplicationView(this); // pass this to ApplicationView for callback purpose
162 m_ApplicationView
->m_VerticalAlignment
= UiAlign_Stretch
;
163 m_ApplicationView
->m_HorizontalAlignment
= UiAlign_Stretch
;
164 m_VSplitter
->Second().Append(m_ApplicationView
);
166 return m_ApplicationView
->Create(m_hWnd
) != NULL
;
169 BOOL
CMainWindow::CreateVSplitter()
171 m_VSplitter
= new CUiSplitPanel();
172 m_VSplitter
->m_VerticalAlignment
= UiAlign_Stretch
;
173 m_VSplitter
->m_HorizontalAlignment
= UiAlign_Stretch
;
174 m_VSplitter
->m_DynamicFirst
= FALSE
;
175 m_VSplitter
->m_Horizontal
= FALSE
;
176 m_VSplitter
->m_MinFirst
= 0;
178 // TODO: m_MinSecond should be calculate dynamically instead of hard-coded
179 m_VSplitter
->m_MinSecond
= 480;
180 m_VSplitter
->m_Pos
= 240;
181 m_ClientPanel
->Children().Append(m_VSplitter
);
183 return m_VSplitter
->Create(m_hWnd
) != NULL
;
186 BOOL
CMainWindow::CreateLayout()
191 m_ClientPanel
= new CUiPanel();
192 m_ClientPanel
->m_VerticalAlignment
= UiAlign_Stretch
;
193 m_ClientPanel
->m_HorizontalAlignment
= UiAlign_Stretch
;
196 b
= b
&& CreateStatusBar();
197 b
= b
&& CreateVSplitter();
200 b
= b
&& CreateTreeView();
201 b
= b
&& CreateApplicationView();
207 /* Size status bar */
208 m_StatusBar
->SendMessageW(WM_SIZE
, 0, 0);
210 ::GetWindowRect(m_StatusBar
->m_hWnd
, &rBottom
);
212 m_VSplitter
->m_Margin
.bottom
= rBottom
.bottom
- rBottom
.top
;
219 VOID
CMainWindow::LayoutCleanup()
222 delete m_ApplicationView
;
228 BOOL
CMainWindow::InitControls()
232 InitCategoriesList();
234 UpdateStatusBarText();
242 VOID
CMainWindow::OnSize(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
244 if (wParam
== SIZE_MINIMIZED
)
247 /* Size status bar */
248 m_StatusBar
->SendMessage(WM_SIZE
, 0, 0);
251 RECT r
= { 0, 0, LOWORD(lParam
), HIWORD(lParam
) };
253 INT count
= m_ClientPanel
->CountSizableChildren();
255 hdwp
= BeginDeferWindowPos(count
);
258 hdwp
= m_ClientPanel
->OnParentSize(r
, hdwp
);
261 EndDeferWindowPos(hdwp
);
266 BOOL
CMainWindow::RemoveSelectedAppFromRegistry()
268 if (!IsInstalledEnum(SelectedEnumType
))
271 ATL::CStringW szMsgText
, szMsgTitle
;
273 if (!szMsgText
.LoadStringW(IDS_APP_REG_REMOVE
) ||
274 !szMsgTitle
.LoadStringW(IDS_INFORMATION
))
277 if (MessageBoxW(szMsgText
, szMsgTitle
, MB_YESNO
| MB_ICONQUESTION
) == IDYES
)
279 CInstalledApplicationInfo
*InstalledApp
= (CInstalledApplicationInfo
*)m_ApplicationView
->GetFocusedItemData();
280 LSTATUS Result
= InstalledApp
->RemoveFromRegistry();
281 if (Result
!= ERROR_SUCCESS
)
283 // TODO: popup a messagebox telling user it fails somehow
287 // as it's already removed form registry, this will also remove it from the list
288 UpdateApplicationsList(-1);
295 BOOL
CMainWindow::UninstallSelectedApp(BOOL bModify
)
297 if (!IsInstalledEnum(SelectedEnumType
))
300 CInstalledApplicationInfo
*InstalledApp
= (CInstalledApplicationInfo
*)m_ApplicationView
->GetFocusedItemData();
302 return InstalledApp
->UninstallApplication(bModify
);
305 BOOL
CMainWindow::ProcessWindowMessage(HWND hwnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&theResult
, DWORD dwMapId
)
312 ::PostMessageW(hwnd
, WM_CLOSE
, 0, 0);
321 m_AvailableApps
.FreeCachedEntries();
322 m_InstalledApps
.FreeCachedEntries();
324 delete m_ClientPanel
;
331 OnCommand(wParam
, lParam
);
336 LPNMHDR data
= (LPNMHDR
)lParam
;
342 if (data
->hwndFrom
== m_TreeView
->m_hWnd
)
344 switch (((LPNMTREEVIEW
)lParam
)->itemNew
.lParam
)
347 UpdateApplicationsList(ENUM_ALL_INSTALLED
);
350 case IDS_APPLICATIONS
:
351 UpdateApplicationsList(ENUM_INSTALLED_APPLICATIONS
);
355 UpdateApplicationsList(ENUM_UPDATES
);
358 case IDS_AVAILABLEFORINST
:
359 UpdateApplicationsList(ENUM_ALL_AVAILABLE
);
363 UpdateApplicationsList(ENUM_CAT_AUDIO
);
367 UpdateApplicationsList(ENUM_CAT_DEVEL
);
370 case IDS_CAT_DRIVERS
:
371 UpdateApplicationsList(ENUM_CAT_DRIVERS
);
375 UpdateApplicationsList(ENUM_CAT_EDU
);
378 case IDS_CAT_ENGINEER
:
379 UpdateApplicationsList(ENUM_CAT_ENGINEER
);
382 case IDS_CAT_FINANCE
:
383 UpdateApplicationsList(ENUM_CAT_FINANCE
);
387 UpdateApplicationsList(ENUM_CAT_GAMES
);
390 case IDS_CAT_GRAPHICS
:
391 UpdateApplicationsList(ENUM_CAT_GRAPHICS
);
394 case IDS_CAT_INTERNET
:
395 UpdateApplicationsList(ENUM_CAT_INTERNET
);
399 UpdateApplicationsList(ENUM_CAT_LIBS
);
403 UpdateApplicationsList(ENUM_CAT_OFFICE
);
407 UpdateApplicationsList(ENUM_CAT_OTHER
);
410 case IDS_CAT_SCIENCE
:
411 UpdateApplicationsList(ENUM_CAT_SCIENCE
);
415 UpdateApplicationsList(ENUM_CAT_TOOLS
);
419 UpdateApplicationsList(ENUM_CAT_VIDEO
);
423 UpdateApplicationsList(ENUM_CAT_THEMES
);
426 case IDS_SELECTEDFORINST
:
427 UpdateApplicationsList(ENUM_CAT_SELECTED
);
432 HMENU mainMenu
= ::GetMenu(hwnd
);
434 /* Disable/enable items based on treeview selection */
435 if (IsSelectedNodeInstalled())
437 EnableMenuItem(mainMenu
, ID_REGREMOVE
, MF_ENABLED
);
438 EnableMenuItem(mainMenu
, ID_INSTALL
, MF_GRAYED
);
439 EnableMenuItem(mainMenu
, ID_UNINSTALL
, MF_ENABLED
);
440 EnableMenuItem(mainMenu
, ID_MODIFY
, MF_ENABLED
);
444 EnableMenuItem(mainMenu
, ID_REGREMOVE
, MF_GRAYED
);
445 EnableMenuItem(mainMenu
, ID_INSTALL
, MF_ENABLED
);
446 EnableMenuItem(mainMenu
, ID_UNINSTALL
, MF_GRAYED
);
447 EnableMenuItem(mainMenu
, ID_MODIFY
, MF_GRAYED
);
457 OnSize(hwnd
, wParam
, lParam
);
462 LPRECT pRect
= (LPRECT
)lParam
;
464 if (pRect
->right
- pRect
->left
< 565)
465 pRect
->right
= pRect
->left
+ 565;
467 if (pRect
->bottom
- pRect
->top
< 300)
468 pRect
->bottom
= pRect
->top
+ 300;
473 case WM_SYSCOLORCHANGE
:
475 /* Forward WM_SYSCOLORCHANGE to common controls */
476 m_ApplicationView
->SendMessageW(WM_SYSCOLORCHANGE
, wParam
, lParam
);
477 m_TreeView
->SendMessageW(WM_SYSCOLORCHANGE
, wParam
, lParam
);
482 if (wParam
== SEARCH_TIMER_ID
)
484 ::KillTimer(hwnd
, SEARCH_TIMER_ID
);
486 UpdateApplicationsList(-1);
494 BOOL
CMainWindow::IsSelectedNodeInstalled()
496 HTREEITEM hSelectedItem
= m_TreeView
->GetSelection();
499 tItem
.mask
= TVIF_PARAM
| TVIF_HANDLE
;
500 tItem
.hItem
= hSelectedItem
;
501 m_TreeView
->GetItem(&tItem
);
502 switch (tItem
.lParam
)
505 case IDS_APPLICATIONS
:
513 VOID
CMainWindow::ShowAboutDlg()
516 ATL::CStringW szAuthors
;
519 szApp
.LoadStringW(IDS_APPTITLE
);
520 szAuthors
.LoadStringW(IDS_APP_AUTHORS
);
521 hIcon
= LoadIconW(hInst
, MAKEINTRESOURCEW(IDI_MAIN
));
522 ShellAboutW(m_hWnd
, szApp
, szAuthors
, hIcon
);
526 VOID
CMainWindow::OnCommand(WPARAM wParam
, LPARAM lParam
)
528 WORD wCommand
= LOWORD(wParam
);
535 CreateSettingsDlg(m_hWnd
);
539 PostMessageW(WM_CLOSE
, 0, 0);
543 if (IsAvailableEnum(SelectedEnumType
))
545 ATL::CSimpleArray
<CAvailableApplicationInfo
> AppsList
;
547 // enum all selected apps
548 m_AvailableApps
.Enum(ENUM_CAT_SELECTED
, s_EnumSelectedAppForDownloadProc
, (PVOID
)&AppsList
);
550 if (AppsList
.GetSize())
552 if (DownloadListOfApplications(AppsList
, FALSE
))
554 m_AvailableApps
.RemoveAllSelected();
555 UpdateApplicationsList(-1);
560 // use the currently focused item in application-view
561 CAvailableApplicationInfo
*FocusedApps
= (CAvailableApplicationInfo
*)m_ApplicationView
->GetFocusedItemData();
564 if (DownloadApplication(FocusedApps
, FALSE
))
566 UpdateApplicationsList(-1);
571 // TODO: in this case, Install button in toolbar (and all other places) should be disabled
572 // or at least popup a messagebox telling user to select/check some app first
579 if (UninstallSelectedApp(FALSE
))
580 UpdateApplicationsList(-1);
584 if (UninstallSelectedApp(TRUE
))
585 UpdateApplicationsList(-1);
589 RemoveSelectedAppFromRegistry();
593 UpdateApplicationsList(-1);
597 CAvailableApps::ForceUpdateAppsDB();
598 UpdateApplicationsList(-1);
602 MessageBoxW(L
"Help not implemented yet", NULL
, MB_OK
);
610 m_ApplicationView
->CheckAll();
616 BOOL
CMainWindow::SearchPatternMatch(LPCWSTR szHaystack
, LPCWSTR szNeedle
)
620 /* TODO: Improve pattern search beyond a simple case-insensitive substring search. */
621 return StrStrIW(szHaystack
, szNeedle
) != NULL
;
624 BOOL CALLBACK
CMainWindow::EnumInstalledAppProc(CInstalledApplicationInfo
*Info
)
626 if (!SearchPatternMatch(Info
->szDisplayName
.GetString(), szSearchPattern
))
630 return m_ApplicationView
->AddInstalledApplication(Info
, Info
); // currently, the callback param is Info itself
633 BOOL CALLBACK
CMainWindow::EnumAvailableAppProc(CAvailableApplicationInfo
*Info
, BOOL bInitialCheckState
)
635 if (!SearchPatternMatch(Info
->m_szName
.GetString(), szSearchPattern
) &&
636 !SearchPatternMatch(Info
->m_szDesc
.GetString(), szSearchPattern
))
640 return m_ApplicationView
->AddAvailableApplication(Info
, bInitialCheckState
, Info
); // currently, the callback param is Info itself
643 BOOL CALLBACK
CMainWindow::s_EnumInstalledAppProc(CInstalledApplicationInfo
*Info
, PVOID param
)
645 CMainWindow
*pThis
= (CMainWindow
*)param
;
646 return pThis
->EnumInstalledAppProc(Info
);
649 BOOL CALLBACK
CMainWindow::s_EnumAvailableAppProc(CAvailableApplicationInfo
*Info
, BOOL bInitialCheckState
, PVOID param
)
651 CMainWindow
*pThis
= (CMainWindow
*)param
;
652 return pThis
->EnumAvailableAppProc(Info
, bInitialCheckState
);
655 BOOL CALLBACK
CMainWindow::s_EnumSelectedAppForDownloadProc(CAvailableApplicationInfo
*Info
, BOOL bInitialCheckState
, PVOID param
)
657 ATL::CSimpleArray
<CAvailableApplicationInfo
> *pAppList
= (ATL::CSimpleArray
<CAvailableApplicationInfo
> *)param
;
658 pAppList
->Add(*Info
);
662 VOID
CMainWindow::UpdateStatusBarText()
666 ATL::CStringW szBuffer
;
668 szBuffer
.Format(IDS_APPS_COUNT
, m_ApplicationView
->GetItemCount(), m_AvailableApps
.GetSelectedCount());
669 m_StatusBar
->SetText(szBuffer
);
673 VOID
CMainWindow::UpdateApplicationsList(INT EnumType
)
679 // keep the old enum type
680 EnumType
= SelectedEnumType
;
684 SelectedEnumType
= EnumType
;
687 m_ApplicationView
->SetRedraw(FALSE
);
688 if (IsInstalledEnum(EnumType
))
690 // set the display type of application-view. this will remove all the item in application-view too.
691 m_ApplicationView
->SetDisplayAppType(AppViewTypeInstalledApps
);
693 // enum installed softwares
694 m_InstalledApps
.Enum(EnumType
, s_EnumInstalledAppProc
, this);
696 else if (IsAvailableEnum(EnumType
))
698 // set the display type of application-view. this will remove all the item in application-view too.
699 m_ApplicationView
->SetDisplayAppType(AppViewTypeAvailableApps
);
701 // enum available softwares
702 m_AvailableApps
.Enum(EnumType
, s_EnumAvailableAppProc
, this);
704 m_ApplicationView
->SetRedraw(TRUE
);
705 m_ApplicationView
->RedrawWindow(0, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
); // force the child window to repaint
706 UpdateStatusBarText();
710 ATL::CWndClassInfo
&CMainWindow::GetWndClassInfo()
712 DWORD csStyle
= CS_VREDRAW
| CS_HREDRAW
;
713 static ATL::CWndClassInfo wc
=
722 LoadIconW(_AtlBaseModule
.GetModuleInstance(), MAKEINTRESOURCEW(IDI_MAIN
)),
723 LoadCursorW(NULL
, IDC_ARROW
),
724 (HBRUSH
)(COLOR_BTNFACE
+ 1),
725 MAKEINTRESOURCEW(IDR_MAINMENU
),
729 NULL
, NULL
, IDC_ARROW
, TRUE
, 0, _T("")
734 HWND
CMainWindow::Create()
736 ATL::CStringW szWindowName
;
737 szWindowName
.LoadStringW(IDS_APPTITLE
);
740 (SettingsInfo
.bSaveWndPos
? SettingsInfo
.Left
: CW_USEDEFAULT
),
741 (SettingsInfo
.bSaveWndPos
? SettingsInfo
.Top
: CW_USEDEFAULT
),
742 (SettingsInfo
.bSaveWndPos
? SettingsInfo
.Width
: 680),
743 (SettingsInfo
.bSaveWndPos
? SettingsInfo
.Height
: 450)
748 return CWindowImpl::Create(NULL
, r
, szWindowName
.GetString(), WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, WS_EX_WINDOWEDGE
);
751 // this function is called when a item of application-view is checked/unchecked
752 // CallbackParam is the param passed to application-view when adding the item (the one getting focus now).
753 BOOL
CMainWindow::ItemCheckStateChanged(BOOL bChecked
, LPVOID CallbackParam
)
759 if (!m_AvailableApps
.AddSelected((CAvailableApplicationInfo
*)CallbackParam
))
766 if (!m_AvailableApps
.RemoveSelected((CAvailableApplicationInfo
*)CallbackParam
))
772 UpdateStatusBarText();
781 // this function is called when one or more application(s) should be installed install
782 // if Info is not zero, this app should be installed. otherwise those checked apps should be installed
783 BOOL
CMainWindow::InstallApplication(CAvailableApplicationInfo
*Info
)
787 if (DownloadApplication(Info
, FALSE
))
789 UpdateApplicationsList(-1);
795 ATL::CSimpleArray
<CAvailableApplicationInfo
> AppsList
;
797 // enum all selected apps
798 m_AvailableApps
.Enum(ENUM_CAT_SELECTED
, s_EnumSelectedAppForDownloadProc
, (PVOID
)&AppsList
);
800 if (AppsList
.GetSize())
802 if (DownloadListOfApplications(AppsList
, FALSE
))
804 m_AvailableApps
.RemoveAllSelected();
805 UpdateApplicationsList(-1);
814 BOOL
CMainWindow::SearchTextChanged(ATL::CStringW
&SearchText
)
816 if (szSearchPattern
== SearchText
)
821 szSearchPattern
= SearchText
;
824 SystemParametersInfoW(SPI_GETMENUSHOWDELAY
, 0, &dwDelay
, 0);
825 SetTimer(SEARCH_TIMER_ID
, dwDelay
);
830 void CMainWindow::HandleTabOrder(int direction
)
832 ATL::CSimpleArray
<HWND
> TabOrderHwndList
;
834 m_TreeView
->AppendTabOrderWindow(direction
, TabOrderHwndList
);
835 m_ApplicationView
->AppendTabOrderWindow(direction
, TabOrderHwndList
);
838 if (TabOrderHwndList
.GetSize() == 0)
840 // in case the list is empty
846 if ((FocusIndex
= TabOrderHwndList
.Find(GetFocus())) == -1)
848 FocusIndex
= 0; // focus the first window in the list
852 FocusIndex
+= direction
;
853 FocusIndex
+= TabOrderHwndList
.GetSize(); // FocusIndex might be negative. we don't want to mod a negative number
854 FocusIndex
%= TabOrderHwndList
.GetSize();
857 ::SetFocus(TabOrderHwndList
[FocusIndex
]);
860 // **** CMainWindow ****
864 VOID
ShowMainWindow(INT nShowCmd
)
869 CMainWindow
* wnd
= new CMainWindow();
873 hMainWnd
= wnd
->Create();
877 /* Maximize it if we must */
878 wnd
->ShowWindow((SettingsInfo
.bSaveWndPos
&& SettingsInfo
.Maximized
) ? SW_MAXIMIZE
: nShowCmd
);
881 /* Load the menu hotkeys */
882 KeyBrd
= LoadAcceleratorsW(NULL
, MAKEINTRESOURCEW(HOTKEYS
));
885 while (GetMessageW(&Msg
, NULL
, 0, 0))
887 if (!TranslateAcceleratorW(hMainWnd
, KeyBrd
, &Msg
))
889 if (Msg
.message
== WM_CHAR
&&
890 Msg
.wParam
== VK_TAB
)
892 // Move backwards if shift is held down
893 int direction
= (GetKeyState(VK_SHIFT
) & 0x8000) ? -1 : 1;
895 wnd
->HandleTabOrder(direction
);
899 TranslateMessage(&Msg
);
900 DispatchMessageW(&Msg
);