source: trunk/DirectShowSpy/FilterGraphList.h @ 211

Last change on this file since 211 was 201, checked in by roman, 11 years ago

Minor tooltip fix, improved subtype reporting

File size: 17.0 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2013
3// Created by Roman Ryltsov roman@alax.info
4
5#pragma once
6
7#include <psapi.h>
8#include <atlctrlx.h>
9#include <atlsplit.h>
10#include "rofiles.h"
11#include "FilterGraphSpy.h"
12#include "FilterGraphHelper.h"
13#include "AboutDialog.h"
14
15#pragma comment(lib, "psapi.lib")
16
17////////////////////////////////////////////////////////////
18// CFilterGraphListPropertySheet
19
20class CFilterGraphListPropertySheet :
21        public CSizablePropertySheetT<CFilterGraphListPropertySheet>
22{
23public:
24
25BEGIN_MSG_MAP_EX(CFilterGraphListPropertySheet)
26        CHAIN_MSG_MAP(CSizablePropertySheet)
27        MSG_WM_SYSCOMMAND(OnSysCommand)
28END_MSG_MAP()
29
30public:
31
32        ////////////////////////////////////////////////////////
33        // CListPropertyPage
34
35        class CListPropertyPage :
36                public CPropertyPageT<CListPropertyPage>,
37                public CDialogResize<CListPropertyPage>
38        {
39        public:
40
41                enum { IDD = IDD_FILTERGRAPHLIST_LIST_PROPERTYPAGE };
42
43        BEGIN_MSG_MAP_EX(CListPropertyPage)
44                CHAIN_MSG_MAP(CPropertyPage)
45                CHAIN_MSG_MAP(CDialogResize<CListPropertyPage>)
46                MSG_WM_INITDIALOG(OnInitDialog)
47                MSG_WM_DESTROY(OnDestroy)
48                MSG_LVN_GETDISPINFO(IDC_FILTERGRAPHLIST_LIST_GRAPH, OnGraphListViewGetDispInfo)
49                MSG_LVN_GETINFOTIP(IDC_FILTERGRAPHLIST_LIST_GRAPH, OnGraphListViewGetInfoTip)
50                MSG_LVN_ITEMCHANGED(IDC_FILTERGRAPHLIST_LIST_GRAPH, OnGraphListViewItemChanged)
51                MSG_LVN_DBLCLK(IDC_FILTERGRAPHLIST_LIST_GRAPH, OnGraphListViewDblClk)
52                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHLIST_LIST_REFRESH, OnRefresh)
53                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHLIST_LIST_CHECK, OnCheck)
54                COMMAND_ID_HANDLER_EX(IDC_FILTERGRAPHLIST_LIST_COPYTOCLIPBOARD, OnCopyToClipboard)
55                REFLECT_NOTIFICATIONS()
56        END_MSG_MAP()
57
58        BEGIN_DLGRESIZE_MAP(CListPropertyPage)
59                DLGRESIZE_CONTROL(IDC_FILTERGRAPHLIST_LIST_GRAPH, DLSZ_SIZE_X | DLSZ_SIZE_Y)
60                DLGRESIZE_CONTROL(IDC_FILTERGRAPHLIST_LIST_REFRESH, DLSZ_MOVE_Y)
61                DLGRESIZE_CONTROL(IDC_FILTERGRAPHLIST_LIST_CHECK, DLSZ_MOVE_Y)
62                DLGRESIZE_CONTROL(IDC_FILTERGRAPHLIST_LIST_COPYTOCLIPBOARD, DLSZ_MOVE_Y)
63        END_DLGRESIZE_MAP()
64
65        public:
66
67                ////////////////////////////////////////////////////
68                // CItem
69
70                class CItem
71                {
72                public:
73                        CComPtr<IMoniker> m_pMoniker;
74                        CStringW m_sDisplayName;
75                        DWORD64 m_nInstance;
76                        DWORD m_nProcessIdentifier;
77                        CPath m_sProcessImagePath;
78                        CString m_sTime;
79                        CComPtr<IUnknown> m_pFilterGraphUnknown;
80                        CComPtr<IFilterGraph> m_pFilterGraph;
81                        SIZE_T m_nFilterCount;
82                        CString m_sState;
83                        DOUBLE m_fDuration;
84                        DOUBLE m_fPosition;
85
86                public:
87                // CItem
88                        CItem() throw() :
89                                m_nFilterCount(0),
90                                m_fDuration(0),
91                                m_fPosition(0)
92                        {
93                        }
94                        CComPtr<IFilterGraph>& FilterGraphNeeded(IRunningObjectTable* pRunningObjectTable)
95                        {
96                                _A(pRunningObjectTable);
97                                if(!m_pFilterGraph && pRunningObjectTable && m_pMoniker)
98                                {
99                                        _A(m_pMoniker);
100                                        CComPtr<IBindCtx> pBindCtx;
101                                        __C(CreateBindCtx(0, &pBindCtx));
102                                        CComPtr<IUnknown> pUnknown;
103                                        __C(pRunningObjectTable->GetObject(m_pMoniker, &pUnknown));
104                                        const CComQIPtr<IFilterGraph> pFilterGraph = pUnknown;
105                                        __D(pFilterGraph, E_NOINTERFACE);
106                                        m_pFilterGraphUnknown = pUnknown;
107                                        m_pFilterGraph = pFilterGraph;
108                                        m_nFilterCount = 0;
109                                        m_sState.Empty();
110                                }
111                                return m_pFilterGraph;
112                        }
113                        BOOL Check()
114                        {
115                                _ATLTRY
116                                {
117                                        _FilterGraphHelper::CFilterArray FilterArray;
118                                        _FilterGraphHelper::GetGraphFilters(m_pFilterGraph, FilterArray);
119                                        m_nFilterCount = FilterArray.GetCount();
120                                        #pragma region IMediaControl
121                                        _ATLTRY
122                                        {
123                                                m_sState.Empty();
124                                                const CComQIPtr<IMediaControl> pMediaControl = m_pFilterGraph;
125                                                if(pMediaControl)
126                                                {
127                                                        OAFilterState State;
128                                                        if(SUCCEEDED(pMediaControl->GetState(0, &State)))
129                                                        {
130                                                                static LPCTSTR g_ppszStates[] = { _T("Stopped"), _T("Paused"), _T("Running") };
131                                                                if((SIZE_T) State < DIM(g_ppszStates))
132                                                                        m_sState = g_ppszStates[(SIZE_T) State];
133                                                        }
134                                                }
135                                        }
136                                        _ATLCATCHALL()
137                                        {
138                                                _Z_EXCEPTION();
139                                        }
140                                        #pragma endregion
141                                        #pragma region IMediaPosition
142                                        _ATLTRY
143                                        {
144                                                m_fDuration = 0;
145                                                m_fPosition = 0;
146                                                const CComQIPtr<IMediaPosition> pMediaPosition = m_pFilterGraph;
147                                                if(pMediaPosition)
148                                                        if(SUCCEEDED(pMediaPosition->get_Duration(&m_fDuration)))
149                                                                pMediaPosition->get_CurrentPosition(&m_fPosition);
150                                        }
151                                        _ATLCATCHALL()
152                                        {
153                                                _Z_EXCEPTION();
154                                        }
155                                        #pragma endregion
156                                        // SUGG: Source and Sink Paths
157                                }
158                                _ATLCATCHALL()
159                                {
160                                        _Z_EXCEPTION();
161                                        return FALSE;
162                                }
163                                return TRUE;
164                        }
165                };
166
167        private:
168                CFilterGraphListPropertySheet& m_PropertySheet;
169                CRoListViewT<CItem, CRoListControlDataTraitsT> m_GraphListView;
170                CButton m_RefreshButton;
171                CButton m_CheckButton;
172                CButton m_CopyToClipboardButton;
173                CComPtr<IRunningObjectTable> m_pRunningObjectTable;
174
175        public:
176        // CListPropertyPage
177                CListPropertyPage(CFilterGraphListPropertySheet* pPropertySheet) throw() :
178                        m_PropertySheet(*pPropertySheet)
179                {
180                }
181                VOID UpdateControls()
182                {
183                        m_CopyToClipboardButton.EnableWindow(m_GraphListView.GetSelectedCount() > 0);
184                }
185                INT SortGraphListViewItems(LPARAM nItemParameter1, LPARAM nItemParameter2)
186                {
187                        const CItem& Item1 = m_GraphListView.DataFromParameter(nItemParameter1);
188                        const CItem& Item2 = m_GraphListView.DataFromParameter(nItemParameter2);
189                        const INT nTime = _tcscmp(Item1.m_sTime, Item2.m_sTime);
190                        if(nTime)
191                                return -nTime;
192                        const INT nProcess = (INT) (Item1.m_nProcessIdentifier, Item2.m_nProcessIdentifier);
193                        if(nProcess)
194                                return -nProcess;
195                        return wcscmp(Item1.m_sDisplayName, Item2.m_sDisplayName);
196                }
197                static int CALLBACK SortGraphListViewItems(LPARAM nItemParameter1, LPARAM nItemParameter2, LPARAM nParameter)
198                {
199                        return ((CListPropertyPage*) nParameter)->SortGraphListViewItems(nItemParameter1, nItemParameter2);
200                }
201                VOID Refresh()
202                {
203                        CRoMapT<CStringW, CItem> ItemMap;
204                        #pragma region Enumerate
205                        _ATLTRY
206                        {
207                                if(!m_pRunningObjectTable)
208                                        __C(GetRunningObjectTable(0, &m_pRunningObjectTable));
209                                CComPtr<IEnumMoniker> pEnumMoniker;
210                                __C(m_pRunningObjectTable->EnumRunning(&pEnumMoniker));
211                                CComPtr<IMalloc> pMalloc;
212                                __C(CoGetMalloc(1, &pMalloc));
213                                CComPtr<IMoniker> pMoniker;
214                                while(pEnumMoniker->Next(1, &pMoniker, NULL) == S_OK)
215                                {
216                                        _ATLTRY
217                                        {
218                                                CComPtr<IBindCtx> pBindCtx;
219                                                __C(CreateBindCtx(0, &pBindCtx));
220                                                LPOLESTR pszDisplayName = NULL;
221                                                __C(pMoniker->GetDisplayName(pBindCtx, NULL, &pszDisplayName));
222                                                const CStringW sDisplayName = pszDisplayName;
223                                                _Z4(atlTraceGeneral, 4, _T("sDisplayName %ls\n"), sDisplayName);
224                                                pMalloc->Free(pszDisplayName);
225                                                static CRoStaticReW g_Expression(L"^\\!FilterGraph {[0-9A-F]+} pid {[0-9A-F]+}(; process\\: {.+?}, time\\: {[0-9]+\\-[0-9]+\\-[0-9]+})?", FALSE);
226                                                CRoReMatchContext MatchContext;
227                                                if(g_Expression.Match(sDisplayName, &MatchContext))
228                                                {
229                                                        CItem Item;
230                                                        Item.m_pMoniker = pMoniker;
231                                                        Item.m_sDisplayName = sDisplayName;
232                                                        _W(StrToInt64ExW(CStringW(L"0x") + MatchContext.GetMatchString(0), STIF_SUPPORT_HEX, &reinterpret_cast<LONGLONG&>(Item.m_nInstance)));
233                                                        _W(StrToIntExW(CStringW(L"0x") + MatchContext.GetMatchString(1), STIF_SUPPORT_HEX, &reinterpret_cast<INT&>(Item.m_nProcessIdentifier)));
234                                                        Item.m_sTime = CString(MatchContext.GetMatchString(3));
235                                                        Item.m_sTime.Replace(_T("-"), _T(":"));
236                                                        _W(ItemMap.SetAt(sDisplayName, Item) >= 0);
237                                                }
238                                        }
239                                        _ATLCATCHALL()
240                                        {
241                                                _Z_EXCEPTION();
242                                        }
243                                        pMoniker.Release();
244                                }
245                        }
246                        _ATLCATCHALL()
247                        {
248                                _Z_EXCEPTION();
249                        }
250                        #pragma endregion
251                        CWindowRedraw GraphListViewRedraw(m_GraphListView);
252                        BOOL bSortNeeded = FALSE;
253                        #pragma region Remove
254                        for(INT nItem = m_GraphListView.GetItemCount() - 1; nItem >= 0; nItem--)
255                        {
256                                const POSITION Position = ItemMap.Lookup(m_GraphListView.GetItemData(nItem).m_sDisplayName);
257                                if(Position)
258                                        ItemMap.RemoveAtPos(Position);
259                                else
260                                        _W(m_GraphListView.DeleteItem(nItem));
261                        }
262                        #pragma endregion
263                        #pragma region Add
264                        INT nItemIndex = m_GraphListView.GetItemCount();
265                        for(POSITION Position = ItemMap.GetStartPosition(); Position; ItemMap.GetNext(Position))
266                        {
267                                CItem& Item = ItemMap.GetValueAt(Position);
268                                _ATLTRY
269                                {
270                                        CHandle Process;
271                                        //Process.Attach(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, Item.m_nProcessIdentifier));
272                                        Process.Attach(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Item.m_nProcessIdentifier));
273                                        __E(Process);
274                                        TCHAR pszPath[MAX_PATH] = { 0 };
275                                        //_W(GetProcessImageFileName(Process, pszPath, DIM(pszPath)));
276                                        _W(GetModuleFileNameEx(Process, NULL, pszPath, DIM(pszPath)));
277                                        Item.m_sProcessImagePath = pszPath;
278                                }
279                                _ATLCATCHALL()
280                                {
281                                        _Z_EXCEPTION();
282                                }
283                                const INT nItem = m_GraphListView.InsertItem(nItemIndex++, Item);
284                                _A(nItem >= 0);
285                                bSortNeeded = TRUE;
286                        }
287                        #pragma endregion
288                        if(bSortNeeded)
289                                m_GraphListView.SortItems(&CListPropertyPage::SortGraphListViewItems, (LPARAM) this);
290                }
291                CString GetText()
292                {
293                        CRoArrayT<CString> GraphArray;
294                        for(INT nItem = m_GraphListView.GetNextItem(-1, LVNI_SELECTED); nItem >= 0; nItem = m_GraphListView.GetNextItem(nItem, LVNI_SELECTED))
295                        {
296                                CItem& Item = m_GraphListView.GetItemData(nItem);
297                                _ATLTRY
298                                {
299                                        if(Item.FilterGraphNeeded(m_pRunningObjectTable))
300                                        {
301                                                Item.Check();
302                                                m_GraphListView.RedrawItems(nItem, nItem);
303                                                CFilterGraphHelper::CProcessData ProcessData;
304                                                ProcessData.m_sDisplayName = Item.m_sDisplayName;
305                                                ProcessData.m_nIdentifier = Item.m_nProcessIdentifier;
306                                                ProcessData.m_sImagePath = Item.m_sProcessImagePath;
307                                                GraphArray.Add(CFilterGraphHelper::GetText(Item.m_pFilterGraph, &ProcessData));
308                                        }
309                                }
310                                _ATLCATCHALL()
311                                {
312                                        _Z_EXCEPTION();
313                                }
314                        }
315                        return _StringHelper::Join(GraphArray, _T("\r\n") _T("---") _T("\r\n") _T("\r\n"));
316                }
317
318        // Window Message Handler
319                LRESULT OnInitDialog(HWND, LPARAM)
320                {
321                        _ATLTRY
322                        {
323                                CWaitCursor WaitCursor;
324                                m_GraphListView.Initialize(GetDlgItem(IDC_FILTERGRAPHLIST_LIST_GRAPH));
325                                CToolTipCtrl ToolTip = m_GraphListView.GetToolTips();
326                                ToolTip.SetDelayTime(TTDT_AUTOPOP, 30 * 1000); // 30 seconds
327                                ToolTip.SetMaxTipWidth(max(GetSystemMetrics(SM_CXSCREEN) * 5 / 8, 600));
328                                m_RefreshButton = GetDlgItem(IDC_FILTERGRAPHLIST_LIST_REFRESH);
329                                m_CheckButton = GetDlgItem(IDC_FILTERGRAPHLIST_LIST_CHECK);
330                                m_CopyToClipboardButton = GetDlgItem(IDC_FILTERGRAPHLIST_LIST_COPYTOCLIPBOARD);
331                                DlgResize_Init(FALSE, FALSE);
332                                Refresh();
333                                #if _DEVELOPMENT
334                                        m_GraphListView.SetItemState(0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
335                                #endif // _DEVELOPMENT
336                                UpdateControls();
337                                #pragma region Default Property Sheet Size
338                                CRect Position;
339                                _W(m_PropertySheet.GetWindowRect(Position));
340                                Position.InflateRect(6 * Position.Width() / 8, 1 * Position.Height() / 8);
341                                CSize ScreenExtent(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
342                                ScreenExtent.cx -= ScreenExtent.cx / 8;
343                                ScreenExtent.cy -= ScreenExtent.cy / 8;
344                                if(Position.Width() > ScreenExtent.cx)
345                                        Position.right = Position.left + ScreenExtent.cx;
346                                if(Position.Height() > ScreenExtent.cy)
347                                        Position.bottom = Position.top + ScreenExtent.cy;
348                                _W(m_PropertySheet.MoveWindow(Position));
349                                _W(m_PropertySheet.CenterWindow());
350                                #pragma endregion
351                                CancelToClose();
352                        }
353                        _ATLCATCHALL()
354                        {
355                                for(CWindow Window = GetWindow(GW_CHILD); Window.IsWindow(); Window = Window.GetWindow(GW_HWNDNEXT))
356                                        Window.EnableWindow(FALSE);
357                                _ATLRETHROW;
358                        }
359                        return TRUE;
360                }
361                LRESULT OnDestroy()
362                {
363                        return 0;
364                }
365                LRESULT OnGraphListViewGetDispInfo(NMLVDISPINFO* pHeader)
366                {
367                        const CItem& Item = m_GraphListView.DataFromParameter(pHeader->item.lParam);
368                        if(pHeader->item.mask & LVIF_TEXT)
369                        {
370                                CString& sTextBuffer = m_GraphListView.GetTextBufferString(TRUE);
371                                switch(pHeader->item.iSubItem)
372                                {
373                                case 1: // Process Name
374                                        sTextBuffer = PathFindFileName(Item.m_sProcessImagePath);
375                                        break;
376                                case 2: // Creation Time
377                                        sTextBuffer = Item.m_sTime;
378                                        break;
379                                case 3: // Filter Count
380                                        if(Item.m_pFilterGraph)
381                                                sTextBuffer = AtlFormatString(_T("%d"), Item.m_nFilterCount);
382                                        break;
383                                case 4: // State
384                                        if(Item.m_pFilterGraph)
385                                                sTextBuffer = Item.m_sState;
386                                        break;
387                                case 5: // Process Image Directory
388                                        sTextBuffer = (LPCTSTR) GetPathDirectory(Item.m_sProcessImagePath);
389                                        break;
390                                default: // Process, Instance
391                                        sTextBuffer = AtlFormatString(_T("%d - 0x%p"), Item.m_nProcessIdentifier, Item.m_nInstance);
392                                }
393                                pHeader->item.pszText = m_GraphListView.GetTextBuffer();
394                        }
395                        return 0;
396                }
397                LRESULT OnGraphListViewGetInfoTip(NMLVGETINFOTIP* pHeader)
398                {
399                        const CItem& Item = m_GraphListView.GetItemData(pHeader->iItem);
400                        CString& sTextBuffer = m_GraphListView.GetTextBufferString(TRUE);
401                        sTextBuffer.AppendFormat(_T("Process: %d (0x%X) %s\r\n"), Item.m_nProcessIdentifier, Item.m_nProcessIdentifier, CString(FindFileName(Item.m_sProcessImagePath)));
402                        if(!Item.m_sTime.IsEmpty())
403                                sTextBuffer.AppendFormat(_T("CreationTime: %s\r\n"), Item.m_sTime);
404                        if(Item.m_pFilterGraph)
405                        {
406                                sTextBuffer.AppendFormat(_T("Filter Count: %d\r\n"), Item.m_nFilterCount);
407                                if(!Item.m_sState.IsEmpty())
408                                        sTextBuffer.AppendFormat(_T("State: %s\r\n"), Item.m_sState);
409                                if(Item.m_fDuration > 0)
410                                {
411                                        sTextBuffer.AppendFormat(_T("Duration: %s seconds\r\n"), _StringHelper::FormatNumber(Item.m_fDuration, 3));
412                                        sTextBuffer.AppendFormat(_T("Position: %s seconds\r\n"), _StringHelper::FormatNumber(Item.m_fPosition, 3));
413                                }
414                        }
415                        sTextBuffer.AppendFormat(_T("Display Name: %ls\r\n"), Item.m_sDisplayName);
416                        sTextBuffer.AppendFormat(_T("Instance: 0x%p\r\n"), Item.m_nInstance);
417                        const CString sDirectory = (LPCTSTR) GetPathDirectory(Item.m_sProcessImagePath);
418                        if(!sDirectory.IsEmpty())
419                                sTextBuffer.AppendFormat(_T("Process Directory: %s\r\n"), sDirectory);
420                        sTextBuffer.TrimRight(_T("\t\n\r ."));
421                        #pragma region Clipboard Copy
422                        if(GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0)
423                                _ATLTRY
424                                {
425                                        SetClipboardText(m_hWnd, sTextBuffer);
426                                        MessageBeep(MB_OK);
427                                }
428                                _ATLCATCHALL()
429                                {
430                                        _Z_EXCEPTION();
431                                        MessageBeep(MB_ICONERROR);
432                                }
433                        #pragma endregion
434                        _tcsncpy_s(pHeader->pszText, pHeader->cchTextMax, m_GraphListView.GetTextBuffer(), _TRUNCATE);
435                        return 0;
436                }
437                LRESULT OnGraphListViewItemChanged(NMLISTVIEW* pHeader)
438                {
439                        UpdateControls();
440                        return 0;
441                }
442                LRESULT OnGraphListViewDblClk(NMITEMACTIVATE* pHeader)
443                {
444                        m_CheckButton.Click();
445                        return 0;
446                }
447                LRESULT OnRefresh(UINT, INT, HWND)
448                {
449                        CWaitCursor WaitCursor;
450                        Refresh();
451                        UpdateControls();
452                        return 0;
453                }
454                LRESULT OnCheck(UINT, INT, HWND)
455                {
456                        CWaitCursor WaitCursor;
457                        for(INT nItem = m_GraphListView.GetNextItem(-1, LVNI_SELECTED); nItem >= 0; nItem = m_GraphListView.GetNextItem(nItem, LVNI_SELECTED))
458                        {
459                                CItem& Item = m_GraphListView.GetItemData(nItem);
460                                if(Item.FilterGraphNeeded(m_pRunningObjectTable))
461                                        if(Item.Check())
462                                                m_GraphListView.RedrawItems(nItem, nItem);
463                        }
464                        return 0;
465                }
466                LRESULT OnCopyToClipboard(UINT, INT, HWND)
467                {
468                        CWaitCursor WaitCursor;
469                        const CString sText = GetText();
470                        if(sText.IsEmpty())
471                                return 0;
472                        SetClipboardText(m_hWnd, sText);
473                        MessageBeep(MB_OK);
474                        return 0;
475                }
476        };
477
478private:
479        CListPropertyPage m_ListPropertyPage;
480
481public:
482// CFilterGraphListPropertySheet
483        CFilterGraphListPropertySheet() :
484                CSizablePropertySheetT<CFilterGraphListPropertySheet>(IDS_FILTERGRAPHLIST_LIST_PROPERTYSHEETCAPTION),
485                m_ListPropertyPage(this)
486        {
487                AddPage(m_ListPropertyPage);
488        }
489        BOOL SetInitialPosition()
490        {
491                if(!__super::SetInitialPosition())
492                        return FALSE;
493                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)), TRUE);
494                SetIcon(AtlLoadIconImage(IDI_MODULE, LR_DEFAULTCOLOR, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)), FALSE);
495                #pragma region Bitness Indication
496                CString sCaption;
497                _W(GetWindowText(sCaption));
498                #if defined(_WIN64)
499                        sCaption.Append(_T(" (64-bit)"));
500                #else
501                        if(SafeIsWow64Process())
502                                sCaption.Append(_T(" (32-bit)"));
503                #endif // defined(_WIN64)
504                _W(SetWindowText(sCaption));
505                #pragma endregion
506                #pragma region System Menu
507                CMenuHandle Menu = GetSystemMenu(FALSE);
508                _W(Menu.AppendMenu(MF_SEPARATOR));
509                _W(Menu.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("&About...")));
510                #pragma endregion
511                return TRUE;
512        }
513
514// Window message handelrs
515        LRESULT OnSysCommand(UINT nCommand, CPoint)
516        {
517                switch(nCommand)
518                {
519                case ID_APP_ABOUT:
520                        {
521                                CAboutDialog Dialog;
522                                Dialog.DoModal(m_hWnd);
523                        }
524                        break;
525                default:
526                        SetMsgHandled(FALSE);
527                }
528                return 0;
529        }
530};
531
Note: See TracBrowser for help on using the repository browser.