Skip to content

Commit 4175fb5

Browse files
authored
Initial version
A simple wxWidgets app that installs itself into the tray bar. Inspiration from wxWidgets taskbarIcon sample, ffmpeg code and DirectShow Sdk samples Icon from https://www.iconfinder.com/bitfreak86
0 parents  commit 4175fb5

14 files changed

Lines changed: 1026 additions & 0 deletions

App.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#include "wx/wxprec.h"
2+
3+
#ifndef WX_PRECOMP
4+
#include "wx/wx.h"
5+
#endif
6+
7+
#include "wx/taskbar.h"
8+
#include "wx/msw/registry.h"
9+
10+
#include "App.h"
11+
#include "TaskBarIcon.h"
12+
13+
wxIMPLEMENT_APP(MyApp);
14+
15+
//check the Windows Dark Mode setting
16+
static bool locCheckDarkMode() {
17+
#ifdef _WIN32
18+
wxRegKey rk(wxRegKey::HKCU, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize");
19+
if (rk.Exists() && rk.HasValue("AppsUseLightTheme"))
20+
{
21+
long value = -1;
22+
rk.QueryValue("AppsUseLightTheme", &value);
23+
return value <= 0;
24+
}
25+
#endif
26+
27+
return wxSystemSettings::GetAppearance().IsDark();
28+
}
29+
30+
//create the taskbar icon
31+
bool MyApp::OnInit()
32+
{
33+
if ( !wxApp::OnInit() )
34+
return false;
35+
36+
if ( !wxTaskBarIcon::IsAvailable() )
37+
{
38+
wxMessageBox("There appears to be no system tray support in your current environment. This sample may not behave as expected.", "Warning", wxOK | wxICON_EXCLAMATION);
39+
}
40+
41+
//needed to load the taskbar icon, as it's a PNG file
42+
wxImage::AddHandler(new wxPNGHandler());
43+
44+
//create the taskbar icon object/logic
45+
m_taskBarIcon = new MyTaskBarIcon(this);
46+
47+
//load the icon from resources, depending on the system theme
48+
bool isDark = locCheckDarkMode();
49+
if(!m_taskBarIcon->SetIcon(wxBitmapBundle::FromResources((isDark)?"IDI_PNG2":"IDI_PNG1"), "Capture device properties\nRight click to show a list of devices"))
50+
{
51+
wxLogError("Could not set icon.");
52+
}
53+
54+
return true;
55+
}
56+
57+
//cleanup
58+
int MyApp::OnExit()
59+
{
60+
delete m_taskBarIcon;
61+
62+
return wxApp::OnExit();
63+
}

App.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#pragma once
2+
3+
class MyTaskBarIcon;
4+
5+
// Define a new application
6+
class MyApp : public wxApp
7+
{
8+
public:
9+
virtual bool OnInit() wxOVERRIDE;
10+
virtual int OnExit() wxOVERRIDE;
11+
private:
12+
MyTaskBarIcon* m_taskBarIcon;
13+
private:
14+
};

CaptureDeviceTaskbar.sln

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.1.32328.378
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CaptureDeviceTaskbar", "CaptureDeviceTaskbar.vcxproj", "{B350F337-808B-5024-8764-D93BEC99F608}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|x64 = Debug|x64
11+
Debug|x86 = Debug|x86
12+
DLL Debug|x64 = DLL Debug|x64
13+
DLL Debug|x86 = DLL Debug|x86
14+
DLL Release|x64 = DLL Release|x64
15+
DLL Release|x86 = DLL Release|x86
16+
Release|x64 = Release|x64
17+
Release|x86 = Release|x86
18+
EndGlobalSection
19+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{B350F337-808B-5024-8764-D93BEC99F608}.Debug|x64.ActiveCfg = Debug|x64
21+
{B350F337-808B-5024-8764-D93BEC99F608}.Debug|x64.Build.0 = Debug|x64
22+
{B350F337-808B-5024-8764-D93BEC99F608}.Debug|x86.ActiveCfg = Debug|Win32
23+
{B350F337-808B-5024-8764-D93BEC99F608}.Debug|x86.Build.0 = Debug|Win32
24+
{B350F337-808B-5024-8764-D93BEC99F608}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
25+
{B350F337-808B-5024-8764-D93BEC99F608}.DLL Debug|x64.Build.0 = DLL Debug|x64
26+
{B350F337-808B-5024-8764-D93BEC99F608}.DLL Debug|x86.ActiveCfg = DLL Debug|Win32
27+
{B350F337-808B-5024-8764-D93BEC99F608}.DLL Debug|x86.Build.0 = DLL Debug|Win32
28+
{B350F337-808B-5024-8764-D93BEC99F608}.DLL Release|x64.ActiveCfg = DLL Release|x64
29+
{B350F337-808B-5024-8764-D93BEC99F608}.DLL Release|x64.Build.0 = DLL Release|x64
30+
{B350F337-808B-5024-8764-D93BEC99F608}.DLL Release|x86.ActiveCfg = DLL Release|Win32
31+
{B350F337-808B-5024-8764-D93BEC99F608}.DLL Release|x86.Build.0 = DLL Release|Win32
32+
{B350F337-808B-5024-8764-D93BEC99F608}.Release|x64.ActiveCfg = Release|x64
33+
{B350F337-808B-5024-8764-D93BEC99F608}.Release|x64.Build.0 = Release|x64
34+
{B350F337-808B-5024-8764-D93BEC99F608}.Release|x86.ActiveCfg = Release|Win32
35+
{B350F337-808B-5024-8764-D93BEC99F608}.Release|x86.Build.0 = Release|Win32
36+
EndGlobalSection
37+
GlobalSection(SolutionProperties) = preSolution
38+
HideSolutionNode = FALSE
39+
EndGlobalSection
40+
GlobalSection(ExtensibilityGlobals) = postSolution
41+
SolutionGuid = {51B8F9B5-20DA-4B8E-8DB7-BDD08CB9F97D}
42+
EndGlobalSection
43+
EndGlobal

CaptureDeviceTaskbar.vcxproj

Lines changed: 529 additions & 0 deletions
Large diffs are not rendered by default.

DShowUtils.cpp

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
#include "wx/wxprec.h"
2+
3+
#ifndef WX_PRECOMP
4+
#include "wx/wx.h"
5+
#endif
6+
7+
#include "DShowUtils.h"
8+
9+
#include "dshow.h"
10+
#include "strmif.h"
11+
#include "objidl.h"
12+
#include "shlwapi.h"
13+
14+
#pragma comment(lib, "strmiids")
15+
16+
//inspiration for this from FFMpeg and the DirectShow SDK (Microsoft)
17+
18+
static void locShowDShowFilterProperties(IBaseFilter* pDeviceFilter)
19+
{
20+
ISpecifyPropertyPages* pPropertyPages = NULL;
21+
IUnknown* pDeviceFilterIUnknown = NULL;
22+
HRESULT hr;
23+
FILTER_INFO filterInfo = { 0 }; /* a warning on this line is false positive GCC bug 53119 AFAICT */
24+
CAUUID ca_guid = { 0 };
25+
26+
hr = pDeviceFilter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPropertyPages);
27+
if (hr != S_OK) //error "requested filter does not have a property page to show"
28+
goto end;
29+
30+
hr = pDeviceFilter->QueryFilterInfo(&filterInfo);
31+
if (hr != S_OK)
32+
goto fail;
33+
34+
hr = pDeviceFilter->QueryInterface(IID_IUnknown, (void**)&pDeviceFilterIUnknown);
35+
if (hr != S_OK)
36+
goto fail;
37+
38+
hr = pPropertyPages->GetPages(&ca_guid);
39+
if (hr != S_OK)
40+
goto fail;
41+
42+
hr = OleCreatePropertyFrame(NULL, 0, 0, filterInfo.achName, 1, &pDeviceFilterIUnknown, ca_guid.cElems, ca_guid.pElems, 0, 0, NULL);
43+
if (hr != S_OK)
44+
goto fail;
45+
46+
goto end;
47+
48+
fail:
49+
//error "Failure showing property pages for filter"
50+
end:
51+
if (pPropertyPages)
52+
pPropertyPages->Release();
53+
if (pDeviceFilterIUnknown)
54+
pDeviceFilterIUnknown->Release();
55+
if (filterInfo.pGraph)
56+
filterInfo.pGraph->Release();
57+
if (ca_guid.pElems)
58+
CoTaskMemFree(ca_guid.pElems);
59+
}
60+
61+
static HRESULT locEnumerateDevices(REFGUID category, IEnumMoniker** ppEnum)
62+
{
63+
// Create the System Device Enumerator.
64+
ICreateDevEnum* pDevEnum;
65+
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
66+
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
67+
68+
if (SUCCEEDED(hr))
69+
{
70+
// Create an enumerator for the category.
71+
hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
72+
if (hr == S_FALSE)
73+
{
74+
hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
75+
}
76+
pDevEnum->Release();
77+
}
78+
return hr;
79+
}
80+
81+
static void locDisplayDeviceInformation(IEnumMoniker* pEnum, wxString sFriendlyName)
82+
{
83+
IMoniker* pMoniker = NULL;
84+
85+
bool foundIt = false;
86+
while (!foundIt && pEnum->Next(1, &pMoniker, NULL) == S_OK)
87+
{
88+
IPropertyBag* pPropBag;
89+
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
90+
91+
if (FAILED(hr))
92+
{
93+
pMoniker->Release();
94+
continue;
95+
}
96+
97+
VARIANT var;
98+
VariantInit(&var);
99+
100+
// Get description or friendly name.
101+
hr = pPropBag->Read(L"Description", &var, 0);
102+
if (FAILED(hr))
103+
{
104+
hr = pPropBag->Read(L"FriendlyName", &var, 0);
105+
}
106+
if (SUCCEEDED(hr))
107+
{
108+
VariantClear(&var);
109+
}
110+
111+
hr = pPropBag->Write(L"FriendlyName", &var);
112+
113+
foundIt = sFriendlyName.CompareTo(var.bstrVal) == 0;
114+
if (foundIt)
115+
{
116+
IBaseFilter* pFilter;
117+
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
118+
if (SUCCEEDED(hr))
119+
{
120+
locShowDShowFilterProperties(pFilter);
121+
pFilter->Release();
122+
}
123+
}
124+
125+
pPropBag->Release();
126+
pMoniker->Release();
127+
}
128+
}
129+
130+
static void locGetFriendlyDeviceNames(IEnumMoniker* pEnum, wxArrayString &outArrResult)
131+
{
132+
IMoniker* pMoniker = NULL;
133+
134+
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
135+
{
136+
IPropertyBag* pPropBag;
137+
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
138+
139+
if (FAILED(hr))
140+
{
141+
pMoniker->Release();
142+
continue;
143+
}
144+
145+
VARIANT var;
146+
VariantInit(&var);
147+
148+
// Get description or friendly name.
149+
hr = pPropBag->Read(L"Description", &var, 0);
150+
if (FAILED(hr))
151+
{
152+
hr = pPropBag->Read(L"FriendlyName", &var, 0);
153+
}
154+
if (SUCCEEDED(hr))
155+
{
156+
VariantClear(&var);
157+
}
158+
159+
hr = pPropBag->Write(L"FriendlyName", &var);
160+
outArrResult.Add(var.bstrVal);
161+
162+
pPropBag->Release();
163+
pMoniker->Release();
164+
}
165+
}
166+
167+
void GetDevicesFriendlyName(wxArrayString& outArrResult)
168+
{
169+
outArrResult.Clear();
170+
171+
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
172+
if (SUCCEEDED(hr))
173+
{
174+
IEnumMoniker* pEnum = NULL;
175+
hr = locEnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
176+
if (SUCCEEDED(hr))
177+
{
178+
locGetFriendlyDeviceNames(pEnum, outArrResult);
179+
pEnum->Release();
180+
}
181+
182+
CoUninitialize();
183+
}
184+
}
185+
186+
void ShowDevicePropertyDialog(wxString sFriendlyName)
187+
{
188+
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
189+
if (SUCCEEDED(hr))
190+
{
191+
IEnumMoniker* pEnum;
192+
193+
hr = locEnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
194+
if (SUCCEEDED(hr))
195+
{
196+
locDisplayDeviceInformation(pEnum, sFriendlyName);
197+
pEnum->Release();
198+
}
199+
200+
CoUninitialize();
201+
}
202+
}

DShowUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
3+
void GetDevicesFriendlyName(wxArrayString &outDeviceNames);
4+
void ShowDevicePropertyDialog(wxString sFriendlyName);

0 commit comments

Comments
 (0)