mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 01:36:31 +02:00
Add ZoomIt panoramic screenshot functionality (#46506)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request This adds several ZoomIt features: - Panorama / scrolling screenshots. The image reconstruction happens based on visual cues and accuracy depends on scroll speed during the capture. - Text extraction when snipping. - Break timer improvements (the break timer is now a screen saver, offering the possibility to lock the computer). - Functionality for standalone clip trimming is present but not exposed in the XAML UI. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed The build is successful both with PowerToys and as a standalone Sysinternals executable. We ensured that the features behave as expected and that no regressions are introduced. --------- Co-authored-by: Mark Russinovich <markruss@ntdev.microsoft.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: markrussinovich <markrussinovich@users.noreply.github.com> Co-authored-by: MarioHewardt <marioh@microsoft.com>
This commit is contained in:
124
.github/actions/spell-check/allow/zoomit.txt
vendored
124
.github/actions/spell-check/allow/zoomit.txt
vendored
@@ -1,9 +1,23 @@
|
||||
accelscroll
|
||||
acq
|
||||
adr
|
||||
Adr
|
||||
APPLYTOSUBMENUS
|
||||
AUDCLNT
|
||||
axisdefer
|
||||
axisflip
|
||||
axisstart
|
||||
bitmaps
|
||||
BREAKSCR
|
||||
BUFFERFLAGS
|
||||
Cands
|
||||
capturepath
|
||||
centiseconds
|
||||
CLASSW
|
||||
coeffs
|
||||
coprime
|
||||
CREATEDIBSECTION
|
||||
crossfades
|
||||
Ctl
|
||||
CTLCOLOR
|
||||
CTLCOLORBTN
|
||||
@@ -11,53 +25,163 @@ CTLCOLORDLG
|
||||
CTLCOLOREDIT
|
||||
CTLCOLORLISTBOX
|
||||
CTrim
|
||||
ddy
|
||||
DFCS
|
||||
dlg
|
||||
dlu
|
||||
DONTCARE
|
||||
downsample
|
||||
DRAWITEM
|
||||
DRAWITEMSTRUCT
|
||||
droppedband
|
||||
Droppedband
|
||||
dsum
|
||||
dupburst
|
||||
dupsegments
|
||||
DWLP
|
||||
EDITCONTROL
|
||||
ENABLEHOOK
|
||||
expectedlock
|
||||
fastscroll
|
||||
FDE
|
||||
GETCHANNELRECT
|
||||
GETCHECK
|
||||
GETSCREENSAVEACTIVE
|
||||
GETSCREENSAVETIMEOUT
|
||||
GETTHUMBRECT
|
||||
GIFs
|
||||
hcfdark
|
||||
hcfwhitespace
|
||||
HTBOTTOMRIGHT
|
||||
HTHEME
|
||||
htol
|
||||
ICONINFORMATION
|
||||
ICONWARNING
|
||||
Inj
|
||||
jumprecover
|
||||
KSDATAFORMAT
|
||||
latestcapture
|
||||
ldx
|
||||
LEFTNOWORDWRAP
|
||||
legitjumps
|
||||
letterbox
|
||||
lld
|
||||
llu
|
||||
llums
|
||||
logfont
|
||||
lookback
|
||||
lround
|
||||
lte
|
||||
luma
|
||||
Luma
|
||||
manualdrop
|
||||
maskcache
|
||||
maxstep
|
||||
MENUINFO
|
||||
mic
|
||||
middledrop
|
||||
middledrop
|
||||
MMRESULT
|
||||
momentumreversal
|
||||
mrate
|
||||
mrt
|
||||
narrowstrip
|
||||
ncapture
|
||||
ncm
|
||||
nduplicates
|
||||
niterations
|
||||
nmonitor
|
||||
NONCLIENTMETRICS
|
||||
nonvle
|
||||
nredraw
|
||||
nstop
|
||||
nsubpixel
|
||||
ntorn
|
||||
nvw
|
||||
osc
|
||||
OWNERDRAW
|
||||
PBGRA
|
||||
periodictrap
|
||||
pfdc
|
||||
playhead
|
||||
pointerreuse
|
||||
pwfx
|
||||
Qpc
|
||||
quantums
|
||||
RCZOOMITSCR
|
||||
realcapture
|
||||
REFKNOWNFOLDERID
|
||||
reposted
|
||||
SCREENSAVE
|
||||
SCRNSAVE
|
||||
SCRNSAVECONFIGURE
|
||||
scrnsavw
|
||||
Scrnsavw
|
||||
scrollramp
|
||||
SCROLLSIZEGRIP
|
||||
selftest
|
||||
SETBARCOLOR
|
||||
SETBKCOLOR
|
||||
SETDEFID
|
||||
SETRECT
|
||||
SETSCREENSAVETIMEOUT
|
||||
SHAREMODE
|
||||
SHAREVIOLATION
|
||||
shortlist
|
||||
slowthenfast
|
||||
smallstart
|
||||
SNIPOCR
|
||||
ssi
|
||||
startuprecovery
|
||||
stf
|
||||
stopafter
|
||||
STREAMFLAGS
|
||||
submix
|
||||
sxx
|
||||
sxy
|
||||
syy
|
||||
tallportal
|
||||
tci
|
||||
tcsicmp
|
||||
TEXTMETRIC
|
||||
tinystep
|
||||
tme
|
||||
toolbars
|
||||
TRACKMOUSEEVENT
|
||||
Unadvise
|
||||
vaddq
|
||||
vaddvq
|
||||
vandq
|
||||
vcgeq
|
||||
vdup
|
||||
vld
|
||||
vle
|
||||
Vle
|
||||
VLE
|
||||
vminq
|
||||
vmlal
|
||||
vmull
|
||||
vqaddq
|
||||
vshrn
|
||||
vsntprintf
|
||||
vsnwprintf
|
||||
vsync
|
||||
WASAPI
|
||||
WAVEFORMATEX
|
||||
WAVEFORMATEXTENSIBLE
|
||||
wfopen
|
||||
wideportal
|
||||
wil
|
||||
WMU
|
||||
wrapjump
|
||||
wtol
|
||||
WTSSESSION
|
||||
WTSUn
|
||||
XEnd
|
||||
XStart
|
||||
XStep
|
||||
YInternal
|
||||
ZMBS
|
||||
zncc
|
||||
Zncc
|
||||
ZNCC
|
||||
|
||||
@@ -427,7 +427,7 @@
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/FileLocksmith/">
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj" Id="49D456D3-F485-45AF-8875-45B44F193DDC" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj" Id="49d456d3-f485-45af-8875-45b44f193ddc" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj" Id="799a50d8-de89-4ed1-8ff8-ad5a9ed8c0ca" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj" Id="57175ec7-92a5-4c1e-8244-e3fbca2a81de" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj" Id="9d52fd25-ef90-4f9a-a015-91efc5daf54f" />
|
||||
@@ -438,7 +438,7 @@
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/FileLocksmith/Tests/">
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj" Id="A1B2C3D4-E5F6-7890-1234-567890ABCDEF" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj" Id="a1b2c3d4-e5f6-7890-1234-567890abcdef" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/Hosts/">
|
||||
<Project Path="src/modules/Hosts/Hosts/Hosts.csproj">
|
||||
@@ -464,13 +464,13 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/imageresizer/">
|
||||
<Project Path="src/modules/imageresizer/dll/ImageResizerExt.vcxproj" Id="0b43679e-edfa-4da0-ad30-f4628b308b1b" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj" Id="93b72a06-c8bd-484f-a6f7-c9f280b150bf" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerLib/ImageResizerLib.vcxproj" Id="18b3db45-4ffe-4d01-97d6-5223feee1853" />
|
||||
<Project Path="src/modules/imageresizer/ui/ImageResizerUI.csproj">
|
||||
<Project Path="src/modules/imageresizer/ImageResizerCLI/ImageResizerCLI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/imageresizer/ImageResizerCLI/ImageResizerCLI.csproj">
|
||||
<Project Path="src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj" Id="93b72a06-c8bd-484f-a6f7-c9f280b150bf" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerLib/ImageResizerLib.vcxproj" Id="18b3db45-4ffe-4d01-97d6-5223feee1853" />
|
||||
<Project Path="src/modules/imageresizer/ui/ImageResizerUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
@@ -1027,7 +1027,10 @@
|
||||
<File Path="src/modules/Workspaces/workspaces-common/WindowUtils.h" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/ZoomIt/">
|
||||
<Project Path="src/modules/ZoomIt/ZoomIt/ZoomIt.vcxproj" Id="0a84f764-3a88-44cd-aa96-41bdbd48627b" />
|
||||
<Project Path="src/modules/ZoomIt/ZoomIt/ZoomIt.vcxproj" Id="0a84f764-3a88-44cd-aa96-41bdbd48627b">
|
||||
<BuildDependency Project="src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj" Id="94ba3051-c8d7-454a-9d46-1a7c78e228a3" />
|
||||
<Project Path="src/modules/ZoomIt/ZoomItModuleInterface/ZoomItModuleInterface.vcxproj" Id="e4585179-2ac1-4d5f-a3ff-cfc5392f694c" />
|
||||
<Project Path="src/modules/ZoomIt/ZoomItSettingsInterop/ZoomItSettingsInterop.vcxproj" Id="ca7d8106-30b9-4aec-9d05-b69b31b8c461" />
|
||||
</Folder>
|
||||
|
||||
@@ -151,6 +151,7 @@ namespace CommonSharedConstants
|
||||
const wchar_t ZOOMIT_BREAK_EVENT[] = L"Local\\PowerToysZoomIt-BreakEvent-17f2e63c-4c56-41dd-90a0-2d12f9f50c6b";
|
||||
const wchar_t ZOOMIT_LIVEZOOM_EVENT[] = L"Local\\PowerToysZoomIt-LiveZoomEvent-390bf0c7-616f-47dc-bafe-a2d228add20d";
|
||||
const wchar_t ZOOMIT_SNIP_EVENT[] = L"Local\\PowerToysZoomIt-SnipEvent-2fd9c211-436d-4f17-a902-2528aaae3e30";
|
||||
const wchar_t ZOOMIT_SNIPOCR_EVENT[] = L"Local\\PowerToysZoomIt-SnipOcrEvent-a7c3b1d2-9e4f-4a6b-8d5c-1f2e3a4b5c6d";
|
||||
const wchar_t ZOOMIT_RECORD_EVENT[] = L"Local\\PowerToysZoomIt-RecordEvent-74539344-eaad-4711-8e83-23946e424512";
|
||||
|
||||
// Path to the events used by PowerDisplay
|
||||
|
||||
18003
src/modules/ZoomIt/ZoomIt/PanoramaCapture.cpp
Normal file
18003
src/modules/ZoomIt/ZoomIt/PanoramaCapture.cpp
Normal file
File diff suppressed because it is too large
Load Diff
42
src/modules/ZoomIt/ZoomIt/PanoramaCapture.h
Normal file
42
src/modules/ZoomIt/ZoomIt/PanoramaCapture.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//============================================================================
|
||||
//
|
||||
// PanoramaCapture.h
|
||||
//
|
||||
// Panorama (scrolling) screen capture and stitching.
|
||||
//
|
||||
// Copyright (C) Mark Russinovich
|
||||
// Sysinternals - www.sysinternals.com
|
||||
//
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
//============================================================================
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
|
||||
// Globals shared with the main ZoomIt module.
|
||||
extern bool g_PanoramaCaptureActive;
|
||||
extern bool g_PanoramaStopRequested;
|
||||
extern bool g_PanoramaDebugMode;
|
||||
|
||||
// Run the panorama capture flow: select a region, capture frames while
|
||||
// scrolling, stitch them together, and copy the result to the clipboard.
|
||||
bool RunPanoramaCaptureToClipboard( HWND hWnd );
|
||||
|
||||
// Run the panorama capture flow and save the result to a file via a
|
||||
// Save As dialog instead of copying to the clipboard.
|
||||
bool RunPanoramaCaptureToFile( HWND hWnd );
|
||||
|
||||
// Run a synthetic, non-interactive self-test for panorama frame stitching.
|
||||
// Returns true when stitching output matches expected dimensions/content.
|
||||
#ifdef _DEBUG
|
||||
bool RunPanoramaStitchSelfTest();
|
||||
|
||||
// Re-stitch frames from a specific debug dump directory.
|
||||
bool RunPanoramaStitchDumpDirectory( const wchar_t* path );
|
||||
|
||||
// Re-stitch accepted panorama frames from the latest debug dump session and
|
||||
// save output into that same session directory.
|
||||
bool RunPanoramaStitchLatestDebugDump();
|
||||
#endif
|
||||
@@ -11,6 +11,23 @@
|
||||
#include "Utility.h"
|
||||
#include "WindowsVersions.h"
|
||||
|
||||
static void SelectRectangleDebugLog( const wchar_t* format, ... )
|
||||
{
|
||||
#if _DEBUG
|
||||
wchar_t message[1024]{};
|
||||
va_list args;
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 26492 )
|
||||
va_start( args, format );
|
||||
#pragma warning( pop )
|
||||
vswprintf_s( message, format, args );
|
||||
va_end( args );
|
||||
OutputDebugStringW( message );
|
||||
#else
|
||||
UNREFERENCED_PARAMETER( format );
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SelectRectangle::Start
|
||||
@@ -18,6 +35,12 @@
|
||||
//----------------------------------------------------------------------------
|
||||
bool SelectRectangle::Start( HWND ownerWindow, bool fullMonitor )
|
||||
{
|
||||
m_stopping = false;
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Start owner=%p fullMonitor=%d minSize=%d alpha=%u\n",
|
||||
ownerWindow,
|
||||
fullMonitor ? 1 : 0,
|
||||
MinSize(),
|
||||
Alpha() );
|
||||
WNDCLASSW windowClass{};
|
||||
windowClass.lpfnWndProc = []( HWND window, UINT message, WPARAM wordParam, LPARAM longParam ) -> LRESULT
|
||||
{
|
||||
@@ -46,10 +69,16 @@ bool SelectRectangle::Start( HWND ownerWindow, bool fullMonitor )
|
||||
|
||||
m_cancel = false;
|
||||
auto rect = GetMonitorRectFromCursor();
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Monitor rect=(%ld,%ld)-(%ld,%ld)\n",
|
||||
rect.left,
|
||||
rect.top,
|
||||
rect.right,
|
||||
rect.bottom );
|
||||
m_window = wil::unique_hwnd( CreateWindowExW( WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST, m_className, nullptr, WS_POPUP,
|
||||
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, ownerWindow,
|
||||
nullptr, nullptr, this ) );
|
||||
THROW_LAST_ERROR_IF_NULL( m_window.get() );
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Window created hwnd=%p\n", m_window.get() );
|
||||
|
||||
if( fullMonitor )
|
||||
{
|
||||
@@ -58,7 +87,11 @@ bool SelectRectangle::Start( HWND ownerWindow, bool fullMonitor )
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLayeredWindowAttributes( m_window.get(), 0, Alpha(), LWA_ALPHA );
|
||||
const BOOL layered = SetLayeredWindowAttributes( m_window.get(), 0, Alpha(), LWA_ALPHA );
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] SetLayeredWindowAttributes(alpha=%u) success=%d err=%lu\n",
|
||||
Alpha(),
|
||||
layered ? 1 : 0,
|
||||
layered ? 0 : GetLastError() );
|
||||
}
|
||||
|
||||
ShowWindow( m_window.get(), SW_SHOW );
|
||||
@@ -69,6 +102,7 @@ bool SelectRectangle::Start( HWND ownerWindow, bool fullMonitor )
|
||||
GetClipCursor( &m_oldClipRect );
|
||||
ClipCursor( &rect );
|
||||
m_setClip = true;
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Cursor clipped to monitor bounds\n" );
|
||||
}
|
||||
|
||||
MSG message;
|
||||
@@ -78,13 +112,20 @@ bool SelectRectangle::Start( HWND ownerWindow, bool fullMonitor )
|
||||
DispatchMessageW( &message );
|
||||
if( m_cancel )
|
||||
{
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Start cancelled via Stop()\n" );
|
||||
return false;
|
||||
}
|
||||
if( m_selected )
|
||||
{
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Selection finalized rect=(%ld,%ld)-(%ld,%ld)\n",
|
||||
m_selectedRect.left,
|
||||
m_selectedRect.top,
|
||||
m_selectedRect.right,
|
||||
m_selectedRect.bottom );
|
||||
break;
|
||||
}
|
||||
}
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Start complete selected=%d cancel=%d\n", m_selected ? 1 : 0, m_cancel ? 1 : 0 );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -95,15 +136,38 @@ bool SelectRectangle::Start( HWND ownerWindow, bool fullMonitor )
|
||||
//----------------------------------------------------------------------------
|
||||
void SelectRectangle::Stop()
|
||||
{
|
||||
if( m_stopping )
|
||||
{
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Stop ignored due to reentrancy\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
m_stopping = true;
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Stop hwnd=%p selected=%d cancel=%d clip=%d rect=(%ld,%ld)-(%ld,%ld)\n",
|
||||
m_window.get(),
|
||||
m_selected ? 1 : 0,
|
||||
m_cancel ? 1 : 0,
|
||||
m_setClip ? 1 : 0,
|
||||
m_selectedRect.left,
|
||||
m_selectedRect.top,
|
||||
m_selectedRect.right,
|
||||
m_selectedRect.bottom );
|
||||
if( m_setClip )
|
||||
{
|
||||
ClipCursor( &m_oldClipRect );
|
||||
m_setClip = false;
|
||||
}
|
||||
m_window.reset();
|
||||
|
||||
HWND window = m_window.release();
|
||||
if( window != nullptr && IsWindow( window ) )
|
||||
{
|
||||
DestroyWindow( window );
|
||||
}
|
||||
|
||||
m_selected = false;
|
||||
m_selectedRect = {};
|
||||
m_cancel = true;
|
||||
m_stopping = false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -114,11 +178,20 @@ void SelectRectangle::Stop()
|
||||
void SelectRectangle::ShowSelected()
|
||||
{
|
||||
m_selected = true;
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] ShowSelected rect=(%ld,%ld)-(%ld,%ld) dpi=%u\n",
|
||||
m_selectedRect.left,
|
||||
m_selectedRect.top,
|
||||
m_selectedRect.right,
|
||||
m_selectedRect.bottom,
|
||||
m_dpi );
|
||||
|
||||
// Set the alpha to match the Windows graphics capture API yellow border
|
||||
// and set the window to be transparent and disabled, so it will be skipped
|
||||
// for hit testing and as a candidate for the next foreground window.
|
||||
SetLayeredWindowAttributes( m_window.get(), 0, 191, LWA_ALPHA );
|
||||
const BOOL layered = SetLayeredWindowAttributes( m_window.get(), 0, 191, LWA_ALPHA );
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] ShowSelected SetLayeredWindowAttributes(alpha=191) success=%d err=%lu\n",
|
||||
layered ? 1 : 0,
|
||||
layered ? 0 : GetLastError() );
|
||||
SetWindowLong( m_window.get(), GWL_EXSTYLE, GetWindowLong( m_window.get(), GWL_EXSTYLE ) | WS_EX_TRANSPARENT );
|
||||
EnableWindow( m_window.get(), FALSE );
|
||||
|
||||
@@ -144,6 +217,12 @@ void SelectRectangle::ShowSelected()
|
||||
point.x += windowRect.left;
|
||||
point.y += windowRect.top;
|
||||
MoveWindow( m_window.get(), point.x, point.y, rect.right, rect.bottom, true );
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Border window moved to (%ld,%ld) size=%ldx%ld borderWidth=%d\n",
|
||||
point.x,
|
||||
point.y,
|
||||
rect.right,
|
||||
rect.bottom,
|
||||
width );
|
||||
|
||||
// Use a region to keep everything but the border transparent.
|
||||
wil::unique_hrgn region{CreateRectRgnIndirect( &rect )};
|
||||
@@ -151,6 +230,11 @@ void SelectRectangle::ShowSelected()
|
||||
wil::unique_hrgn insideRegion{CreateRectRgnIndirect( &rect )};
|
||||
CombineRgn( region.get(), region.get(), insideRegion.get(), RGN_XOR );
|
||||
SetWindowRgn( m_window.get(), region.release(), true );
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Border window region applied\n" );
|
||||
|
||||
// Force immediate paint so the yellow border is visible instead of a
|
||||
// transient black frame from the class background brush.
|
||||
RedrawWindow( m_window.get(), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -162,6 +246,7 @@ void SelectRectangle::UpdateOwner( HWND window )
|
||||
{
|
||||
if( m_window != nullptr )
|
||||
{
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] UpdateOwner hwnd=%p newOwner=%p\n", m_window.get(), window );
|
||||
SetWindowLongPtr( m_window.get(), GWLP_HWNDPARENT, reinterpret_cast<LONG_PTR>(window) );
|
||||
SetWindowPos( m_window.get(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
|
||||
}
|
||||
@@ -179,10 +264,24 @@ LRESULT SelectRectangle::WindowProc( HWND window, UINT message, WPARAM wordParam
|
||||
case WM_CREATE:
|
||||
m_dpi = GetDpiForWindowHelper( window );
|
||||
SetWindowDisplayAffinity( window, WDA_EXCLUDEFROMCAPTURE );
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] WM_CREATE hwnd=%p dpi=%u\n", window, m_dpi );
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
Stop();
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] WM_DESTROY hwnd=%p\n", window );
|
||||
if( m_window.get() == window )
|
||||
{
|
||||
m_window.release();
|
||||
}
|
||||
if( m_setClip )
|
||||
{
|
||||
ClipCursor( &m_oldClipRect );
|
||||
m_setClip = false;
|
||||
}
|
||||
m_selected = false;
|
||||
m_selectedRect = {};
|
||||
m_cancel = true;
|
||||
m_stopping = false;
|
||||
return 0;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
@@ -190,6 +289,7 @@ LRESULT SelectRectangle::WindowProc( HWND window, UINT message, WPARAM wordParam
|
||||
SetCapture( window );
|
||||
|
||||
m_startPoint = { GET_X_LPARAM( longParam ), GET_Y_LPARAM( longParam ) };
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] WM_LBUTTONDOWN startPoint=(%ld,%ld)\n", m_startPoint.x, m_startPoint.y );
|
||||
[[fallthrough]];
|
||||
}
|
||||
case WM_MOUSEMOVE:
|
||||
@@ -199,6 +299,11 @@ LRESULT SelectRectangle::WindowProc( HWND window, UINT message, WPARAM wordParam
|
||||
GetClientRect( window, &rect );
|
||||
POINT point{ GET_X_LPARAM( longParam ), GET_Y_LPARAM( longParam ) };
|
||||
m_selectedRect = ForceRectInBounds( RectFromPointsMinSize( m_startPoint, point, MinSize() ), rect );
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] Drag rect=(%ld,%ld)-(%ld,%ld)\n",
|
||||
m_selectedRect.left,
|
||||
m_selectedRect.top,
|
||||
m_selectedRect.right,
|
||||
m_selectedRect.bottom );
|
||||
|
||||
// Use a region to carve out the selected rectangle.
|
||||
wil::unique_hrgn region{CreateRectRgnIndirect( &m_selectedRect )};
|
||||
@@ -211,6 +316,7 @@ LRESULT SelectRectangle::WindowProc( HWND window, UINT message, WPARAM wordParam
|
||||
case WM_KEYDOWN:
|
||||
if( wordParam == VK_ESCAPE )
|
||||
{
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] WM_KEYDOWN Escape pressed\n" );
|
||||
Stop();
|
||||
}
|
||||
return 0;
|
||||
@@ -218,12 +324,18 @@ LRESULT SelectRectangle::WindowProc( HWND window, UINT message, WPARAM wordParam
|
||||
case WM_KILLFOCUS:
|
||||
if( !m_selected )
|
||||
{
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] WM_KILLFOCUS before selection complete\n" );
|
||||
Stop();
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
{
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] WM_LBUTTONUP selectedRect=(%ld,%ld)-(%ld,%ld)\n",
|
||||
m_selectedRect.left,
|
||||
m_selectedRect.top,
|
||||
m_selectedRect.right,
|
||||
m_selectedRect.bottom );
|
||||
if( m_setClip )
|
||||
{
|
||||
ClipCursor( &m_oldClipRect );
|
||||
@@ -249,6 +361,11 @@ LRESULT SelectRectangle::WindowProc( HWND window, UINT message, WPARAM wordParam
|
||||
|
||||
RECT rect;
|
||||
GetClientRect( window, &rect );
|
||||
SelectRectangleDebugLog( L"[SelectRectangle] WM_PAINT selected border rect=(%ld,%ld)-(%ld,%ld)\n",
|
||||
rect.left,
|
||||
rect.top,
|
||||
rect.right,
|
||||
rect.bottom );
|
||||
|
||||
// Draw a border matching the Windows graphics capture API border.
|
||||
// The outer frame is yellow and two logical pixels wide, while the
|
||||
|
||||
@@ -20,10 +20,14 @@ public:
|
||||
void MinSize( int minSize ) { m_minSize = minSize; }
|
||||
int MinSize() const { return m_minSize; }
|
||||
RECT SelectedRect() const { return m_selectedRect; }
|
||||
bool IsActive() const { return m_window != nullptr; }
|
||||
|
||||
bool Start( HWND ownerWindow = nullptr, bool fullMonitor = false );
|
||||
void Stop();
|
||||
void UpdateOwner( HWND window );
|
||||
void Hide() { if( m_window ) ShowWindow( m_window.get(), SW_HIDE ); }
|
||||
void Show() { if( m_window ) ShowWindow( m_window.get(), SW_SHOWNA ); }
|
||||
void SetExcludeFromCapture( bool exclude ) { if( m_window ) SetWindowDisplayAffinity( m_window.get(), exclude ? WDA_EXCLUDEFROMCAPTURE : WDA_NONE ); }
|
||||
|
||||
private:
|
||||
BYTE m_alpha = 176;
|
||||
@@ -36,6 +40,7 @@ private:
|
||||
RECT m_oldClipRect{};
|
||||
bool m_selected{ false };
|
||||
bool m_setClip{ false };
|
||||
bool m_stopping{ false };
|
||||
POINT m_startPoint{};
|
||||
wil::unique_hwnd m_window;
|
||||
|
||||
|
||||
@@ -406,7 +406,10 @@ static bool LoadGifFrames(const std::wstring& gifPath, VideoRecordingSession::Tr
|
||||
|
||||
const auto& lastFrame = pData->gifFrames.back();
|
||||
pData->videoDuration = winrt::TimeSpan{ lastFrame.start.count() + lastFrame.duration.count() };
|
||||
pData->trimEnd = pData->videoDuration;
|
||||
if( pData->trimEnd.count() <= 0 )
|
||||
{
|
||||
pData->trimEnd = pData->videoDuration;
|
||||
}
|
||||
pData->gifFramesLoaded = true;
|
||||
pData->gifLastFrameIndex = 0;
|
||||
|
||||
@@ -721,13 +724,9 @@ namespace
|
||||
SetDlgItemText(hDlg, IDC_TRIM_DURATION_LABEL, durationText.c_str());
|
||||
}
|
||||
|
||||
// Enable OK when trimming is active (even if unchanged since dialog opened),
|
||||
// or when the user changed the selection (including reverting to full length).
|
||||
const bool trimChanged = (pData->trimStart.count() != pData->originalTrimStart.count()) ||
|
||||
(pData->trimEnd.count() != pData->originalTrimEnd.count());
|
||||
const bool trimIsActive = (pData->trimStart.count() > 0) ||
|
||||
(pData->videoDuration.count() > 0 && pData->trimEnd.count() < pData->videoDuration.count());
|
||||
EnableWindow(GetDlgItem(hDlg, IDOK), trimChanged || trimIsActive);
|
||||
// Always enable OK so users can close the dialog after previewing
|
||||
// without being forced to use Cancel.
|
||||
EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
|
||||
}
|
||||
|
||||
RECT GetTimelineTrackRect(const RECT& clientRect, UINT dpi)
|
||||
@@ -1345,7 +1344,10 @@ public:
|
||||
auto trimResult = VideoRecordingSession::ShowTrimDialog(hParent, m_videoPath, *m_pTrimStart, *m_pTrimEnd);
|
||||
if (trimResult == IDOK)
|
||||
{
|
||||
*m_pShouldTrim = true;
|
||||
// Trim values are only written back when the user actually
|
||||
// changed the selection, so a non-zero trimEnd means a
|
||||
// real trim is requested.
|
||||
*m_pShouldTrim = (m_pTrimEnd->count() > 0);
|
||||
}
|
||||
else if( trimResult == IDCANCEL )
|
||||
{
|
||||
@@ -1502,12 +1504,13 @@ INT_PTR VideoRecordingSession::ShowTrimDialog(
|
||||
HWND hParent,
|
||||
const std::wstring& videoPath,
|
||||
winrt::TimeSpan& trimStart,
|
||||
winrt::TimeSpan& trimEnd)
|
||||
winrt::TimeSpan& trimEnd,
|
||||
bool standaloneMode)
|
||||
{
|
||||
std::promise<INT_PTR> resultPromise;
|
||||
auto resultFuture = resultPromise.get_future();
|
||||
|
||||
std::thread staThread([hParent, videoPath, &trimStart, &trimEnd, promise = std::move(resultPromise)]() mutable
|
||||
std::thread staThread([hParent, videoPath, &trimStart, &trimEnd, standaloneMode, promise = std::move(resultPromise)]() mutable
|
||||
{
|
||||
bool coInitialized = false;
|
||||
try
|
||||
@@ -1525,7 +1528,7 @@ INT_PTR VideoRecordingSession::ShowTrimDialog(
|
||||
|
||||
try
|
||||
{
|
||||
INT_PTR dlgResult = ShowTrimDialogInternal(hParent, videoPath, trimStart, trimEnd);
|
||||
INT_PTR dlgResult = ShowTrimDialogInternal(hParent, videoPath, trimStart, trimEnd, standaloneMode);
|
||||
promise.set_value(dlgResult);
|
||||
}
|
||||
catch (const winrt::hresult_error& e)
|
||||
@@ -1584,7 +1587,8 @@ INT_PTR VideoRecordingSession::ShowTrimDialogInternal(
|
||||
HWND hParent,
|
||||
const std::wstring& videoPath,
|
||||
winrt::TimeSpan& trimStart,
|
||||
winrt::TimeSpan& trimEnd)
|
||||
winrt::TimeSpan& trimEnd,
|
||||
bool standaloneMode)
|
||||
{
|
||||
TrimDialogData data;
|
||||
data.videoPath = videoPath;
|
||||
@@ -1592,6 +1596,7 @@ INT_PTR VideoRecordingSession::ShowTrimDialogInternal(
|
||||
data.trimStart = trimStart;
|
||||
data.trimEnd = trimEnd;
|
||||
data.isGif = IsGifPath(videoPath);
|
||||
data.standaloneMode = standaloneMode;
|
||||
|
||||
if (data.isGif)
|
||||
{
|
||||
@@ -1786,8 +1791,17 @@ INT_PTR VideoRecordingSession::ShowTrimDialogInternal(
|
||||
|
||||
if (result == IDOK)
|
||||
{
|
||||
trimStart = data.trimStart;
|
||||
trimEnd = data.trimEnd;
|
||||
// Only write back trim values when the user actually changed the
|
||||
// selection. This lets the caller distinguish "confirmed without
|
||||
// trimming" (preview-only) from a real trim operation.
|
||||
const bool selectionChanged =
|
||||
(data.trimStart.count() != data.originalTrimStart.count()) ||
|
||||
(data.trimEnd.count() != data.originalTrimEnd.count());
|
||||
if (selectionChanged)
|
||||
{
|
||||
trimStart = data.trimStart;
|
||||
trimEnd = data.trimEnd;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -3890,6 +3904,12 @@ INT_PTR CALLBACK VideoRecordingSession::TrimDialogProc(HWND hDlg, UINT message,
|
||||
// Make OK the default button
|
||||
SendMessage(hDlg, DM_SETDEFID, IDOK, 0);
|
||||
|
||||
// In standalone mode, change OK button text to "Save As"
|
||||
if (pData->standaloneMode)
|
||||
{
|
||||
SetDlgItemText(hDlg, IDOK, L"Save As");
|
||||
}
|
||||
|
||||
// Subclass the dialog to handle resize grip hit testing
|
||||
SetWindowSubclass(hDlg, TrimDialogSubclassProc, 0, reinterpret_cast<DWORD_PTR>(pData));
|
||||
|
||||
@@ -5029,6 +5049,115 @@ INT_PTR CALLBACK VideoRecordingSession::TrimDialogProc(HWND hDlg, UINT message,
|
||||
case IDOK:
|
||||
pData = reinterpret_cast<TrimDialogData*>(GetWindowLongPtr(hDlg, DWLP_USER));
|
||||
StopPlayback(hDlg, pData);
|
||||
|
||||
if (pData->standaloneMode)
|
||||
{
|
||||
// In standalone mode, "Save As" shows a save dialog and performs the trim
|
||||
auto saveDialog = wil::CoCreateInstance<::IFileSaveDialog>(CLSID_FileSaveDialog);
|
||||
|
||||
FILEOPENDIALOGOPTIONS options;
|
||||
if (SUCCEEDED(saveDialog->GetOptions(&options)))
|
||||
saveDialog->SetOptions(options | FOS_FORCEFILESYSTEM);
|
||||
|
||||
wil::com_ptr<::IShellItem> videosItem;
|
||||
if (SUCCEEDED(SHGetKnownFolderItem(FOLDERID_Videos, KF_FLAG_DEFAULT, nullptr,
|
||||
IID_IShellItem, (void**)videosItem.put())))
|
||||
saveDialog->SetDefaultFolder(videosItem.get());
|
||||
|
||||
// Derive suggested filename from source
|
||||
std::wstring suggestedName;
|
||||
{
|
||||
auto pos = pData->videoPath.find_last_of(L"\\/");
|
||||
suggestedName = (pos != std::wstring::npos) ? pData->videoPath.substr(pos + 1) : pData->videoPath;
|
||||
auto dot = suggestedName.find_last_of(L'.');
|
||||
if (dot != std::wstring::npos)
|
||||
suggestedName.insert(dot, L"_trimmed");
|
||||
else
|
||||
suggestedName += L"_trimmed";
|
||||
}
|
||||
|
||||
if (pData->isGif)
|
||||
{
|
||||
saveDialog->SetDefaultExtension(L".gif");
|
||||
COMDLG_FILTERSPEC fileTypes[] = { { L"GIF Animation", L"*.gif" } };
|
||||
saveDialog->SetFileTypes(_countof(fileTypes), fileTypes);
|
||||
}
|
||||
else
|
||||
{
|
||||
saveDialog->SetDefaultExtension(L".mp4");
|
||||
COMDLG_FILTERSPEC fileTypes[] = { { L"MP4 Video", L"*.mp4" } };
|
||||
saveDialog->SetFileTypes(_countof(fileTypes), fileTypes);
|
||||
}
|
||||
saveDialog->SetFileName(suggestedName.c_str());
|
||||
saveDialog->SetTitle(L"ZoomIt: Save Trimmed Video As...");
|
||||
|
||||
HRESULT hr = saveDialog->Show(hDlg);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// User cancelled save dialog — return to trim editor
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
wil::com_ptr<::IShellItem> resultItem;
|
||||
THROW_IF_FAILED(saveDialog->GetResult(resultItem.put()));
|
||||
wil::unique_cotaskmem_string savePath;
|
||||
THROW_IF_FAILED(resultItem->GetDisplayName(SIGDN_FILESYSPATH, savePath.put()));
|
||||
|
||||
// Capture what we need before closing the dialog
|
||||
std::wstring videoPath = pData->videoPath;
|
||||
bool isGif = pData->isGif;
|
||||
auto trimStart = pData->trimStart;
|
||||
auto trimEnd = pData->trimEnd;
|
||||
std::wstring savePathStr(savePath.get());
|
||||
|
||||
// Close the trim dialog immediately
|
||||
EndDialog(hDlg, IDOK);
|
||||
|
||||
// Perform the trim after the dialog is closed
|
||||
try
|
||||
{
|
||||
auto trimOp = isGif
|
||||
? TrimGifAsync(videoPath, trimStart, trimEnd)
|
||||
: TrimVideoAsync(videoPath, trimStart, trimEnd);
|
||||
|
||||
// Pump messages while waiting for async operation
|
||||
while (trimOp.Status() == winrt::AsyncStatus::Started)
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
auto trimmedPath = std::wstring(trimOp.GetResults());
|
||||
if (trimmedPath.empty())
|
||||
{
|
||||
MessageBox(nullptr, L"Failed to trim video.", L"Error", MB_OK | MB_ICONERROR);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Copy trimmed file to the user-chosen save location
|
||||
if (!CopyFile(trimmedPath.c_str(), savePathStr.c_str(), FALSE))
|
||||
{
|
||||
MessageBox(nullptr, L"Failed to save the trimmed file.", L"Error", MB_OK | MB_ICONERROR);
|
||||
DeleteFile(trimmedPath.c_str());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Clean up temp file
|
||||
DeleteFile(trimmedPath.c_str());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
MessageBox(nullptr, L"Failed to trim video.", L"Error", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Trim times are already set by mouse dragging
|
||||
EndDialog(hDlg, IDOK);
|
||||
return TRUE;
|
||||
|
||||
@@ -132,6 +132,7 @@ public:
|
||||
bool isDragging{ false };
|
||||
int lastPlayheadX{ -1 }; // Track last playhead pixel position for efficient invalidation
|
||||
MMRESULT mmTimerId{ 0 }; // Multimedia timer for smooth MP4 playback
|
||||
bool standaloneMode{ false }; // When true, OK becomes "Save As" and handles file saving directly
|
||||
|
||||
// Helper to convert time to pixel position
|
||||
int TimeToPixel(winrt::Windows::Foundation::TimeSpan time, int timelineWidth) const
|
||||
@@ -162,7 +163,8 @@ public:
|
||||
HWND hParent,
|
||||
const std::wstring& videoPath,
|
||||
winrt::Windows::Foundation::TimeSpan& trimStart,
|
||||
winrt::Windows::Foundation::TimeSpan& trimEnd);
|
||||
winrt::Windows::Foundation::TimeSpan& trimEnd,
|
||||
bool standaloneMode = false);
|
||||
|
||||
private:
|
||||
static INT_PTR CALLBACK TrimDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
@@ -179,7 +181,8 @@ private:
|
||||
HWND hParent,
|
||||
const std::wstring& videoPath,
|
||||
winrt::Windows::Foundation::TimeSpan& trimStart,
|
||||
winrt::Windows::Foundation::TimeSpan& trimEnd);
|
||||
winrt::Windows::Foundation::TimeSpan& trimEnd,
|
||||
bool standaloneMode = false);
|
||||
|
||||
private:
|
||||
VideoRecordingSession(
|
||||
|
||||
@@ -113,26 +113,26 @@ END
|
||||
// Dialog
|
||||
//
|
||||
|
||||
OPTIONS DIALOGEX 0, 0, 299, 325
|
||||
OPTIONS DIALOGEX 0, 0, 299, 331
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_CONTROLPARENT
|
||||
CAPTION "ZoomIt - Sysinternals: www.sysinternals.com"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,186,306,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,243,306,50,14
|
||||
DEFPUSHBUTTON "OK",IDOK,184,308,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,241,308,50,14
|
||||
LTEXT "ZoomIt v10.1",IDC_VERSION,42,7,73,10
|
||||
LTEXT "Copyright \251 2006-2026 Mark Russinovich",IDC_COPYRIGHT,42,17,251,8
|
||||
CONTROL "<a HREF=""https://www.sysinternals.com"">Sysinternals - www.sysinternals.com</a>",IDC_LINK,
|
||||
"SysLink",WS_TABSTOP,42,26,150,9
|
||||
ICON "APPICON",IDC_STATIC,12,9,20,20
|
||||
CONTROL "Show tray icon",IDC_SHOW_TRAY_ICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,295,105,10
|
||||
CONTROL "",IDC_TAB,"SysTabControl32",TCS_MULTILINE | WS_TABSTOP,8,46,285,247
|
||||
CONTROL "Run ZoomIt when Windows starts",IDC_AUTOSTART,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,309,122,10
|
||||
CONTROL "Show tray icon",IDC_SHOW_TRAY_ICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,302,105,10
|
||||
CONTROL "",IDC_TAB,"SysTabControl32",TCS_MULTILINE | WS_TABSTOP,8,45,285,255
|
||||
CONTROL "Run ZoomIt when Windows starts",IDC_AUTOSTART,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,316,122,10
|
||||
END
|
||||
|
||||
ADVANCED_BREAK DIALOGEX 0, 0, 209, 225
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
ADVANCED_BREAK DIALOGEX 0, 0, 209, 223
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Advanced Break Options"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
@@ -158,8 +158,8 @@ BEGIN
|
||||
EDITTEXT IDC_BACKGROUND_FILE,62,164,125,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
PUSHBUTTON "&...",IDC_BACKGROUND_BROWSE,188,164,13,11
|
||||
CONTROL "Scale to screen:",IDC_CHECK_BACKGROUND_STRETCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,58,180,67,10,WS_EX_RIGHT
|
||||
DEFPUSHBUTTON "OK",IDOK,97,199,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,150,199,50,14
|
||||
DEFPUSHBUTTON "OK",IDOK,97,202,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,150,202,50,14
|
||||
LTEXT "Alarm Sound File:",IDC_STATIC_SOUND_FILE,61,26,56,8
|
||||
LTEXT "Timer Opacity:",IDC_STATIC,8,59,48,8
|
||||
LTEXT "Timer Position:",IDC_STATIC,8,77,48,8
|
||||
@@ -215,21 +215,23 @@ BEGIN
|
||||
GROUPBOX "Sample",IDC_TEXT_FONT,8,61,99,28
|
||||
END
|
||||
|
||||
BREAK DIALOGEX 0, 0, 260, 123
|
||||
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_SYSMENU
|
||||
BREAK DIALOGEX 0, 0, 260, 159
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_BREAK_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,52,67,80,12
|
||||
EDITTEXT IDC_TIMER,52,86,31,13,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_SPIN_TIMER,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,66,86,11,12
|
||||
LTEXT "minutes",IDC_STATIC,88,88,25,8
|
||||
PUSHBUTTON "&Advanced",IDC_ADVANCED_BREAK,192,102,41,14
|
||||
LTEXT "Enter timer mode by using the ZoomIt tray icon's Break menu item. Increase and decrease time with the arrow keys. If you Alt-Tab away from the timer window, reactivate it by left-clicking on the ZoomIt tray icon. Exit timer mode with Escape. ",IDC_STATIC,7,7,230,33
|
||||
LTEXT "Start Timer:",IDC_STATIC,7,70,39,8
|
||||
LTEXT "Timer:",IDC_STATIC,7,88,20,8
|
||||
LTEXT "Change the break timer color using the same keys that the drawing color. The break timer font is the same as text font.",IDC_STATIC,7,45,230,20
|
||||
CONTROL "",IDC_BREAK_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,52,74,80,12
|
||||
EDITTEXT IDC_TIMER,52,93,31,13,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_SPIN_TIMER,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,66,93,11,12
|
||||
LTEXT "minutes",IDC_STATIC,88,95,25,8
|
||||
PUSHBUTTON "&Advanced",IDC_ADVANCED_BREAK,213,140,41,14
|
||||
LTEXT "Enter timer mode by using the ZoomIt tray icon's Break menu item. Increase and decrease time with the arrow keys. If you Alt-Tab away from the timer window, reactivate it by left-clicking on the ZoomIt tray icon. Exit timer mode with Escape. ",IDC_STATIC,7,7,242,33
|
||||
LTEXT "Start Timer:",IDC_STATIC,7,77,39,8
|
||||
LTEXT "Timer:",IDC_STATIC,7,95,20,8
|
||||
LTEXT "Change the break timer color using the same keys that the drawing color, including background color. The break timer font is the same as text font.",IDC_STATIC,7,45,241,26
|
||||
CONTROL "Show Time Elapsed After Expiration:",IDC_CHECK_SHOW_EXPIRED,
|
||||
"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,8,104,132,10
|
||||
"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,111,130,10
|
||||
CONTROL "Lock Workstation During Break:",IDC_CHECK_LOCK_WORKSTATION,
|
||||
"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,126,113,10
|
||||
END
|
||||
|
||||
1543 DIALOGEX 100, 50, 216, 131
|
||||
@@ -249,19 +251,19 @@ BEGIN
|
||||
CTEXT "AaBbYyZz",1092,16,88,127,31,SS_NOPREFIX | NOT WS_VISIBLE
|
||||
END
|
||||
|
||||
LIVEZOOM DIALOGEX 0, 0, 260, 134
|
||||
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_SYSMENU
|
||||
LIVEZOOM DIALOGEX 0, 0, 317, 136
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_LIVE_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,69,108,80,12
|
||||
LTEXT "LiveZoom mode is supported on Windows 7 and higher where window updates show while zoomed. ",IDC_STATIC,7,7,230,18
|
||||
LTEXT "LiveZoom mode is supported on Windows 7 and higher where window updates show while zoomed. ",IDC_STATIC,7,7,255,18
|
||||
LTEXT "LiveZoom Toggle:",IDC_STATIC,7,110,62,8
|
||||
LTEXT "To enter and exit LiveZoom, enter the hotkey specified below.",IDC_STATIC,7,94,230,13
|
||||
LTEXT "Note that in LiveZoom you must use Ctrl+Up and Ctrl+Down to control the zoom level. To enter drawing mode, use the standard zoom-without-draw hotkey and then escape to go back to LiveZoom.",IDC_STATIC,7,30,230,27
|
||||
LTEXT "Use LiveDraw to draw and annotate the live desktop. To activate LiveDraw, enter the hotkey with the Shift key in the opposite mode. You can remove LiveDraw annotations by activating LiveDraw and enter the escape key",IDC_STATIC,7,62,230,32
|
||||
LTEXT "Use LiveDraw to draw and annotate the live desktop. To activate LiveDraw, enter the hotkey with the Shift key in the opposite mode. You can remove LiveDraw annotations by activating LiveDraw and enter the escape key",IDC_STATIC,7,62,249,32
|
||||
LTEXT "Note that in LiveZoom you must use Ctrl+Up and Ctrl+Down to control the zoom level. To enter drawing mode, use the standard zoom-without-draw hotkey and then escape to go back to LiveZoom.",IDC_STATIC,7,30,255,27
|
||||
END
|
||||
|
||||
RECORD DIALOGEX 0, 0, 260, 181
|
||||
RECORD DIALOGEX 0, 0, 263, 224
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
@@ -282,19 +284,33 @@ BEGIN
|
||||
CONTROL "Mono",IDC_MIC_MONO_MIX,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,98,161,30,10
|
||||
COMBOBOX IDC_MICROPHONE,81,176,152,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Microphone:",IDC_MICROPHONE_LABEL,32,178,47,8
|
||||
PUSHBUTTON "&Trim",IDC_TRIM_FILE,207,209,53,14
|
||||
END
|
||||
|
||||
SNIP DIALOGEX 0, 0, 260, 68
|
||||
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
|
||||
SNIP DIALOGEX 0, 0, 260, 80
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_SNIP_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,55,32,80,12
|
||||
LTEXT "Copy a region of the screen to the clipboard or enter the hotkey with the Shift key in the opposite mode to save it to a file.",IDC_STATIC,7,7,230,19
|
||||
LTEXT "Snip Toggle:",IDC_STATIC,7,33,45,8
|
||||
LTEXT "Copy a region of the screen to the clipboard or enter the hotkey with the Shift key in the opposite mode to save it to a file. ",IDC_STATIC,7,7,230,19
|
||||
CONTROL "",IDC_SNIP_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,67,32,80,12
|
||||
LTEXT "Copy text from the selected region to the clipboard:",IDC_STATIC,7,50,230,10
|
||||
LTEXT "Text Toggle:",IDC_STATIC,7,65,55,8
|
||||
CONTROL "",IDC_SNIP_OCR_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,67,63,80,12
|
||||
END
|
||||
|
||||
PANORAMA DIALOGEX 0, 0, 260, 105
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "Capture a scrolling panorama of a selected screen region. Select the area, then scroll the content. Move slowly and consistently, and do not rewind to previously covered areas. Press the hotkey again or with Shift to save to a file.",IDC_STATIC,7,7,245,33
|
||||
LTEXT "Panorama Toggle:",IDC_STATIC,7,74,63,8
|
||||
CONTROL "",IDC_SNIP_PANORAMA_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,73,72,80,12
|
||||
LTEXT "For the best results, scroll slowly and at a constant rate, do not include stationary content (like scrollbars) in the capture area, and avoid content that is changing (e.g., animations or videos). ",IDC_STATIC,7,41,245,30
|
||||
END
|
||||
|
||||
DEMOTYPE DIALOGEX 0, 0, 260, 249
|
||||
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_DEMOTYPE_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,74,154,80,12
|
||||
@@ -308,11 +324,11 @@ BEGIN
|
||||
LTEXT "Fast",IDC_DEMOTYPE_STATIC2,186,213,17,8
|
||||
EDITTEXT IDC_DEMOTYPE_FILE,44,137,167,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
LTEXT "Input file:",IDC_STATIC,7,139,32,8
|
||||
LTEXT "When you reach the end of the file, ZoomIt will reload the file and start at the beginning. Enter the hotkey with the Shift key in the opposite mode to step back to the last [end].",IDC_STATIC,7,108,230,24
|
||||
LTEXT "DemoType has ZoomIt type text specified in the input file when you enter the DemoType toggle. Simply separate snippets with the [end] keyword, or you can insert text from the clipboard if it is prefixed with the [start].",IDC_STATIC,7,7,230,24
|
||||
LTEXT "When you reach the end of the file, ZoomIt will reload the file and start at the beginning. Enter the hotkey with the Shift key in the opposite mode to step back to the last [end].",IDC_STATIC,7,108,249,24
|
||||
LTEXT "DemoType has ZoomIt type text specified in the input file when you enter the DemoType toggle. Simply separate snippets with the [end] keyword, or you can insert text from the clipboard if it is prefixed with the [start].",IDC_STATIC,7,7,247,24
|
||||
LTEXT " - Insert pauses with the [pause:n] keyword where 'n' is seconds. ",IDC_STATIC,19,34,218,11
|
||||
LTEXT "You can have ZoomIt send text automatically, or select the option to drive input with typing. ZoomIt will block keyboard input while sending output.",IDC_STATIC,7,68,230,16
|
||||
LTEXT "When driving input, hit the space bar to unblock keyboard input at the end of a snippet. In auto mode, control will be returned upon completion.",IDC_STATIC,7,88,230,16
|
||||
LTEXT "You can have ZoomIt send text automatically, or select the option to drive input with typing. ZoomIt will block keyboard input while sending output.",IDC_STATIC,7,68,245,16
|
||||
LTEXT "When driving input, hit the space bar to unblock keyboard input at the end of a snippet. In auto mode, control will be returned upon completion.",IDC_STATIC,7,88,243,16
|
||||
LTEXT "- Send text via the clipboard with [paste] and [/paste]. ",IDC_STATIC,23,45,210,8
|
||||
LTEXT "- Send keystrokes with [enter], [up], [down], [left], and [right].",IDC_STATIC,23,56,210,8
|
||||
END
|
||||
@@ -349,13 +365,13 @@ BEGIN
|
||||
"OPTIONS", DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 293
|
||||
BOTTOMMARGIN, 320
|
||||
BOTTOMMARGIN, 326
|
||||
END
|
||||
|
||||
"ADVANCED_BREAK", DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 207
|
||||
BOTTOMMARGIN, 215
|
||||
BOTTOMMARGIN, 214
|
||||
END
|
||||
|
||||
"ZOOM", DIALOG
|
||||
@@ -383,7 +399,7 @@ BEGIN
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 116
|
||||
BOTTOMMARGIN, 154
|
||||
END
|
||||
|
||||
1543, DIALOG
|
||||
@@ -395,22 +411,27 @@ BEGIN
|
||||
"LIVEZOOM", DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 181
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 127
|
||||
BOTTOMMARGIN, 89
|
||||
END
|
||||
|
||||
"RECORD", DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 260
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 164
|
||||
BOTTOMMARGIN, 223
|
||||
END
|
||||
|
||||
"SNIP", DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 61
|
||||
END
|
||||
|
||||
"PANORAMA", DIALOG
|
||||
BEGIN
|
||||
END
|
||||
|
||||
"DEMOTYPE", DIALOG
|
||||
@@ -496,6 +517,16 @@ BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
ADVANCED_BREAK AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
PANORAMA AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<DisableSpecificWarnings>4100;4091;4245</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>..\..\..\;$(MSBuildThisFileDirectory)..\..\..\common\sysinternals;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>26451;4100;4091;4245</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>..\..\..\;$(MSBuildThisFileDirectory)..\..\..\common\sysinternals;..\ZoomItBreak;$(MSBuildThisFileDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
@@ -90,7 +90,7 @@
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;$(InterPlatformDir)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>true</RandomizedBaseAddress>
|
||||
@@ -109,10 +109,10 @@
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;_M_X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;$(MSBuildThisFileDirectory)..\ZoomItBreak\$(Platform)\$(Configuration)\</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>true</RandomizedBaseAddress>
|
||||
@@ -132,10 +132,10 @@
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;_M_ARM64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;$(MSBuildThisFileDirectory)..\ZoomItBreak\$(Platform)\$(Configuration)\</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<FixedBaseAddress>
|
||||
@@ -156,7 +156,7 @@
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;$(InterPlatformDir)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
@@ -174,10 +174,10 @@
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;_M_X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;$(MSBuildThisFileDirectory)..\ZoomItBreak\$(Platform)\$(Configuration)\</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<UACUIAccess>true</UACUIAccess>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -196,10 +196,10 @@
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;_M_ARM64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\..\common\version;$(MSBuildThisFileDirectory)PowerToys;$(MSBuildThisFileDirectory)..\ZoomItBreak\$(Platform)\$(Configuration)\</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Shlwapi.lib;comctl32.lib;odbc32.lib;odbccp32.lib;version.lib;Winmm.lib;gdiplus.lib;Msimg32.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<UACUIAccess>true</UACUIAccess>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -208,6 +208,14 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\ZoomItBreak\BreakTimer.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AudioSampleGenerator.cpp">
|
||||
<MultiProcessorCompilation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</MultiProcessorCompilation>
|
||||
<MultiProcessorCompilation Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</MultiProcessorCompilation>
|
||||
@@ -249,6 +257,14 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GifRecordingSession.cpp" />
|
||||
<ClCompile Include="PanoramaCapture.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Use</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Use</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="SelectRectangle.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
|
||||
@@ -300,11 +316,13 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\ZoomItBreak\BreakTimer.h" />
|
||||
<ClInclude Include="AudioSampleGenerator.h" />
|
||||
<ClInclude Include="LoopbackCapture.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\common\sysinternals\Eula\Eula.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)..\ZoomItModuleInterface\Trace.h" />
|
||||
<ClInclude Include="GifRecordingSession.h" />
|
||||
<ClInclude Include="PanoramaCapture.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="Registry.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
@@ -378,4 +396,4 @@
|
||||
<Import Project="..\..\..\..\packages\robmikh.common.0.0.23-beta\build\native\robmikh.common.targets" Condition="Exists('..\..\..\..\packages\robmikh.common.0.0.23-beta\build\native\robmikh.common.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -60,6 +60,12 @@
|
||||
<ClCompile Include="GifRecordingSession.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PanoramaCapture.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ZoomItBreak\BreakTimer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Registry.h">
|
||||
@@ -107,6 +113,12 @@
|
||||
<ClInclude Include="GifRecordingSession.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PanoramaCapture.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ZoomItBreak\BreakTimer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="appicon.ico">
|
||||
|
||||
@@ -17,6 +17,8 @@ DWORD g_BreakToggleKey = ((HOTKEYF_CONTROL) << 8)| '3';
|
||||
DWORD g_DemoTypeToggleKey = ((HOTKEYF_CONTROL) << 8) | '7';
|
||||
DWORD g_RecordToggleKey = ((HOTKEYF_CONTROL) << 8) | '5';
|
||||
DWORD g_SnipToggleKey = ((HOTKEYF_CONTROL) << 8) | '6';
|
||||
DWORD g_SnipPanoramaToggleKey = ((HOTKEYF_CONTROL) << 8) | '8';
|
||||
DWORD g_SnipOcrToggleKey = ((HOTKEYF_CONTROL | HOTKEYF_ALT) << 8) | '6';
|
||||
|
||||
DWORD g_ShowExpiredTime = 1;
|
||||
DWORD g_SliderZoomLevel = 3;
|
||||
@@ -24,6 +26,7 @@ BOOLEAN g_AnimateZoom = TRUE;
|
||||
BOOLEAN g_SmoothImage = TRUE;
|
||||
DWORD g_PenColor = COLOR_RED;
|
||||
DWORD g_BreakPenColor = COLOR_RED;
|
||||
DWORD g_BreakBackgroundColor = 0;
|
||||
DWORD g_RootPenWidth = PEN_WIDTH;
|
||||
int g_FontScale = 10;
|
||||
DWORD g_BreakTimeout = 10;
|
||||
@@ -40,6 +43,7 @@ BOOLEAN g_ShowTrayIcon = TRUE;
|
||||
BOOLEAN g_SnapToGrid = TRUE;
|
||||
BOOLEAN g_TelescopeZoomOut = TRUE;
|
||||
BOOLEAN g_BreakOnSecondary = FALSE;
|
||||
BOOLEAN g_BreakLockWorkstation = FALSE;
|
||||
LOGFONT g_LogFont;
|
||||
BOOLEAN g_DemoTypeUserDriven = false;
|
||||
TCHAR g_DemoTypeFile[MAX_PATH] = {0};
|
||||
@@ -66,10 +70,13 @@ REG_SETTING RegSettings[] = {
|
||||
{ L"DrawToggleKey", SETTING_TYPE_DWORD, 0, &g_DrawToggleKey, static_cast<DOUBLE>(g_DrawToggleKey) },
|
||||
{ L"RecordToggleKey", SETTING_TYPE_DWORD, 0, &g_RecordToggleKey, static_cast<DOUBLE>(g_RecordToggleKey) },
|
||||
{ L"SnipToggleKey", SETTING_TYPE_DWORD, 0, &g_SnipToggleKey, static_cast<DOUBLE>(g_SnipToggleKey) },
|
||||
{ L"SnipPanoramaToggleKey", SETTING_TYPE_DWORD, 0, &g_SnipPanoramaToggleKey, static_cast<DOUBLE>(g_SnipPanoramaToggleKey) },
|
||||
{ L"SnipOcrToggleKey", SETTING_TYPE_DWORD, 0, &g_SnipOcrToggleKey, static_cast<DOUBLE>(g_SnipOcrToggleKey) },
|
||||
{ L"PenColor", SETTING_TYPE_DWORD, 0, &g_PenColor, static_cast<DOUBLE>(g_PenColor) },
|
||||
{ L"PenWidth", SETTING_TYPE_DWORD, 0, &g_RootPenWidth, static_cast<DOUBLE>(g_RootPenWidth) },
|
||||
{ L"OptionsShown", SETTING_TYPE_BOOLEAN, 0, &g_OptionsShown, static_cast<DOUBLE>(g_OptionsShown) },
|
||||
{ L"BreakPenColor", SETTING_TYPE_DWORD, 0, &g_BreakPenColor, static_cast<DOUBLE>(g_BreakPenColor) },
|
||||
{ L"BreakBackgroundColor", SETTING_TYPE_DWORD, 0, &g_BreakBackgroundColor, static_cast<DOUBLE>(g_BreakBackgroundColor) },
|
||||
{ L"BreakTimerKey", SETTING_TYPE_DWORD, 0, &g_BreakToggleKey, static_cast<DOUBLE>(g_BreakToggleKey) },
|
||||
{ L"DemoTypeToggleKey", SETTING_TYPE_DWORD, 0, &g_DemoTypeToggleKey, static_cast<DOUBLE>(g_DemoTypeToggleKey) },
|
||||
{ L"DemoTypeFile", SETTING_TYPE_STRING, sizeof( g_DemoTypeFile ), g_DemoTypeFile, static_cast<DOUBLE>(0) },
|
||||
@@ -85,6 +92,7 @@ REG_SETTING RegSettings[] = {
|
||||
{ L"BreakTimerPosition", SETTING_TYPE_DWORD, 0, &g_BreakTimerPosition, static_cast<DOUBLE>(g_BreakTimerPosition) },
|
||||
{ L"BreakShowDesktop", SETTING_TYPE_BOOLEAN, 0, &g_BreakShowDesktop, static_cast<DOUBLE>(g_BreakShowDesktop) },
|
||||
{ L"BreakOnSecondary", SETTING_TYPE_BOOLEAN, 0, &g_BreakOnSecondary,static_cast<DOUBLE>(g_BreakOnSecondary) },
|
||||
{ L"BreakLockWorkstation", SETTING_TYPE_BOOLEAN, 0, &g_BreakLockWorkstation, static_cast<DOUBLE>(g_BreakLockWorkstation) },
|
||||
{ L"FontScale", SETTING_TYPE_DWORD, 0, &g_FontScale, static_cast<DOUBLE>(g_FontScale) },
|
||||
{ L"ShowExpiredTime", SETTING_TYPE_BOOLEAN, 0, &g_ShowExpiredTime, static_cast<DOUBLE>(g_ShowExpiredTime) },
|
||||
{ L"ShowTrayIcon", SETTING_TYPE_BOOLEAN, 0, &g_ShowTrayIcon, static_cast<DOUBLE>(g_ShowTrayIcon) },
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,4 +15,14 @@ RCZOOMIT64 BINRES MOVEABLE PURE RCZOOMIT_x64_path
|
||||
|
||||
#endif
|
||||
|
||||
// Embed the break timer screensaver for the current platform.
|
||||
// The .scr is built by the ZoomItBreak project into the shared output directory.
|
||||
#ifdef _M_IX86
|
||||
RCZOOMITSCR BINRES MOVEABLE PURE "ZoomItBreak.scr"
|
||||
#elif defined(_M_X64)
|
||||
RCZOOMITSCR BINRES MOVEABLE PURE "ZoomItBreak64.scr"
|
||||
#elif defined(_M_ARM64)
|
||||
RCZOOMITSCR BINRES MOVEABLE PURE "ZoomItBreak64a.scr"
|
||||
#endif
|
||||
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "ZoomIt.exe.manifest"
|
||||
|
||||
@@ -53,6 +53,9 @@
|
||||
#include <winrt/Windows.Storage.Pickers.h>
|
||||
#include <winrt/Windows.Storage.FileProperties.h>
|
||||
#include <winrt/Windows.Devices.Enumeration.h>
|
||||
#include <winrt/Windows.Media.Ocr.h>
|
||||
|
||||
#include <Windows.Graphics.Imaging.Interop.h>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
#define IDC_RECORD_FRAME_RATE2 1059
|
||||
#define IDC_RECORD_SCALING 1059
|
||||
#define IDC_SNIP_HOTKEY 1060
|
||||
#define IDC_SNIP_OCR_HOTKEY 1112
|
||||
#define IDC_SNIP_PANORAMA_HOTKEY 1114
|
||||
#define IDC_CAPTURE_AUDIO 1061
|
||||
#define IDC_MICROPHONE 1062
|
||||
#define IDC_PEN_CONTROL 1063
|
||||
@@ -111,12 +113,15 @@
|
||||
#define IDC_SMOOTH_IMAGE 1107
|
||||
#define IDC_CAPTURE_SYSTEM_AUDIO 1108
|
||||
#define IDC_MICROPHONE_LABEL 1109
|
||||
#define IDC_MIC_MONO_MIX 1110
|
||||
#define IDC_TRIM_FILE 1110
|
||||
#define IDC_MIC_MONO_MIX 1111
|
||||
#define IDC_CHECK_LOCK_WORKSTATION 1112
|
||||
#define IDC_SAVE 40002
|
||||
#define IDC_COPY 40004
|
||||
#define IDC_RECORD 40006
|
||||
#define IDC_RECORD_HOTKEY 40007
|
||||
#define IDC_COPY_CROP 40008
|
||||
#define IDC_COPY_OCR 40014
|
||||
#define IDC_SAVE_CROP 40009
|
||||
#define IDC_DEMOTYPE_HOTKEY 40011
|
||||
|
||||
@@ -125,8 +130,8 @@
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 120
|
||||
#define _APS_NEXT_COMMAND_VALUE 40013
|
||||
#define _APS_NEXT_CONTROL_VALUE 1099
|
||||
#define _APS_NEXT_COMMAND_VALUE 40015
|
||||
#define _APS_NEXT_CONTROL_VALUE 1113
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
||||
520
src/modules/ZoomIt/ZoomItBreak/BreakTimer.cpp
Normal file
520
src/modules/ZoomIt/ZoomItBreak/BreakTimer.cpp
Normal file
@@ -0,0 +1,520 @@
|
||||
//============================================================================
|
||||
//
|
||||
// BreakTimer.cpp
|
||||
//
|
||||
// Shared break timer rendering module used by both ZoomIt and the
|
||||
// ZoomItBreak screensaver (.scr).
|
||||
//
|
||||
// Copyright (C) Mark Russinovich
|
||||
// Sysinternals - www.sysinternals.com
|
||||
//
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
//============================================================================
|
||||
|
||||
// When built inside ZoomIt (with PCH), pch.h is included automatically.
|
||||
// When built for the screensaver project, we include the headers we need.
|
||||
#ifndef __ZOOMIT_SCREENSAVER__
|
||||
#include "pch.h"
|
||||
#endif
|
||||
|
||||
#include "BreakTimer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#pragma comment(lib, "gdiplus.lib")
|
||||
#pragma comment(lib, "Msimg32.lib")
|
||||
#pragma comment(lib, "Winmm.lib")
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakTimer_UpdateMonitorInfo
|
||||
//
|
||||
// Determine monitor geometry for the given screen point.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
void BreakTimer_UpdateMonitorInfo( POINT point, MONITORINFO* monInfo )
|
||||
{
|
||||
HMONITOR hMon = MonitorFromPoint( point, MONITOR_DEFAULTTONEAREST );
|
||||
if( hMon != nullptr )
|
||||
{
|
||||
monInfo->cbSize = sizeof *monInfo;
|
||||
GetMonitorInfo( hMon, monInfo );
|
||||
}
|
||||
else
|
||||
{
|
||||
*monInfo = {};
|
||||
HDC hdcScreen = CreateDC( L"DISPLAY", nullptr, nullptr, nullptr );
|
||||
if( hdcScreen != nullptr )
|
||||
{
|
||||
monInfo->rcMonitor.right = GetDeviceCaps( hdcScreen, HORZRES );
|
||||
monInfo->rcMonitor.bottom = GetDeviceCaps( hdcScreen, VERTRES );
|
||||
DeleteDC( hdcScreen );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakTimer_LoadImageFile
|
||||
//
|
||||
// Use GDI+ to load an image file and return an HBITMAP.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
HBITMAP BreakTimer_LoadImageFile( PTCHAR Filename )
|
||||
{
|
||||
HBITMAP hBmp;
|
||||
Gdiplus::Bitmap* bitmap = Gdiplus::Bitmap::FromFile( Filename );
|
||||
if( bitmap == nullptr || bitmap->GetHBITMAP( NULL, &hBmp ) != Gdiplus::Ok )
|
||||
{
|
||||
delete bitmap;
|
||||
return NULL;
|
||||
}
|
||||
delete bitmap;
|
||||
return hBmp;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakTimer_CreateFadedDesktopBackground
|
||||
//
|
||||
// Creates a snapshot of the desktop that is faded and alpha-blended
|
||||
// with black.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
HBITMAP BreakTimer_CreateFadedDesktopBackground( HDC hdc, LPRECT rcScreen, LPRECT rcCrop )
|
||||
{
|
||||
int width = rcScreen->right - rcScreen->left;
|
||||
int height = rcScreen->bottom - rcScreen->top;
|
||||
HDC hdcScreen = hdc;
|
||||
HDC hdcMem = CreateCompatibleDC( hdcScreen );
|
||||
HBITMAP hBitmap = CreateCompatibleBitmap( hdcScreen, width, height );
|
||||
HBITMAP hOld = static_cast<HBITMAP>( SelectObject( hdcMem, hBitmap ) );
|
||||
HBRUSH hBrush = CreateSolidBrush( RGB( 0, 0, 0 ) );
|
||||
|
||||
// Start with black background.
|
||||
FillRect( hdcMem, rcScreen, hBrush );
|
||||
if( rcCrop != NULL && rcCrop->left != -1 )
|
||||
{
|
||||
// Copy screen contents that are not cropped.
|
||||
BitBlt( hdcMem, rcCrop->left, rcCrop->top,
|
||||
rcCrop->right - rcCrop->left,
|
||||
rcCrop->bottom - rcCrop->top,
|
||||
hdcScreen, rcCrop->left, rcCrop->top, SRCCOPY );
|
||||
}
|
||||
|
||||
// Blend screen contents into the black background.
|
||||
BLENDFUNCTION blend = { 0 };
|
||||
blend.BlendOp = AC_SRC_OVER;
|
||||
blend.BlendFlags = 0;
|
||||
blend.SourceConstantAlpha = 0x4F;
|
||||
blend.AlphaFormat = 0;
|
||||
AlphaBlend( hdcMem, 0, 0, width, height,
|
||||
hdcScreen, rcScreen->left, rcScreen->top,
|
||||
width, height, blend );
|
||||
|
||||
SelectObject( hdcMem, hOld );
|
||||
DeleteDC( hdcMem );
|
||||
DeleteObject( hBrush );
|
||||
|
||||
return hBitmap;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakTimer_Init
|
||||
//
|
||||
// Create fonts, backing bitmap, and optionally load background.
|
||||
// Returns TRUE on success.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
BOOLEAN BreakTimer_Init(
|
||||
HWND hWnd,
|
||||
BreakTimerState* state,
|
||||
const BreakTimerSettings* settings,
|
||||
int timeoutSeconds,
|
||||
HBITMAP hExistingBackground,
|
||||
HDC hExistingBackgroundDC )
|
||||
{
|
||||
state->active = TRUE;
|
||||
state->timeoutSeconds = timeoutSeconds;
|
||||
|
||||
// Get screen DC.
|
||||
state->hdcScreen = CreateDC( L"DISPLAY", static_cast<PTCHAR>( NULL ),
|
||||
static_cast<PTCHAR>( NULL ),
|
||||
static_cast<CONST DEVMODE*>( NULL ) );
|
||||
if( !state->hdcScreen )
|
||||
return FALSE;
|
||||
|
||||
// Determine monitor.
|
||||
POINT cursorPos;
|
||||
GetCursorPos( &cursorPos );
|
||||
BreakTimer_UpdateMonitorInfo( cursorPos, &state->monInfo );
|
||||
state->width = state->monInfo.rcMonitor.right - state->monInfo.rcMonitor.left;
|
||||
state->height = state->monInfo.rcMonitor.bottom - state->monInfo.rcMonitor.top;
|
||||
|
||||
// Manage background bitmap.
|
||||
if( hExistingBackground )
|
||||
{
|
||||
// Caller supplied a pre-captured background (e.g. from command line).
|
||||
state->hBackgroundBmp = hExistingBackground;
|
||||
state->hDcBackgroundFile = hExistingBackgroundDC;
|
||||
}
|
||||
else if( settings->showBackgroundFile && !settings->showDesktop )
|
||||
{
|
||||
// Load image file.
|
||||
state->hBackgroundBmp = BreakTimer_LoadImageFile(
|
||||
const_cast<PTCHAR>( settings->backgroundFile ) );
|
||||
if( !state->hBackgroundBmp )
|
||||
return FALSE;
|
||||
state->hDcBackgroundFile = CreateCompatibleDC( state->hdcScreen );
|
||||
SelectObject( state->hDcBackgroundFile, state->hBackgroundBmp );
|
||||
}
|
||||
else if( settings->showBackgroundFile && settings->showDesktop )
|
||||
{
|
||||
// Faded desktop screenshot.
|
||||
HDC hDcDesktop = GetDC( NULL );
|
||||
state->hBackgroundBmp = BreakTimer_CreateFadedDesktopBackground(
|
||||
hDcDesktop, &state->monInfo.rcMonitor, NULL );
|
||||
ReleaseDC( NULL, hDcDesktop );
|
||||
state->hDcBackgroundFile = CreateCompatibleDC( state->hdcScreen );
|
||||
SelectObject( state->hDcBackgroundFile, state->hBackgroundBmp );
|
||||
}
|
||||
else
|
||||
{
|
||||
state->hBackgroundBmp = NULL;
|
||||
state->hDcBackgroundFile = NULL;
|
||||
}
|
||||
|
||||
// Create fonts.
|
||||
LOGFONT lf = settings->logFont;
|
||||
lf.lfHeight = state->height / 5;
|
||||
state->hTimerFont = CreateFontIndirect( &lf );
|
||||
lf.lfHeight = state->height / 8;
|
||||
state->hNegativeTimerFont = CreateFontIndirect( &lf );
|
||||
|
||||
// Create backing bitmap for double buffering.
|
||||
state->hdcScreenCompat = CreateCompatibleDC( state->hdcScreen );
|
||||
state->bmp.bmBitsPixel = static_cast<BYTE>( GetDeviceCaps( state->hdcScreen, BITSPIXEL ) );
|
||||
state->bmp.bmPlanes = static_cast<BYTE>( GetDeviceCaps( state->hdcScreen, PLANES ) );
|
||||
state->bmp.bmWidth = state->width;
|
||||
state->bmp.bmHeight = state->height;
|
||||
state->bmp.bmWidthBytes = ( ( state->bmp.bmWidth + 15 ) & ~15 ) / 8;
|
||||
state->hbmpCompat = CreateBitmap( state->bmp.bmWidth, state->bmp.bmHeight,
|
||||
state->bmp.bmPlanes, state->bmp.bmBitsPixel, static_cast<CONST VOID*>( NULL ) );
|
||||
SelectObject( state->hdcScreenCompat, state->hbmpCompat );
|
||||
|
||||
SetTextColor( state->hdcScreenCompat, settings->penColor );
|
||||
SetBkMode( state->hdcScreenCompat, TRANSPARENT );
|
||||
SelectObject( state->hdcScreenCompat, state->hTimerFont );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakTimer_Tick
|
||||
//
|
||||
// Decrement counter, invalidate window, play sound at zero.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
void BreakTimer_Tick(
|
||||
HWND hWnd,
|
||||
BreakTimerState* state,
|
||||
const BreakTimerSettings* settings )
|
||||
{
|
||||
state->timeoutSeconds -= 1;
|
||||
InvalidateRect( hWnd, NULL, FALSE );
|
||||
|
||||
if( state->timeoutSeconds == 0 && settings->playSound )
|
||||
{
|
||||
PlaySound( settings->soundFile, NULL, SND_FILENAME | SND_ASYNC );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakTimer_Paint
|
||||
//
|
||||
// Render the break timer into the back buffer and blit to the paint DC.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
void BreakTimer_Paint(
|
||||
HDC hdc,
|
||||
BreakTimerState* state,
|
||||
const BreakTimerSettings* settings )
|
||||
{
|
||||
RECT rc, rc1;
|
||||
TCHAR timerText[16];
|
||||
TCHAR negativeTimerText[16];
|
||||
|
||||
// Fill background (white by default, black if backgroundColor == 1).
|
||||
rc.top = rc.left = 0;
|
||||
rc.bottom = state->height;
|
||||
rc.right = state->width;
|
||||
if( settings->backgroundColor )
|
||||
{
|
||||
HBRUSH hBrush = CreateSolidBrush( RGB( 0, 0, 0 ) );
|
||||
FillRect( state->hdcScreenCompat, &rc, hBrush );
|
||||
DeleteObject( hBrush );
|
||||
}
|
||||
else
|
||||
{
|
||||
FillRect( state->hdcScreenCompat, &rc, GetSysColorBrush( COLOR_WINDOW ) );
|
||||
}
|
||||
|
||||
// Draw background bitmap if present.
|
||||
if( state->hBackgroundBmp )
|
||||
{
|
||||
BITMAP local_bmp;
|
||||
GetObject( state->hBackgroundBmp, sizeof( local_bmp ), &local_bmp );
|
||||
SetStretchBltMode( state->hdcScreenCompat,
|
||||
settings->smoothImage ? HALFTONE : COLORONCOLOR );
|
||||
if( settings->backgroundStretch )
|
||||
{
|
||||
StretchBlt( state->hdcScreenCompat, 0, 0, state->width, state->height,
|
||||
state->hDcBackgroundFile, 0, 0,
|
||||
local_bmp.bmWidth, local_bmp.bmHeight, SRCCOPY | CAPTUREBLT );
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBlt( state->hdcScreenCompat,
|
||||
state->width / 2 - local_bmp.bmWidth / 2,
|
||||
state->height / 2 - local_bmp.bmHeight / 2,
|
||||
local_bmp.bmWidth, local_bmp.bmHeight,
|
||||
state->hDcBackgroundFile, 0, 0, SRCCOPY | CAPTUREBLT );
|
||||
}
|
||||
}
|
||||
|
||||
// Format timer text.
|
||||
if( state->timeoutSeconds > 0 )
|
||||
{
|
||||
_stprintf( timerText, L"% 2d:%02d",
|
||||
state->timeoutSeconds / 60, state->timeoutSeconds % 60 );
|
||||
}
|
||||
else
|
||||
{
|
||||
_tcscpy( timerText, L"0:00" );
|
||||
}
|
||||
|
||||
// Measure timer text.
|
||||
rc.left = rc.top = 0;
|
||||
DrawText( state->hdcScreenCompat, timerText, -1, &rc,
|
||||
DT_NOCLIP | DT_LEFT | DT_NOPREFIX | DT_CALCRECT );
|
||||
|
||||
// Measure expired text if needed.
|
||||
rc1.left = rc1.right = rc1.bottom = rc1.top = 0;
|
||||
if( settings->showExpiredTime && state->timeoutSeconds < 0 )
|
||||
{
|
||||
_stprintf( negativeTimerText, L"(-% 2d:%02d)",
|
||||
-state->timeoutSeconds / 60, -state->timeoutSeconds % 60 );
|
||||
HFONT prevFont = static_cast<HFONT>(
|
||||
SelectObject( state->hdcScreenCompat, state->hNegativeTimerFont ) );
|
||||
DrawText( state->hdcScreenCompat, negativeTimerText, -1, &rc1,
|
||||
DT_NOCLIP | DT_LEFT | DT_NOPREFIX | DT_CALCRECT );
|
||||
SelectObject( state->hdcScreenCompat, prevFont );
|
||||
}
|
||||
|
||||
// Position vertically.
|
||||
switch( settings->timerPosition )
|
||||
{
|
||||
case 0: case 1: case 2:
|
||||
rc.top = 50;
|
||||
break;
|
||||
case 3: case 4: case 5:
|
||||
rc.top = ( state->height - ( rc.bottom - rc.top ) ) / 2;
|
||||
break;
|
||||
case 6: case 7: case 8:
|
||||
rc.top = state->height - rc.bottom - 50 - rc1.bottom;
|
||||
break;
|
||||
}
|
||||
|
||||
// Position horizontally.
|
||||
switch( settings->timerPosition )
|
||||
{
|
||||
case 0: case 3: case 6:
|
||||
rc.left = 50;
|
||||
break;
|
||||
case 1: case 4: case 7:
|
||||
rc.left = ( state->width - ( rc.right - rc.left ) ) / 2;
|
||||
break;
|
||||
case 2: case 5: case 8:
|
||||
rc.left = state->width - rc.right - 50;
|
||||
break;
|
||||
}
|
||||
rc.bottom += rc.top;
|
||||
rc.right += rc.left;
|
||||
|
||||
// Draw timer text.
|
||||
DrawText( state->hdcScreenCompat, timerText, -1, &rc,
|
||||
DT_NOCLIP | DT_LEFT | DT_NOPREFIX );
|
||||
|
||||
// Draw expired text below the timer.
|
||||
if( settings->showExpiredTime && state->timeoutSeconds < 0 )
|
||||
{
|
||||
rc1.top = rc.bottom + 10;
|
||||
rc1.left = rc.left + ( ( rc.right - rc.left ) - ( rc1.right - rc1.left ) ) / 2;
|
||||
HFONT prevFont = static_cast<HFONT>(
|
||||
SelectObject( state->hdcScreenCompat, state->hNegativeTimerFont ) );
|
||||
DrawText( state->hdcScreenCompat, negativeTimerText, -1, &rc1,
|
||||
DT_NOCLIP | DT_LEFT | DT_NOPREFIX );
|
||||
SelectObject( state->hdcScreenCompat, prevFont );
|
||||
}
|
||||
|
||||
// Copy to screen.
|
||||
BitBlt( hdc, 0, 0, state->width, state->height,
|
||||
state->hdcScreenCompat, 0, 0, SRCCOPY | CAPTUREBLT );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakTimer_Cleanup
|
||||
//
|
||||
// Free the GDI resources used by the break timer.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
void BreakTimer_Cleanup(
|
||||
BreakTimerState* state,
|
||||
BOOLEAN freeBackground )
|
||||
{
|
||||
if( freeBackground && state->hBackgroundBmp )
|
||||
{
|
||||
DeleteObject( state->hBackgroundBmp );
|
||||
DeleteDC( state->hDcBackgroundFile );
|
||||
state->hBackgroundBmp = NULL;
|
||||
state->hDcBackgroundFile = NULL;
|
||||
}
|
||||
|
||||
if( state->hTimerFont )
|
||||
{
|
||||
DeleteObject( state->hTimerFont );
|
||||
state->hTimerFont = NULL;
|
||||
}
|
||||
if( state->hNegativeTimerFont )
|
||||
{
|
||||
DeleteObject( state->hNegativeTimerFont );
|
||||
state->hNegativeTimerFont = NULL;
|
||||
}
|
||||
if( state->hdcScreen )
|
||||
{
|
||||
DeleteDC( state->hdcScreen );
|
||||
state->hdcScreen = NULL;
|
||||
}
|
||||
if( state->hdcScreenCompat )
|
||||
{
|
||||
DeleteDC( state->hdcScreenCompat );
|
||||
state->hdcScreenCompat = NULL;
|
||||
}
|
||||
if( state->hbmpCompat )
|
||||
{
|
||||
DeleteObject( state->hbmpCompat );
|
||||
state->hbmpCompat = NULL;
|
||||
}
|
||||
|
||||
state->active = FALSE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakTimer_AdjustTime
|
||||
//
|
||||
// Round to the nearest minute boundary and adjust by deltaMinutes.
|
||||
// Resets the 1-second timer on the window.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
void BreakTimer_AdjustTime(
|
||||
HWND hWnd,
|
||||
BreakTimerState* state,
|
||||
int deltaMinutes )
|
||||
{
|
||||
int breakTimeout = state->timeoutSeconds;
|
||||
|
||||
if( deltaMinutes > 0 )
|
||||
{
|
||||
if( breakTimeout < 0 ) breakTimeout = 0;
|
||||
if( breakTimeout % 60 )
|
||||
{
|
||||
breakTimeout += ( 60 - breakTimeout % 60 );
|
||||
deltaMinutes--;
|
||||
}
|
||||
breakTimeout += deltaMinutes * 60;
|
||||
}
|
||||
else
|
||||
{
|
||||
int absDelta = -deltaMinutes;
|
||||
if( breakTimeout % 60 )
|
||||
{
|
||||
breakTimeout -= breakTimeout % 60;
|
||||
absDelta--;
|
||||
}
|
||||
breakTimeout -= absDelta * 60;
|
||||
}
|
||||
|
||||
if( breakTimeout < 0 ) breakTimeout = 0;
|
||||
state->timeoutSeconds = breakTimeout;
|
||||
|
||||
KillTimer( hWnd, 0 );
|
||||
SetTimer( hWnd, 0, 1000, NULL );
|
||||
InvalidateRect( hWnd, NULL, TRUE );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakScrConfig_GetPath
|
||||
//
|
||||
// Build the full path to the config file in %TEMP%.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
static void BreakScrConfig_GetPath( TCHAR* path, size_t cch )
|
||||
{
|
||||
GetTempPath( static_cast<DWORD>( cch ), path );
|
||||
_tcscat( path, BREAKSCR_CONFIG_FILE );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakScrConfig_Write
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
BOOLEAN BreakScrConfig_Write( const BreakScrConfig* config )
|
||||
{
|
||||
TCHAR path[MAX_PATH];
|
||||
BreakScrConfig_GetPath( path, MAX_PATH );
|
||||
|
||||
HANDLE hFile = CreateFile( path, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
if( hFile == INVALID_HANDLE_VALUE )
|
||||
return FALSE;
|
||||
|
||||
DWORD written;
|
||||
BOOL ok = WriteFile( hFile, config, sizeof( *config ), &written, NULL );
|
||||
CloseHandle( hFile );
|
||||
return ok && written == sizeof( *config );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// BreakScrConfig_Read
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
BOOLEAN BreakScrConfig_Read( BreakScrConfig* config )
|
||||
{
|
||||
TCHAR path[MAX_PATH];
|
||||
BreakScrConfig_GetPath( path, MAX_PATH );
|
||||
|
||||
HANDLE hFile = CreateFile( path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
if( hFile == INVALID_HANDLE_VALUE )
|
||||
return FALSE;
|
||||
|
||||
DWORD bytesRead;
|
||||
BOOL ok = ReadFile( hFile, config, sizeof( *config ), &bytesRead, NULL );
|
||||
CloseHandle( hFile );
|
||||
|
||||
if( !ok || bytesRead != sizeof( *config ) )
|
||||
return FALSE;
|
||||
if( config->magic != BREAKSCR_CONFIG_MAGIC )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
141
src/modules/ZoomIt/ZoomItBreak/BreakTimer.h
Normal file
141
src/modules/ZoomIt/ZoomItBreak/BreakTimer.h
Normal file
@@ -0,0 +1,141 @@
|
||||
//============================================================================
|
||||
//
|
||||
// BreakTimer.h
|
||||
//
|
||||
// Shared break timer rendering module used by both ZoomIt and the
|
||||
// ZoomItBreak screensaver (.scr).
|
||||
//
|
||||
// Copyright (C) Mark Russinovich
|
||||
// Sysinternals - www.sysinternals.com
|
||||
//
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
//============================================================================
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#define GDIPVER 0x0110
|
||||
#include <gdiplus.h>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// BreakTimerSettings — read-only configuration, populated from globals
|
||||
// or from command-line arguments in the screensaver.
|
||||
//----------------------------------------------------------------------------
|
||||
struct BreakTimerSettings
|
||||
{
|
||||
DWORD penColor;
|
||||
DWORD backgroundColor; // 0 = white, 1 = black
|
||||
DWORD timerPosition; // 0–8 (3×3 grid)
|
||||
DWORD opacity; // 0–100
|
||||
DWORD showExpiredTime; // 0 or 1
|
||||
BOOLEAN smoothImage;
|
||||
BOOLEAN backgroundStretch;
|
||||
BOOLEAN playSound;
|
||||
TCHAR soundFile[MAX_PATH];
|
||||
BOOLEAN showDesktop;
|
||||
BOOLEAN showBackgroundFile;
|
||||
TCHAR backgroundFile[MAX_PATH];
|
||||
LOGFONT logFont;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// BreakTimerState — runtime state for an active break timer.
|
||||
//----------------------------------------------------------------------------
|
||||
struct BreakTimerState
|
||||
{
|
||||
BOOLEAN active;
|
||||
int timeoutSeconds; // counts down; goes negative if expired
|
||||
HFONT hTimerFont;
|
||||
HFONT hNegativeTimerFont;
|
||||
HBITMAP hBackgroundBmp;
|
||||
HDC hDcBackgroundFile;
|
||||
HDC hdcScreen;
|
||||
HDC hdcScreenCompat;
|
||||
HBITMAP hbmpCompat;
|
||||
BITMAP bmp;
|
||||
int width;
|
||||
int height;
|
||||
MONITORINFO monInfo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Shared utility functions
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Determine monitor geometry for the given screen point.
|
||||
void BreakTimer_UpdateMonitorInfo( POINT point, MONITORINFO* monInfo );
|
||||
|
||||
// Load an image file via GDI+; returns an HBITMAP or NULL on failure.
|
||||
HBITMAP BreakTimer_LoadImageFile( PTCHAR Filename );
|
||||
|
||||
// Capture a faded (alpha-blended with black) screenshot of the desktop.
|
||||
HBITMAP BreakTimer_CreateFadedDesktopBackground( HDC hdc, LPRECT rcScreen, LPRECT rcCrop );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Break timer lifecycle
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Create fonts, backing bitmap, and load background.
|
||||
// The caller is responsible for creating/showing the window itself.
|
||||
// |timeoutSeconds| is already in seconds (e.g. g_BreakTimeout * 60 + 1).
|
||||
BOOLEAN BreakTimer_Init(
|
||||
HWND hWnd,
|
||||
BreakTimerState* state,
|
||||
const BreakTimerSettings* settings,
|
||||
int timeoutSeconds,
|
||||
HBITMAP hExistingBackground, // optional pre-captured background
|
||||
HDC hExistingBackgroundDC // optional DC for above
|
||||
);
|
||||
|
||||
// Called every second; decrements the counter and invalidates the window.
|
||||
void BreakTimer_Tick(
|
||||
HWND hWnd,
|
||||
BreakTimerState* state,
|
||||
const BreakTimerSettings* settings
|
||||
);
|
||||
|
||||
// Render the timer into hdcScreenCompat then BitBlt to hdc (from BeginPaint).
|
||||
void BreakTimer_Paint(
|
||||
HDC hdc,
|
||||
BreakTimerState* state,
|
||||
const BreakTimerSettings* settings
|
||||
);
|
||||
|
||||
// Free fonts, DCs, bitmaps. If |freeBackground| is false the background
|
||||
// bitmap/DC are left for the caller to manage (e.g. shallow destroy).
|
||||
void BreakTimer_Cleanup(
|
||||
BreakTimerState* state,
|
||||
BOOLEAN freeBackground
|
||||
);
|
||||
|
||||
// Adjust the remaining time by |deltaMinutes| (positive = add time).
|
||||
// Resets the 1-second timer on hWnd.
|
||||
void BreakTimer_AdjustTime(
|
||||
HWND hWnd,
|
||||
BreakTimerState* state,
|
||||
int deltaMinutes
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// BreakScrConfig — binary blob written to a temp file by ZoomIt and
|
||||
// read by the screensaver on startup. This avoids command-line arg
|
||||
// issues since Windows launches screensavers with only /s.
|
||||
//----------------------------------------------------------------------------
|
||||
#define BREAKSCR_CONFIG_MAGIC 0x5A4D4253 // 'ZMBS'
|
||||
#define BREAKSCR_CONFIG_FILE L"ZoomItBreakConfig.dat"
|
||||
|
||||
struct BreakScrConfig
|
||||
{
|
||||
DWORD magic; // must be BREAKSCR_CONFIG_MAGIC
|
||||
int timeoutSeconds;
|
||||
BOOL resumed; // set TRUE by screensaver on first launch
|
||||
BreakTimerSettings settings;
|
||||
TCHAR screenshotPath[MAX_PATH];
|
||||
};
|
||||
|
||||
// Write config to %TEMP%\BREAKSCR_CONFIG_FILE.
|
||||
BOOLEAN BreakScrConfig_Write( const BreakScrConfig* config );
|
||||
|
||||
// Read config from %TEMP%\BREAKSCR_CONFIG_FILE.
|
||||
BOOLEAN BreakScrConfig_Read( BreakScrConfig* config );
|
||||
10
src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.manifest
Normal file
10
src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.manifest
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"
|
||||
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
27
src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.rc
Normal file
27
src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.rc
Normal file
@@ -0,0 +1,27 @@
|
||||
//============================================================================
|
||||
//
|
||||
// ZoomItBreak.rc
|
||||
//
|
||||
// Minimal resources required by Scrnsavw.lib.
|
||||
//
|
||||
//============================================================================
|
||||
#include <windows.h>
|
||||
#include <scrnsave.h>
|
||||
|
||||
// Embed DPI-awareness manifest so the screensaver sees native resolution.
|
||||
// This ensures the pre-captured desktop screenshot (saved at physical pixels
|
||||
// by the DPI-aware ZoomIt process) matches the screensaver window dimensions.
|
||||
1 RT_MANIFEST "ZoomItBreak.manifest"
|
||||
|
||||
// IDS_DESCRIPTION is used by scrnsavw.lib as the window class name.
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_DESCRIPTION, "ZoomIt Break Timer"
|
||||
END
|
||||
|
||||
// Stub configuration dialog - never shown (ScreenSaverConfigureDialog returns FALSE).
|
||||
DLG_SCRNSAVECONFIGURE DIALOG 0, 0, 200, 60
|
||||
STYLE WS_DLGFRAME | WS_POPUP | WS_VISIBLE | DS_MODALFRAME | WS_CAPTION
|
||||
CAPTION "ZoomIt Break Timer"
|
||||
BEGIN
|
||||
END
|
||||
230
src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj
Normal file
230
src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj
Normal file
@@ -0,0 +1,230 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>18.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{94ba3051-c8d7-454a-9d46-1a7c78e228a3}</ProjectGuid>
|
||||
<RootNamespace>ZoomItBreak</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<!--
|
||||
Output .scr instead of .exe. A screensaver is a renamed executable.
|
||||
Use a separate intermediate dir to avoid colliding with ZoomIt.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<TargetExt>.scr</TargetExt>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IntDir>$(Platform)\$(Configuration)\ZoomItBreak\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(MsBuildProjectDirectory)\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(MsBuildProjectDirectory)\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(MsBuildProjectDirectory)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>$(ProjectName)64</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<OutDir>$(MsBuildProjectDirectory)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>$(ProjectName)64a</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(MsBuildProjectDirectory)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>$(ProjectName)64</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<OutDir>$(MsBuildProjectDirectory)\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>$(ProjectName)64a</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<DisableSpecificWarnings>4100;4091;4245</DisableSpecificWarnings>
|
||||
<AdditionalIncludeDirectories>..\..\..\;$(MSBuildThisFileDirectory)..\..\..\common\sysinternals;..\ZoomIt;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>__ZOOMIT_SCREENSAVER__;_UNICODE;UNICODE;WINVER=0x0602;_DEBUG;_WIN32_WINNT=0x602;_WIN32_WINDOWS=0x600;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>__ZOOMIT_SCREENSAVER__;_UNICODE;UNICODE;WINVER=0x602;NDEBUG;_WIN32_WINNT=0x602;_WIN32_WINDOWS=0x501;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>__ZOOMIT_SCREENSAVER__;_UNICODE;UNICODE;WINVER=0x0602;_DEBUG;_WIN32_WINNT=0x602;_WIN32_WINDOWS=0x600;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>__ZOOMIT_SCREENSAVER__;_UNICODE;UNICODE;WINVER=0x0602;_DEBUG;_WIN32_WINNT=0x602;_WIN32_WINDOWS=0x600;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>__ZOOMIT_SCREENSAVER__;_UNICODE;UNICODE;WINVER=0x602;NDEBUG;_WIN32_WINNT=0x602;_WIN32_WINDOWS=0x501;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>__ZOOMIT_SCREENSAVER__;_UNICODE;UNICODE;WINVER=0x602;NDEBUG;_WIN32_WINNT=0x602;_WIN32_WINDOWS=0x501;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BreakTimer.cpp" />
|
||||
<ClCompile Include="ZoomItBreakScr.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="ZoomItBreak.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BreakTimer.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</Project>
|
||||
38
src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj.filters
Normal file
38
src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj.filters
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BreakTimer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZoomItBreakScr.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BreakTimer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="ZoomItBreak.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
283
src/modules/ZoomIt/ZoomItBreak/ZoomItBreakScr.cpp
Normal file
283
src/modules/ZoomIt/ZoomItBreak/ZoomItBreakScr.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
//============================================================================
|
||||
//
|
||||
// ZoomItBreakScr.cpp
|
||||
//
|
||||
// ZoomIt break timer screensaver (.scr). When launched by Winlogon on the
|
||||
// Screen-saver desktop with password protection, the user must authenticate
|
||||
// to dismiss it. The break timer countdown and rendering are provided by
|
||||
// the shared BreakTimer module.
|
||||
//
|
||||
// Copyright (C) Mark Russinovich
|
||||
// Sysinternals - www.sysinternals.com
|
||||
//
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
//============================================================================
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <scrnsave.h>
|
||||
#define GDIPVER 0x0110
|
||||
#include <gdiplus.h>
|
||||
|
||||
#include "BreakTimer.h"
|
||||
|
||||
static void DbgPrint( LPCTSTR fmt, ... )
|
||||
{
|
||||
TCHAR buf[512];
|
||||
va_list ap;
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 26492 )
|
||||
va_start( ap, fmt );
|
||||
#pragma warning( pop )
|
||||
_vsntprintf( buf, _countof(buf), fmt, ap );
|
||||
va_end( ap );
|
||||
buf[_countof(buf)-1] = 0;
|
||||
OutputDebugString( buf );
|
||||
}
|
||||
|
||||
#pragma comment(lib, "scrnsavw.lib")
|
||||
#pragma comment(lib, "comctl32.lib")
|
||||
#pragma comment(lib, "gdiplus.lib")
|
||||
#pragma comment(lib, "Msimg32.lib")
|
||||
#pragma comment(lib, "Winmm.lib")
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Globals
|
||||
//----------------------------------------------------------------------------
|
||||
static BreakTimerSettings g_Settings;
|
||||
static BreakTimerState g_State;
|
||||
static ULONG_PTR g_GdiplusToken;
|
||||
static TCHAR g_ScreenshotPath[MAX_PATH] = { 0 };
|
||||
static int g_LastSavedTimeout = 0; // For state persistence
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Load settings from the binary config file written by ZoomIt,
|
||||
// falling back to hard-coded defaults if the file is missing.
|
||||
//----------------------------------------------------------------------------
|
||||
static void LoadSettings( void )
|
||||
{
|
||||
BreakScrConfig config;
|
||||
if( BreakScrConfig_Read( &config ) )
|
||||
{
|
||||
g_Settings = config.settings;
|
||||
g_State.timeoutSeconds = config.timeoutSeconds;
|
||||
_tcscpy( g_ScreenshotPath, config.screenshotPath );
|
||||
DbgPrint( L"[BreakScr] Config loaded: timeout=%d, bgFile=%d, showDesktop=%d, screenshot=%s\n",
|
||||
config.timeoutSeconds, config.settings.showBackgroundFile,
|
||||
config.settings.showDesktop, config.screenshotPath );
|
||||
return;
|
||||
}
|
||||
|
||||
DbgPrint( L"[BreakScr] Config file not found, using fallback defaults\n" );
|
||||
// Fallback defaults (for testing the .scr directly).
|
||||
memset( &g_Settings, 0, sizeof( g_Settings ) );
|
||||
g_Settings.penColor = RGB( 255, 0, 0 );
|
||||
g_Settings.timerPosition = 4;
|
||||
g_Settings.opacity = 100;
|
||||
g_Settings.showExpiredTime = 1;
|
||||
g_Settings.smoothImage = TRUE;
|
||||
g_Settings.backgroundStretch = FALSE;
|
||||
g_Settings.showDesktop = TRUE;
|
||||
g_Settings.showBackgroundFile = FALSE;
|
||||
g_State.timeoutSeconds = 600;
|
||||
|
||||
NONCLIENTMETRICS ncm = { sizeof( ncm ) };
|
||||
SystemParametersInfo( SPI_GETNONCLIENTMETRICS, sizeof( ncm ), &ncm, 0 );
|
||||
g_Settings.logFont = ncm.lfMessageFont;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// ScreenSaverProc
|
||||
//
|
||||
// Main window procedure for the screensaver, called by Scrnsavw.lib.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
LRESULT WINAPI ScreenSaverProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
case WM_CREATE:
|
||||
{
|
||||
DbgPrint( L"[BreakScr] WM_CREATE: hwnd=%p\n", hWnd );
|
||||
|
||||
// Initialize GDI+.
|
||||
Gdiplus::GdiplusStartupInput startupIn;
|
||||
Gdiplus::GdiplusStartup( &g_GdiplusToken, &startupIn, NULL );
|
||||
|
||||
LoadSettings();
|
||||
|
||||
// Check if a previous screensaver instance already ran (resumed == TRUE).
|
||||
// On first launch, ZoomIt sets resumed = FALSE, so we skip the deduction.
|
||||
BreakScrConfig resumeConfig;
|
||||
if( BreakScrConfig_Read( &resumeConfig ) && resumeConfig.resumed )
|
||||
{
|
||||
// Subtract the screensaver idle timeout to compensate for
|
||||
// the time the screensaver wasn't running on the lock screen.
|
||||
UINT scrTimeout = 0;
|
||||
SystemParametersInfo( SPI_GETSCREENSAVETIMEOUT, 0, &scrTimeout, 0 );
|
||||
g_State.timeoutSeconds -= static_cast<int>( scrTimeout );
|
||||
if( g_State.timeoutSeconds < 0 && !g_Settings.showExpiredTime )
|
||||
g_State.timeoutSeconds = 0;
|
||||
DbgPrint( L"[BreakScr] Resumption: subtracted %u sec idle, timeout=%d\n",
|
||||
scrTimeout, g_State.timeoutSeconds );
|
||||
}
|
||||
|
||||
// Mark as resumed so subsequent screensaver launches know to deduct idle time.
|
||||
{
|
||||
BreakScrConfig markConfig;
|
||||
if( BreakScrConfig_Read( &markConfig ) )
|
||||
{
|
||||
markConfig.resumed = TRUE;
|
||||
BreakScrConfig_Write( &markConfig );
|
||||
}
|
||||
}
|
||||
|
||||
// Load pre-captured screenshot if provided.
|
||||
HBITMAP hBgBmp = NULL;
|
||||
HDC hBgDC = NULL;
|
||||
if( g_ScreenshotPath[0] )
|
||||
{
|
||||
hBgBmp = BreakTimer_LoadImageFile( g_ScreenshotPath );
|
||||
DbgPrint( L"[BreakScr] LoadImageFile(%s) => %p\n", g_ScreenshotPath, hBgBmp );
|
||||
if( hBgBmp )
|
||||
{
|
||||
HDC hdcScreen = CreateDC( L"DISPLAY", NULL, NULL, NULL );
|
||||
hBgDC = CreateCompatibleDC( hdcScreen );
|
||||
SelectObject( hBgDC, hBgBmp );
|
||||
DeleteDC( hdcScreen );
|
||||
}
|
||||
}
|
||||
|
||||
int timeout = g_State.timeoutSeconds;
|
||||
memset( &g_State, 0, sizeof( g_State ) );
|
||||
|
||||
DbgPrint( L"[BreakScr] Calling BreakTimer_Init, timeout=%d\n", timeout );
|
||||
if( !BreakTimer_Init( hWnd, &g_State, &g_Settings, timeout, hBgBmp, hBgDC ) )
|
||||
{
|
||||
DbgPrint( L"[BreakScr] BreakTimer_Init FAILED\n" );
|
||||
PostMessage( hWnd, WM_CLOSE, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
DbgPrint( L"[BreakScr] BreakTimer_Init OK, active=%d\n", g_State.active );
|
||||
|
||||
// Prevent the monitor from blanking due to power management.
|
||||
SetThreadExecutionState( ES_CONTINUOUS | ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED );
|
||||
|
||||
// Kick off the first tick and start the 1-second timer.
|
||||
SendMessage( hWnd, WM_TIMER, 1, 0 );
|
||||
SetTimer( hWnd, 1, 1000, NULL );
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_TIMER:
|
||||
if( wParam == 1 )
|
||||
{
|
||||
BreakTimer_Tick( hWnd, &g_State, &g_Settings );
|
||||
|
||||
// Periodically save state (every 5 seconds) for resumption after
|
||||
// credential provider timeout. This allows the screensaver to continue
|
||||
// from where it left off if a student triggers the login screen but
|
||||
// doesn't authenticate.
|
||||
if( g_State.timeoutSeconds != g_LastSavedTimeout &&
|
||||
g_State.timeoutSeconds % 5 == 0 )
|
||||
{
|
||||
BreakScrConfig config;
|
||||
if( BreakScrConfig_Read( &config ) )
|
||||
{
|
||||
config.timeoutSeconds = g_State.timeoutSeconds;
|
||||
if( BreakScrConfig_Write( &config ) )
|
||||
{
|
||||
g_LastSavedTimeout = g_State.timeoutSeconds;
|
||||
DbgPrint( L"[BreakScr] Saved state: %d seconds remaining\n",
|
||||
g_State.timeoutSeconds );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_PAINT:
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint( hWnd, &ps );
|
||||
if( g_State.active )
|
||||
{
|
||||
BreakTimer_Paint( hdc, &g_State, &g_Settings );
|
||||
}
|
||||
EndPaint( hWnd, &ps );
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
DbgPrint( L"[BreakScr] WM_DESTROY\n" );
|
||||
SetThreadExecutionState( ES_CONTINUOUS ); // Restore default power behavior
|
||||
KillTimer( hWnd, 1 );
|
||||
BreakTimer_Cleanup( &g_State, TRUE );
|
||||
Gdiplus::GdiplusShutdown( g_GdiplusToken );
|
||||
return 0;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Prevent DefScreenSaverProc from auto-closing on user input.
|
||||
// The screensaver must stay up until the break timer expires or
|
||||
// the user authenticates via Ctrl+Alt+Del. DefScreenSaverProc
|
||||
// would close the window on mouse movement, clicks, keyboard,
|
||||
// or deactivation.
|
||||
//------------------------------------------------------------------
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_KEYDOWN:
|
||||
if( wParam == 'W' || wParam == 'K' )
|
||||
{
|
||||
g_Settings.backgroundColor = ( wParam == 'K' ) ? 1 : 0;
|
||||
InvalidateRect( hWnd, NULL, FALSE );
|
||||
}
|
||||
return 0;
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
return 0;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
case WM_ACTIVATEAPP:
|
||||
// Don't close on deactivation (e.g. LockWorkStation switches desktop).
|
||||
return 0;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
// Block SC_CLOSE from Alt+F4 etc.
|
||||
if( ( wParam & 0xFFF0 ) == SC_CLOSE )
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return DefScreenSaverProc( hWnd, msg, wParam, lParam );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// ScreenSaverConfigureDialog
|
||||
//
|
||||
// No configuration — ZoomIt handles all settings.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
BOOL WINAPI ScreenSaverConfigureDialog( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// RegisterDialogClasses
|
||||
//
|
||||
// Nothing to register.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
BOOL WINAPI RegisterDialogClasses( HANDLE hInst )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -91,3 +91,12 @@ void Trace::ZoomItActivateSnip() noexcept
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
void Trace::ZoomItActivateSnipOcr() noexcept
|
||||
{
|
||||
TraceLoggingWriteWrapper(
|
||||
g_hProvider,
|
||||
"ZoomIt_ActivateSnipOcr",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
@@ -14,4 +14,5 @@ public:
|
||||
static void ZoomItActivateDemoType() noexcept;
|
||||
static void ZoomItActivateRecord() noexcept;
|
||||
static void ZoomItActivateSnip() noexcept;
|
||||
static void ZoomItActivateSnipOcr() noexcept;
|
||||
};
|
||||
|
||||
@@ -70,6 +70,8 @@ namespace winrt::PowerToys::ZoomItSettingsInterop::implementation
|
||||
{ L"DrawToggleKey", SPECIAL_SEMANTICS_SHORTCUT },
|
||||
{ L"RecordToggleKey", SPECIAL_SEMANTICS_SHORTCUT },
|
||||
{ L"SnipToggleKey", SPECIAL_SEMANTICS_SHORTCUT },
|
||||
{ L"SnipOcrToggleKey", SPECIAL_SEMANTICS_SHORTCUT },
|
||||
{ L"SnipPanoramaToggleKey", SPECIAL_SEMANTICS_SHORTCUT },
|
||||
{ L"BreakTimerKey", SPECIAL_SEMANTICS_SHORTCUT },
|
||||
{ L"DemoTypeToggleKey", SPECIAL_SEMANTICS_SHORTCUT },
|
||||
{ L"PenColor", SPECIAL_SEMANTICS_COLOR },
|
||||
|
||||
@@ -28,6 +28,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
[CmdConfigureIgnore]
|
||||
public static HotkeySettings DefaultSnipToggleKey => new HotkeySettings(false, true, false, false, '6'); // Ctrl+6
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
public static HotkeySettings DefaultSnipOcrToggleKey => new HotkeySettings(false, true, true, false, '6'); // Ctrl+Alt+6
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
public static HotkeySettings DefaultSnipPanoramaToggleKey => new HotkeySettings(false, true, false, false, '8'); // Ctrl+8
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
public static HotkeySettings DefaultBreakTimerKey => new HotkeySettings(false, true, false, false, '3'); // Ctrl+3
|
||||
|
||||
@@ -44,6 +50,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
|
||||
public KeyboardKeysProperty SnipToggleKey { get; set; }
|
||||
|
||||
public KeyboardKeysProperty SnipOcrToggleKey { get; set; }
|
||||
|
||||
public KeyboardKeysProperty SnipPanoramaToggleKey { get; set; }
|
||||
|
||||
public KeyboardKeysProperty BreakTimerKey { get; set; }
|
||||
|
||||
public StringProperty Font { get; set; }
|
||||
@@ -96,5 +106,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
public BoolProperty MicMonoMix { get; set; }
|
||||
|
||||
public StringProperty MicrophoneDeviceId { get; set; }
|
||||
|
||||
public BoolProperty BreakLockWorkstation { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,9 @@
|
||||
Visibility="{x:Bind ViewModel.BreakShowBackgroundFile, Mode=OneWay}">
|
||||
<CheckBox x:Uid="ZoomIt_Break_BackgroundStretch" IsChecked="{x:Bind ViewModel.BreakBackgroundStretch, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard Name="ZoomItBreakLockWorkstation" ContentAlignment="Left">
|
||||
<CheckBox x:Uid="ZoomIt_Break_LockWorkstation" IsChecked="{x:Bind ViewModel.BreakLockWorkstation, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard.Description>
|
||||
<tkcontrols:MarkdownTextBlock x:Uid="ZoomIt_BreakFAQ" Config="{StaticResource DescriptionTextMarkdownConfig}" />
|
||||
@@ -325,6 +328,22 @@
|
||||
</tkcontrols:SettingsCard>
|
||||
</tkcontrols:SettingsExpander.Items>
|
||||
</tkcontrols:SettingsExpander>
|
||||
<tkcontrols:SettingsExpander
|
||||
Name="ZoomItSnipOcrShortcut"
|
||||
x:Uid="ZoomIt_SnipOcr_Shortcut"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind ViewModel.SnipOcrToggleKey, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsExpander>
|
||||
</controls:SettingsGroup>
|
||||
<controls:SettingsGroup x:Uid="ZoomIt_PanoramaGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
|
||||
<tkcontrols:SettingsExpander
|
||||
Name="ZoomItPanoramaShortcut"
|
||||
x:Uid="ZoomIt_Panorama_Shortcut"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind ViewModel.SnipPanoramaToggleKey, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsExpander>
|
||||
</controls:SettingsGroup>
|
||||
</StackPanel>
|
||||
</controls:SettingsPageControl.ModuleContent>
|
||||
|
||||
@@ -4813,6 +4813,9 @@ The break timer font matches the text font.</value>
|
||||
<data name="ZoomIt_Record_Microphones_Default_Name" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Break_LockWorkstation.Content" xml:space="preserve">
|
||||
<value>Lock workstation during break</value>
|
||||
</data>
|
||||
<data name="ZoomIt_SnipGroup.Header" xml:space="preserve">
|
||||
<value>Snip</value>
|
||||
</data>
|
||||
@@ -4825,6 +4828,24 @@ The break timer font matches the text font.</value>
|
||||
<data name="ZoomIt_Snip_Shortcut_Save" xml:space="preserve">
|
||||
<value>Press **{0}** to save the snip to a file instead of the clipboard.</value>
|
||||
</data>
|
||||
<data name="ZoomIt_SnipOcr_Shortcut.Header" xml:space="preserve">
|
||||
<value>Snip OCR activation</value>
|
||||
</data>
|
||||
<data name="ZoomIt_SnipOcr_Shortcut.Description" xml:space="preserve">
|
||||
<value>Copy text from the selected region to the clipboard.</value>
|
||||
</data>
|
||||
<data name="ZoomIt_PanoramaGroup.Header" xml:space="preserve">
|
||||
<value>Panorama</value>
|
||||
</data>
|
||||
<data name="ZoomIt_PanoramaGroup.Description" xml:space="preserve">
|
||||
<value>Capture a scrolling panorama of a selected screen region.</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Panorama_Shortcut.Header" xml:space="preserve">
|
||||
<value>Panorama activation</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Panorama_Shortcut.Description" xml:space="preserve">
|
||||
<value>Select the area, then scroll the content. Move slowly and consistently, and do not rewind to previously covered areas. Press the hotkey again or with Shift to save to a file.</value>
|
||||
</data>
|
||||
<data name="Oobe_ZoomIt.Description" xml:space="preserve">
|
||||
<value>ZoomIt is a screen zoom, annotation, and recording tool for technical presentations and demos. You can also use ZoomIt to snip screenshots to the clipboard or to a file.</value>
|
||||
<comment>{Locked="ZoomIt"}</comment>
|
||||
|
||||
@@ -367,6 +367,34 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public HotkeySettings SnipOcrToggleKey
|
||||
{
|
||||
get => _zoomItSettings.Properties.SnipOcrToggleKey.Value;
|
||||
set
|
||||
{
|
||||
if (_zoomItSettings.Properties.SnipOcrToggleKey.Value != value)
|
||||
{
|
||||
_zoomItSettings.Properties.SnipOcrToggleKey.Value = value ?? ZoomItProperties.DefaultSnipOcrToggleKey;
|
||||
OnPropertyChanged(nameof(SnipOcrToggleKey));
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HotkeySettings SnipPanoramaToggleKey
|
||||
{
|
||||
get => _zoomItSettings.Properties.SnipPanoramaToggleKey.Value;
|
||||
set
|
||||
{
|
||||
if (_zoomItSettings.Properties.SnipPanoramaToggleKey.Value != value)
|
||||
{
|
||||
_zoomItSettings.Properties.SnipPanoramaToggleKey.Value = value ?? ZoomItProperties.DefaultSnipPanoramaToggleKey;
|
||||
OnPropertyChanged(nameof(SnipPanoramaToggleKey));
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HotkeySettings BreakTimerKey
|
||||
{
|
||||
get => _zoomItSettings.Properties.BreakTimerKey.Value;
|
||||
@@ -783,6 +811,20 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool BreakLockWorkstation
|
||||
{
|
||||
get => _zoomItSettings.Properties.BreakLockWorkstation.Value;
|
||||
set
|
||||
{
|
||||
if (_zoomItSettings.Properties.BreakLockWorkstation.Value != value)
|
||||
{
|
||||
_zoomItSettings.Properties.BreakLockWorkstation.Value = value;
|
||||
OnPropertyChanged(nameof(BreakLockWorkstation));
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double RecordScaling
|
||||
{
|
||||
get
|
||||
|
||||
Reference in New Issue
Block a user