A Windows WPF application that provides an edge-docked floating menu interface for camera switching, signal source management, and ppInk screen annotation integration on interactive flat panel displays (IFPD).
- Overview
- Features
- System Requirements
- Quick Start
- Architecture
- Configuration
- User Interface
- Camera Management
- Signal Source Detection
- Screen Annotation Integration
- TouchBack Integration
- Troubleshooting
- Contributing
- License
The Floating Menu application provides a convenient edge-docked interface for managing camera feeds and signal sources on Windows-based interactive displays. It features a collapsible menu system, real-time camera preview, automatic camera detection via Windows PnP utilities, and integration with ppInk screen annotation tool (automatically downloaded during build).
┌─────────────────────────────────────────────────────────────────┐
│ Floating Menu Application │
├─────────────────────────────────────────────────────────────────┤
│ Edge Handle → Menu Control → Signal Source Manager │
│ ↓ ↓ ↓ │
│ Draggable Menu Items Camera Detection (pnputil) │
│ Collapse - Home Camera List (ObservableCollection)│
│ Expand - Exit ↓ │
│ Always-On - Signal Source → Camera Window │
│ - Annotation (AForge.NET) │
│ - Settings ↓ │
│ Full Screen Display │
├─────────────────────────────────────────────────────────────────┤
│ External Integration: ppInk Annotation Tool (auto-downloaded) │
└─────────────────────────────────────────────────────────────────┘
Windows/
├── FloatingMenu/
│ ├── MainWindow.xaml(.cs) # Main application window and logic
│ ├── App.xaml(.cs) # Application startup and configuration
│ ├── AssemblyInfo.cs # Assembly metadata and configuration
│ ├── FloatingMenu.csproj # Project file with build targets
│ ├── config.json # Application configuration
│ ├── Controls/
│ │ ├── EdgeHandleControl.xaml(.cs) # Collapsible edge handle
│ │ ├── EdgeMenuControl.xaml(.cs) # Main menu interface
│ │ ├── SignalSource.xaml(.cs) # Camera/signal source management
│ │ └── CameraWindow.xaml(.cs) # Full-screen camera display
│ ├── Helpers/
│ │ ├── SignalSourceModel.cs # Camera/signal source data model
│ │ └── DeviceStatusEnum.cs # Device connection status enum
│ ├── Styles/
│ │ ├── ButtonDictionary.xaml # Custom button styles
│ │ └── ListDictionary.xaml # Custom list styles
│ └── bin/
│ └── Release/
│ └── net10.0-windows/
│ ├── FloatingMenu.exe # Published executable
│ ├── ppInk_Extracted/ # ppInk annotation tool (auto-downloaded)
│ │ └── ppInk/
│ │ └── ppInk.exe
│ └── ExternalTools/ # External services (auto-copied)
│ └── TouchDataCaptureService/
│ └──TouchDataCaptureService.exe
├── GetTouchInfo/
│ ├── TouchDataCaptureService.csproj # Touch data capture service project
│ └── Program.cs # Touch data capture implementation
└── ExternalTools/
└── TouchDataCaptureService/ # Staging area for build process
└── TouchDataCaptureService.exe
- Edge-Docked Interface - Always-accessible menu docked to the right edge of the screen
- Collapsible Design - Expands/collapses with smooth animations
- Draggable Handle - Vertically repositionable while staying docked to the edge
- Auto-Docking - Automatically returns to right edge when moved
- Automatic Camera Detection - Enumerates connected cameras using Windows PnP utilities (
pnputil) - Real-Time Preview - Full-screen camera feed using AForge.NET framework
- Multi-Camera Support - Switch between multiple connected cameras via DirectShow
- Optimized Resolution - Automatically selects highest available camera resolution
- Frame Rate Optimization - Adaptive frame display with frame skipping (30 FPS effective)
- Async Camera Loading - Non-blocking camera enumeration for smooth UI experience
- Automatic Cleanup - Camera resources released on window close
- Device Status Tracking - Shows Available, Connected, or Disconnected states
- Observable Collection - Real-time UI updates when devices change
- Single Connection Mode - Only one camera can be active at a time
- Visual Status Indicators - Color-coded status for each signal source
- Device Indexing - Cameras automatically indexed (PC 1, PC 2, etc.)
- Event-Driven Architecture - Uses
DeviceSelectedandCameraClosedevents for state management
- Automatic ppInk Integration - ppInk downloaded during build, no manual installation
- External App Launch - Integrates with ppInk annotation tool
- Process Monitoring - Detects when ppInk closes
- Seamless Workflow - Menu auto-collapses when launching annotation
- Bundled Deployment - ppInk included with application package
- Responsive Sizing - Adapts to screen dimensions dynamically
- Smooth Animations - Polished expand/collapse transitions
- Flyout Panels - Slide-out configuration panels
- Custom Styling - Branded button and list styles
- Menu Items:
- Home (Collapse menu)
- Exit (Close application)
- Signal Source (Camera selection)
- Annotation (Toggle ppInk annotation tool - click once to open, click again to close)
- Settings (Future expansion)
- Operating System: Windows 11
- Display: Interactive flat panel display or standard monitor
- Camera: USB camera(s) compatible with DirectShow (DSHOW)
- RAM: Minimum 4 GB (8 GB recommended for HD camera feeds)
- Disk Space: 200 MB (for application, dependencies, and ppInk)
- .NET Runtime: .NET 10 Runtime or SDK
- Camera Drivers: DirectShow-compatible camera drivers
- ppInk: Automatically included (no separate installation needed)
- AForge.Video: Video processing framework for camera capture
- AForge.Video.DirectShow: DirectShow wrapper for video input devices
- System.Drawing.Common: Bitmap processing and GDI+ interop
- Standard User - No administrator rights required for normal operation
- Camera Access - Windows Camera privacy settings must allow desktop apps
- PnP Enumeration - Access to Windows Plug and Play device enumeration
-
Install .NET 10 Runtime
- Download from: https://dotnet.microsoft.com/download/dotnet/10.0
- Or use winget:
winget install Microsoft.DotNet.Runtime.10
-
Download or Build the Application
- Clone repository:
git clone https://github.com/intel-sandbox/ifpd-touchback-floatingmenu.git cd ifpd-touchback-floatingmenu\Windows\FloatingMenu
- Build Release version:
dotnet build -c Release
- Clone repository:
-
Run the Application
- Navigate to build output:
cd bin\Release\net10.0-windows
- Launch application:
.\FloatingMenu.exe
- Navigate to build output:
- Application starts with a thin edge handle on the right side of the screen
- Click the edge handle to expand the menu
- Select "Signal Source" to view available cameras (automatically detected)
- Click a camera from the list to open full-screen preview
- Drag the edge handle vertically to reposition as needed
- Click the connected camera again to disconnect and close the preview
- Window Position: Right edge of screen, vertically centered
- Collapsed Size: 3.5% screen width × 25% screen height
- Expanded Size: 18% screen width × 45% screen height
- Effective Frame Rate: ~30 FPS (frame skipping every other frame)
- Camera Resolution: Highest available resolution from camera capabilities
- Video Capture API: DirectShow (DSHOW) via AForge.NET
- Camera Naming: Automatic sequential naming (PC 1, PC 2, etc.)
To modify window dimensions, edit MainWindow.xaml.cs:
// Collapsed state
this.Width = screenWidth * 0.035; // 3.5% of screen width
this.Height = screenHeight * 0.25; // 25% of screen height
// Expanded state
this.Width = screenWidth * 0.18; // 18% of screen width
this.Height = screenHeight * 0.45; // 45% of screen heightTo adjust camera resolution selection, edit CameraWindow.xaml.cs:
// Current: Selects highest resolution automatically
VideoCapabilities best = _videoSource.VideoCapabilities
.OrderByDescending(c => c.FrameSize.Width * c.FrameSize.Height)
.First();
_videoSource.VideoResolution = best;
// Alternative: Manually select specific resolution
// _videoSource.VideoResolution = _videoSource.VideoCapabilities
// .First(c => c.FrameSize.Width == 1920 && c.FrameSize.Height == 1080);To adjust frame display rate, edit CameraWindow.xaml.cs:
// Current: Displays every other frame (~30 FPS effective)
if (++_frameCounter % 2 != 0)
return;
// For full frame rate, remove frame skipping:
// if (++_frameCounter % 1 != 0) // Shows all frames
// return;
// For lower frame rate:
// if (++_frameCounter % 3 != 0) // Shows every 3rd frame (~20 FPS)
// return;The ppInk path is automatically configured using relative pathing:
string exePath = System.IO.Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"ppInk_Extracted",
"ppInk",
"ppInk.exe");No manual configuration needed! ppInk is automatically downloaded during the build process and bundled with the application.
|
|
- Display: Full-screen borderless window
- Resolution: Highest available from camera capabilities
- Effective Frame Rate: ~30 FPS (with frame skipping optimization)
- Controls: Close window to disconnect camera
- Auto-Return: Menu reopens with Signal Source flyout when camera closes via
CameraClosedevent
The application uses Windows pnputil command to enumerate connected cameras asynchronously:
var process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c pnputil /enum-devices /class Camera /connected";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
string output = await process.StandardOutput.ReadToEndAsync();
process.WaitForExit();The application uses AForge.NET framework for DirectShow camera access:
// Enumerate DirectShow video devices
_videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
// Select camera by index
_videoSource = new VideoCaptureDevice(_videoDevices[cameraIndex].MonikerString);
// Get highest resolution capability
VideoCapabilities best = _videoSource.VideoCapabilities
.OrderByDescending(c => c.FrameSize.Width * c.FrameSize.Height)
.First();
// Set video resolution
_videoSource.VideoResolution = best;
// Register frame event handler
_videoSource.NewFrame += VideoSource_NewFrame;
// Start camera capture
_videoSource.Start();Each new frame is processed and displayed:
private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
// Frame skipping for performance (display every other frame)
if (++_frameCounter % 2 != 0)
return;
using (Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone())
{
IntPtr hBitmap = bitmap.GetHbitmap();
Dispatcher.BeginInvoke(new Action(() =>
{
try
{
var source = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
CameraImage.Source = source;
}
finally
{
DeleteObject(hBitmap); // Release GDI+ resource
}
}));
}
}
catch
{
// Silently handle frame processing errors
}
}- Page loads and calls
LoadCameras()asynchronously - Application queries connected cameras via PnP utility
- Devices populate in observable collection with automatic indexing
- User selects a camera from the list via mouse click
- Device status toggles to Connected (all others set to Available)
DeviceSelectedevent fires with camera index- Camera window opens in full-screen mode
- AForge.NET enumerates DirectShow devices and initializes selected camera
- Highest resolution is automatically selected from camera capabilities
- Frame capture starts with
NewFrameevent handler - Frames display at ~30 FPS effective rate (every other frame)
- Close camera window - Window
Closedevent triggers cleanup andCameraClosedevent - Toggle in Signal Source list - Click connected camera to disconnect (fires
DeviceSelected(-1)) - Select "Exit" from menu while camera is active
- Exception handling - Errors during camera start trigger automatic cleanup and close
The application properly manages camera resources:
private void StopCamera()
{
try
{
if (_videoSource != null)
{
_videoSource.SignalToStop(); // Signal camera to stop
_videoSource.WaitForStop(); // Wait for camera thread to terminate
_videoSource = null;
}
}
catch
{
// Ignore cleanup errors
}
}When camera initialization fails (e.g., PC Cast not enabled):
catch(Exception e)
{
MessageBox.Show("PC Cast is not Enabled for the selected device.");
StopCamera();
Dispatcher.BeginInvoke(() =>
{
CameraClosed?.Invoke();
this.Close();
});
}- USB webcams (UVC-compatible)
- Integrated laptop cameras
- Document cameras
- Any DirectShow-compatible video capture device
- PC Cast enabled devices (required for some hardware)
var process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c pnputil /enum-devices /class Camera /connected";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
string output = await process.StandardOutput.ReadToEndAsync();
The application extracts camera names from:
- Device Description fields in pnputil output
- Friendly Name fields in pnputil output
- Both are checked using case-insensitive comparison
- Available (default): Camera detected and ready for connection
- Connected: Camera actively streaming (only one device at a time)
- Disconnected: Camera removed or unavailable (future use)
- ppInk - Open-source screen annotation tool
- Version: 1.9.0 RC1
- Platform: Windows x64
- Automatically downloaded during build - No manual installation required!
- Repository: https://github.com/pubpub-zz/ppInk
- Automatic Download: ppInk downloaded during build process via MSBuild target
- Bundled Deployment: ppInk included with application (no separate installation)
- Toggle Control: Click once to open ppInk, click again to close it
- Process Management: Starts and stops ppInk annotation application on demand
- Process Monitoring: Tracks ppInk process state and detects when user closes it
- UI Coordination: Menu auto-collapses when launching ppInk
- Menu State: Clears selection when ppInk closes
- Relative Pathing: Automatically locates ppInk relative to application directory
Opening ppInk:
- User clicks Annotation menu item (first click)
- Application launches ppInk.exe from bundled location
- Menu auto-collapses to minimize interference
- User annotates screen using ppInk
Closing ppInk: 5. User closes ppInk via:
- Annotation menu item (click again) - Application terminates ppInk process
- ESC key or ppInk toolbar exit - User closes ppInk directly
- Application detects exit and clears menu selection
The application automatically locates ppInk using a relative path:
string exePath = System.IO.Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"ppInk_Extracted",
"ppInk",
"ppInk.exe");To integrate a different annotation tool instead of ppInk:
-
Modify the
exePathinLaunchAnnotationAppAsyncmethod inMainWindow.xaml.cs:string exePath = @"C:\Path\To\Your\AnnotationTool.exe";
-
(Optional) Remove or modify the ppInk download MSBuild target in
FloatingMenu.csproj:<Target Name="DownloadAndExtract_ppInk" AfterTargets="Build">
-
Rebuild the application
The Floating Menu application integrates with the TouchDataCaptureService executable to capture and process touch data from interactive display devices. This service runs as a separate process and communicates with the hardware via a configured COM port.
The TouchBack functionality enables:
- Touch Data Capture - Captures raw touch input from IFPD devices
- Process Management - Automatically starts/stops the service with camera selection
- COM Port Communication - Configurable serial port communication with touch hardware
- Automated Build - Service executable is automatically built and deployed with the main application
The TouchDataCaptureService executable is automatically published during the FloatingMenu build process through custom MSBuild targets defined in FloatingMenu.csproj:
<Target Name="PublishAndCopyGetTouchInfo" AfterTargets="Build">
<!-- Publish TouchDataCaptureService as self-contained single-file executable -->
<Exec Command="dotnet publish "$(MSBuildThisFileDirectory)..\GetTouchInfo\TouchDataCaptureService.csproj"
-c Release
-r win-x64
--self-contained true
-p:PublishSingleFile=true
-p:IncludeNativeLibrariesForSelfExtract=true
-o "$(MSBuildThisFileDirectory)..\GetTouchInfo\bin\Release\Publish"" />
<!-- Create ExternalTools directory -->
<MakeDir Directories="$(MSBuildThisFileDirectory)..\ExternalTools\TouchDataCaptureService" />
<!-- Copy executable to ExternalTools -->
<Copy SourceFiles="$(MSBuildThisFileDirectory)..\GetTouchInfo\bin\Release\Publish\TouchDataCaptureService.exe"
DestinationFolder="$(MSBuildThisFileDirectory)..\ExternalTools\TouchDataCaptureService"
SkipUnchangedFiles="true" />
</Target>After building, the structure is:
Windows/
├── FloatingMenu/
│ └── bin/
│ └── Release/
│ └── net10.0-windows/
│ ├── FloatingMenu.exe
│ └── ExternalTools/
│ └── TouchDataCaptureService/
│ └── TouchDataCaptureService.exe
└── GetTouchInfo/
└── bin/
└── Release/
└── Publish/
└── TouchDataCaptureService.exe
Two additional targets ensure the ExternalTools folder is copied to the output:
<!-- Copy during Build -->
<Target Name="CopyExternalTools_Build" AfterTargets="Build">
<ItemGroup>
<ExternalFiles Include="$(ProjectDir)..\ExternalTools\**\*" />
</ItemGroup>
<Copy SourceFiles="@(ExternalFiles)"
DestinationFolder="$(OutDir)ExternalTools\%(RecursiveDir)" />
</Target>
<!-- Copy during Publish -->
<Target Name="CopyExternalTools_Publish" AfterTargets="Publish">
<ItemGroup>
<ExternalFiles Include="$(ProjectDir)..\ExternalTools\**\*" />
</ItemGroup>
<Copy SourceFiles="@(ExternalFiles)"
DestinationFolder="$(PublishDir)ExternalTools\%(RecursiveDir)" />
</Target>When a signal source (camera) is selected, the TouchDataCaptureService is launched automatically:
// In MainWindow.xaml.cs - DeviceSelected event handler
private void SignalSourcePage_DeviceSelected(int cameraIndex)
{
if (cameraIndex >= 0)
{
// Start TouchDataCaptureService process
StartTouchDataCaptureService();
// Open camera window
cameraWindow = new CameraWindow(cameraIndex);
cameraWindow.CameraClosed += CameraWindow_CameraClosed;
cameraWindow.Show();
}
else
{
// Stop TouchDataCaptureService process
StopTouchDataCaptureService();
// Close camera
cameraWindow?.Close();
}
}private Process _touchDataCaptureProcess;
private void StartTouchDataCaptureService()
{
try
{
// Path to the TouchDataCaptureService executable
string exePath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"ExternalTools",
"TouchDataCaptureService",
"TouchDataCaptureService.exe"
);
if (!File.Exists(exePath))
{
MessageBox.Show($"TouchDataCaptureService not found at: {exePath}");
return;
}
// Start the process
_touchDataCaptureProcess = new Process();
_touchDataCaptureProcess.StartInfo.FileName = exePath;
_touchDataCaptureProcess.StartInfo.UseShellExecute = false;
_touchDataCaptureProcess.StartInfo.CreateNoWindow = true;
_touchDataCaptureProcess.Start();
}
catch (Exception ex)
{
MessageBox.Show($"Failed to start TouchDataCaptureService: {ex.Message}");
}
}
private void StopTouchDataCaptureService()
{
try
{
if (_touchDataCaptureProcess != null && !_touchDataCaptureProcess.HasExited)
{
_touchDataCaptureProcess.Kill();
_touchDataCaptureProcess.WaitForExit(1000);
_touchDataCaptureProcess.Dispose();
_touchDataCaptureProcess = null;
}
}
catch (Exception ex)
{
// Silently handle cleanup errors
}
}The service is automatically stopped when:
- User disconnects the camera (toggles signal source to Available)
- User closes the camera window
- Application exits
DeviceSelectedevent fires with index-1
-
Device Manager Method
Device Manager → Ports (COM & LPT) → Look for your touch device -
PowerShell Method
Get-WmiObject Win32_SerialPort | Select-Object Name, DeviceID
-
Windows Settings
Settings → Bluetooth & devices → Devices → More devices and printer settings
To change the COM port:
-
Locate config.json
FloatingMenu.exe directory → ExternalTools → TouchDataCaptureService → config.json -
Edit the file using any text editor:
{ "ComPort": "COM5", // Change to your COM port "BaudRate": 115200 } -
Restart the application for changes to take effect
The TouchDataCaptureService validates the configuration on startup:
- Checks if the specified COM port exists
- Verifies port is not already in use
- Logs configuration errors to the log file (if logging enabled)
- User selects camera from Signal Source list
- FloatingMenu fires
DeviceSelectedevent with camera index - TouchDataCaptureService.exe launches as background process
- Reads
config.jsonfor COM port settings - Opens serial port connection
- Begins capturing touch data
- Reads
- Camera window opens in full-screen mode
- Touch data is captured while camera is active
- User clicks connected camera or closes camera window
- FloatingMenu fires
DeviceSelectedevent with index-1 - TouchDataCaptureService process is terminated
- Serial port connection closed gracefully
- Resources released
- Camera window closes
- Menu returns to Signal Source selection state
Problem: TouchDataCaptureService doesn't start when camera is selected
Solutions:
-
Verify executable exists
Test-Path "ExternalTools\TouchDataCaptureService\TouchDataCaptureService.exe"
-
Check build output
- Build FloatingMenu project
- Look for "Published TouchDataCaptureService.exe" message in build output
-
Manually rebuild service
dotnet publish ..\GetTouchInfo\TouchDataCaptureService.csproj -c Release -r win-x64 --self-contained
-
Check for antivirus blocking
- Some antivirus software may block unsigned executables
- Add exception for TouchDataCaptureService.exe
Problem: Service starts but can't connect to COM port
Solutions:
-
Verify COM port exists
[System.IO.Ports.SerialPort]::GetPortNames() -
Check port not in use
- Close other applications using the port
- Check Task Manager for lingering processes
-
Update config.json
{ "ComPort": "COM3", // Verify this matches Device Manager "BaudRate": 115200 } -
Check permissions
- Ensure user has access to serial ports
- May require administrator rights on some systems
-
Verify hardware connection
- Check USB cable for touch device
- Ensure device drivers are installed
Problem: TouchDataCaptureService continues running after camera closes
Solutions:
-
Manually kill process
Get-Process TouchDataCaptureService | Stop-Process -Force
-
Check Task Manager
- Look for orphaned TouchDataCaptureService.exe processes
- End task manually
-
Restart FloatingMenu
- Close application completely
- Relaunch to reset process management
Problem: Changes to config.json don't take effect
Solutions:
-
Verify JSON syntax
- Use online JSON validator
- Check for missing commas or quotes
-
Check file location
ExternalTools/TouchDataCaptureService/config.json- Must be in same directory as .exe
-
Verify file encoding
- Save as UTF-8 without BOM
- Use Notepad++ or VS Code
-
Restart service
- Disconnect and reconnect camera
- Configuration loaded on process start
Problem: Service runs but no touch data is captured
Solutions:
-
Check log file
-
Enable logging in config.json
{ "EnableLogging": true, "LogFilePath": "TouchDataLog.txt" } -
Verify hardware communication
- Test COM port with serial terminal (PuTTY, etc.)
- Confirm device is sending data
-
Check baud rate
- Verify matches hardware specifications
- Common values: 9600, 19200, 38400, 115200
Problem: Signal Source list is empty or doesn't populate
Solutions:
-
Verify camera connection
- Check USB cable
- Try different USB port
- Restart camera if external
-
Check Windows Camera permissions
- Settings → Privacy → Camera
- Enable "Allow desktop apps to access your camera"
-
Verify camera in Device Manager
- Device Manager → Cameras or Imaging devices
- Ensure no yellow warning icons
-
Test with PowerShell
pnputil /enum-devices /class Camera /connected
-
Check pnputil output manually
- Look for "Device Description:" or "Friendly Name:" fields
- Ensure camera appears in the output
-
Update camera drivers
- Device Manager → Right-click camera → Update driver
-
Test camera with Camera app
start microsoft.windows.camera:
-
Restart the application
- Close and reopen FloatingMenu to trigger re-enumeration
Problem: Camera window opens but displays black/frozen image
Solutions:
-
Check camera is not in use by another application
- Close Zoom, Teams, Skype, etc.
- Check for other camera apps in Task Manager
-
Verify DirectShow support
- Some cameras may not support DirectShow API
- Try with different camera
-
Check camera index
- Ensure the correct camera index is being used
- Try different cameras from the list
-
Check for insufficient capabilities
- Camera must support at least one video resolution
- Verify camera capabilities:
FilterInfoCollection devices = new FilterInfoCollection(FilterCategory.VideoInputDevice); VideoCaptureDevice device = new VideoCaptureDevice(devices[0].MonikerString); foreach (var cap in device.VideoCapabilities) { Console.WriteLine($"{cap.FrameSize.Width}x{cap.FrameSize.Height} @ {cap.AverageFrameRate} fps"); }
-
Check AForge.NET installation
dotnet list package | findstr AForge -
Restart camera device
- Device Manager → Right-click camera → Disable device
- Wait 5 seconds
- Right-click camera → Enable device
-
Verify camera cleanup
- Ensure previous camera session was properly released
- Check that
StopCamera()was called
Problem: Camera selection shows error message about PC Cast
Solutions:
-
Enable PC Cast on device
- This is specific to certain interactive display hardware
- Check device documentation for PC Cast setup
-
Verify device compatibility
- Ensure the camera/device supports PC Cast mode
- Try with standard USB webcam for testing
-
Check device firmware
- Update firmware to latest version
- Consult manufacturer documentation
-
Try different camera
- Select another camera from the list
- Some devices may not require PC Cast
Problem: Double-clicking executable does nothing or shows error
Solutions:
-
Verify .NET 10 Runtime installed
dotnet --list-runtimes
Should show:
Microsoft.WindowsDesktop.App 10.x.x -
Check for missing dependencies
- Ensure AForge.NET assemblies are present
- Run from command prompt to see error messages:
.\FloatingMenu.exe
-
Verify required assemblies
dir *.dll | Select-String "AForge"
Should show:
- AForge.Video.dll
- AForge.Video.DirectShow.dll
-
Run as different user
- Right-click → Run as administrator (if needed)
-
Check Event Viewer for errors
- Event Viewer → Windows Logs → Application
- Look for .NET Runtime errors
Problem: Menu appears in wrong position or doesn't dock correctly
Solutions:
-
Check multi-monitor setup
- Application targets primary monitor
- Move to primary monitor if on secondary
-
Reset window position
- Close application
- Delete user settings (if any)
- Restart application
-
Verify screen resolution
- Application calculates position based on screen dimensions
- Try at native resolution
Problem: Clicking Annotation menu item does nothing or shows error
Solutions:
-
Verify ppInk was downloaded during build
Test-Path "ppInk_Extracted\ppInk\ppInk.exe"
-
Check build output for ppInk download messages
- Look for "Downloading ppInk..." in build output
- Look for "ppInk setup completed successfully."
-
Rebuild the application
dotnet clean dotnet build -c Release
- Ensure internet connection is available for download
-
Manually verify ppInk location
Get-ChildItem -Path . -Filter "ppInk.exe" -Recurse
-
Check for antivirus blocking
- Some antivirus software may block the download
- Add exception for ppInk.exe
-
Verify MSBuild target is present
- Check
FloatingMenu.csprojforDownloadAndExtract_ppInktarget - Ensure target runs after build
- Check
-
Check file permissions
- Ensure user has execute permission for ppInk.exe
-
Check Event Viewer for errors
Event Viewer → Windows Logs → Application
Problem: Camera stays in use after closing Camera Window
Solutions:
-
Force application restart
- Close FloatingMenu completely
- Relaunch application
-
Check Task Manager
- Look for lingering FloatingMenu processes
- End any orphaned processes
-
Verify cleanup is called
- Ensure window
Closedevent is firing - Check
StopCamera()implementation:_videoSource.SignalToStop(); _videoSource.WaitForStop();
- Ensure window
-
Check for background threads
- AForge creates background threads for video capture
- Ensure
WaitForStop()completes before disposing
-
Manual camera release
- Use third-party tool to release camera lock
- Restart computer if persistent
Problem: Application consuming excessive resources
Solutions:
-
Increase frame skipping
// Current: Every other frame if (++_frameCounter % 2 != 0) return; // Alternative: Every 3rd frame (~20 FPS) if (++_frameCounter % 3 != 0) return;
-
Select lower camera resolution
// Instead of highest resolution, select specific resolution var desiredCap = _videoSource.VideoCapabilities .FirstOrDefault(c => c.FrameSize.Width == 1280 && c.FrameSize.Height == 720); if (desiredCap != null) _videoSource.VideoResolution = desiredCap;
-
Close unused camera windows
- Ensure only one camera is active
-
Check for memory leaks
Get-Process FloatingMenu | Select-Object Name, CPU, WorkingSet
-
Monitor GDI+ object handles
- Ensure
DeleteObject(hBitmap)is called in finally block - Check for bitmap leaks
- Ensure
-
Monitor over time
- Open Task Manager
- Performance tab → Monitor FloatingMenu process
Problem: Video appears choppy or slow
Solutions:
-
Reduce frame skipping
// Display all frames if (++_frameCounter % 1 != 0) return;
-
Check camera capabilities
- Some cameras have limited frame rates
- Verify actual camera frame rate support
-
Optimize UI thread
- Ensure dispatcher isn't overloaded
- Consider async bitmap conversion
-
Check system resources
- Close other resource-intensive applications
- Monitor CPU/GPU usage
Problem: Clicking devices in Signal Source list doesn't connect camera
Solutions:
-
Check event wiring
- Verify
DeviceSelectedevent has subscribers - Ensure parent component is handling the event
- Verify
-
Verify ListBox interaction
- Check
DeviceList_PreviewMouseLeftButtonUpevent handler - Ensure
ItemsControl.ContainerFromElementfinds the item
- Check
-
Check device status
- Use debugger to verify status transitions
- Ensure only Available and Connected states toggle
-
Verify camera indices
- Check that
CameraIndexmatches actual DirectShow device count - PnP enumeration may differ from DirectShow enumeration
- Check that
-
Cross-reference device lists
- PnP devices and DirectShow devices may not align
- Ensure indices match between enumeration methods
This is an internal Intel project. For contributions or issues:
- Fork the repository
- Create a feature branch (
git checkout -b feature/improvement) - Commit your changes (
git commit -am 'Add new feature') - Push to the branch (
git push origin feature/improvement) - Create a Pull Request
Copyright (C) 2026 Intel Corporation
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0. See Apache-2.0.txt file for details.
- Repository: https://github.com/intel-sandbox/ifpd-touchback-floatingmenu
- Issue Tracker: Report bugs and request features via GitHub Issues
- .NET Documentation: https://docs.microsoft.com/dotnet
- WPF Documentation: https://docs.microsoft.com/dotnet/desktop/wpf/
- AForge.NET Framework: http://www.aforgenet.com/framework/
- AForge.NET Documentation: http://www.aforgenet.com/framework/docs/
- ppInk Screen Annotation Tool: https://github.com/pubpub-zz/ppInk
- Version: 1.0.0
- Last Updated: March 2026
- Target Framework: .NET 10
- C# Version: 14.0
- Platform: Windows 11 (x64)
- UI Framework: WPF (Windows Presentation Foundation)



