commit 7c67e6081b0360fcaa010abc3c794c2965a21c29 Author: Master Date: Fri Aug 7 05:15:01 2026 -0300 release diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cdf94e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +.vs/ +bin/ +obj/ +Debug/ +x64/ +*.user +*.suo +*.VC.db +*.VC.opendb +*.obj +*.pdb +*.ipdb +*.iobj +*.ilk +*.exp +*.lib +*.tlog +*.lastbuildstate +*.recipe diff --git a/README.md b/README.md new file mode 100644 index 0000000..f16ee03 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# ScreenPrivacy + +ScreenPrivacy é um plugin nativo para Notepad++ que oculta a janela inteira do editor em capturas de tela compatíveis com a proteção de conteúdo do Windows. + +A proteção é global e inicia ativada automaticamente. O conteúdo permanece visível e editável no monitor local, mas não aparece em compartilhamentos ou capturas que respeitem `WDA_EXCLUDEFROMCAPTURE`. + +## Requisitos + +- Windows 10 versão 2004 ou superior, ou Windows 11; +- Notepad++ x64. + +## Instalação + +1. Feche o Notepad++. +2. Crie a pasta: + +```text +C:\Program Files\Notepad++\plugins\ScreenPrivacy +``` + +3. Baixe `ScreenPrivacy.dll` na página de [Releases](https://git.raulbank.com/Master/ScreenPrivacy/releases) e copie o arquivo para essa pasta. +4. Abra o Notepad++ novamente. + +## Compilação + +Instale o Visual Studio 2022 ou Visual Studio 2022 Build Tools com a workload `Desktop development with C++`, o MSVC v143 e um Windows 10/11 SDK. + +Abra o Developer PowerShell for Visual Studio na pasta do projeto e execute: + +```powershell +msbuild ScreenPrivacy.sln /m /t:Rebuild /p:Configuration=Release /p:Platform=x64 +``` + +O DLL compilado será gerado em: + +```text +bin\Release\ScreenPrivacy.dll +``` + +## Uso + +A proteção inicia ligada. Para desativar ou reativar, use: + +```text +Plugins > ScreenPrivacy > Proteção global contra captura +``` diff --git a/ScreenPrivacy.sln b/ScreenPrivacy.sln new file mode 100644 index 0000000..569accc --- /dev/null +++ b/ScreenPrivacy.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{BC8A1FFA-BEE3-4634-8014-F334798102B3}") = "ScreenPrivacy", "ScreenPrivacy.vcxproj", "{BD13C572-E131-489D-9667-D1BA520026EC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BD13C572-E131-489D-9667-D1BA520026EC}.Debug|x64.ActiveCfg = Debug|x64 + {BD13C572-E131-489D-9667-D1BA520026EC}.Debug|x64.Build.0 = Debug|x64 + {BD13C572-E131-489D-9667-D1BA520026EC}.Release|x64.ActiveCfg = Release|x64 + {BD13C572-E131-489D-9667-D1BA520026EC}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ScreenPrivacy.vcxproj b/ScreenPrivacy.vcxproj new file mode 100644 index 0000000..b3416c5 --- /dev/null +++ b/ScreenPrivacy.vcxproj @@ -0,0 +1,97 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {BD13C572-E131-489D-9667-D1BA520026EC} + ScreenPrivacy + ScreenPrivacy + 10.0 + + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + false + Unicode + + + + + + + + + + + + + $(SolutionDir)bin\$(Configuration)\ + $(SolutionDir)obj\$(Configuration)\ + ScreenPrivacy + + + + Level4 + true + true + stdcpplatest + UNICODE;_UNICODE;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0A00;WINVER=0x0A00;%(PreprocessorDefinitions) + MultiThreadedDebug + /utf-8 /permissive- %(AdditionalOptions) + + + Windows + true + + + + + Level4 + true + true + true + true + stdcpplatest + UNICODE;_UNICODE;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0A00;WINVER=0x0A00;NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + None + /utf-8 /permissive- %(AdditionalOptions) + + + Windows + true + true + false + /DEBUG:NONE /NOCOFFGRPINFO /EMITTOOLVERSIONINFO:NO %(AdditionalOptions) + + + powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command "$p='$(TargetPath)'; $b=[System.IO.File]::ReadAllBytes($p); $o=[BitConverter]::ToInt32($b,60); [Array]::Clear($b,$o+8,4); [Array]::Clear($b,$o+26,2); [System.IO.File]::WriteAllBytes($p,$b)" + + + + + + + + + + + diff --git a/src/PluginApi.h b/src/PluginApi.h new file mode 100644 index 0000000..27694a5 --- /dev/null +++ b/src/PluginApi.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +constexpr UINT NPPMSG = WM_USER + 1000; +constexpr UINT NPPM_SETMENUITEMCHECK = NPPMSG + 40; +constexpr UINT NPPN_FIRST = 1000; +constexpr UINT NPPN_READY = NPPN_FIRST + 1; +constexpr UINT NPPN_SHUTDOWN = NPPN_FIRST + 9; + +struct NppData +{ + HWND nppHandle; + HWND scintillaMainHandle; + HWND scintillaSecondHandle; +}; + +using PluginCommand = void(__cdecl*)(); + +struct ShortcutKey +{ + bool isCtrl; + bool isAlt; + bool isShift; + UCHAR key; +}; + +struct FuncItem +{ + wchar_t itemName[64]; + PluginCommand function; + int commandId; + bool checkedOnInit; + ShortcutKey* shortcut; +}; + +struct SCNotification +{ + NMHDR header; +}; diff --git a/src/ScreenPrivacy.cpp b/src/ScreenPrivacy.cpp new file mode 100644 index 0000000..353a32d --- /dev/null +++ b/src/ScreenPrivacy.cpp @@ -0,0 +1,171 @@ +#include "PluginApi.h" + +#include + +namespace +{ + constexpr DWORD CaptureExcluded = 0x00000011; + constexpr wchar_t PluginName[] = L"ScreenPrivacy"; + + NppData nppData{}; + DWORD originalAffinity = WDA_NONE; + DWORD currentAffinity = WDA_NONE; + bool affinityKnown = false; + bool failureReported = false; + bool protectionEnabled = true; + + void toggleProtection(); + + FuncItem functions[] = { + {L"Proteção global contra captura", toggleProtection, 0, true, nullptr} + }; + + void showAffinityError(DWORD errorCode) + { + std::wstring message = L"Não foi possível alterar a proteção contra captura da janela do Notepad++.\n\nErro do Windows: "; + message += std::to_wstring(errorCode); + + wchar_t* systemMessage = nullptr; + const DWORD length = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + errorCode, + 0, + reinterpret_cast(&systemMessage), + 0, + nullptr + ); + + if (length != 0 && systemMessage != nullptr) + { + message += L"\n"; + message.append(systemMessage, length); + LocalFree(systemMessage); + } + + MessageBoxW(nppData.nppHandle, message.c_str(), PluginName, MB_OK | MB_ICONERROR); + } + + bool setAffinity(DWORD affinity, bool reportFailure) + { + if (nppData.nppHandle == nullptr) + { + return false; + } + + if (affinityKnown && currentAffinity == affinity) + { + failureReported = false; + return true; + } + + SetLastError(ERROR_SUCCESS); + if (SetWindowDisplayAffinity(nppData.nppHandle, affinity) != FALSE) + { + currentAffinity = affinity; + affinityKnown = true; + failureReported = false; + return true; + } + + if (reportFailure && !failureReported) + { + failureReported = true; + showAffinityError(GetLastError()); + } + + return false; + } + + void setMenuCheck(bool checked) + { + SendMessageW( + nppData.nppHandle, + NPPM_SETMENUITEMCHECK, + static_cast(functions[0].commandId), + static_cast(checked ? TRUE : FALSE) + ); + } + + void toggleProtection() + { + const bool requestedState = !protectionEnabled; + const DWORD requestedAffinity = requestedState ? CaptureExcluded : originalAffinity; + if (setAffinity(requestedAffinity, true)) + { + protectionEnabled = requestedState; + setMenuCheck(protectionEnabled); + } + } +} + +BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID) +{ + if (reason == DLL_PROCESS_ATTACH) + { + DisableThreadLibraryCalls(module); + } + return TRUE; +} + +extern "C" __declspec(dllexport) void setInfo(NppData data) +{ + nppData = data; + DWORD affinity = WDA_NONE; + if (GetWindowDisplayAffinity(nppData.nppHandle, &affinity) != FALSE) + { + originalAffinity = affinity; + currentAffinity = affinity; + affinityKnown = true; + } +} + +extern "C" __declspec(dllexport) const wchar_t* getName() +{ + return PluginName; +} + +extern "C" __declspec(dllexport) FuncItem* getFuncsArray(int* count) +{ + if (count != nullptr) + { + *count = static_cast(sizeof(functions) / sizeof(functions[0])); + } + return functions; +} + +extern "C" __declspec(dllexport) void beNotified(SCNotification* notification) +{ + if (notification == nullptr) + { + return; + } + + switch (notification->header.code) + { + case NPPN_READY: + if (!setAffinity(CaptureExcluded, true)) + { + protectionEnabled = false; + } + setMenuCheck(protectionEnabled); + break; + + case NPPN_SHUTDOWN: + setAffinity(originalAffinity, false); + break; + + default: + break; + } +} + +extern "C" __declspec(dllexport) LRESULT messageProc(UINT, WPARAM, LPARAM) +{ + return TRUE; +} + +extern "C" __declspec(dllexport) BOOL isUnicode() +{ + return TRUE; +}