1 // This file has been adapted to the Win32 version of apcctrl
2 // by Kern E. Sibbald.  Many thanks to ATT and James Weatherall,
3 // the original author, for providing an excellent template.
4 //
5 // Rewrite/Refactoring by Adam Kropelin
6 //
7 // Copyright (2009) Adam D. Kropelin
8 // Copyright (2000) Kern E. Sibbald
9 //
10 
11 // Implementation of the Events dialogue
12 
13 #include <windows.h>
14 #include "winevents.h"
15 #include "resource.h"
16 #include "statmgr.h"
17 #include "listview.h"
18 #include "wintray.h"
19 
20 // Constructor/destructor
upsEvents(HINSTANCE appinst,upsMenu * menu)21 upsEvents::upsEvents(HINSTANCE appinst, upsMenu *menu) :
22    _appinst(appinst),
23    _hwnd(NULL),
24    _menu(menu)
25 {
26 }
27 
~upsEvents()28 upsEvents::~upsEvents()
29 {
30 }
31 
32 // Dialog box handling functions
Show()33 void upsEvents::Show()
34 {
35    if (!_hwnd)
36    {
37       DialogBoxParam(_appinst,
38                      MAKEINTRESOURCE(IDD_EVENTS),
39                      NULL,
40                      (DLGPROC)DialogProc,
41                      (LONG)this);
42    }
43 }
44 
DialogProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)45 BOOL CALLBACK upsEvents::DialogProc(
46    HWND hwnd,
47    UINT uMsg,
48    WPARAM wParam,
49    LPARAM lParam)
50 {
51    upsEvents *_this;
52 
53    // Retrieve virtual 'this' pointer. When we come in here the first time for
54    // the WM_INITDIALOG message, the pointer is in lParam. We then store it in
55    // the user data so it can be retrieved on future calls.
56    if (uMsg == WM_INITDIALOG)
57    {
58       // Set dialog user data to our "this" pointer which comes in via lParam.
59       // On subsequent calls, this will be retrieved by the code below.
60       SetWindowLong(hwnd, GWL_USERDATA, lParam);
61       _this = (upsEvents *)lParam;
62    }
63    else
64    {
65       // We've previously been initialized, so retrieve pointer from user data
66       _this = (upsEvents *)GetWindowLong(hwnd, GWL_USERDATA);
67    }
68 
69    // Call thru to non-static member function
70    return _this->DialogProcess(hwnd, uMsg, wParam, lParam);
71 }
72 
DialogProcess(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)73 BOOL upsEvents::DialogProcess(
74    HWND hwnd,
75    UINT uMsg,
76    WPARAM wParam,
77    LPARAM lParam)
78 {
79    switch (uMsg) {
80    case WM_INITDIALOG:
81       // Silly: Save initial window size for use as minimum size. There's
82       // probably some programmatic way to fetch this from the resource when
83       // we need it, but I can't find it. So we'll save it at runtime.
84       GetWindowRect(hwnd, &_rect);
85 
86       // Initialize control wrappers
87       _events = new ListView(hwnd, IDC_LIST, 1);
88 
89       // Save a copy of our window handle for later use.
90       // Important to do this AFTER everything needed by Update() is
91       // initialized and ready to go since that function may be called at any
92       // time from the wintray timer thread.
93       _hwnd = hwnd;
94 
95       // Show the dialog
96       _menu->Refresh();
97       SetForegroundWindow(hwnd);
98       return TRUE;
99 
100    case WM_GETMINMAXINFO:
101    {
102       // Restrict minimum size to initial window size
103       MINMAXINFO *mmi = (MINMAXINFO*)lParam;
104       mmi->ptMinTrackSize.x = _rect.right - _rect.left;
105       mmi->ptMinTrackSize.y = _rect.bottom - _rect.top;
106       return TRUE;
107    }
108 
109    case WM_SIZE:
110    {
111       // Fetch new window size (esp client area size)
112       WINDOWINFO wininfo;
113       wininfo.cbSize = sizeof(wininfo);
114       GetWindowInfo(hwnd, &wininfo);
115 
116       // Fetch current listview position
117       HWND ctrl = GetDlgItem(hwnd, IDC_LIST);
118       RECT gridrect;
119       GetWindowRect(ctrl, &gridrect);
120 
121       // Calculate new position and size of listview
122       int left = gridrect.left - wininfo.rcClient.left;
123       int top = gridrect.top - wininfo.rcClient.top;
124       int width = wininfo.rcClient.right - wininfo.rcClient.left - 2*left;
125       int height = wininfo.rcClient.bottom - wininfo.rcClient.top - top - left;
126 
127       // Resize listview
128       SetWindowPos(
129          ctrl, NULL, left, top, width, height, SWP_NOZORDER | SWP_SHOWWINDOW);
130 
131       return TRUE;
132    }
133 
134    case WM_COMMAND:
135       switch (LOWORD(wParam)) {
136       case IDCANCEL:
137       case IDOK:
138          // Close the dialog
139          EndDialog(hwnd, TRUE);
140          return TRUE;
141       }
142       break;
143 
144    case WM_DESTROY:
145       _mutex.lock();
146       _hwnd = NULL;
147       delete _events;
148       _mutex.unlock();
149       return TRUE;
150    }
151 
152    return 0;
153 }
154 
Update(StatMgr * statmgr)155 void upsEvents::Update(StatMgr *statmgr)
156 {
157    // Bail if window is not open
158    _mutex.lock();
159    if (!_hwnd)
160    {
161       _mutex.unlock();
162       return;
163    }
164 
165    // Fetch events from apcctrl
166    alist<astring> events;
167    if (!statmgr->GetEvents(events) || events.empty())
168    {
169       _mutex.unlock();
170       return;
171    }
172 
173    // Update listview
174    alist<astring> *data[] = {&events};
175    _events->UpdateAll(data);
176 
177    _mutex.unlock();
178 }
179